diff options
Diffstat (limited to 'packages/contracts/test/forwarder/forwarder.ts')
-rw-r--r-- | packages/contracts/test/forwarder/forwarder.ts | 1248 |
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 |