aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts/test/forwarder/forwarder.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/contracts/test/forwarder/forwarder.ts')
-rw-r--r--packages/contracts/test/forwarder/forwarder.ts1248
1 files changed, 683 insertions, 565 deletions
diff --git a/packages/contracts/test/forwarder/forwarder.ts b/packages/contracts/test/forwarder/forwarder.ts
index 0256d7d81..f2966fe75 100644
--- a/packages/contracts/test/forwarder/forwarder.ts
+++ b/packages/contracts/test/forwarder/forwarder.ts
@@ -47,10 +47,10 @@ describe(ContractName.Forwarder, () => {
let forwarderWrapper: ForwarderWrapper;
let exchangeWrapper: ExchangeWrapper;
- let signedOrder: SignedOrder;
- let signedOrders: SignedOrder[];
+ let orderWithoutFee: SignedOrder;
+ let ordersWithoutFee: SignedOrder[];
let orderWithFee: SignedOrder;
- let signedOrdersWithFee: SignedOrder[];
+ let ordersWithFee: SignedOrder[];
let feeOrder: SignedOrder;
let feeOrders: SignedOrder[];
let orderFactory: OrderFactory;
@@ -59,7 +59,9 @@ describe(ContractName.Forwarder, () => {
let tx: TransactionReceiptWithDecodedLogs;
let erc721MakerAssetIds: BigNumber[];
- let feeProportion: number = 0;
+ let takerEthBalanceBefore: BigNumber;
+ let feePercentage: BigNumber;
+ const MAX_WETH_FILL_PERCENTAGE = 95;
before(async () => {
await blockchainLifecycle.startAsync();
@@ -135,7 +137,11 @@ describe(ContractName.Forwarder, () => {
wethAssetData,
);
forwarderContract = new ForwarderContract(forwarderInstance.abi, forwarderInstance.address, provider);
- forwarderWrapper = new ForwarderWrapper(forwarderContract, provider, zrxToken.address);
+ forwarderWrapper = new ForwarderWrapper(forwarderContract, provider);
+ const zrxDepositAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18);
+ await web3Wrapper.awaitTransactionSuccessAsync(
+ await zrxToken.transfer.sendTransactionAsync(forwarderContract.address, zrxDepositAmount),
+ );
erc20Wrapper.addTokenOwnerAddress(forwarderInstance.address);
web3Wrapper.abiDecoder.addABI(forwarderContract.abi);
@@ -146,673 +152,785 @@ describe(ContractName.Forwarder, () => {
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
- feeProportion = 0;
erc20Balances = await erc20Wrapper.getBalancesAsync();
- signedOrder = await orderFactory.newSignedOrderAsync();
- signedOrders = [signedOrder];
+ takerEthBalanceBefore = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
+ orderWithoutFee = await orderFactory.newSignedOrderAsync();
feeOrder = await orderFactory.newSignedOrderAsync({
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
});
- feeOrders = [feeOrder];
orderWithFee = await orderFactory.newSignedOrderAsync({
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
});
- signedOrdersWithFee = [orderWithFee];
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
- describe('calculations', () => {
- it('throws if partially filled orders passed in are not enough to satisfy requested amount', async () => {
- feeOrders = [feeOrder];
- const makerTokenFillAmount = feeOrder.makerAssetAmount.div(2);
- const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
- feeOrders,
- [],
- feeProportion,
- makerTokenFillAmount,
- );
- // Fill the feeOrder
- tx = await forwarderWrapper.marketBuyTokensWithEthAsync(feeOrders, [], makerTokenFillAmount, {
- from: takerAddress,
- value: fillAmountWei,
- });
- return expect(
- forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
- feeOrders,
- [],
- feeProportion,
- makerTokenFillAmount,
- ),
- ).to.be.rejectedWith('Unable to satisfy makerAssetFillAmount with provided orders');
- });
- it('throws if orders passed are cancelled', async () => {
- tx = await exchangeWrapper.cancelOrderAsync(feeOrder, makerAddress);
- // Cancel the feeOrder
- return expect(
- forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
- feeOrders,
- [],
- feeProportion,
- feeOrder.makerAssetAmount.div(2),
- ),
- ).to.be.rejectedWith('Unable to satisfy makerAssetFillAmount with provided orders');
- });
- });
- describe('marketSellEthForERC20 without extra fees', () => {
+
+ describe('marketSellOrdersWithEth without extra fees', () => {
it('should fill the order', async () => {
- const fillAmount = signedOrder.takerAssetAmount.div(2);
- const makerBalanceBefore = erc20Balances[makerAddress][defaultMakerAssetAddress];
- const takerBalanceBefore = erc20Balances[takerAddress][defaultMakerAssetAddress];
+ ordersWithoutFee = [orderWithoutFee];
feeOrders = [];
- tx = await forwarderWrapper.marketSellEthForERC20Async(signedOrders, feeOrders, {
- value: fillAmount,
+ const ethValue = orderWithoutFee.takerAssetAmount.dividedToIntegerBy(2);
+
+ tx = await forwarderWrapper.marketSellOrdersWithEthAsync(ordersWithoutFee, feeOrders, {
+ value: ethValue,
from: takerAddress,
});
+ const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
+ const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
const newBalances = await erc20Wrapper.getBalancesAsync();
- const makerBalanceAfter = newBalances[makerAddress][defaultMakerAssetAddress];
- const takerBalanceAfter = newBalances[takerAddress][defaultMakerAssetAddress];
- const makerTokenFillAmount = fillAmount
- .times(signedOrder.makerAssetAmount)
- .dividedToIntegerBy(signedOrder.takerAssetAmount);
-
- expect(makerBalanceAfter).to.be.bignumber.equal(makerBalanceBefore.minus(makerTokenFillAmount));
- expect(takerBalanceAfter).to.be.bignumber.equal(takerBalanceBefore.plus(makerTokenFillAmount));
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(new BigNumber(0));
+
+ const primaryTakerAssetFillAmount = ForwarderWrapper.getPercentageOfValue(
+ ethValue,
+ MAX_WETH_FILL_PERCENTAGE,
+ );
+ const makerAssetFillAmount = primaryTakerAssetFillAmount
+ .times(orderWithoutFee.makerAssetAmount)
+ .dividedToIntegerBy(orderWithoutFee.takerAssetAmount);
+ const totalEthSpent = primaryTakerAssetFillAmount.plus(DEFAULT_GAS_PRICE.times(tx.gasUsed));
+
+ expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
+ expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
+ );
+ expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
+ );
+ expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
+ );
+ expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
+ expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ constants.ZERO_AMOUNT,
+ );
+ expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
- it('should fill the order and perform fee abstraction', async () => {
- const fillAmount = signedOrder.takerAssetAmount.div(4);
- const takerBalanceBefore = erc20Balances[takerAddress][defaultMakerAssetAddress];
- tx = await forwarderWrapper.marketSellEthForERC20Async(signedOrdersWithFee, feeOrders, {
- value: fillAmount,
+ it('should fill the order and pay ZRX fees from feeOrders', async () => {
+ ordersWithFee = [orderWithFee];
+ feeOrders = [feeOrder];
+ const ethValue = orderWithFee.takerAssetAmount.dividedToIntegerBy(2);
+
+ tx = await forwarderWrapper.marketSellOrdersWithEthAsync(ordersWithFee, feeOrders, {
+ value: ethValue,
from: takerAddress,
});
+ const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
+ const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
const newBalances = await erc20Wrapper.getBalancesAsync();
- const takerBalanceAfter = newBalances[takerAddress][defaultMakerAssetAddress];
- const acceptPercentage = 98;
- const acceptableThreshold = takerBalanceBefore.plus(fillAmount.times(acceptPercentage).dividedBy(100));
- const isWithinThreshold = takerBalanceAfter.greaterThanOrEqualTo(acceptableThreshold);
- expect(isWithinThreshold).to.be.true();
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(new BigNumber(0));
+ const primaryTakerAssetFillAmount = ForwarderWrapper.getPercentageOfValue(
+ ethValue,
+ MAX_WETH_FILL_PERCENTAGE,
+ );
+ const makerAssetFillAmount = primaryTakerAssetFillAmount
+ .times(orderWithoutFee.makerAssetAmount)
+ .dividedToIntegerBy(orderWithoutFee.takerAssetAmount);
+ const feeAmount = ForwarderWrapper.getPercentageOfValue(
+ orderWithFee.takerFee.dividedToIntegerBy(2),
+ MAX_WETH_FILL_PERCENTAGE,
+ );
+ const wethSpentOnFeeOrders = ForwarderWrapper.getWethForFeeOrders(feeAmount, feeOrders);
+ const totalEthSpent = primaryTakerAssetFillAmount
+ .plus(wethSpentOnFeeOrders)
+ .plus(DEFAULT_GAS_PRICE.times(tx.gasUsed));
+
+ expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
+ expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
+ );
+ expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
+ );
+ expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount).plus(wethSpentOnFeeOrders),
+ );
+ expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
+ expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ constants.ZERO_AMOUNT,
+ );
+ expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('should fill the order when token is ZRX with fees', async () => {
orderWithFee = await orderFactory.newSignedOrderAsync({
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
});
- signedOrdersWithFee = [orderWithFee];
+ ordersWithFee = [orderWithFee];
feeOrders = [];
- const fillAmount = signedOrder.takerAssetAmount.div(4);
- const takerBalanceBefore = erc20Balances[takerAddress][zrxToken.address];
- tx = await forwarderWrapper.marketSellEthForERC20Async(signedOrdersWithFee, feeOrders, {
- value: fillAmount,
+ const ethValue = orderWithFee.takerAssetAmount.dividedToIntegerBy(2);
+
+ tx = await forwarderWrapper.marketSellOrdersWithEthAsync(ordersWithFee, feeOrders, {
+ value: ethValue,
from: takerAddress,
});
+ const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
+ const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
const newBalances = await erc20Wrapper.getBalancesAsync();
- const takerBalanceAfter = newBalances[takerAddress][zrxToken.address];
- const acceptPercentage = 98;
- const acceptableThreshold = takerBalanceBefore.plus(fillAmount.times(acceptPercentage).dividedBy(100));
- const isWithinThreshold = takerBalanceAfter.greaterThanOrEqualTo(acceptableThreshold);
- expect(isWithinThreshold).to.be.true();
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(new BigNumber(0));
+ const makerAssetFillAmount = orderWithFee.makerAssetAmount.dividedToIntegerBy(2);
+ const totalEthSpent = ethValue.plus(DEFAULT_GAS_PRICE.times(tx.gasUsed));
+ const takerFeePaid = orderWithFee.takerFee.dividedToIntegerBy(2);
+ const makerFeePaid = orderWithFee.makerFee.dividedToIntegerBy(2);
+
+ expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
+ expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][zrxToken.address].minus(makerAssetFillAmount).minus(makerFeePaid),
+ );
+ expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
+ erc20Balances[takerAddress][zrxToken.address].plus(makerAssetFillAmount).minus(takerFeePaid),
+ );
+ expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][weth.address].plus(ethValue),
+ );
+ expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
+ expect(newBalances[forwarderContract.address][zrxToken.address]).to.be.bignumber.equal(
+ erc20Balances[forwarderContract.address][zrxToken.address],
+ );
+ expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
- it('should fail if sent an ETH amount too high', async () => {
- signedOrder = await orderFactory.newSignedOrderAsync({
- makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
+ it('should refund remaining ETH if amount is greater than takerAssetAmount', async () => {
+ ordersWithoutFee = [orderWithoutFee];
+ const ethValue = orderWithoutFee.takerAssetAmount.times(2);
+
+ tx = await forwarderWrapper.marketSellOrdersWithEthAsync(ordersWithoutFee, feeOrders, {
+ value: ethValue,
+ from: takerAddress,
});
- const fillAmount = signedOrder.takerAssetAmount.times(2);
- return expectTransactionFailedAsync(
- forwarderWrapper.marketSellEthForERC20Async(signedOrdersWithFee, feeOrders, {
- value: fillAmount,
- from: takerAddress,
- }),
- RevertReason.UnacceptableThreshold,
- );
+ const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
+ const totalEthSpent = orderWithoutFee.takerAssetAmount.plus(DEFAULT_GAS_PRICE.times(tx.gasUsed));
+
+ expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
});
- it('should fail if fee abstraction amount is too high', async () => {
+ it('should revert if ZRX cannot be fully repurchased', async () => {
orderWithFee = await orderFactory.newSignedOrderAsync({
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), DECIMALS_DEFAULT),
});
- signedOrdersWithFee = [orderWithFee];
+ ordersWithFee = [orderWithFee];
feeOrder = await orderFactory.newSignedOrderAsync({
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
});
feeOrders = [feeOrder];
- const fillAmount = signedOrder.takerAssetAmount.div(4);
+ const ethValue = orderWithFee.takerAssetAmount;
return expectTransactionFailedAsync(
- forwarderWrapper.marketSellEthForERC20Async(signedOrdersWithFee, feeOrders, {
- value: fillAmount,
+ forwarderWrapper.marketSellOrdersWithEthAsync(ordersWithFee, feeOrders, {
+ value: ethValue,
from: takerAddress,
}),
- RevertReason.TransferFailed,
+ RevertReason.CompleteFillFailed,
);
});
- it('throws when mixed ERC721 and ERC20 assets with ERC20 first', async () => {
+ it('should not fill orders with different makerAssetData than the first order', async () => {
const makerAssetId = erc721MakerAssetIds[0];
const erc721SignedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
});
const erc20SignedOrder = await orderFactory.newSignedOrderAsync();
- signedOrders = [erc20SignedOrder, erc721SignedOrder];
- const fillAmountWei = erc20SignedOrder.takerAssetAmount.plus(erc721SignedOrder.takerAssetAmount);
- return expectTransactionFailedAsync(
- forwarderWrapper.marketSellEthForERC20Async(signedOrders, feeOrders, {
- from: takerAddress,
- value: fillAmountWei,
- }),
- RevertReason.InvalidOrderSignature,
- );
+ ordersWithoutFee = [erc20SignedOrder, erc721SignedOrder];
+ const ethValue = erc20SignedOrder.takerAssetAmount.plus(erc721SignedOrder.takerAssetAmount);
+
+ tx = await forwarderWrapper.marketSellOrdersWithEthAsync(ordersWithoutFee, feeOrders, {
+ value: ethValue,
+ from: takerAddress,
+ });
+ const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
+ const totalEthSpent = erc20SignedOrder.takerAssetAmount.plus(DEFAULT_GAS_PRICE.times(tx.gasUsed));
+
+ expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
});
});
- describe('marketSellEthForERC20 with extra fees', () => {
- it('should fill the order and send fee to fee recipient', async () => {
- const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(feeRecipientAddress);
- const fillAmount = signedOrder.takerAssetAmount.div(2);
- feeProportion = 150; // 1.5%
+ describe('marketSellOrdersWithEth with extra fees', () => {
+ it('should fill the order and send fee to feeRecipient', async () => {
+ ordersWithoutFee = [orderWithoutFee];
feeOrders = [];
- tx = await forwarderWrapper.marketSellEthForERC20Async(
- signedOrders,
+ const ethValue = orderWithoutFee.takerAssetAmount.div(2);
+
+ const baseFeePercentage = 2;
+ feePercentage = ForwarderWrapper.getPercentageOfValue(constants.PERCENTAGE_DENOMINATOR, baseFeePercentage);
+ const feeRecipientEthBalanceBefore = await web3Wrapper.getBalanceInWeiAsync(feeRecipientAddress);
+ tx = await forwarderWrapper.marketSellOrdersWithEthAsync(
+ ordersWithoutFee,
feeOrders,
{
+ value: ethValue,
from: takerAddress,
- value: fillAmount,
- gasPrice: DEFAULT_GAS_PRICE,
- },
- {
- feeProportion,
- feeRecipient: feeRecipientAddress,
},
+ { feePercentage, feeRecipient: feeRecipientAddress },
);
+ const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
+ const feeRecipientEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(feeRecipientAddress);
+ const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
const newBalances = await erc20Wrapper.getBalancesAsync();
- const makerBalanceBefore = erc20Balances[makerAddress][defaultMakerAssetAddress];
- const makerBalanceAfter = newBalances[makerAddress][defaultMakerAssetAddress];
- const takerBalanceAfter = newBalances[takerAddress][defaultMakerAssetAddress];
- const afterEthBalance = await web3Wrapper.getBalanceInWeiAsync(feeRecipientAddress);
- const takerBoughtAmount = takerBalanceAfter.minus(erc20Balances[takerAddress][defaultMakerAssetAddress]);
- expect(makerBalanceAfter).to.be.bignumber.equal(makerBalanceBefore.minus(takerBoughtAmount));
- expect(afterEthBalance).to.be.bignumber.equal(
- initEthBalance.plus(fillAmount.times(feeProportion).dividedBy(10000)),
+ const primaryTakerAssetFillAmount = ForwarderWrapper.getPercentageOfValue(
+ ethValue,
+ MAX_WETH_FILL_PERCENTAGE,
+ );
+ const makerAssetFillAmount = primaryTakerAssetFillAmount
+ .times(orderWithoutFee.makerAssetAmount)
+ .dividedToIntegerBy(orderWithoutFee.takerAssetAmount);
+ const ethSpentOnFee = ForwarderWrapper.getPercentageOfValue(primaryTakerAssetFillAmount, baseFeePercentage);
+ const totalEthSpent = primaryTakerAssetFillAmount
+ .plus(ethSpentOnFee)
+ .plus(DEFAULT_GAS_PRICE.times(tx.gasUsed));
+
+ expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
+ expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
);
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(new BigNumber(0));
+ expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
+ );
+ expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
+ );
+ expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
+ expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ constants.ZERO_AMOUNT,
+ );
+ expect(feeRecipientEthBalanceAfter).to.be.bignumber.equal(feeRecipientEthBalanceBefore.plus(ethSpentOnFee));
+ expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('should fail if the fee is set too high', async () => {
- const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(feeRecipientAddress);
- const fillAmount = signedOrder.takerAssetAmount.div(2);
- feeProportion = 1500; // 15.0%
+ const feeRecipientEthBalanceBefore = await web3Wrapper.getBalanceInWeiAsync(feeRecipientAddress);
+ const ethValue = orderWithoutFee.takerAssetAmount.div(2);
+ const baseFeePercentage = 6;
+ feePercentage = ForwarderWrapper.getPercentageOfValue(ethValue, baseFeePercentage);
feeOrders = [];
await expectTransactionFailedAsync(
- forwarderWrapper.marketSellEthForERC20Async(
- signedOrders,
+ forwarderWrapper.marketSellOrdersWithEthAsync(
+ ordersWithoutFee,
feeOrders,
- { from: takerAddress, value: fillAmount, gasPrice: DEFAULT_GAS_PRICE },
- { feeProportion, feeRecipient: feeRecipientAddress },
+ { from: takerAddress, value: ethValue, gasPrice: DEFAULT_GAS_PRICE },
+ { feePercentage, feeRecipient: feeRecipientAddress },
),
- RevertReason.FeeProportionTooLarge,
+ RevertReason.FeePercentageTooLarge,
);
- const afterEthBalance = await web3Wrapper.getBalanceInWeiAsync(feeRecipientAddress);
- expect(afterEthBalance).to.be.bignumber.equal(initEthBalance);
+ const feeRecipientEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(feeRecipientAddress);
+ expect(feeRecipientEthBalanceAfter).to.be.bignumber.equal(feeRecipientEthBalanceBefore);
});
});
- describe('marketBuyTokensWithEth', () => {
+ describe('marketBuyOrdersWithEth without extra fees', () => {
it('should buy the exact amount of assets', async () => {
- const makerAssetAmount = signedOrder.makerAssetAmount.div(2);
- const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const balancesBefore = await erc20Wrapper.getBalancesAsync();
- const rate = signedOrder.makerAssetAmount.dividedBy(signedOrder.takerAssetAmount);
- const fillAmountWei = makerAssetAmount.dividedToIntegerBy(rate);
+ ordersWithoutFee = [orderWithoutFee];
feeOrders = [];
- tx = await forwarderWrapper.marketBuyTokensWithEthAsync(signedOrders, feeOrders, makerAssetAmount, {
+ const makerAssetFillAmount = orderWithoutFee.makerAssetAmount.dividedToIntegerBy(2);
+ const ethValue = orderWithoutFee.takerAssetAmount.dividedToIntegerBy(2);
+
+ tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithoutFee, feeOrders, makerAssetFillAmount, {
+ value: ethValue,
from: takerAddress,
- value: fillAmountWei,
- gasPrice: DEFAULT_GAS_PRICE,
});
+ const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
+ const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
const newBalances = await erc20Wrapper.getBalancesAsync();
- const takerBalanceBefore = balancesBefore[takerAddress][defaultMakerAssetAddress];
- const takerBalanceAfter = newBalances[takerAddress][defaultMakerAssetAddress];
- const afterEthBalance = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const expectedEthBalanceAfterGasCosts = initEthBalance.minus(fillAmountWei).minus(tx.gasUsed);
- expect(takerBalanceAfter).to.be.bignumber.eq(takerBalanceBefore.plus(makerAssetAmount));
- expect(afterEthBalance).to.be.bignumber.eq(expectedEthBalanceAfterGasCosts);
+
+ const primaryTakerAssetFillAmount = ethValue;
+ const totalEthSpent = primaryTakerAssetFillAmount.plus(DEFAULT_GAS_PRICE.times(tx.gasUsed));
+
+ expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
+ expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
+ );
+ expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
+ );
+ expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
+ );
+ expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
+ expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ constants.ZERO_AMOUNT,
+ );
+ expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
it('should buy the exact amount of assets and return excess ETH', async () => {
- const makerAssetAmount = signedOrder.makerAssetAmount.div(2);
- const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const balancesBefore = await erc20Wrapper.getBalancesAsync();
- const rate = signedOrder.makerAssetAmount.dividedBy(signedOrder.takerAssetAmount);
- const fillAmount = makerAssetAmount.dividedToIntegerBy(rate);
- const excessFillAmount = fillAmount.times(2);
- feeOrders = [];
- tx = await forwarderWrapper.marketBuyTokensWithEthAsync(signedOrders, feeOrders, makerAssetAmount, {
- from: takerAddress,
- value: excessFillAmount,
- gasPrice: DEFAULT_GAS_PRICE,
- });
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const takerBalanceBefore = balancesBefore[takerAddress][defaultMakerAssetAddress];
- const takerBalanceAfter = newBalances[takerAddress][defaultMakerAssetAddress];
- const afterEthBalance = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const expectedEthBalanceAfterGasCosts = initEthBalance.minus(fillAmount).minus(tx.gasUsed);
- expect(takerBalanceAfter).to.be.bignumber.eq(takerBalanceBefore.plus(makerAssetAmount));
- expect(afterEthBalance).to.be.bignumber.eq(expectedEthBalanceAfterGasCosts);
- });
- it('should buy the exact amount of assets with fee abstraction', async () => {
- const makerAssetAmount = signedOrder.makerAssetAmount.div(2);
- const balancesBefore = await erc20Wrapper.getBalancesAsync();
- const rate = signedOrder.makerAssetAmount.dividedBy(signedOrder.takerAssetAmount);
- const fillAmount = makerAssetAmount.dividedToIntegerBy(rate);
- const excessFillAmount = fillAmount.times(2);
- tx = await forwarderWrapper.marketBuyTokensWithEthAsync(signedOrdersWithFee, feeOrders, makerAssetAmount, {
- from: takerAddress,
- value: excessFillAmount,
- });
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const takerBalanceBefore = balancesBefore[takerAddress][defaultMakerAssetAddress];
- const takerBalanceAfter = newBalances[takerAddress][defaultMakerAssetAddress];
- expect(takerBalanceAfter).to.be.bignumber.eq(takerBalanceBefore.plus(makerAssetAmount));
- });
- it('should buy the exact amount of assets when buying zrx with fee abstraction', async () => {
- signedOrder = await orderFactory.newSignedOrderAsync({
- makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
- });
- signedOrdersWithFee = [signedOrder];
+ ordersWithoutFee = [orderWithoutFee];
feeOrders = [];
- const makerAssetAmount = signedOrder.makerAssetAmount.div(2);
- const takerWeiBalanceBefore = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const balancesBefore = await erc20Wrapper.getBalancesAsync();
- const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
- signedOrdersWithFee,
- feeOrders,
- feeProportion,
- makerAssetAmount,
- );
- tx = await forwarderWrapper.marketBuyTokensWithEthAsync(signedOrdersWithFee, feeOrders, makerAssetAmount, {
+ const makerAssetFillAmount = orderWithoutFee.makerAssetAmount.dividedToIntegerBy(2);
+ const ethValue = orderWithoutFee.takerAssetAmount;
+
+ tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithoutFee, feeOrders, makerAssetFillAmount, {
+ value: ethValue,
from: takerAddress,
- value: fillAmountWei,
- gasPrice: DEFAULT_GAS_PRICE,
});
+ const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
+ const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
const newBalances = await erc20Wrapper.getBalancesAsync();
- const takerTokenBalanceBefore = balancesBefore[takerAddress][zrxToken.address];
- const takerTokenBalanceAfter = newBalances[takerAddress][zrxToken.address];
- const takerWeiBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const expectedCostAfterGas = fillAmountWei.plus(tx.gasUsed);
- expect(takerTokenBalanceAfter).to.be.bignumber.greaterThan(takerTokenBalanceBefore.plus(makerAssetAmount));
- expect(takerWeiBalanceAfter).to.be.bignumber.equal(takerWeiBalanceBefore.minus(expectedCostAfterGas));
- });
- it('throws if fees are higher than 5% when buying zrx', async () => {
- const highFeeZRXOrder = await orderFactory.newSignedOrderAsync({
- makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
- makerAssetAmount: signedOrder.makerAssetAmount,
- takerFee: signedOrder.makerAssetAmount.times(0.06),
- });
- signedOrdersWithFee = [highFeeZRXOrder];
- feeOrders = [];
- const makerAssetAmount = signedOrder.makerAssetAmount.div(2);
- const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
- signedOrdersWithFee,
- feeOrders,
- feeProportion,
- makerAssetAmount,
+
+ const primaryTakerAssetFillAmount = ethValue.dividedToIntegerBy(2);
+ const totalEthSpent = primaryTakerAssetFillAmount.plus(DEFAULT_GAS_PRICE.times(tx.gasUsed));
+
+ expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
+ expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
);
- return expectTransactionFailedAsync(
- forwarderWrapper.marketBuyTokensWithEthAsync(signedOrdersWithFee, feeOrders, makerAssetAmount, {
- from: takerAddress,
- value: fillAmountWei,
- }),
- RevertReason.UnacceptableThreshold,
+ expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
);
- });
- it('throws if fees are higher than 5% when buying erc20', async () => {
- const highFeeERC20Order = await orderFactory.newSignedOrderAsync({
- takerFee: signedOrder.makerAssetAmount.times(0.06),
- });
- signedOrdersWithFee = [highFeeERC20Order];
- feeOrders = [feeOrder];
- const makerAssetAmount = signedOrder.makerAssetAmount.div(2);
- const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
- signedOrdersWithFee,
- feeOrders,
- feeProportion,
- makerAssetAmount,
+ expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
);
- return expectTransactionFailedAsync(
- forwarderWrapper.marketBuyTokensWithEthAsync(signedOrdersWithFee, feeOrders, makerAssetAmount, {
- from: takerAddress,
- value: fillAmountWei,
- }),
- RevertReason.UnacceptableThreshold as any,
+ expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
+ expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ constants.ZERO_AMOUNT,
);
+ expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
- it('throws if makerAssetAmount is 0', async () => {
- const makerAssetAmount = new BigNumber(0);
- const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
- signedOrdersWithFee,
- feeOrders,
- feeProportion,
- makerAssetAmount,
- );
- return expectTransactionFailedAsync(
- forwarderWrapper.marketBuyTokensWithEthAsync(signedOrdersWithFee, feeOrders, makerAssetAmount, {
- from: takerAddress,
- value: fillAmountWei,
- }),
- RevertReason.ValueGreaterThanZero as any,
- );
- });
- it('throws if the amount of ETH sent in is less than the takerAssetFilledAmount', async () => {
- const makerAssetAmount = signedOrder.makerAssetAmount;
- const fillAmount = signedOrder.takerAssetAmount.div(2);
- const zero = new BigNumber(0);
- // Deposit enough taker balance to fill the order
- const wethDepositTxHash = await wethContract.deposit.sendTransactionAsync({
+ it('should buy the exact amount of assets with fee abstraction', async () => {
+ ordersWithFee = [orderWithFee];
+ feeOrders = [feeOrder];
+ const makerAssetFillAmount = orderWithFee.makerAssetAmount.dividedToIntegerBy(2);
+ const ethValue = orderWithoutFee.takerAssetAmount;
+
+ tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithFee, feeOrders, makerAssetFillAmount, {
+ value: ethValue,
from: takerAddress,
- value: signedOrder.takerAssetAmount,
});
- await web3Wrapper.awaitTransactionSuccessAsync(wethDepositTxHash);
- // Transfer all of this WETH to the forwarding contract
- const wethTransferTxHash = await wethContract.transfer.sendTransactionAsync(
- forwarderContract.address,
- signedOrder.takerAssetAmount,
- { from: takerAddress },
- );
- await web3Wrapper.awaitTransactionSuccessAsync(wethTransferTxHash);
- // We use the contract directly to get around wrapper validations and calculations
- const formattedOrders = formatters.createMarketSellOrders(signedOrders, zero);
- const formattedFeeOrders = formatters.createMarketSellOrders(feeOrders, zero);
- return expectTransactionFailedAsync(
- forwarderContract.marketBuyTokensWithEth.sendTransactionAsync(
- formattedOrders.orders,
- formattedOrders.signatures,
- formattedFeeOrders.orders,
- formattedFeeOrders.signatures,
- makerAssetAmount,
- zero,
- constants.NULL_ADDRESS,
- { value: fillAmount, from: takerAddress },
- ),
- RevertReason.InvalidMsgValue,
+ const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
+ const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
+ const newBalances = await erc20Wrapper.getBalancesAsync();
+
+ const primaryTakerAssetFillAmount = orderWithFee.takerAssetAmount.dividedToIntegerBy(2);
+ const feeAmount = orderWithFee.takerFee.dividedToIntegerBy(2);
+ const wethSpentOnFeeOrders = ForwarderWrapper.getWethForFeeOrders(feeAmount, feeOrders);
+ const totalEthSpent = primaryTakerAssetFillAmount
+ .plus(wethSpentOnFeeOrders)
+ .plus(DEFAULT_GAS_PRICE.times(tx.gasUsed));
+
+ expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
+ expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
);
- });
- });
- describe('marketBuyTokensWithEth - ERC721', async () => {
- it('buys ERC721 assets', async () => {
- const makerAssetId = erc721MakerAssetIds[0];
- signedOrder = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber(1),
- makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
- });
- feeOrders = [];
- signedOrders = [signedOrder];
- const makerAssetAmount = new BigNumber(signedOrders.length);
- const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
- signedOrders,
- feeOrders,
- feeProportion,
- makerAssetAmount,
+ expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
);
- tx = await forwarderWrapper.marketBuyTokensWithEthAsync(signedOrders, feeOrders, makerAssetAmount, {
- from: takerAddress,
- value: fillAmountWei,
- });
- const newOwnerTakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
- expect(newOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
+ expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount).plus(wethSpentOnFeeOrders),
+ );
+ expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
+ expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
+ constants.ZERO_AMOUNT,
+ );
+ expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
- it('buys ERC721 assets with fee abstraction', async () => {
- const makerAssetId = erc721MakerAssetIds[0];
- signedOrder = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber(1),
+ it('should buy the exact amount of assets when buying ZRX with fee abstraction', async () => {
+ orderWithFee = await orderFactory.newSignedOrderAsync({
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
- makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
});
- signedOrders = [signedOrder];
- const makerAssetAmount = new BigNumber(signedOrders.length);
- const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
- signedOrders,
- feeOrders,
- feeProportion,
- makerAssetAmount,
- );
- tx = await forwarderWrapper.marketBuyTokensWithEthAsync(signedOrders, feeOrders, makerAssetAmount, {
+ ordersWithFee = [orderWithFee];
+ feeOrders = [];
+ const makerAssetFillAmount = orderWithFee.makerAssetAmount.dividedToIntegerBy(2);
+ const ethValue = orderWithFee.takerAssetAmount;
+ tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithFee, feeOrders, makerAssetFillAmount, {
+ value: ethValue,
from: takerAddress,
- value: fillAmountWei,
});
- const newOwnerTakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
- expect(newOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
- });
- it('buys ERC721 assets with fee abstraction and pays fee to fee recipient', async () => {
- const makerAssetId = erc721MakerAssetIds[0];
- signedOrder = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber(1),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
- makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
- });
- signedOrders = [signedOrder];
- feeProportion = 100;
- const initTakerBalanceWei = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const initFeeRecipientBalanceWei = await web3Wrapper.getBalanceInWeiAsync(feeRecipientAddress);
- const makerAssetAmount = new BigNumber(signedOrders.length);
- const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
- signedOrders,
- feeOrders,
- feeProportion,
- makerAssetAmount,
- );
- tx = await forwarderWrapper.marketBuyTokensWithEthAsync(
- signedOrders,
- feeOrders,
- makerAssetAmount,
- {
- from: takerAddress,
- value: fillAmountWei,
- gasPrice: DEFAULT_GAS_PRICE,
- },
- {
- feeProportion,
- feeRecipient: feeRecipientAddress,
- },
+ const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
+ const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
+ const newBalances = await erc20Wrapper.getBalancesAsync();
+
+ const primaryTakerAssetFillAmount = ForwarderWrapper.getWethForFeeOrders(
+ makerAssetFillAmount,
+ ordersWithFee,
);
- const afterFeeRecipientEthBalance = await web3Wrapper.getBalanceInWeiAsync(feeRecipientAddress);
- const afterTakerBalanceWei = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const takerFilledAmount = initTakerBalanceWei.minus(afterTakerBalanceWei).plus(tx.gasUsed);
- const newOwnerTakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
- expect(newOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
- const balanceDiff = afterFeeRecipientEthBalance.minus(initFeeRecipientBalanceWei);
- expect(takerFilledAmount.dividedToIntegerBy(balanceDiff)).to.be.bignumber.equal(101);
- expect(takerFilledAmount.minus(balanceDiff).dividedToIntegerBy(balanceDiff)).to.be.bignumber.equal(100);
- });
- it('buys multiple ERC721 assets with fee abstraction and pays fee to fee recipient', async () => {
- const makerAssetId1 = erc721MakerAssetIds[0];
- const makerAssetId2 = erc721MakerAssetIds[1];
- const signedOrder1 = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber(1),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(3), DECIMALS_DEFAULT),
- makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId1),
- });
- const signedOrder2 = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber(1),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(4), DECIMALS_DEFAULT),
- makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId2),
- });
- signedOrders = [signedOrder1, signedOrder2];
- feeProportion = 10;
- const makerAssetAmount = new BigNumber(signedOrders.length);
- const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
- signedOrders,
- feeOrders,
- feeProportion,
- makerAssetAmount,
+ const totalEthSpent = primaryTakerAssetFillAmount.plus(DEFAULT_GAS_PRICE.times(tx.gasUsed));
+ const makerAssetFilledAmount = orderWithFee.makerAssetAmount
+ .times(primaryTakerAssetFillAmount)
+ .dividedToIntegerBy(orderWithFee.takerAssetAmount);
+ const takerFeePaid = orderWithFee.takerFee
+ .times(primaryTakerAssetFillAmount)
+ .dividedToIntegerBy(orderWithFee.takerAssetAmount);
+ const makerFeePaid = orderWithFee.makerFee
+ .times(primaryTakerAssetFillAmount)
+ .dividedToIntegerBy(orderWithFee.takerAssetAmount);
+
+ expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
+ expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][zrxToken.address].minus(makerAssetFilledAmount).minus(makerFeePaid),
);
- tx = await forwarderWrapper.marketBuyTokensWithEthAsync(signedOrders, feeOrders, makerAssetAmount, {
- from: takerAddress,
- value: fillAmountWei,
- });
- const newOwnerTakerAsset1 = await erc721Token.ownerOf.callAsync(makerAssetId1);
- expect(newOwnerTakerAsset1).to.be.bignumber.equal(takerAddress);
- const newOwnerTakerAsset2 = await erc721Token.ownerOf.callAsync(makerAssetId2);
- expect(newOwnerTakerAsset2).to.be.bignumber.equal(takerAddress);
- });
- it('buys ERC721 assets with fee abstraction and handles fee orders filled and excess eth', async () => {
- const makerAssetId = erc721MakerAssetIds[0];
- feeProportion = 0;
- // In this scenario a total of 6 ZRX fees need to be paid.
- // There are two fee orders, but the first fee order is partially filled while
- // the Forwarding contract tx is in the mempool.
- const erc721MakerAssetAmount = new BigNumber(1);
- signedOrder = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: erc721MakerAssetAmount,
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(6), DECIMALS_DEFAULT),
- makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
- });
- signedOrders = [signedOrder];
- const firstFeeOrder = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(8), DECIMALS_DEFAULT),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.1), DECIMALS_DEFAULT),
- makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT),
- });
- const secondFeeOrder = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(8), DECIMALS_DEFAULT),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.12), DECIMALS_DEFAULT),
- makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT),
- });
- feeOrders = [firstFeeOrder, secondFeeOrder];
- const makerAssetAmount = new BigNumber(signedOrders.length);
- const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
- signedOrders,
- feeOrders,
- feeProportion,
- erc721MakerAssetAmount,
- );
- // Simulate another otherAddress user partially filling firstFeeOrder
- const firstFeeOrderFillAmount = firstFeeOrder.makerAssetAmount.div(2);
- tx = await forwarderWrapper.marketBuyTokensWithEthAsync([firstFeeOrder], [], firstFeeOrderFillAmount, {
- from: otherAddress,
- value: fillAmountWei,
- });
- // For tests we calculate how much this should've cost given that firstFeeOrder was filled
- const expectedFillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
- signedOrders,
- feeOrders,
- feeProportion,
- erc721MakerAssetAmount,
- );
- // With 4 ZRX remaining in firstFeeOrder, the secondFeeOrder will need to be filled to make up
- // the total amount of fees required (6)
- // Since the fee orders can be filled while the transaction is pending the user safely sends in
- // extra ether to cover any slippage
- const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const slippageFillAmountWei = fillAmountWei.times(2);
- tx = await forwarderWrapper.marketBuyTokensWithEthAsync(signedOrders, feeOrders, makerAssetAmount, {
- from: takerAddress,
- value: slippageFillAmountWei,
- gasPrice: DEFAULT_GAS_PRICE,
- });
- const afterEthBalance = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const expectedEthBalanceAfterGasCosts = initEthBalance.minus(expectedFillAmountWei).minus(tx.gasUsed);
- const newOwnerTakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
- expect(newOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
- expect(afterEthBalance).to.be.bignumber.equal(expectedEthBalanceAfterGasCosts);
- });
- it('buys ERC721 assets with fee abstraction and handles fee orders filled', async () => {
- const makerAssetId = erc721MakerAssetIds[0];
- feeProportion = 0;
- // In this scenario a total of 6 ZRX fees need to be paid.
- // There are two fee orders, but the first fee order is partially filled while
- // the Forwarding contract tx is in the mempool.
- const erc721MakerAssetAmount = new BigNumber(1);
- signedOrder = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: erc721MakerAssetAmount,
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(6), DECIMALS_DEFAULT),
- makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
- });
- const zrxMakerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(8), DECIMALS_DEFAULT);
- signedOrders = [signedOrder];
- const firstFeeOrder = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: zrxMakerAssetAmount,
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.1), DECIMALS_DEFAULT),
- makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT),
- });
- const secondFeeOrder = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: zrxMakerAssetAmount,
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.12), DECIMALS_DEFAULT),
- makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT),
- });
- feeOrders = [firstFeeOrder, secondFeeOrder];
- const makerAssetAmount = new BigNumber(signedOrders.length);
- const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
- signedOrders,
- feeOrders,
- feeProportion,
- erc721MakerAssetAmount,
- );
- // Simulate another otherAddress user partially filling firstFeeOrder
- const firstFeeOrderFillAmount = firstFeeOrder.makerAssetAmount.div(2);
- tx = await forwarderWrapper.marketBuyTokensWithEthAsync([firstFeeOrder], [], firstFeeOrderFillAmount, {
- from: otherAddress,
- value: fillAmountWei,
- });
- const expectedFillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
- signedOrders,
- feeOrders,
- feeProportion,
- erc721MakerAssetAmount,
+ expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
+ erc20Balances[takerAddress][zrxToken.address].plus(makerAssetFilledAmount).minus(takerFeePaid),
);
- tx = await forwarderWrapper.marketBuyTokensWithEthAsync(signedOrders, feeOrders, makerAssetAmount, {
- from: takerAddress,
- value: expectedFillAmountWei,
- });
- const newOwnerTakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
- expect(newOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
- });
- it('throws when mixed ERC721 and ERC20 assets', async () => {
- const makerAssetId = erc721MakerAssetIds[0];
- const erc721SignedOrder = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber(1),
- makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
- });
- const erc20SignedOrder = await orderFactory.newSignedOrderAsync();
- signedOrders = [erc721SignedOrder, erc20SignedOrder];
- const makerAssetAmount = new BigNumber(signedOrders.length);
- const fillAmountWei = erc20SignedOrder.takerAssetAmount.plus(erc721SignedOrder.takerAssetAmount);
- return expectTransactionFailedAsync(
- forwarderWrapper.marketBuyTokensWithEthAsync(signedOrders, feeOrders, makerAssetAmount, {
- from: takerAddress,
- value: fillAmountWei,
- }),
- RevertReason.LibBytesGreaterOrEqualTo32LengthRequired,
+ expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
);
- });
- it('throws when mixed ERC721 and ERC20 assets with ERC20 first', async () => {
- const makerAssetId = erc721MakerAssetIds[0];
- const erc721SignedOrder = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber(1),
- makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
- });
- const erc20SignedOrder = await orderFactory.newSignedOrderAsync();
- signedOrders = [erc20SignedOrder, erc721SignedOrder];
- const makerAssetAmount = new BigNumber(signedOrders.length);
- const fillAmountWei = erc20SignedOrder.takerAssetAmount.plus(erc721SignedOrder.takerAssetAmount);
- return expectTransactionFailedAsync(
- forwarderWrapper.marketBuyTokensWithEthAsync(signedOrders, feeOrders, makerAssetAmount, {
- from: takerAddress,
- value: fillAmountWei,
- }),
- RevertReason.InvalidTakerAmount,
+ expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
+ expect(newBalances[forwarderContract.address][zrxToken.address]).to.be.bignumber.equal(
+ erc20Balances[forwarderContract.address][zrxToken.address],
);
+ expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
+ // it('throws if fees are higher than 5% when buying zrx', async () => {
+ // const highFeeZRXOrder = orderFactory.newSignedOrder({
+ // makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
+ // makerAssetAmount: orderWithoutFee.makerAssetAmount,
+ // takerFee: orderWithoutFee.makerAssetAmount.times(0.06),
+ // });
+ // ordersWithFee = [highFeeZRXOrder];
+ // feeOrders = [];
+ // const makerAssetAmount = orderWithoutFee.makerAssetAmount.div(2);
+ // const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
+ // ordersWithFee,
+ // feeOrders,
+ // feePercentage,
+ // makerAssetAmount,
+ // );
+ // return expectTransactionFailedAsync(
+ // forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithFee, feeOrders, makerAssetAmount, {
+ // from: takerAddress,
+ // value: fillAmountWei,
+ // }),
+ // RevertReason.UnacceptableThreshold,
+ // );
+ // });
+ // it('throws if fees are higher than 5% when buying erc20', async () => {
+ // const highFeeERC20Order = orderFactory.newSignedOrder({
+ // takerFee: orderWithoutFee.makerAssetAmount.times(0.06),
+ // });
+ // ordersWithFee = [highFeeERC20Order];
+ // feeOrders = [feeOrder];
+ // const makerAssetAmount = orderWithoutFee.makerAssetAmount.div(2);
+ // const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
+ // ordersWithFee,
+ // feeOrders,
+ // feePercentage,
+ // makerAssetAmount,
+ // );
+ // return expectTransactionFailedAsync(
+ // forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithFee, feeOrders, makerAssetAmount, {
+ // from: takerAddress,
+ // value: fillAmountWei,
+ // }),
+ // RevertReason.UnacceptableThreshold as any,
+ // );
+ // });
+ // it('throws if makerAssetAmount is 0', async () => {
+ // const makerAssetAmount = new BigNumber(0);
+ // const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
+ // ordersWithFee,
+ // feeOrders,
+ // feePercentage,
+ // makerAssetAmount,
+ // );
+ // return expectTransactionFailedAsync(
+ // forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithFee, feeOrders, makerAssetAmount, {
+ // from: takerAddress,
+ // value: fillAmountWei,
+ // }),
+ // RevertReason.ValueGreaterThanZero as any,
+ // );
+ // });
+ // it('throws if the amount of ETH sent in is less than the takerAssetFilledAmount', async () => {
+ // const makerAssetAmount = orderWithoutFee.makerAssetAmount;
+ // const primaryTakerAssetFillAmount = orderWithoutFee.takerAssetAmount.div(2);
+ // const zero = new BigNumber(0);
+ // // Deposit enough taker balance to fill the order
+ // const wethDepositTxHash = await wethContract.deposit.sendTransactionAsync({
+ // from: takerAddress,
+ // value: orderWithoutFee.takerAssetAmount,
+ // });
+ // await web3Wrapper.awaitTransactionSuccessAsync(wethDepositTxHash);
+ // // Transfer all of this WETH to the forwarding contract
+ // const wethTransferTxHash = await wethContract.transfer.sendTransactionAsync(
+ // forwarderContract.address,
+ // orderWithoutFee.takerAssetAmount,
+ // { from: takerAddress },
+ // );
+ // await web3Wrapper.awaitTransactionSuccessAsync(wethTransferTxHash);
+ // // We use the contract directly to get around wrapper validations and calculations
+ // const formattedOrders = formatters.createMarketSellOrders(signedOrders, zero);
+ // const formattedFeeOrders = formatters.createMarketSellOrders(feeOrders, zero);
+ // return expectTransactionFailedAsync(
+ // forwarderContract.marketBuyOrdersWithEth.sendTransactionAsync(
+ // formattedOrders.orders,
+ // formattedOrders.signatures,
+ // formattedFeeOrders.orders,
+ // formattedFeeOrders.signatures,
+ // makerAssetAmount,
+ // zero,
+ // constants.NULL_ADDRESS,
+ // { value: primaryTakerAssetFillAmount, from: takerAddress },
+ // ),
+ // RevertReason.InvalidMsgValue,
+ // );
+ // });
});
+ // describe('marketBuyOrdersWithEth - ERC721', async () => {
+ // it('buys ERC721 assets', async () => {
+ // const makerAssetId = erc721MakerAssetIds[0];
+ // orderWithoutFee = orderFactory.newSignedOrder({
+ // makerAssetAmount: new BigNumber(1),
+ // makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
+ // });
+ // feeOrders = [];
+ // signedOrders = [orderWithoutFee];
+ // const makerAssetAmount = new BigNumber(signedOrders.length);
+ // const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
+ // signedOrders,
+ // feeOrders,
+ // feePercentage,
+ // makerAssetAmount,
+ // );
+ // tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(signedOrders, feeOrders, makerAssetAmount, {
+ // from: takerAddress,
+ // value: fillAmountWei,
+ // });
+ // const newOwnerTakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
+ // expect(newOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
+ // });
+ // it('buys ERC721 assets with fee abstraction', async () => {
+ // const makerAssetId = erc721MakerAssetIds[0];
+ // orderWithoutFee = orderFactory.newSignedOrder({
+ // makerAssetAmount: new BigNumber(1),
+ // takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
+ // makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
+ // });
+ // signedOrders = [orderWithoutFee];
+ // const makerAssetAmount = new BigNumber(signedOrders.length);
+ // const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
+ // signedOrders,
+ // feeOrders,
+ // feePercentage,
+ // makerAssetAmount,
+ // );
+ // tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(signedOrders, feeOrders, makerAssetAmount, {
+ // from: takerAddress,
+ // value: fillAmountWei,
+ // });
+ // const newOwnerTakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
+ // expect(newOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
+ // });
+ // it('buys ERC721 assets with fee abstraction and pays fee to fee recipient', async () => {
+ // const makerAssetId = erc721MakerAssetIds[0];
+ // orderWithoutFee = orderFactory.newSignedOrder({
+ // makerAssetAmount: new BigNumber(1),
+ // takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
+ // makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
+ // });
+ // signedOrders = [orderWithoutFee];
+ // feePercentage = 100;
+ // const initTakerBalanceWei = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
+ // const initFeeRecipientBalanceWei = await web3Wrapper.getBalanceInWeiAsync(feeRecipientAddress);
+ // const makerAssetAmount = new BigNumber(signedOrders.length);
+ // const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
+ // signedOrders,
+ // feeOrders,
+ // feePercentage,
+ // makerAssetAmount,
+ // );
+ // tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(
+ // signedOrders,
+ // feeOrders,
+ // makerAssetAmount,
+ // {
+ // from: takerAddress,
+ // value: fillAmountWei,
+ // gasPrice: DEFAULT_GAS_PRICE,
+ // },
+ // {
+ // feePercentage,
+ // feeRecipient: feeRecipientAddress,
+ // },
+ // );
+ // const afterFeeRecipientEthBalance = await web3Wrapper.getBalanceInWeiAsync(feeRecipientAddress);
+ // const afterTakerBalanceWei = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
+ // const takerFilledAmount = initTakerBalanceWei.minus(afterTakerBalanceWei).plus(tx.gasUsed);
+ // const newOwnerTakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
+ // expect(newOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
+ // const balanceDiff = afterFeeRecipientEthBalance.minus(initFeeRecipientBalanceWei);
+ // expect(takerFilledAmount.dividedToIntegerBy(balanceDiff)).to.be.bignumber.equal(101);
+ // expect(takerFilledAmount.minus(balanceDiff).dividedToIntegerBy(balanceDiff)).to.be.bignumber.equal(100);
+ // });
+ // it('buys multiple ERC721 assets with fee abstraction and pays fee to fee recipient', async () => {
+ // const makerAssetId1 = erc721MakerAssetIds[0];
+ // const makerAssetId2 = erc721MakerAssetIds[1];
+ // const signedOrder1 = orderFactory.newSignedOrder({
+ // makerAssetAmount: new BigNumber(1),
+ // takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(3), DECIMALS_DEFAULT),
+ // makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId1),
+ // });
+ // const signedOrder2 = orderFactory.newSignedOrder({
+ // makerAssetAmount: new BigNumber(1),
+ // takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(4), DECIMALS_DEFAULT),
+ // makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId2),
+ // });
+ // signedOrders = [signedOrder1, signedOrder2];
+ // feePercentage = 10;
+ // const makerAssetAmount = new BigNumber(signedOrders.length);
+ // const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
+ // signedOrders,
+ // feeOrders,
+ // feePercentage,
+ // makerAssetAmount,
+ // );
+ // tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(signedOrders, feeOrders, makerAssetAmount, {
+ // from: takerAddress,
+ // value: fillAmountWei,
+ // });
+ // const newOwnerTakerAsset1 = await erc721Token.ownerOf.callAsync(makerAssetId1);
+ // expect(newOwnerTakerAsset1).to.be.bignumber.equal(takerAddress);
+ // const newOwnerTakerAsset2 = await erc721Token.ownerOf.callAsync(makerAssetId2);
+ // expect(newOwnerTakerAsset2).to.be.bignumber.equal(takerAddress);
+ // });
+ // it('buys ERC721 assets with fee abstraction and handles fee orders filled and excess eth', async () => {
+ // const makerAssetId = erc721MakerAssetIds[0];
+ // feePercentage = 0;
+ // // In this scenario a total of 6 ZRX fees need to be paid.
+ // // There are two fee orders, but the first fee order is partially filled while
+ // // the Forwarding contract tx is in the mempool.
+ // const erc721MakerAssetAmount = new BigNumber(1);
+ // orderWithoutFee = orderFactory.newSignedOrder({
+ // makerAssetAmount: erc721MakerAssetAmount,
+ // takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT),
+ // takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(6), DECIMALS_DEFAULT),
+ // makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
+ // });
+ // signedOrders = [orderWithoutFee];
+ // const firstFeeOrder = orderFactory.newSignedOrder({
+ // makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(8), DECIMALS_DEFAULT),
+ // takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.1), DECIMALS_DEFAULT),
+ // makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
+ // takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT),
+ // });
+ // const secondFeeOrder = orderFactory.newSignedOrder({
+ // makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(8), DECIMALS_DEFAULT),
+ // takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.12), DECIMALS_DEFAULT),
+ // makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
+ // takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT),
+ // });
+ // feeOrders = [firstFeeOrder, secondFeeOrder];
+ // const makerAssetAmount = new BigNumber(signedOrders.length);
+ // const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
+ // signedOrders,
+ // feeOrders,
+ // feePercentage,
+ // erc721MakerAssetAmount,
+ // );
+ // // Simulate another otherAddress user partially filling firstFeeOrder
+ // const firstFeeOrderFillAmount = firstFeeOrder.makerAssetAmount.div(2);
+ // tx = await forwarderWrapper.marketBuyOrdersWithEthAsync([firstFeeOrder], [], firstFeeOrderFillAmount, {
+ // from: otherAddress,
+ // value: fillAmountWei,
+ // });
+ // // For tests we calculate how much this should've cost given that firstFeeOrder was filled
+ // const expectedFillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
+ // signedOrders,
+ // feeOrders,
+ // feePercentage,
+ // erc721MakerAssetAmount,
+ // );
+ // // With 4 ZRX remaining in firstFeeOrder, the secondFeeOrder will need to be filled to make up
+ // // the total amount of fees required (6)
+ // // Since the fee orders can be filled while the transaction is pending the user safely sends in
+ // // extra ether to cover any slippage
+ // const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
+ // const slippageFillAmountWei = fillAmountWei.times(2);
+ // tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(signedOrders, feeOrders, makerAssetAmount, {
+ // from: takerAddress,
+ // value: slippageFillAmountWei,
+ // gasPrice: DEFAULT_GAS_PRICE,
+ // });
+ // const afterEthBalance = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
+ // const expectedEthBalanceAfterGasCosts = initEthBalance.minus(expectedFillAmountWei).minus(tx.gasUsed);
+ // const newOwnerTakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
+ // expect(newOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
+ // expect(afterEthBalance).to.be.bignumber.equal(expectedEthBalanceAfterGasCosts);
+ // });
+ // it('buys ERC721 assets with fee abstraction and handles fee orders filled', async () => {
+ // const makerAssetId = erc721MakerAssetIds[0];
+ // feePercentage = 0;
+ // // In this scenario a total of 6 ZRX fees need to be paid.
+ // // There are two fee orders, but the first fee order is partially filled while
+ // // the Forwarding contract tx is in the mempool.
+ // const erc721MakerAssetAmount = new BigNumber(1);
+ // orderWithoutFee = orderFactory.newSignedOrder({
+ // makerAssetAmount: erc721MakerAssetAmount,
+ // takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT),
+ // takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(6), DECIMALS_DEFAULT),
+ // makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
+ // });
+ // const zrxMakerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(8), DECIMALS_DEFAULT);
+ // signedOrders = [orderWithoutFee];
+ // const firstFeeOrder = orderFactory.newSignedOrder({
+ // makerAssetAmount: zrxMakerAssetAmount,
+ // takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.1), DECIMALS_DEFAULT),
+ // makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
+ // takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT),
+ // });
+ // const secondFeeOrder = orderFactory.newSignedOrder({
+ // makerAssetAmount: zrxMakerAssetAmount,
+ // takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.12), DECIMALS_DEFAULT),
+ // makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
+ // takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT),
+ // });
+ // feeOrders = [firstFeeOrder, secondFeeOrder];
+ // const makerAssetAmount = new BigNumber(signedOrders.length);
+ // const fillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
+ // signedOrders,
+ // feeOrders,
+ // feePercentage,
+ // erc721MakerAssetAmount,
+ // );
+ // // Simulate another otherAddress user partially filling firstFeeOrder
+ // const firstFeeOrderFillAmount = firstFeeOrder.makerAssetAmount.div(2);
+ // tx = await forwarderWrapper.marketBuyOrdersWithEthAsync([firstFeeOrder], [], firstFeeOrderFillAmount, {
+ // from: otherAddress,
+ // value: fillAmountWei,
+ // });
+ // const expectedFillAmountWei = await forwarderWrapper.calculateMarketBuyFillAmountWeiAsync(
+ // signedOrders,
+ // feeOrders,
+ // feePercentage,
+ // erc721MakerAssetAmount,
+ // );
+ // tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(signedOrders, feeOrders, makerAssetAmount, {
+ // from: takerAddress,
+ // value: expectedFillAmountWei,
+ // });
+ // const newOwnerTakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
+ // expect(newOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
+ // });
+ // it('throws when mixed ERC721 and ERC20 assets', async () => {
+ // const makerAssetId = erc721MakerAssetIds[0];
+ // const erc721SignedOrder = orderFactory.newSignedOrder({
+ // makerAssetAmount: new BigNumber(1),
+ // makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
+ // });
+ // const erc20SignedOrder = orderFactory.newSignedOrder();
+ // signedOrders = [erc721SignedOrder, erc20SignedOrder];
+ // const makerAssetAmount = new BigNumber(signedOrders.length);
+ // const fillAmountWei = erc20SignedOrder.takerAssetAmount.plus(erc721SignedOrder.takerAssetAmount);
+ // return expectTransactionFailedAsync(
+ // forwarderWrapper.marketBuyOrdersWithEthAsync(signedOrders, feeOrders, makerAssetAmount, {
+ // from: takerAddress,
+ // value: fillAmountWei,
+ // }),
+ // RevertReason.LibBytesGreaterOrEqualTo32LengthRequired,
+ // );
+ // });
+ // it('throws when mixed ERC721 and ERC20 assets with ERC20 first', async () => {
+ // const makerAssetId = erc721MakerAssetIds[0];
+ // const erc721SignedOrder = orderFactory.newSignedOrder({
+ // makerAssetAmount: new BigNumber(1),
+ // makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
+ // });
+ // const erc20SignedOrder = orderFactory.newSignedOrder();
+ // signedOrders = [erc20SignedOrder, erc721SignedOrder];
+ // const makerAssetAmount = new BigNumber(signedOrders.length);
+ // const fillAmountWei = erc20SignedOrder.takerAssetAmount.plus(erc721SignedOrder.takerAssetAmount);
+ // return expectTransactionFailedAsync(
+ // forwarderWrapper.marketBuyOrdersWithEthAsync(signedOrders, feeOrders, makerAssetAmount, {
+ // from: takerAddress,
+ // value: fillAmountWei,
+ // }),
+ // RevertReason.InvalidTakerAmount,
+ // );
+ // });
+ // });
});
// tslint:disable:max-file-line-count
// tslint:enable:no-unnecessary-type-assertion