diff --git a/contracts/integrations/test/internal-integration-tests/match_orders_test.ts b/contracts/integrations/test/internal-integration-tests/match_orders_test.ts index 09885e66b6..487ff4a861 100644 --- a/contracts/integrations/test/internal-integration-tests/match_orders_test.ts +++ b/contracts/integrations/test/internal-integration-tests/match_orders_test.ts @@ -1,110 +1,139 @@ -import { - artifacts as assetProxyArtifacts, - ERC1155ProxyContract, - ERC1155ProxyWrapper, - ERC20ProxyContract, - ERC20Wrapper, - ERC721ProxyContract, - ERC721Wrapper, - MultiAssetProxyContract, -} from '@0x/contracts-asset-proxy'; import { DevUtilsContract } from '@0x/contracts-dev-utils'; -import { ERC1155Contract as ERC1155TokenContract, Erc1155Wrapper as ERC1155Wrapper } from '@0x/contracts-erc1155'; -import { DummyERC20TokenContract } from '@0x/contracts-erc20'; -import { DummyERC721TokenContract } from '@0x/contracts-erc721'; -import { artifacts as exchangeArtifacts, ExchangeContract, ExchangeWrapper } from '@0x/contracts-exchange'; +import { BlockchainBalanceStore } from '@0x/contracts-exchange'; import { ReferenceFunctions as LibReferenceFunctions } from '@0x/contracts-exchange-libs'; import { toBaseUnitAmount } from '@0x/contracts-staking'; -import { blockchainTests, constants, expect, OrderFactory, orderUtils } from '@0x/contracts-test-utils'; -import { ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils'; +import { blockchainTests, constants, expect } from '@0x/contracts-test-utils'; +import { assetDataUtils, ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils'; import { OrderStatus, SignedOrder } from '@0x/types'; import { BigNumber } from '@0x/utils'; import * as _ from 'lodash'; +import { Actor } from '../actors/base'; +import { Maker } from '../actors/maker'; import { DeploymentManager } from '../utils/deployment_manager'; -import { MatchOrderTester, TokenBalances } from '../utils/match_order_tester'; +import { MatchOrderTester } from '../utils/match_order_tester'; -const ZERO = new BigNumber(0); -const ONE = new BigNumber(1); -const TWO = new BigNumber(2); const { isRoundingErrorCeil, isRoundingErrorFloor } = LibReferenceFunctions; -// Reduce the number of tokens to deploy to speed up tests, since we don't need -// so many. -constants.NUM_DUMMY_ERC721_TO_DEPLOY = 1; -constants.NUM_DUMMY_ERC1155_CONTRACTS_TO_DEPLOY = 1; +const ZERO = constants.ZERO_AMOUNT; -blockchainTests.resets('matchOrders', env => { - let chainId: number; - let makerAddressLeft: string; - let makerAddressRight: string; - let owner: string; - let takerAddress: string; - let feeRecipientAddressLeft: string; - let feeRecipientAddressRight: string; +blockchainTests.resets.only('matchOrders', env => { + let feeRecipientLeft: Actor; + let feeRecipientRight: Actor; - let erc1155ProxyWrapper: ERC1155ProxyWrapper; + let matcher: Actor; - let erc20Wrapper: ERC20Wrapper; - let erc721Wrapper: ERC721Wrapper; + let makerLeft: Maker; + let makerRight: Maker; - let tokenBalances: TokenBalances; + let makerAssetAddressLeft: string; + let makerAssetAddressRight: string; + let feeAssetAddress: string; let matchOrderTester: MatchOrderTester; const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider, txDefaults); let deployment: DeploymentManager; + const PROTOCOL_FEE = DeploymentManager.protocolFeeMultiplier.times(constants.DEFAULT_GAS_PRICE); + before(async () => { - // Get the chain ID. - chainId = await env.getChainIdAsync(); - // Create accounts - const accounts = await env.getAccountAddressesAsync(); - const usedAddresses = ([ - owner, - makerAddressLeft, - makerAddressRight, - takerAddress, - feeRecipientAddressLeft, - feeRecipientAddressRight, - ] = accounts); - const addressesWithBalances = usedAddresses.slice(1); + deployment = await DeploymentManager.deployAsync(env, { + numErc20TokensToDeploy: 3, + numErc721TokensToDeploy: 1, + numErc1155TokensToDeploy: 1, + }); + makerAssetAddressLeft = deployment.tokens.erc20[0].address; + makerAssetAddressRight = deployment.tokens.erc20[1].address; + feeAssetAddress = deployment.tokens.erc20[2].address; - deployment = await DeploymentManager.deployAsync(env); + // Create the fee recipient actors. + feeRecipientLeft = new Actor({ + name: 'left fee recipient', + deployment, + }); + feeRecipientRight = new Actor({ + name: 'left fee recipient', + deployment, + }); - // FIXME - Remove these and all dependencies on wrappers - // Create wrappers - erc20Wrapper = new ERC20Wrapper(env.provider, addressesWithBalances, owner); - erc721Wrapper = new ERC721Wrapper(env.provider, addressesWithBalances, owner); - erc1155ProxyWrapper = new ERC1155ProxyWrapper(env.provider, addressesWithBalances, owner); + // Create two market makers with compatible orders for matching. + makerLeft = new Maker({ + name: 'left maker', + deployment, + orderConfig: { + makerAssetData: assetDataUtils.encodeERC20AssetData(makerAssetAddressLeft), + takerAssetData: assetDataUtils.encodeERC20AssetData(makerAssetAddressRight), + makerFeeAssetData: assetDataUtils.encodeERC20AssetData(feeAssetAddress), + takerFeeAssetData: assetDataUtils.encodeERC20AssetData(feeAssetAddress), + feeRecipientAddress: feeRecipientLeft.address, + }, + }); + makerRight = new Maker({ + name: 'right maker', + deployment, + orderConfig: { + makerAssetData: assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[1].address), + takerAssetData: assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[0].address), + makerFeeAssetData: assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[2].address), + takerFeeAssetData: assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[2].address), + feeRecipientAddress: feeRecipientRight.address, + }, + }); - // Create match order tester - matchOrderTester = new MatchOrderTester( - exchangeWrapper, - erc20Wrapper, - erc721Wrapper, - erc1155ProxyWrapper, - devUtils, + // Create a matcher. + matcher = new Actor({ + name: 'matcher', + deployment, + }); + + // Configure the appropriate actors with initial balances. + await Promise.all([ + ...deployment.tokens.erc20.map(async token => makerLeft.configureERC20TokenAsync(token)), + ...deployment.tokens.erc20.map(async token => makerRight.configureERC20TokenAsync(token)), + matcher.configureERC20TokenAsync(deployment.tokens.erc20[2]), + matcher.configureERC20TokenAsync(deployment.tokens.weth), + feeRecipientLeft.configureERC20TokenAsync(deployment.tokens.erc20[2]), + feeRecipientLeft.configureERC20TokenAsync(deployment.tokens.weth), + feeRecipientRight.configureERC20TokenAsync(deployment.tokens.erc20[2]), + feeRecipientRight.configureERC20TokenAsync(deployment.tokens.weth), + ]); + + const blockchainBalanceStore = new BlockchainBalanceStore( + { + feeRecipientLeft: feeRecipientLeft.address, + feeRecipientRight: feeRecipientRight.address, + makerLeft: makerLeft.address, + makerRight: makerRight.address, + matcher: matcher.address, + stakingProxy: deployment.staking.stakingProxy.address, + }, + { + erc20: { + makerTokenLeft: deployment.tokens.erc20[0], + makerTokenRight: deployment.tokens.erc20[1], + feeToken: deployment.tokens.erc20[2], + weth: deployment.tokens.weth, + }, + }, + {}, ); - tokenBalances = await matchOrderTester.getBalancesAsync(); + + matchOrderTester = new MatchOrderTester(deployment, blockchainBalanceStore); }); - /* describe('matchOrders', () => { it('Should transfer correct amounts when right order is fully filled and values pass isRoundingErrorFloor but fail isRoundingErrorCeil', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(17, 0), takerAssetAmount: toBaseUnitAmount(98, 0), - feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(75, 0), takerAssetAmount: toBaseUnitAmount(13, 0), - feeRecipientAddress: feeRecipientAddressRight, }); + // Assert is rounding error ceil & not rounding error floor // These assertions are taken from MixinMatchOrders::calculateMatchedFillResults // The rounding error is derived computating how much the left maker will sell. @@ -115,6 +144,7 @@ blockchainTests.resets('matchOrders', env => { expect(_isRoundingErrorCeil).to.be.true(); const _isRoundingErrorFloor = isRoundingErrorFloor(numerator, denominator, target); expect(_isRoundingErrorFloor).to.be.false(); + // Match signedOrderLeft with signedOrderRight // Note that the left maker received a slightly better sell price. // This is intentional; see note in MixinMatchOrders.calculateMatchedFillResults. @@ -131,32 +161,33 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('76.5306122448979591'), 16), // 76.53% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; + await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); }); it('Should transfer correct amounts when left order is fully filled and values pass isRoundingErrorCeil but fail isRoundingErrorFloor', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(15, 0), takerAssetAmount: toBaseUnitAmount(90, 0), - feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(97, 0), takerAssetAmount: toBaseUnitAmount(14, 0), - feeRecipientAddress: feeRecipientAddressRight, }); + // Assert is rounding error floor & not rounding error ceil // These assertions are taken from MixinMatchOrders::calculateMatchedFillResults // The rounding error is derived computating how much the right maker will buy. @@ -167,6 +198,7 @@ blockchainTests.resets('matchOrders', env => { expect(_isRoundingErrorFloor).to.be.true(); const _isRoundingErrorCeil = isRoundingErrorCeil(numerator, denominator, target); expect(_isRoundingErrorCeil).to.be.false(); + // Match signedOrderLeft isRoundingErrorFloor right maker received a slightly better purchase price. // This is intentional; see note in MixinMatchOrders.calculateMatchedFillResults. // Because the right maker received a slightly more favorable buy price, the fee @@ -184,41 +216,33 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(2, 0), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('92.8571428571428571'), 16), // 92.85% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; + await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); }); it('Should give right maker a better buy price when rounding', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(16, 0), takerAssetAmount: toBaseUnitAmount(22, 0), - feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, -<<<<<<< HEAD - makerAssetData: await devUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress).callAsync(), - takerAssetData: await devUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress).callAsync(), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(83, 0), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(49, 0), -======= - makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress), - takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress), + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(83, 0), takerAssetAmount: toBaseUnitAmount(49, 0), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` - feeRecipientAddress: feeRecipientAddressRight, }); + // Note: // The correct price buy price for the right maker would yield (49/83) * 22 = 12.988 units // of the left maker asset. This gets rounded up to 13, giving the right maker a better price. @@ -238,42 +262,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 0), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('26.5306122448979591'), 16), // 26.531% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; + // Match signedOrderLeft with signedOrderRight await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); }); it('Should give left maker a better sell price when rounding', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(12, 0), takerAssetAmount: toBaseUnitAmount(97, 0), - feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, -<<<<<<< HEAD - makerAssetData: await devUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress).callAsync(), - takerAssetData: await devUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress).callAsync(), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(89, 0), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0), -======= - makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress), - takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress), + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(89, 0), takerAssetAmount: toBaseUnitAmount(1, 0), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` - feeRecipientAddress: feeRecipientAddressRight, }); + // Note: // The maker/taker fee percentage paid on the left order differs because // they received different sale prices. The left maker pays a fee @@ -290,44 +306,36 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(10, 0), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('91.7525773195876288'), 16), // 91.75% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; + // Match signedOrderLeft with signedOrderRight await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); }); it('Should give right maker and right taker a favorable fee price when rounding', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(16, 0), takerAssetAmount: toBaseUnitAmount(22, 0), - feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, -<<<<<<< HEAD - makerAssetData: await devUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress).callAsync(), - takerAssetData: await devUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress).callAsync(), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(83, 0), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(49, 0), -======= - makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress), - takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress), + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(83, 0), takerAssetAmount: toBaseUnitAmount(49, 0), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` - feeRecipientAddress: feeRecipientAddressRight, makerFee: toBaseUnitAmount(10000, 0), takerFee: toBaseUnitAmount(10000, 0), }); + // Note: // The maker/taker fee percentage paid on the right order differs because // they received different sale prices. The right maker pays a @@ -344,44 +352,36 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 0), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(2653, 0), // 2653.1 rounded down to 2653 + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; + // Match signedOrderLeft with signedOrderRight await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); }); it('Should give left maker and left taker a favorable fee price when rounding', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(12, 0), takerAssetAmount: toBaseUnitAmount(97, 0), - feeRecipientAddress: feeRecipientAddressLeft, makerFee: toBaseUnitAmount(10000, 0), takerFee: toBaseUnitAmount(10000, 0), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, -<<<<<<< HEAD - makerAssetData: await devUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress).callAsync(), - takerAssetData: await devUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress).callAsync(), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(89, 0), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0), -======= - makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress), - takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress), + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(89, 0), takerAssetAmount: toBaseUnitAmount(1, 0), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` - feeRecipientAddress: feeRecipientAddressRight, }); + // Note: // The maker/taker fee percentage paid on the left order differs because // they received different sale prices. The left maker pays a @@ -398,42 +398,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(10, 0), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(9175, 0), // 9175.2 rounded down to 9175 rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; + // Match signedOrderLeft with signedOrderRight await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); }); it('Should transfer correct amounts when right order fill amount deviates from amount derived by `Exchange.fillOrder`', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1000, 0), takerAssetAmount: toBaseUnitAmount(1005, 0), - feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, -<<<<<<< HEAD - makerAssetData: await devUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress).callAsync(), - takerAssetData: await devUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress).callAsync(), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(2126, 0), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1063, 0), -======= - makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress), - takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress), + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(2126, 0), takerAssetAmount: toBaseUnitAmount(1063, 0), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` - feeRecipientAddress: feeRecipientAddressRight, }); + const expectedTransferAmounts = { // Left Maker leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(1000, 0), @@ -460,26 +452,30 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(497, 0), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('47.3189087488240827'), 16), // 47.31% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; + // Match signedOrderLeft with signedOrderRight await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); }); it('should transfer the correct amounts when orders completely fill each other', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); @@ -496,28 +492,33 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; + await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); }); it('should transfer the correct amounts when orders completely fill each other and taker doesnt take a profit', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(5, 18), }); + // Match signedOrderLeft with signedOrderRight const expectedTransferAmounts = { // Left Maker @@ -529,26 +530,30 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; + // Match signedOrderLeft with signedOrderRight await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); }); it('should transfer the correct amounts when left order is completely filled and right order is partially filled', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(20, 18), takerAssetAmount: toBaseUnitAmount(4, 18), }); @@ -565,6 +570,8 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; // Match signedOrderLeft with signedOrderRight await matchOrderTester.matchOrdersAndAssertEffectsAsync( @@ -572,19 +579,20 @@ blockchainTests.resets('matchOrders', env => { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); }); it('should transfer the correct amounts when right order is completely filled and left order is partially filled', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(50, 18), takerAssetAmount: toBaseUnitAmount(100, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); @@ -601,6 +609,8 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(10, 16), // 10% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; // Match signedOrderLeft with signedOrderRight await matchOrderTester.matchOrdersAndAssertEffectsAsync( @@ -608,19 +618,20 @@ blockchainTests.resets('matchOrders', env => { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); }); it('should transfer the correct amounts when consecutive calls are used to completely fill the left order', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(50, 18), takerAssetAmount: toBaseUnitAmount(100, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); @@ -637,6 +648,8 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(10, 16), // 10% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; // prettier-ignore const matchResults = await matchOrderTester.matchOrdersAndAssertEffectsAsync( @@ -644,15 +657,16 @@ blockchainTests.resets('matchOrders', env => { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); // Construct second right order // Note: This order needs makerAssetAmount=90/takerAssetAmount=[anything <= 45] to fully fill the right order. // However, we use 100/50 to ensure a partial fill as we want to go down the "left fill" // branch in the contract twice for this test. - const signedOrderRight2 = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight2 = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(100, 18), takerAssetAmount: toBaseUnitAmount(50, 18), }); @@ -667,6 +681,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(90, 16), // 90% (10% paid earlier) rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(90, 16), // 90% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( @@ -675,24 +691,24 @@ blockchainTests.resets('matchOrders', env => { rightOrder: signedOrderRight2, leftOrderTakerAssetFilledAmount: matchResults.orders.leftOrderTakerAssetFilledAmount, }, - takerAddress, expectedTransferAmounts2, + matcher.address, + PROTOCOL_FEE.times(2), false, - await matchOrderTester.getBalancesAsync(), ); }); it('should transfer the correct amounts when consecutive calls are used to completely fill the right order', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); - - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(50, 18), takerAssetAmount: toBaseUnitAmount(100, 18), }); + // Match orders const expectedTransferAmounts = { // Left Maker @@ -706,14 +722,17 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(6, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(4, 16), // 4% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; const matchResults = await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); @@ -721,10 +740,11 @@ blockchainTests.resets('matchOrders', env => { // Note: This order needs makerAssetAmount=96/takerAssetAmount=48 to fully fill the right order. // However, we use 100/50 to ensure a partial fill as we want to go down the "right fill" // branch in the contract twice for this test. - const signedOrderLeft2 = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft2 = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(100, 18), takerAssetAmount: toBaseUnitAmount(50, 18), }); + // Match signedOrderLeft2 with signedOrderRight const expectedTransferAmounts2 = { // Left Maker @@ -736,6 +756,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(96, 16), // 96% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(96, 16), // 96% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { @@ -743,25 +765,26 @@ blockchainTests.resets('matchOrders', env => { rightOrder: signedOrderRight, rightOrderTakerAssetFilledAmount: matchResults.orders.rightOrderTakerAssetFilledAmount, }, - takerAddress, expectedTransferAmounts2, + matcher.address, + PROTOCOL_FEE.times(2), false, - await matchOrderTester.getBalancesAsync(), ); }); it('should transfer the correct amounts if fee recipient is the same across both matched orders', async () => { - const feeRecipientAddress = feeRecipientAddressLeft; - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const feeRecipientAddress = feeRecipientLeft.address; + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), feeRecipientAddress, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), feeRecipientAddress, }); + // Match orders const expectedTransferAmounts = { // Left Maker @@ -775,30 +798,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); }); it('should transfer the correct amounts if taker == leftMaker', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); + // Match orders - takerAddress = signedOrderLeft.makerAddress; + const matcherAddress = signedOrderLeft.makerAddress; const expectedTransferAmounts = { // Left Maker leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(5, 18), @@ -811,30 +838,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcherAddress, + PROTOCOL_FEE.times(2), false, ); }); it('should transfer the correct amounts if taker == rightMaker', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); + // Match orders - takerAddress = signedOrderRight.makerAddress; + const matcherAddress = signedOrderRight.makerAddress; const expectedTransferAmounts = { // Left Maker leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(5, 18), @@ -847,30 +878,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcherAddress, + PROTOCOL_FEE.times(2), false, ); }); it('should transfer the correct amounts if taker == leftFeeRecipient', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); + // Match orders - takerAddress = feeRecipientAddressLeft; + const matcherAddress = feeRecipientLeft.address; const expectedTransferAmounts = { // Left Maker leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(5, 18), @@ -883,30 +918,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcherAddress, + PROTOCOL_FEE.times(2), false, ); }); it('should transfer the correct amounts if taker == rightFeeRecipient', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); + // Match orders - takerAddress = feeRecipientAddressRight; + const matcherAddress = feeRecipientRight.address; const expectedTransferAmounts = { // Left Maker leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(5, 18), @@ -919,30 +958,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcherAddress, + PROTOCOL_FEE.times(2), false, ); }); it('should transfer the correct amounts if leftMaker == leftFeeRecipient && rightMaker == rightFeeRecipient', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), - feeRecipientAddress: makerAddressLeft, + feeRecipientAddress: makerLeft.address, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), - feeRecipientAddress: makerAddressRight, + feeRecipientAddress: makerRight.address, }); + // Match orders const expectedTransferAmounts = { // Left Maker @@ -956,30 +999,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); }); it('should transfer the correct amounts if leftMaker == leftFeeRecipient && leftMakerFeeAsset == leftTakerAsset', async () => { // Create orders to match - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), makerFeeAssetData: signedOrderRight.makerAssetData, - feeRecipientAddress: makerAddressLeft, + feeRecipientAddress: makerLeft.address, }); + // Match orders const expectedTransferAmounts = { // Left Maker @@ -993,30 +1040,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); }); it('should transfer the correct amounts if rightMaker == rightFeeRecipient && rightMakerFeeAsset == rightTakerAsset', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), makerFeeAssetData: signedOrderLeft.makerAssetData, - feeRecipientAddress: makerAddressRight, + feeRecipientAddress: makerRight.address, }); + // Match orders const expectedTransferAmounts = { // Left Maker @@ -1030,38 +1081,37 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); }); - it('should transfer the correct amounts if rightMaker == rightFeeRecipient && rightTakerAsset == rightMakerFeeAsset && leftMaker == leftFeeRecipient && leftTakerAsset == leftMakerFeeAsset', async () => { + it(`should transfer the correct amounts if rightMaker == rightFeeRecipient && rightTakerAsset == rightMakerFeeAsset + && leftMaker == leftFeeRecipient && leftTakerAsset == leftMakerFeeAsset`, async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ -<<<<<<< HEAD - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18), - makerFeeAssetData: await devUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress).callAsync(), -======= + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` - feeRecipientAddress: makerAddressLeft, + feeRecipientAddress: makerLeft.address, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), makerFeeAssetData: signedOrderLeft.makerAssetData, - feeRecipientAddress: makerAddressRight, + feeRecipientAddress: makerRight.address, }); + // Match orders const expectedTransferAmounts = { // Left Maker @@ -1075,91 +1125,115 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), false, ); }); it('Should revert if left order is not fillable', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); const orderHashHexLeft = orderHashUtils.getOrderHashHex(signedOrderLeft); + // Cancel left order - await exchangeWrapper.cancelOrderAsync(signedOrderLeft, signedOrderLeft.makerAddress); + await deployment.exchange.cancelOrder.awaitTransactionSuccessAsync(signedOrderLeft, { + from: makerLeft.address, + }); + // Match orders const expectedError = new ExchangeRevertErrors.OrderStatusError(orderHashHexLeft, OrderStatus.Cancelled); - const tx = exchangeWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, takerAddress); + const tx = deployment.exchange.matchOrders.awaitTransactionSuccessAsync( + signedOrderLeft, + signedOrderRight, + signedOrderLeft.signature, + signedOrderRight.signature, + { from: matcher.address }, + ); return expect(tx).to.revertWith(expectedError); }); it('Should revert if right order is not fillable', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); const orderHashHexRight = orderHashUtils.getOrderHashHex(signedOrderRight); + // Cancel right order - await exchangeWrapper.cancelOrderAsync(signedOrderRight, signedOrderRight.makerAddress); + await deployment.exchange.cancelOrder.awaitTransactionSuccessAsync(signedOrderRight, { + from: makerRight.address, + }); + // Match orders const expectedError = new ExchangeRevertErrors.OrderStatusError(orderHashHexRight, OrderStatus.Cancelled); - const tx = exchangeWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, takerAddress); + const tx = deployment.exchange.matchOrders.awaitTransactionSuccessAsync( + signedOrderLeft, + signedOrderRight, + signedOrderLeft.signature, + signedOrderRight.signature, + { from: matcher.address }, + ); return expect(tx).to.revertWith(expectedError); }); it('should revert if there is not a positive spread', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(100, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 18), takerAssetAmount: toBaseUnitAmount(200, 18), }); const orderHashHexLeft = orderHashUtils.getOrderHashHex(signedOrderLeft); const orderHashHexRight = orderHashUtils.getOrderHashHex(signedOrderRight); + // Match orders const expectedError = new ExchangeRevertErrors.NegativeSpreadError(orderHashHexLeft, orderHashHexRight); - const tx = exchangeWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, takerAddress); + const tx = deployment.exchange.matchOrders.awaitTransactionSuccessAsync( + signedOrderLeft, + signedOrderRight, + signedOrderLeft.signature, + signedOrderRight.signature, + { from: matcher.address }, + ); return expect(tx).to.revertWith(expectedError); }); it('should revert if the left maker asset is not equal to the right taker asset ', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ -<<<<<<< HEAD - takerAssetData: await devUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress).callAsync(), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(2, 18), -======= - takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress), makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` }); + // We are assuming assetData fields of the right order are the // reverse of the left order, rather than checking equality. This // saves a bunch of gas, but as a result if the assetData fields are @@ -1175,25 +1249,26 @@ blockchainTests.resets('matchOrders', env => { signedOrderRight.makerAddress, signedOrderRight.signature, ); + // Match orders - const tx = exchangeWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, takerAddress); + const tx = deployment.exchange.matchOrders.awaitTransactionSuccessAsync( + signedOrderLeft, + signedOrderRight, + signedOrderLeft.signature, + signedOrderRight.signature, + { from: matcher.address }, + ); return expect(tx).to.revertWith(expectedError); }); it('should revert if the right maker asset is not equal to the left taker asset', async () => { // Create orders to match const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ -<<<<<<< HEAD takerAssetData: await devUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress).callAsync(), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18), -======= - takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress), makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); @@ -1209,24 +1284,27 @@ blockchainTests.resets('matchOrders', env => { signedOrderRight.signature, ); // Match orders - const tx = exchangeWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, takerAddress); + const tx = deployment.exchange.matchOrders.awaitTransactionSuccessAsync( + signedOrderLeft, + signedOrderRight, + signedOrderLeft.signature, + signedOrderRight.signature, + { from: matcher.address }, + ); return expect(tx).to.revertWith(expectedError); }); }); + describe('matchOrdersWithMaximalFill', () => { it('should transfer correct amounts when right order is fully filled and values pass isRoundingErrorCeil but fail isRoundingErrorFloor', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(17, 0), takerAssetAmount: toBaseUnitAmount(98, 0), - feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(75, 0), takerAssetAmount: toBaseUnitAmount(13, 0), - feeRecipientAddress: feeRecipientAddressRight, }); // Assert is rounding error ceil & not rounding error floor // These assertions are taken from MixinMatchOrders::calculateMatchedFillResults @@ -1254,32 +1332,32 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('76.5306122448979591'), 16), // 76.53% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); }); it('Should transfer correct amounts when left order is fully filled and values pass isRoundingErrorCeil and isRoundingErrorFloor', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(15, 0), takerAssetAmount: toBaseUnitAmount(90, 0), - feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(196, 0), takerAssetAmount: toBaseUnitAmount(28, 0), - feeRecipientAddress: feeRecipientAddressRight, }); + // Assert is rounding error floor // These assertions are taken from MixinMatchOrders::calculateMatchedFillResults // The rounding error is derived computating how much the right maker will buy. @@ -1290,6 +1368,7 @@ blockchainTests.resets('matchOrders', env => { expect(_isRoundingErrorCeil).to.be.false(); const _isRoundingErrorFloor = isRoundingErrorFloor(numerator, denominator, target); expect(_isRoundingErrorFloor).to.be.false(); + // Match signedOrderLeft with signedOrderRight // Note that the right maker received a slightly better purchase price. // This is intentional; see note in MixinMatchOrders.calculateMatchedFillResults. @@ -1309,41 +1388,33 @@ blockchainTests.resets('matchOrders', env => { rightMakerAssetReceivedByTakerAmount: toBaseUnitAmount(15, 0), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('53.5714285714285714'), 16), // 53.57% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); }); it('Should transfer correct amounts when left order is fully filled', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(16, 0), takerAssetAmount: toBaseUnitAmount(22, 0), - feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, -<<<<<<< HEAD - makerAssetData: await devUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress).callAsync(), - takerAssetData: await devUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress).callAsync(), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(87, 0), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(48, 0), -======= - makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress), - takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress), makerAssetAmount: toBaseUnitAmount(87, 0), takerAssetAmount: toBaseUnitAmount(48, 0), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` - feeRecipientAddress: feeRecipientAddressRight, }); + + // Match the orders. const expectedTransferAmounts = { // Left Maker leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(16, 0), @@ -1357,32 +1428,33 @@ blockchainTests.resets('matchOrders', env => { rightMakerAssetReceivedByTakerAmount: toBaseUnitAmount(7, 0), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('33.3333333333333333'), 16), // 33.33% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; - // Match signedOrderLeft with signedOrderRight await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); }); it('should fully fill both orders and pay out profit in both maker assets', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(7, 0), takerAssetAmount: toBaseUnitAmount(4, 0), - feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(8, 0), takerAssetAmount: toBaseUnitAmount(6, 0), }); + + // Match the orders. const expectedTransferAmounts = { // Left Maker leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(7, 0), @@ -1397,42 +1469,32 @@ blockchainTests.resets('matchOrders', env => { rightMakerAssetReceivedByTakerAmount: toBaseUnitAmount(4, 0), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; - // Match signedOrderLeft with signedOrderRight await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); }); it('Should give left maker a better sell price when rounding', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(12, 0), takerAssetAmount: toBaseUnitAmount(97, 0), - feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, -<<<<<<< HEAD - makerAssetData: await devUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress).callAsync(), - takerAssetData: await devUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress).callAsync(), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(89, 0), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0), -======= - makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress), - takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress), + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(89, 0), takerAssetAmount: toBaseUnitAmount(1, 0), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` - feeRecipientAddress: feeRecipientAddressRight, }); + // Note: // The maker/taker fee percentage paid on the left order differs because // they received different sale prices. The left maker pays a fee @@ -1449,44 +1511,37 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(10, 0), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('91.7525773195876288'), 16), // 91.75% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; + // Match signedOrderLeft with signedOrderRight await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); }); it('Should give right maker and right taker a favorable fee price when rounding', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(16, 0), takerAssetAmount: toBaseUnitAmount(22, 0), - feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, -<<<<<<< HEAD - makerAssetData: await devUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress).callAsync(), - takerAssetData: await devUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress).callAsync(), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(87, 0), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(48, 0), -======= - makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress), - takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress), + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(87, 0), takerAssetAmount: toBaseUnitAmount(48, 0), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` - feeRecipientAddress: feeRecipientAddressRight, makerFee: toBaseUnitAmount(10000, 0), takerFee: toBaseUnitAmount(10000, 0), }); + + // Match the orders. const expectedTransferAmounts = { // Left Maker leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(16, 0), @@ -1500,44 +1555,34 @@ blockchainTests.resets('matchOrders', env => { rightMakerAssetReceivedByTakerAmount: toBaseUnitAmount(7, 0), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(3333, 0), // 3333.3 repeating rounded down to 3333 + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; - // Match signedOrderLeft with signedOrderRight await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); }); it('Should give left maker and left taker a favorable fee price when rounding', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(12, 0), takerAssetAmount: toBaseUnitAmount(97, 0), - feeRecipientAddress: feeRecipientAddressLeft, makerFee: toBaseUnitAmount(10000, 0), takerFee: toBaseUnitAmount(10000, 0), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, -<<<<<<< HEAD - makerAssetData: await devUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress).callAsync(), - takerAssetData: await devUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress).callAsync(), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(89, 0), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0), -======= - makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress), - takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress), + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(89, 0), takerAssetAmount: toBaseUnitAmount(1, 0), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` - feeRecipientAddress: feeRecipientAddressRight, }); + // Note: // The maker/taker fee percentage paid on the left order differs because // they received different sale prices. The left maker pays a @@ -1554,42 +1599,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(10, 0), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(9175, 0), // 9175.2 rounded down to 9175 rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; + // Match signedOrderLeft with signedOrderRight await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); }); it('Should give left maker a better sell price when rounding', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(12, 0), takerAssetAmount: toBaseUnitAmount(97, 0), - feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, -<<<<<<< HEAD - makerAssetData: await devUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress).callAsync(), - takerAssetData: await devUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress).callAsync(), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(89, 0), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0), -======= - makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress), - takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress), + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(89, 0), takerAssetAmount: toBaseUnitAmount(1, 0), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` - feeRecipientAddress: feeRecipientAddressRight, }); + // Note: // The maker/taker fee percentage paid on the left order differs because // they received different sale prices. The left maker pays a fee @@ -1606,29 +1643,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(10, 0), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('91.7525773195876288'), 16), // 91.75% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; - // Match signedOrderLeft with signedOrderRight + + // Match the orders. await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); }); it('should transfer the correct amounts when consecutive calls are used to completely fill the left order', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(50, 18), takerAssetAmount: toBaseUnitAmount(100, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); + // Match orders const expectedTransferAmounts = { // Left Maker @@ -1642,6 +1684,8 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(10, 16), // 10% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; // prettier-ignore const matchResults = await matchOrderTester.matchOrdersAndAssertEffectsAsync( @@ -1649,19 +1693,22 @@ blockchainTests.resets('matchOrders', env => { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); + // Construct second right order // Note: This order needs makerAssetAmount=90/takerAssetAmount=[anything <= 45] to fully fill the right order. // However, we use 100/50 to ensure a partial fill as we want to go down the "left fill" // branch in the contract twice for this test. - const signedOrderRight2 = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight2 = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(100, 18), takerAssetAmount: toBaseUnitAmount(50, 18), }); - // Match signedOrderLeft with signedOrderRight2 + + // Match the orders. const expectedTransferAmounts2 = { // Left Maker leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(45, 18), @@ -1672,44 +1719,34 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(90, 16), // 90% (10% paid earlier) rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(90, 16), // 90% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; - await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight2, leftOrderTakerAssetFilledAmount: matchResults.orders.leftOrderTakerAssetFilledAmount, }, - takerAddress, expectedTransferAmounts2, + matcher.address, + PROTOCOL_FEE.times(2), true, - await matchOrderTester.getBalancesAsync(), ); }); it('Should transfer correct amounts when right order fill amount deviates from amount derived by `Exchange.fillOrder`', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1000, 0), takerAssetAmount: toBaseUnitAmount(1005, 0), - feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, -<<<<<<< HEAD - makerAssetData: await devUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress).callAsync(), - takerAssetData: await devUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress).callAsync(), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(2126, 0), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1063, 0), -======= - makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress), - takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress), + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(2126, 0), takerAssetAmount: toBaseUnitAmount(1063, 0), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` - feeRecipientAddress: feeRecipientAddressRight, }); + + // Match the orders. const expectedTransferAmounts = { // Left Maker leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(1000, 0), @@ -1736,30 +1773,33 @@ blockchainTests.resets('matchOrders', env => { rightMakerAssetReceivedByTakerAmount: toBaseUnitAmount(995, 0), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('94.0733772342427093'), 16), // 94.07% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; - // Match signedOrderLeft with signedOrderRight await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); }); - it('should transfer the correct amounts when orders completely fill each other and taker doesnt take a profit', async () => { + it("should transfer the correct amounts when orders completely fill each other and taker doesn't take a profit", async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(5, 18), }); - // Match signedOrderLeft with signedOrderRight + + // Match the orders. const expectedTransferAmounts = { // Left Maker leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(5, 18), @@ -1770,27 +1810,29 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; - // Match signedOrderLeft with signedOrderRight await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); }); it('should transfer the correct amounts when consecutive calls are used to completely fill the right order', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(50, 18), takerAssetAmount: toBaseUnitAmount(100, 18), }); @@ -1809,14 +1851,17 @@ blockchainTests.resets('matchOrders', env => { rightMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(10, 16), // 10% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; const matchResults = await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); @@ -1824,7 +1869,7 @@ blockchainTests.resets('matchOrders', env => { // Note: This order needs makerAssetAmount=96/takerAssetAmount=48 to fully fill the right order. // However, we use 100/50 to ensure a partial fill as we want to go down the "right fill" // branch in the contract twice for this test. - const signedOrderLeft2 = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft2 = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(100, 18), takerAssetAmount: toBaseUnitAmount(50, 18), }); @@ -1840,6 +1885,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(90, 16), // 96% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(90, 16), // 90% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( @@ -1848,25 +1895,26 @@ blockchainTests.resets('matchOrders', env => { rightOrder: signedOrderRight, rightOrderTakerAssetFilledAmount: matchResults.orders.rightOrderTakerAssetFilledAmount, }, - takerAddress, expectedTransferAmounts2, + matcher.address, + PROTOCOL_FEE.times(2), true, - await matchOrderTester.getBalancesAsync(), ); }); it('should transfer the correct amounts if fee recipient is the same across both matched orders', async () => { - const feeRecipientAddress = feeRecipientAddressLeft; - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const feeRecipientAddress = feeRecipientLeft.address; + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), feeRecipientAddress, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), feeRecipientAddress, }); + // Match orders const expectedTransferAmounts = { // Left Maker @@ -1880,30 +1928,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); }); it('should transfer the correct amounts if taker == leftMaker', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); + // Match orders - takerAddress = signedOrderLeft.makerAddress; + const matcherAddress = makerLeft.address; const expectedTransferAmounts = { // Left Maker leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(5, 18), @@ -1916,30 +1968,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcherAddress, + PROTOCOL_FEE.times(2), true, ); }); it('should transfer the correct amounts if taker == rightMaker', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); + // Match orders - takerAddress = signedOrderRight.makerAddress; + const matcherAddress = makerRight.address; const expectedTransferAmounts = { // Left Maker leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(5, 18), @@ -1952,30 +2008,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcherAddress, + PROTOCOL_FEE.times(2), true, ); }); it('should transfer the correct amounts if taker == leftFeeRecipient', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); + // Match orders - takerAddress = feeRecipientAddressLeft; + const matcherAddress = feeRecipientLeft.address; const expectedTransferAmounts = { // Left Maker leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(5, 18), @@ -1988,30 +2048,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcherAddress, + PROTOCOL_FEE.times(2), true, ); }); it('should transfer the correct amounts if taker == rightFeeRecipient', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); + // Match orders - takerAddress = feeRecipientAddressRight; + const matcherAddress = feeRecipientRight.address; const expectedTransferAmounts = { // Left Maker leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(5, 18), @@ -2024,30 +2088,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcherAddress, + PROTOCOL_FEE.times(2), true, ); }); it('should transfer the correct amounts if leftMaker == leftFeeRecipient && rightMaker == rightFeeRecipient', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), - feeRecipientAddress: makerAddressLeft, + feeRecipientAddress: makerLeft.address, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), - feeRecipientAddress: makerAddressRight, + feeRecipientAddress: makerRight.address, }); + // Match orders const expectedTransferAmounts = { // Left Maker @@ -2061,30 +2129,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); }); it('should transfer the correct amounts if leftMaker == leftFeeRecipient && leftMakerFeeAsset == leftTakerAsset', async () => { // Create orders to match - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), makerFeeAssetData: signedOrderRight.makerAssetData, - feeRecipientAddress: makerAddressLeft, + feeRecipientAddress: makerLeft.address, }); + // Match orders const expectedTransferAmounts = { // Left Maker @@ -2098,30 +2170,34 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); }); it('should transfer the correct amounts if rightMaker == rightFeeRecipient && rightMakerFeeAsset == rightTakerAsset', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), makerFeeAssetData: signedOrderLeft.makerAssetData, - feeRecipientAddress: makerAddressRight, + feeRecipientAddress: makerRight.address, }); + // Match orders const expectedTransferAmounts = { // Left Maker @@ -2135,38 +2211,36 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); }); it('should transfer the correct amounts if rightMaker == rightFeeRecipient && rightTakerAsset == rightMakerFeeAsset && leftMaker == leftFeeRecipient && leftTakerAsset == leftMakerFeeAsset', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ -<<<<<<< HEAD - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18), - makerFeeAssetData: await devUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress).callAsync(), -======= - makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress), + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` - feeRecipientAddress: makerAddressLeft, + makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress), + feeRecipientAddress: makerLeft.address, }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), makerFeeAssetData: signedOrderLeft.makerAssetData, - feeRecipientAddress: makerAddressRight, + feeRecipientAddress: makerRight.address, }); + // Match orders const expectedTransferAmounts = { // Left Maker @@ -2180,63 +2254,82 @@ blockchainTests.resets('matchOrders', env => { leftMakerAssetReceivedByTakerAmount: toBaseUnitAmount(3, 18), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }; await matchOrderTester.matchOrdersAndAssertEffectsAsync( { leftOrder: signedOrderLeft, rightOrder: signedOrderRight, }, - takerAddress, expectedTransferAmounts, + matcher.address, + PROTOCOL_FEE.times(2), true, ); }); it('Should revert if left order is not fillable', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); const orderHashHexLeft = orderHashUtils.getOrderHashHex(signedOrderLeft); // Cancel left order - await exchangeWrapper.cancelOrderAsync(signedOrderLeft, signedOrderLeft.makerAddress); + await deployment.exchange.cancelOrder.awaitTransactionSuccessAsync(signedOrderLeft, { + from: makerLeft.address, + }); // Match orders const expectedError = new ExchangeRevertErrors.OrderStatusError(orderHashHexLeft, OrderStatus.Cancelled); - const tx = exchangeWrapper.matchOrdersWithMaximalFillAsync(signedOrderLeft, signedOrderRight, takerAddress); + const tx = deployment.exchange.matchOrdersWithMaximalFill.awaitTransactionSuccessAsync( + signedOrderLeft, + signedOrderRight, + signedOrderLeft.signature, + signedOrderRight.signature, + { from: matcher.address }, + ); return expect(tx).to.revertWith(expectedError); }); it('Should revert if right order is not fillable', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); const orderHashHexRight = orderHashUtils.getOrderHashHex(signedOrderRight); // Cancel right order - await exchangeWrapper.cancelOrderAsync(signedOrderRight, signedOrderRight.makerAddress); + await deployment.exchange.cancelOrder.awaitTransactionSuccessAsync(signedOrderRight, { + from: makerRight.address, + }); // Match orders const expectedError = new ExchangeRevertErrors.OrderStatusError(orderHashHexRight, OrderStatus.Cancelled); - const tx = exchangeWrapper.matchOrdersWithMaximalFillAsync(signedOrderLeft, signedOrderRight, takerAddress); + const tx = deployment.exchange.matchOrdersWithMaximalFill.awaitTransactionSuccessAsync( + signedOrderLeft, + signedOrderRight, + signedOrderLeft.signature, + signedOrderRight.signature, + { from: matcher.address }, + ); return expect(tx).to.revertWith(expectedError); }); it('should revert if there is not a positive spread', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(100, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 18), takerAssetAmount: toBaseUnitAmount(200, 18), }); @@ -2244,26 +2337,26 @@ blockchainTests.resets('matchOrders', env => { const orderHashHexRight = orderHashUtils.getOrderHashHex(signedOrderRight); // Match orders const expectedError = new ExchangeRevertErrors.NegativeSpreadError(orderHashHexLeft, orderHashHexRight); - const tx = exchangeWrapper.matchOrdersWithMaximalFillAsync(signedOrderLeft, signedOrderRight, takerAddress); + const tx = deployment.exchange.matchOrdersWithMaximalFill.awaitTransactionSuccessAsync( + signedOrderLeft, + signedOrderRight, + signedOrderLeft.signature, + signedOrderRight.signature, + { from: matcher.address }, + ); return expect(tx).to.revertWith(expectedError); }); it('should revert if the left maker asset is not equal to the right taker asset ', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + const signedOrderLeft = await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ -<<<<<<< HEAD - takerAssetData: await devUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress).callAsync(), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(2, 18), -======= + const signedOrderRight = await makerRight.signOrderAsync({ takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress), makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` }); // We are assuming assetData fields of the right order are the // reverse of the left order, rather than checking equality. This @@ -2281,24 +2374,24 @@ blockchainTests.resets('matchOrders', env => { signedOrderRight.signature, ); // Match orders - const tx = exchangeWrapper.matchOrdersWithMaximalFillAsync(signedOrderLeft, signedOrderRight, takerAddress); + const tx = deployment.exchange.matchOrdersWithMaximalFill.awaitTransactionSuccessAsync( + signedOrderLeft, + signedOrderRight, + signedOrderLeft.signature, + signedOrderRight.signature, + { from: matcher.address }, + ); return expect(tx).to.revertWith(expectedError); }); it('should revert if the right maker asset is not equal to the left taker asset', async () => { // Create orders to match - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ -<<<<<<< HEAD - takerAssetData: await devUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress).callAsync(), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18), -======= + const signedOrderLeft = await makerLeft.signOrderAsync({ takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress), makerAssetAmount: toBaseUnitAmount(5, 18), takerAssetAmount: toBaseUnitAmount(10, 18), ->>>>>>> `@0x:contracts-integrations` Made an initial refactor of `MatchOrderTester` }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + const signedOrderRight = await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(10, 18), takerAssetAmount: toBaseUnitAmount(2, 18), }); @@ -2314,507 +2407,18 @@ blockchainTests.resets('matchOrders', env => { signedOrderRight.signature, ); // Match orders - const tx = exchangeWrapper.matchOrdersWithMaximalFillAsync(signedOrderLeft, signedOrderRight, takerAddress); + const tx = deployment.exchange.matchOrdersWithMaximalFill.awaitTransactionSuccessAsync( + signedOrderLeft, + signedOrderRight, + signedOrderLeft.signature, + signedOrderRight.signature, + { from: matcher.address }, + ); return expect(tx).to.revertWith(expectedError); }); }); - describe('matchOrders and matchOrdersWithMaximalFill combinations', () => { - // tslint:disable: enum-naming - enum AssetType { - ERC20A = 'ERC20_A', - ERC20B = 'ERC20_B', - ERC20C = 'ERC20_C', - ERC20D = 'ERC20_D', - ERC721LeftMaker = 'ERC721_LEFT_MAKER', - ERC721RightMaker = 'ERC721_RIGHT_MAKER', - ERC721Taker = 'ERC721_TAKER', - ERC1155FungibleA = 'ERC1155_FUNGIBLE_A', - ERC1155FungibleB = 'ERC1155_FUNGIBLE_B', - ERC1155FungibleC = 'ERC1155_FUNGIBLE_C', - ERC1155FungibleD = 'ERC1155_FUNGIBLE_D', - ERC1155NonFungibleLeftMaker = 'ERC1155_NON_FUNGIBLE_LEFT_MAKER', - ERC1155NonFungibleRightMaker = 'ERC1155_NON_FUNGIBLE_RIGHT_MAKER', - ERC1155NonFungibleTaker = 'ERC1155_NON_FUNGIBLE_TAKER', - MultiAssetA = 'MULTI_ASSET_A', - MultiAssetB = 'MULTI_ASSET_B', - MultiAssetC = 'MULTI_ASSET_C', - MultiAssetD = 'MULTI_ASSET_D', - } - const fungibleTypes = [ - AssetType.ERC20A, - AssetType.ERC20B, - AssetType.ERC20C, - AssetType.ERC20D, - AssetType.ERC1155FungibleA, - AssetType.ERC1155FungibleB, - AssetType.ERC1155FungibleC, - AssetType.ERC1155FungibleD, - AssetType.MultiAssetA, - AssetType.MultiAssetB, - AssetType.MultiAssetC, - AssetType.MultiAssetD, - ]; - interface AssetCombination { - leftMaker: AssetType; - rightMaker: AssetType; - leftMakerFee: AssetType; - rightMakerFee: AssetType; - leftTakerFee: AssetType; - rightTakerFee: AssetType; - description?: string; - shouldFail?: boolean; - } - const assetCombinations: AssetCombination[] = [ - { - leftMaker: AssetType.ERC20A, - rightMaker: AssetType.ERC20B, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC20C, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - leftMaker: AssetType.ERC721LeftMaker, - rightMaker: AssetType.ERC721RightMaker, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC20C, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - leftMaker: AssetType.ERC721LeftMaker, - rightMaker: AssetType.ERC20A, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC20C, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - leftMaker: AssetType.ERC20A, - rightMaker: AssetType.ERC721RightMaker, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC20C, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - leftMaker: AssetType.ERC1155FungibleA, - rightMaker: AssetType.ERC20A, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC20C, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - leftMaker: AssetType.ERC20A, - rightMaker: AssetType.ERC1155FungibleB, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC20C, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - leftMaker: AssetType.ERC1155FungibleA, - rightMaker: AssetType.ERC1155FungibleA, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC20C, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - leftMaker: AssetType.ERC1155NonFungibleLeftMaker, - rightMaker: AssetType.ERC20A, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC20C, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - leftMaker: AssetType.ERC20A, - rightMaker: AssetType.ERC1155NonFungibleRightMaker, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC20C, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - leftMaker: AssetType.ERC1155NonFungibleLeftMaker, - rightMaker: AssetType.ERC1155NonFungibleRightMaker, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC20C, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - leftMaker: AssetType.ERC1155FungibleA, - rightMaker: AssetType.ERC20A, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC20C, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - leftMaker: AssetType.ERC20A, - rightMaker: AssetType.ERC1155FungibleB, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC20C, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - leftMaker: AssetType.ERC1155FungibleB, - rightMaker: AssetType.ERC1155FungibleB, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC20C, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - leftMaker: AssetType.MultiAssetA, - rightMaker: AssetType.ERC20A, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC20C, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - leftMaker: AssetType.ERC20A, - rightMaker: AssetType.MultiAssetB, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC20C, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - leftMaker: AssetType.MultiAssetA, - rightMaker: AssetType.MultiAssetB, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC20C, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - leftMaker: AssetType.MultiAssetA, - rightMaker: AssetType.ERC1155FungibleA, - leftMakerFee: AssetType.ERC1155FungibleA, - rightMakerFee: AssetType.MultiAssetA, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - }, - { - description: 'Paying maker fees with the same ERC20 tokens being bought.', - leftMaker: AssetType.ERC20A, - rightMaker: AssetType.ERC20B, - leftMakerFee: AssetType.ERC20B, - rightMakerFee: AssetType.ERC20A, - leftTakerFee: AssetType.ERC20B, - rightTakerFee: AssetType.ERC20A, - }, - { - description: 'Paying maker fees with the same ERC20 tokens being sold.', - leftMaker: AssetType.ERC20A, - rightMaker: AssetType.ERC20B, - leftMakerFee: AssetType.ERC20A, - rightMakerFee: AssetType.ERC20B, - leftTakerFee: AssetType.ERC20A, - rightTakerFee: AssetType.ERC20B, - }, - { - description: 'Using all the same ERC20 asset.', - leftMaker: AssetType.ERC20A, - rightMaker: AssetType.ERC20A, - leftMakerFee: AssetType.ERC20A, - rightMakerFee: AssetType.ERC20A, - leftTakerFee: AssetType.ERC20A, - rightTakerFee: AssetType.ERC20A, - }, - { - description: 'Paying fees with the same MAP assets being sold.', - leftMaker: AssetType.MultiAssetA, - rightMaker: AssetType.MultiAssetB, - leftMakerFee: AssetType.MultiAssetA, - rightMakerFee: AssetType.MultiAssetB, - leftTakerFee: AssetType.MultiAssetA, - rightTakerFee: AssetType.MultiAssetB, - }, - { - description: 'Paying fees with the same MAP assets being bought.', - leftMaker: AssetType.MultiAssetA, - rightMaker: AssetType.MultiAssetB, - leftMakerFee: AssetType.MultiAssetB, - rightMakerFee: AssetType.MultiAssetA, - leftTakerFee: AssetType.MultiAssetB, - rightTakerFee: AssetType.MultiAssetA, - }, - { - description: 'Using all the same MAP assets.', - leftMaker: AssetType.MultiAssetA, - rightMaker: AssetType.MultiAssetA, - leftMakerFee: AssetType.MultiAssetA, - rightMakerFee: AssetType.MultiAssetA, - leftTakerFee: AssetType.MultiAssetA, - rightTakerFee: AssetType.MultiAssetA, - }, - { - description: 'Swapping ERC721s then using them to pay maker fees.', - leftMaker: AssetType.ERC721LeftMaker, - rightMaker: AssetType.ERC721RightMaker, - leftMakerFee: AssetType.ERC721RightMaker, - rightMakerFee: AssetType.ERC721LeftMaker, - leftTakerFee: AssetType.ERC20A, - rightTakerFee: AssetType.ERC20A, - }, - { - description: 'Swapping ERC1155 NFTs then using them to pay maker fees.', - leftMaker: AssetType.ERC1155NonFungibleLeftMaker, - rightMaker: AssetType.ERC1155NonFungibleRightMaker, - leftMakerFee: AssetType.ERC1155NonFungibleRightMaker, - rightMakerFee: AssetType.ERC1155NonFungibleLeftMaker, - leftTakerFee: AssetType.ERC20A, - rightTakerFee: AssetType.ERC20A, - }, - { - description: 'Double-spend by trying to pay maker fees with sold ERC721 token (fail).', - leftMaker: AssetType.ERC721LeftMaker, - rightMaker: AssetType.ERC721RightMaker, - leftMakerFee: AssetType.ERC721LeftMaker, - rightMakerFee: AssetType.ERC721LeftMaker, - leftTakerFee: AssetType.ERC20A, - rightTakerFee: AssetType.ERC20A, - shouldFail: true, - }, - { - description: 'Double-spend by trying to pay maker fees with sold ERC1155 NFT (fail).', - leftMaker: AssetType.ERC20A, - rightMaker: AssetType.ERC1155NonFungibleLeftMaker, - leftMakerFee: AssetType.ERC20C, - rightMakerFee: AssetType.ERC1155NonFungibleLeftMaker, - leftTakerFee: AssetType.ERC20C, - rightTakerFee: AssetType.ERC20C, - shouldFail: true, - }, - ]; - - let nameToERC20Asset: { [name: string]: string }; - let nameToERC721Asset: { [name: string]: [string, BigNumber] }; - let nameToERC1155FungibleAsset: { [name: string]: [string, BigNumber] }; - let nameToERC1155NonFungibleAsset: { [name: string]: [string, BigNumber] }; - let nameToMultiAssetAsset: { [name: string]: [BigNumber[], string[]] }; - - async function getAssetDataAsync(assetType: AssetType): Promise { - if (nameToERC20Asset[assetType] !== undefined) { - const tokenAddress = nameToERC20Asset[assetType]; - return devUtils.encodeERC20AssetData(tokenAddress).callAsync(); - } - if (nameToERC721Asset[assetType] !== undefined) { - const [tokenAddress, tokenId] = nameToERC721Asset[assetType]; - return devUtils.encodeERC721AssetData(tokenAddress, tokenId).callAsync(); - } - if (nameToERC1155FungibleAsset[assetType] !== undefined) { - const [tokenAddress, tokenId] = nameToERC1155FungibleAsset[assetType]; - return devUtils - .encodeERC1155AssetData(tokenAddress, [tokenId], [ONE], constants.NULL_BYTES) - .callAsync(); - } - if (nameToERC1155NonFungibleAsset[assetType] !== undefined) { - const [tokenAddress, tokenId] = nameToERC1155NonFungibleAsset[assetType]; - return devUtils - .encodeERC1155AssetData(tokenAddress, [tokenId], [ONE], constants.NULL_BYTES) - .callAsync(); - } - if (nameToMultiAssetAsset[assetType] !== undefined) { - const [amounts, nestedAssetData] = nameToMultiAssetAsset[assetType]; - return devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync(); - } - throw new Error(`Unknown asset type: ${assetType}`); - } - - before(async () => { - nameToERC20Asset = { - ERC20_A: erc20Tokens[0].address, - ERC20_B: erc20Tokens[1].address, - ERC20_C: erc20Tokens[2].address, - ERC20_D: erc20Tokens[3].address, - }; - const erc721TokenIds = _.mapValues(tokenBalances.erc721, v => v[defaultERC721AssetAddress][0]); - nameToERC721Asset = { - ERC721_LEFT_MAKER: [defaultERC721AssetAddress, erc721TokenIds[makerAddressLeft]], - ERC721_RIGHT_MAKER: [defaultERC721AssetAddress, erc721TokenIds[makerAddressRight]], - ERC721_TAKER: [defaultERC721AssetAddress, erc721TokenIds[takerAddress]], - }; - const erc1155FungibleTokens = _.keys( - _.values(tokenBalances.erc1155)[0][defaultERC1155AssetAddress].fungible, - ).map(k => new BigNumber(k)); - nameToERC1155FungibleAsset = { - ERC1155_FUNGIBLE_A: [defaultERC1155AssetAddress, erc1155FungibleTokens[0]], - ERC1155_FUNGIBLE_B: [defaultERC1155AssetAddress, erc1155FungibleTokens[1]], - ERC1155_FUNGIBLE_C: [defaultERC1155AssetAddress, erc1155FungibleTokens[2]], - ERC1155_FUNGIBLE_D: [defaultERC1155AssetAddress, erc1155FungibleTokens[3]], - }; - const erc1155NonFungibleTokenIds = _.mapValues( - tokenBalances.erc1155, - v => v[defaultERC1155AssetAddress].nonFungible[0], - ); - nameToERC1155NonFungibleAsset = { - ERC1155_NON_FUNGIBLE_LEFT_MAKER: [ - defaultERC1155AssetAddress, - erc1155NonFungibleTokenIds[makerAddressLeft], - ], - ERC1155_NON_FUNGIBLE_RIGHT_MAKER: [ - defaultERC1155AssetAddress, - erc1155NonFungibleTokenIds[makerAddressRight], - ], - ERC1155_NON_FUNGIBLE_TAKER: [defaultERC1155AssetAddress, erc1155NonFungibleTokenIds[takerAddress]], - }; - nameToMultiAssetAsset = { - MULTI_ASSET_A: [ - [ONE, TWO], - [ - await devUtils.encodeERC20AssetData(erc20Tokens[0].address).callAsync(), - await devUtils - .encodeERC1155AssetData( - defaultERC1155AssetAddress, - [erc1155FungibleTokens[0]], - [ONE], - constants.NULL_BYTES, - ) - .callAsync(), - ], - ], - MULTI_ASSET_B: [ - [ONE, TWO], - [ - await devUtils.encodeERC20AssetData(erc20Tokens[1].address).callAsync(), - await devUtils - .encodeERC1155AssetData( - defaultERC1155AssetAddress, - [erc1155FungibleTokens[1]], - [ONE], - constants.NULL_BYTES, - ) - .callAsync(), - ], - ], - MULTI_ASSET_C: [ - [ONE, TWO], - [ - await devUtils.encodeERC20AssetData(erc20Tokens[2].address).callAsync(), - await devUtils - .encodeERC1155AssetData( - defaultERC1155AssetAddress, - [erc1155FungibleTokens[2]], - [ONE], - constants.NULL_BYTES, - ) - .callAsync(), - ], - ], - MULTI_ASSET_D: [ - [ONE, TWO], - [ - await devUtils.encodeERC20AssetData(erc20Tokens[3].address).callAsync(), - await devUtils - .encodeERC1155AssetData( - erc1155Token.address, - [erc1155FungibleTokens[3]], - [ONE], - constants.NULL_BYTES, - ) - .callAsync(), - ], - ], - }; - }); - - // matchOrders - for (const combo of assetCombinations) { - const description = combo.description || JSON.stringify(combo); - it(description, async () => { - // Create orders to match. For ERC20s, there will be a spread. - const leftMakerAssetAmount = _.includes(fungibleTypes, combo.leftMaker) - ? toBaseUnitAmount(15, 18) - : toBaseUnitAmount(1, 0); - const leftTakerAssetAmount = _.includes(fungibleTypes, combo.rightMaker) - ? toBaseUnitAmount(30, 18) - : toBaseUnitAmount(1, 0); - const rightMakerAssetAmount = _.includes(fungibleTypes, combo.rightMaker) - ? toBaseUnitAmount(30, 18) - : toBaseUnitAmount(1, 0); - const rightTakerAssetAmount = _.includes(fungibleTypes, combo.leftMaker) - ? toBaseUnitAmount(14, 18) - : toBaseUnitAmount(1, 0); - const leftMakerFeeAssetAmount = _.includes(fungibleTypes, combo.leftMakerFee) - ? toBaseUnitAmount(8, 12) - : toBaseUnitAmount(1, 0); - const rightMakerFeeAssetAmount = _.includes(fungibleTypes, combo.rightMakerFee) - ? toBaseUnitAmount(7, 12) - : toBaseUnitAmount(1, 0); - const leftTakerFeeAssetAmount = _.includes(fungibleTypes, combo.leftTakerFee) - ? toBaseUnitAmount(6, 12) - : toBaseUnitAmount(1, 0); - const rightTakerFeeAssetAmount = _.includes(fungibleTypes, combo.rightTakerFee) - ? toBaseUnitAmount(5, 12) - : toBaseUnitAmount(1, 0); - const leftMakerAssetReceivedByTakerAmount = _.includes(fungibleTypes, combo.leftMaker) - ? leftMakerAssetAmount.minus(rightTakerAssetAmount) - : toBaseUnitAmount(0, 0); - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAssetData: await getAssetDataAsync(combo.leftMaker), - takerAssetData: await getAssetDataAsync(combo.rightMaker), - makerFeeAssetData: await getAssetDataAsync(combo.leftMakerFee), - takerFeeAssetData: await getAssetDataAsync(combo.leftTakerFee), - makerAssetAmount: leftMakerAssetAmount, - takerAssetAmount: leftTakerAssetAmount, - makerFee: leftMakerFeeAssetAmount, - takerFee: leftTakerFeeAssetAmount, - }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAssetData: await getAssetDataAsync(combo.rightMaker), - takerAssetData: await getAssetDataAsync(combo.leftMaker), - makerFeeAssetData: await getAssetDataAsync(combo.rightMakerFee), - takerFeeAssetData: await getAssetDataAsync(combo.rightTakerFee), - makerAssetAmount: rightMakerAssetAmount, - takerAssetAmount: rightTakerAssetAmount, - makerFee: rightMakerFeeAssetAmount, - takerFee: rightTakerFeeAssetAmount, - }); - // Match signedOrderLeft with signedOrderRight - const expectedTransferAmounts = { - // Left Maker - leftMakerAssetSoldByLeftMakerAmount: leftMakerAssetAmount, - leftMakerFeeAssetPaidByLeftMakerAmount: leftMakerFeeAssetAmount, - // Right Maker - rightMakerAssetSoldByRightMakerAmount: rightMakerAssetAmount, - leftMakerAssetBoughtByRightMakerAmount: rightTakerAssetAmount, - rightMakerFeeAssetPaidByRightMakerAmount: rightMakerFeeAssetAmount, - // Taker - leftMakerAssetReceivedByTakerAmount, - leftTakerFeeAssetPaidByTakerAmount: leftTakerFeeAssetAmount, - rightTakerFeeAssetPaidByTakerAmount: rightTakerFeeAssetAmount, - }; - if (!combo.shouldFail) { - await matchOrderTester.matchOrdersAndAssertEffectsAsync( - { - leftOrder: signedOrderLeft, - rightOrder: signedOrderRight, - }, - takerAddress, - expectedTransferAmounts, - false, - ); - } else { - const tx = exchangeWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, takerAddress); - return expect(tx).to.be.rejected(); - } - }); - } - - // matchOrdersWithMaximalFill - for (const combo of assetCombinations) { - const description = combo.description || JSON.stringify(combo); - it(description, async () => { - // Create orders to match. For ERC20s, there will be a spread. + /* FIXME const leftMakerAssetAmount = _.includes(fungibleTypes, combo.leftMaker) ? toBaseUnitAmount(15, 18) : toBaseUnitAmount(1, 0); @@ -2845,197 +2449,164 @@ blockchainTests.resets('matchOrders', env => { const rightMakerAssetReceivedByTakerAmount = _.includes(fungibleTypes, combo.leftMaker) ? rightMakerAssetAmount.minus(leftTakerAssetAmount) : toBaseUnitAmount(0, 0); - const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ - makerAssetData: await getAssetDataAsync(combo.leftMaker), - takerAssetData: await getAssetDataAsync(combo.rightMaker), - makerFeeAssetData: await getAssetDataAsync(combo.leftMakerFee), - takerFeeAssetData: await getAssetDataAsync(combo.leftTakerFee), - makerAssetAmount: leftMakerAssetAmount, - takerAssetAmount: leftTakerAssetAmount, - makerFee: leftMakerFeeAssetAmount, - takerFee: leftTakerFeeAssetAmount, - }); - const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ - makerAssetData: await getAssetDataAsync(combo.rightMaker), - takerAssetData: await getAssetDataAsync(combo.leftMaker), - makerFeeAssetData: await getAssetDataAsync(combo.rightMakerFee), - takerFeeAssetData: await getAssetDataAsync(combo.rightTakerFee), - makerAssetAmount: rightMakerAssetAmount, - takerAssetAmount: rightTakerAssetAmount, - makerFee: rightMakerFeeAssetAmount, - takerFee: rightTakerFeeAssetAmount, - }); - // Match signedOrderLeft with signedOrderRight - const expectedTransferAmounts = { - // Left Maker - leftMakerAssetSoldByLeftMakerAmount: leftMakerAssetAmount, - leftMakerFeeAssetPaidByLeftMakerAmount: leftMakerFeeAssetAmount, - // Right Maker - rightMakerAssetSoldByRightMakerAmount: rightMakerAssetAmount, - leftMakerAssetBoughtByRightMakerAmount: rightTakerAssetAmount, - rightMakerFeeAssetPaidByRightMakerAmount: rightMakerFeeAssetAmount, - // Taker - leftMakerAssetReceivedByTakerAmount, - rightMakerAssetReceivedByTakerAmount, - leftTakerFeeAssetPaidByTakerAmount: leftTakerFeeAssetAmount, - rightTakerFeeAssetPaidByTakerAmount: rightTakerFeeAssetAmount, - }; - if (!combo.shouldFail) { - await matchOrderTester.matchOrdersAndAssertEffectsAsync( - { - leftOrder: signedOrderLeft, - rightOrder: signedOrderRight, - }, - takerAddress, - expectedTransferAmounts, - true, - ); - } else { - const tx = exchangeWrapper.matchOrdersWithMaximalFillAsync( - signedOrderLeft, - signedOrderRight, - takerAddress, - ); - return expect(tx).to.be.rejected(); - } - }); - } - }); + */ describe('batchMatchOrders and batchMatchOrdersWithMaximalFill rich errors', async () => { it('should fail if there are zero leftOrders with the ZeroLeftOrders rich error reason', async () => { const leftOrders: SignedOrder[] = []; const rightOrders = [ - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressRight, }), ]; const expectedError = new ExchangeRevertErrors.BatchMatchOrdersError( ExchangeRevertErrors.BatchMatchOrdersErrorCodes.ZeroLeftOrders, ); - let tx = exchangeWrapper.batchMatchOrdersAsync(leftOrders, rightOrders, takerAddress); + let tx = deployment.exchange.batchMatchOrders.awaitTransactionSuccessAsync( + leftOrders, + rightOrders, + leftOrders.map(order => order.signature), + rightOrders.map(order => order.signature), + { from: matcher.address }, + ); await expect(tx).to.revertWith(expectedError); - tx = exchangeWrapper.batchMatchOrdersWithMaximalFillAsync(leftOrders, rightOrders, takerAddress); + tx = deployment.exchange.batchMatchOrdersWithMaximalFill.awaitTransactionSuccessAsync( + leftOrders, + rightOrders, + leftOrders.map(order => order.signature), + rightOrders.map(order => order.signature), + { from: matcher.address }, + ); return expect(tx).to.revertWith(expectedError); }); + it('should fail if there are zero rightOrders', async () => { const leftOrders = [ - await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressLeft, }), ]; const rightOrders: SignedOrder[] = []; const expectedError = new ExchangeRevertErrors.BatchMatchOrdersError( ExchangeRevertErrors.BatchMatchOrdersErrorCodes.ZeroRightOrders, ); - let tx = exchangeWrapper.batchMatchOrdersAsync(leftOrders, rightOrders, takerAddress); + let tx = deployment.exchange.batchMatchOrders.awaitTransactionSuccessAsync( + leftOrders, + rightOrders, + leftOrders.map(order => order.signature), + rightOrders.map(order => order.signature), + { from: matcher.address }, + ); await expect(tx).to.revertWith(expectedError); - tx = exchangeWrapper.batchMatchOrdersWithMaximalFillAsync(leftOrders, rightOrders, takerAddress); + tx = deployment.exchange.batchMatchOrdersWithMaximalFill.awaitTransactionSuccessAsync( + leftOrders, + rightOrders, + leftOrders.map(order => order.signature), + rightOrders.map(order => order.signature), + { from: matcher.address }, + ); return expect(tx).to.revertWith(expectedError); }); + it('should fail if there are a different number of left orders and signatures', async () => { const leftOrders = [ - await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(2, 0), takerAssetAmount: toBaseUnitAmount(1, 0), - feeRecipientAddress: feeRecipientAddressLeft, }), - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressRight, }), ]; const rightOrders = [ - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressRight, }), - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressRight, }), ]; - const params = orderUtils.createBatchMatchOrders(leftOrders, rightOrders); - // Set params left signatures to only include the first left signature - params.leftSignatures = [params.leftSignatures[0]]; const expectedError = new ExchangeRevertErrors.BatchMatchOrdersError( ExchangeRevertErrors.BatchMatchOrdersErrorCodes.InvalidLengthLeftSignatures, ); - let tx = exchangeWrapper.batchMatchOrdersRawAsync(params, takerAddress); + let tx = deployment.exchange.batchMatchOrders.awaitTransactionSuccessAsync( + leftOrders, + rightOrders, + [leftOrders[0].signature], + rightOrders.map(order => order.signature), + { from: matcher.address }, + ); await expect(tx).to.revertWith(expectedError); - tx = exchangeWrapper.batchMatchOrdersWithMaximalFillRawAsync(params, takerAddress); + tx = deployment.exchange.batchMatchOrdersWithMaximalFill.awaitTransactionSuccessAsync( + leftOrders, + rightOrders, + [leftOrders[0].signature], + rightOrders.map(order => order.signature), + { from: matcher.address }, + ); return expect(tx).to.revertWith(expectedError); }); + it('should fail if there are a different number of right orders and signatures', async () => { const leftOrders = [ - await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(2, 0), takerAssetAmount: toBaseUnitAmount(1, 0), - feeRecipientAddress: feeRecipientAddressLeft, }), - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, - makerAssetAmount: toBaseUnitAmount(1, 0), - takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressRight, + await makerLeft.signOrderAsync({ + makerAssetAmount: toBaseUnitAmount(2, 0), + takerAssetAmount: toBaseUnitAmount(1, 0), }), ]; const rightOrders = [ - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressRight, }), - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressRight, }), ]; - const params = orderUtils.createBatchMatchOrders(leftOrders, rightOrders); - // Set params right signatures to only include the first right signature - params.rightSignatures = [params.rightSignatures[0]]; const expectedError = new ExchangeRevertErrors.BatchMatchOrdersError( ExchangeRevertErrors.BatchMatchOrdersErrorCodes.InvalidLengthRightSignatures, ); - let tx = exchangeWrapper.batchMatchOrdersRawAsync(params, takerAddress); + let tx = deployment.exchange.batchMatchOrders.awaitTransactionSuccessAsync( + leftOrders, + rightOrders, + leftOrders.map(order => order.signature), + [rightOrders[0].signature], + { from: matcher.address }, + ); await expect(tx).to.revertWith(expectedError); - tx = exchangeWrapper.batchMatchOrdersWithMaximalFillRawAsync(params, takerAddress); + tx = deployment.exchange.batchMatchOrdersWithMaximalFill.awaitTransactionSuccessAsync( + leftOrders, + rightOrders, + leftOrders.map(order => order.signature), + [rightOrders[0].signature], + { from: matcher.address }, + ); return expect(tx).to.revertWith(expectedError); }); }); + describe('batchMatchOrders', () => { it('should correctly match two opposite orders', async () => { const leftOrders = [ - await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(2, 0), takerAssetAmount: toBaseUnitAmount(1, 0), - feeRecipientAddress: feeRecipientAddressLeft, }), ]; const rightOrders = [ - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressRight, }), ]; const expectedTransferAmounts = [ @@ -3049,6 +2620,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }, ]; await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync( @@ -3058,7 +2631,8 @@ blockchainTests.resets('matchOrders', env => { leftOrdersTakerAssetFilledAmounts: [ZERO], rightOrdersTakerAssetFilledAmounts: [ZERO], }, - takerAddress, + matcher.address, + PROTOCOL_FEE.times(2), [[0, 0]], expectedTransferAmounts, false, @@ -3066,19 +2640,15 @@ blockchainTests.resets('matchOrders', env => { }); it('Should correctly match a partial fill', async () => { const leftOrders = [ - await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(4, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressLeft, }), ]; const rightOrders = [ - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressRight, }), ]; const expectedTransferAmounts = [ @@ -3092,6 +2662,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }, ]; await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync( @@ -3101,7 +2673,8 @@ blockchainTests.resets('matchOrders', env => { leftOrdersTakerAssetFilledAmounts: [ZERO], rightOrdersTakerAssetFilledAmounts: [ZERO], }, - takerAddress, + matcher.address, + PROTOCOL_FEE.times(2), [[0, 0]], expectedTransferAmounts, false, @@ -3109,25 +2682,19 @@ blockchainTests.resets('matchOrders', env => { }); it('should correctly match two left orders to one complementary right order', async () => { const leftOrders = [ - await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(2, 0), takerAssetAmount: toBaseUnitAmount(1, 0), - feeRecipientAddress: feeRecipientAddressLeft, }), - await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(2, 0), takerAssetAmount: toBaseUnitAmount(1, 0), - feeRecipientAddress: feeRecipientAddressLeft, }), ]; const rightOrders = [ - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(2, 0), takerAssetAmount: toBaseUnitAmount(4, 0), - feeRecipientAddress: feeRecipientAddressRight, }), ]; const expectedTransferAmounts = [ @@ -3142,6 +2709,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 50% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }, { // Left Maker @@ -3154,6 +2723,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 50% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }, ]; await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync( @@ -3163,7 +2734,8 @@ blockchainTests.resets('matchOrders', env => { leftOrdersTakerAssetFilledAmounts: [ZERO, ZERO], rightOrdersTakerAssetFilledAmounts: [ZERO], }, - takerAddress, + matcher.address, + PROTOCOL_FEE.times(4), [[0, 0], [1, 0]], expectedTransferAmounts, false, @@ -3171,25 +2743,19 @@ blockchainTests.resets('matchOrders', env => { }); it('should correctly match one left order to two complementary right orders', async () => { const leftOrders = [ - await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(4, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressLeft, }), ]; const rightOrders = [ - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressRight, }), - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressRight, }), ]; const expectedTransferAmounts = [ @@ -3203,6 +2769,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }, { // Left Maker @@ -3214,6 +2782,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }, ]; await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync( @@ -3223,7 +2793,8 @@ blockchainTests.resets('matchOrders', env => { leftOrdersTakerAssetFilledAmounts: [ZERO], rightOrdersTakerAssetFilledAmounts: [ZERO, ZERO], }, - takerAddress, + matcher.address, + PROTOCOL_FEE.times(4), [[0, 0], [0, 1]], expectedTransferAmounts, false, @@ -3231,25 +2802,19 @@ blockchainTests.resets('matchOrders', env => { }); it('should correctly match one left order to two right orders, where the last should not be touched', async () => { const leftOrders = [ - await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(2, 0), takerAssetAmount: toBaseUnitAmount(1, 0), - feeRecipientAddress: feeRecipientAddressLeft, }), ]; const rightOrders = [ - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressRight, }), - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressRight, }), ]; const expectedTransferAmounts = [ @@ -3263,6 +2828,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }, ]; await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync( @@ -3272,7 +2839,8 @@ blockchainTests.resets('matchOrders', env => { leftOrdersTakerAssetFilledAmounts: [ZERO], rightOrdersTakerAssetFilledAmounts: [ZERO, ZERO], }, - takerAddress, + matcher.address, + PROTOCOL_FEE.times(2), [[0, 0]], expectedTransferAmounts, false, @@ -3280,31 +2848,23 @@ blockchainTests.resets('matchOrders', env => { }); it('should have three order matchings with only two left orders and two right orders', async () => { const leftOrders = [ - await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(4, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressLeft, }), - await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(2, 0), takerAssetAmount: toBaseUnitAmount(1, 0), - feeRecipientAddress: feeRecipientAddressLeft, }), ]; const rightOrders = [ - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressRight, }), - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(2, 0), takerAssetAmount: toBaseUnitAmount(4, 0), - feeRecipientAddress: feeRecipientAddressRight, }), ]; const expectedTransferAmounts = [ @@ -3318,6 +2878,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }, { // Left Maker @@ -3329,6 +2891,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }, { // Left Maker @@ -3340,6 +2904,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }, ]; await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync( @@ -3349,30 +2915,28 @@ blockchainTests.resets('matchOrders', env => { leftOrdersTakerAssetFilledAmounts: [ZERO, ZERO], rightOrdersTakerAssetFilledAmounts: [ZERO, ZERO], }, - takerAddress, + matcher.address, + PROTOCOL_FEE.times(6), [[0, 0], [0, 1], [1, 1]], expectedTransferAmounts, false, ); }); }); + describe('batchMatchOrdersWithMaximalFill', () => { it('should fully fill the the right order and pay the profit denominated in the left maker asset', async () => { // Create orders to match const leftOrders = [ - await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(17, 0), takerAssetAmount: toBaseUnitAmount(98, 0), - feeRecipientAddress: feeRecipientAddressLeft, }), ]; const rightOrders = [ - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(75, 0), takerAssetAmount: toBaseUnitAmount(13, 0), - feeRecipientAddress: feeRecipientAddressRight, }), ]; const expectedTransferAmounts = [ @@ -3386,6 +2950,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('76.5306122448979591'), 16), // 76.53% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }, ]; await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync( @@ -3395,7 +2961,8 @@ blockchainTests.resets('matchOrders', env => { leftOrdersTakerAssetFilledAmounts: [ZERO], rightOrdersTakerAssetFilledAmounts: [ZERO], }, - takerAddress, + matcher.address, + PROTOCOL_FEE.times(2), [[0, 0]], expectedTransferAmounts, true, @@ -3404,19 +2971,15 @@ blockchainTests.resets('matchOrders', env => { it('Should transfer correct amounts when left order is fully filled', async () => { // Create orders to match const leftOrders = [ - await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(15, 0), takerAssetAmount: toBaseUnitAmount(90, 0), - feeRecipientAddress: feeRecipientAddressLeft, }), ]; const rightOrders = [ - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(196, 0), takerAssetAmount: toBaseUnitAmount(28, 0), - feeRecipientAddress: feeRecipientAddressRight, }), ]; // Match signedOrderLeft with signedOrderRight @@ -3442,6 +3005,8 @@ blockchainTests.resets('matchOrders', env => { rightMakerAssetReceivedByTakerAmount: toBaseUnitAmount(15, 0), leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('53.5714285714285714'), 16), // 53.57% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }, ]; await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync( @@ -3451,7 +3016,8 @@ blockchainTests.resets('matchOrders', env => { leftOrdersTakerAssetFilledAmounts: [ZERO], rightOrdersTakerAssetFilledAmounts: [ZERO], }, - takerAddress, + matcher.address, + PROTOCOL_FEE.times(2), [[0, 0]], expectedTransferAmounts, true, @@ -3459,25 +3025,19 @@ blockchainTests.resets('matchOrders', env => { }); it('should correctly match one left order to two right orders, where the last should not be touched', async () => { const leftOrders = [ - await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(2, 0), takerAssetAmount: toBaseUnitAmount(1, 0), - feeRecipientAddress: feeRecipientAddressLeft, }), ]; const rightOrders = [ - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressRight, }), - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(1, 0), takerAssetAmount: toBaseUnitAmount(2, 0), - feeRecipientAddress: feeRecipientAddressRight, }), ]; const expectedTransferAmounts = [ @@ -3491,6 +3051,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }, ]; await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync( @@ -3500,7 +3062,8 @@ blockchainTests.resets('matchOrders', env => { leftOrdersTakerAssetFilledAmounts: [ZERO], rightOrdersTakerAssetFilledAmounts: [ZERO, ZERO], }, - takerAddress, + matcher.address, + PROTOCOL_FEE.times(2), [[0, 0]], expectedTransferAmounts, true, @@ -3508,31 +3071,23 @@ blockchainTests.resets('matchOrders', env => { }); it('should correctly fill all four orders in three matches', async () => { const leftOrders = [ - await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(2, 0), takerAssetAmount: toBaseUnitAmount(1, 0), - feeRecipientAddress: feeRecipientAddressLeft, }), - await orderFactoryLeft.newSignedOrderAsync({ - makerAddress: makerAddressLeft, + await makerLeft.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(72, 0), takerAssetAmount: toBaseUnitAmount(36, 0), - feeRecipientAddress: feeRecipientAddressLeft, }), ]; const rightOrders = [ - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(15, 0), takerAssetAmount: toBaseUnitAmount(30, 0), - feeRecipientAddress: feeRecipientAddressRight, }), - await orderFactoryRight.newSignedOrderAsync({ - makerAddress: makerAddressRight, + await makerRight.signOrderAsync({ makerAssetAmount: toBaseUnitAmount(22, 0), takerAssetAmount: toBaseUnitAmount(44, 0), - feeRecipientAddress: feeRecipientAddressRight, }), ]; const expectedTransferAmounts = [ @@ -3546,6 +3101,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('6.6666666666666666'), 16), // 6.66% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }, { // Left Maker @@ -3560,6 +3117,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('38.8888888888888888'), 16), // 38.88% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('93.3333333333333333'), 16), // 93.33% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }, { // Left Maker @@ -3571,6 +3130,8 @@ blockchainTests.resets('matchOrders', env => { // Taker leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('61.1111111111111111'), 16), // 61.11% rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100% + leftProtocolFeePaidByTakerAmount: PROTOCOL_FEE, + rightProtocolFeePaidByTakerAmount: PROTOCOL_FEE, }, ]; await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync( @@ -3580,13 +3141,13 @@ blockchainTests.resets('matchOrders', env => { leftOrdersTakerAssetFilledAmounts: [ZERO, ZERO], rightOrdersTakerAssetFilledAmounts: [ZERO, ZERO], }, - takerAddress, + matcher.address, + PROTOCOL_FEE.times(6), [[0, 0], [1, 0], [1, 1]], expectedTransferAmounts, true, ); }); }); - */ }); // tslint:disable-line:max-file-line-count diff --git a/contracts/integrations/test/utils/match_order_tester.ts b/contracts/integrations/test/utils/match_order_tester.ts index 184f448104..60100a21d4 100644 --- a/contracts/integrations/test/utils/match_order_tester.ts +++ b/contracts/integrations/test/utils/match_order_tester.ts @@ -1,9 +1,8 @@ -import { ERC1155ProxyWrapper, ERC20Wrapper, ERC721Wrapper } from '@0x/contracts-asset-proxy'; import { DevUtilsContract } from '@0x/contracts-dev-utils'; import { BlockchainBalanceStore, ExchangeContract, LocalBalanceStore } from '@0x/contracts-exchange'; -import { constants, ERC1155HoldingsByOwner, expect, OrderStatus } from '@0x/contracts-test-utils'; +import { constants, expect, OrderStatus } from '@0x/contracts-test-utils'; import { orderHashUtils } from '@0x/order-utils'; -import { AssetProxyId, BatchMatchedFillResults, FillResults, MatchedFillResults, SignedOrder } from '@0x/types'; +import { BatchMatchedFillResults, FillResults, MatchedFillResults, SignedOrder } from '@0x/types'; import { BigNumber } from '@0x/utils'; import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import * as _ from 'lodash'; @@ -12,13 +11,6 @@ import { DeploymentManager } from './deployment_manager'; const ZERO = new BigNumber(0); -export interface IndividualERC1155Holdings { - fungible: { - [tokenId: string]: BigNumber; - }; - nonFungible: BigNumber[]; -} - export interface FillEventArgs { orderHash: string; makerAddress: string; @@ -27,6 +19,7 @@ export interface FillEventArgs { takerAssetFilledAmount: BigNumber; makerFeePaid: BigNumber; takerFeePaid: BigNumber; + protocolFeePaid: BigNumber; } export interface MatchTransferAmounts { @@ -35,17 +28,18 @@ export interface MatchTransferAmounts { rightMakerAssetSoldByRightMakerAmount: BigNumber; // rightMakerAssetBoughtByLeftMakerAmount if omitted. rightMakerAssetBoughtByLeftMakerAmount: BigNumber; // rightMakerAssetSoldByRightMakerAmount if omitted. leftMakerAssetBoughtByRightMakerAmount: BigNumber; // leftMakerAssetSoldByLeftMakerAmount if omitted. - // Taker profit. leftMakerAssetReceivedByTakerAmount: BigNumber; // 0 if omitted. rightMakerAssetReceivedByTakerAmount: BigNumber; // 0 if omitted. - // Maker fees. leftMakerFeeAssetPaidByLeftMakerAmount: BigNumber; // 0 if omitted. rightMakerFeeAssetPaidByRightMakerAmount: BigNumber; // 0 if omitted. // Taker fees. leftTakerFeeAssetPaidByTakerAmount: BigNumber; // 0 if omitted. rightTakerFeeAssetPaidByTakerAmount: BigNumber; // 0 if omitted. + // Protocol fees. + leftProtocolFeePaidByTakerAmount: BigNumber; // 0 if omitted + rightProtocolFeePaidByTakerAmount: BigNumber; // 0 if omitted } export interface MatchResults { @@ -60,31 +54,6 @@ export interface BatchMatchResults { rightFilledResults: FillEventArgs[]; } -export interface ERC1155Holdings { - [owner: string]: { - [contract: string]: { - fungible: { - [tokenId: string]: BigNumber; - }; - nonFungible: BigNumber[]; - }; - }; -} - -export interface TokenBalances { - erc20: { - [owner: string]: { - [contract: string]: BigNumber; - }; - }; - erc721: { - [owner: string]: { - [contract: string]: BigNumber[]; - }; - }; - erc1155: ERC1155Holdings; -} - export interface BatchMatchedOrders { leftOrders: SignedOrder[]; rightOrders: SignedOrder[]; @@ -100,21 +69,18 @@ export interface MatchedOrders { } export class MatchOrderTester { - // FIXME - Should this be public - public deployment: DeploymentManager; - protected _devUtils: DevUtilsContract; + private readonly _devUtils: DevUtilsContract; + private readonly _deployment: DeploymentManager; private readonly _blockchainBalanceStore: BlockchainBalanceStore; - private readonly _localBalanceStore: LocalBalanceStore; constructor( deployment: DeploymentManager, devUtils: DevUtilsContract, blockchainBalanceStore: BlockchainBalanceStore, ) { - this.deployment = deployment; + this._deployment = deployment; this._devUtils = devUtils; this._blockchainBalanceStore = blockchainBalanceStore; - this._localBalanceStore = LocalBalanceStore.create(blockchainBalanceStore); } /** @@ -133,10 +99,10 @@ export class MatchOrderTester { public async batchMatchOrdersAndAssertEffectsAsync( orders: BatchMatchedOrders, takerAddress: string, + value: BigNumber, matchPairs: Array<[number, number]>, expectedTransferAmounts: Array>, withMaximalFill: boolean, - initialTokenBalances?: TokenBalances, ): Promise { // Ensure that the provided input is valid. expect(matchPairs.length).to.be.eq(expectedTransferAmounts.length); @@ -144,52 +110,56 @@ export class MatchOrderTester { expect(orders.rightOrders.length).to.be.eq(orders.rightOrdersTakerAssetFilledAmounts.length); // Ensure that the exchange is in the expected state. - await assertBatchOrderStatesAsync(orders, this.deployment.exchange); + await assertBatchOrderStatesAsync(orders, this._deployment.exchange); - // Get the token balances before executing `batchMatchOrders()`. + // Update the blockchain balance store and create a new local balance store + // with the same initial balances. await this._blockchainBalanceStore.updateBalancesAsync(); + const localBalanceStore = LocalBalanceStore.create(this._blockchainBalanceStore); // Execute `batchMatchOrders()` let actualBatchMatchResults; let transactionReceipt; if (withMaximalFill) { - actualBatchMatchResults = await this.deployment.exchange.batchMatchOrdersWithMaximalFill.callAsync( + actualBatchMatchResults = await this._deployment.exchange.batchMatchOrdersWithMaximalFill.callAsync( orders.leftOrders, orders.rightOrders, orders.leftOrders.map(order => order.signature), orders.rightOrders.map(order => order.signature), - { from: takerAddress }, + { from: takerAddress, gasPrice: constants.DEFAULT_GAS_PRICE, value }, ); - transactionReceipt = await this.deployment.exchange.batchMatchOrdersWithMaximalFill.awaitTransactionSuccessAsync( + transactionReceipt = await this._deployment.exchange.batchMatchOrdersWithMaximalFill.awaitTransactionSuccessAsync( orders.leftOrders, orders.rightOrders, orders.leftOrders.map(order => order.signature), orders.rightOrders.map(order => order.signature), - { from: takerAddress }, + { from: takerAddress, gasPrice: constants.DEFAULT_GAS_PRICE, value }, ); } else { - actualBatchMatchResults = await this.deployment.exchange.batchMatchOrders.callAsync( + actualBatchMatchResults = await this._deployment.exchange.batchMatchOrders.callAsync( orders.leftOrders, orders.rightOrders, orders.leftOrders.map(order => order.signature), orders.rightOrders.map(order => order.signature), - { from: takerAddress }, + { from: takerAddress, gasPrice: constants.DEFAULT_GAS_PRICE, value }, ); - transactionReceipt = await this.deployment.exchange.batchMatchOrders.awaitTransactionSuccessAsync( + transactionReceipt = await this._deployment.exchange.batchMatchOrders.awaitTransactionSuccessAsync( orders.leftOrders, orders.rightOrders, orders.leftOrders.map(order => order.signature), orders.rightOrders.map(order => order.signature), - { from: takerAddress }, + { from: takerAddress, gasPrice: constants.DEFAULT_GAS_PRICE, value }, ); } + localBalanceStore.burnGas(takerAddress, constants.DEFAULT_GAS_PRICE * transactionReceipt.gasUsed); // Simulate the batch order match. const expectedBatchMatchResults = await simulateBatchMatchOrdersAsync( orders, takerAddress, + this._deployment.staking.stakingProxy.address, this._blockchainBalanceStore, - this._localBalanceStore, + localBalanceStore, matchPairs, expectedTransferAmounts, this._devUtils, @@ -202,8 +172,8 @@ export class MatchOrderTester { expectedBatchMatchResults, transactionReceipt, this._blockchainBalanceStore, - this._localBalanceStore, - this.deployment.exchange, + localBalanceStore, + this._deployment.exchange, ); return expectedBatchMatchResults; } @@ -221,56 +191,63 @@ export class MatchOrderTester { */ public async matchOrdersAndAssertEffectsAsync( orders: MatchedOrders, - takerAddress: string, expectedTransferAmounts: Partial, + takerAddress: string, + value: BigNumber, withMaximalFill: boolean, - initialTokenBalances?: TokenBalances, ): Promise { - await assertInitialOrderStatesAsync(orders, this.deployment.exchange); + await assertInitialOrderStatesAsync(orders, this._deployment.exchange); + + // Update the blockchain balance store and create a new local balance store + // with the same initial balances. + await this._blockchainBalanceStore.updateBalancesAsync(); + const localBalanceStore = LocalBalanceStore.create(this._blockchainBalanceStore); // Execute `matchOrders()` let actualMatchResults; let transactionReceipt; if (withMaximalFill) { - actualMatchResults = await this.deployment.exchange.matchOrdersWithMaximalFill.callAsync( + actualMatchResults = await this._deployment.exchange.matchOrdersWithMaximalFill.callAsync( orders.leftOrder, orders.rightOrder, orders.leftOrder.signature, orders.rightOrder.signature, - { from: takerAddress }, + { from: takerAddress, gasPrice: constants.DEFAULT_GAS_PRICE, value }, ); - transactionReceipt = await this.deployment.exchange.matchOrdersWithMaximalFill.awaitTransactionSuccessAsync( + transactionReceipt = await this._deployment.exchange.matchOrdersWithMaximalFill.awaitTransactionSuccessAsync( orders.leftOrder, orders.rightOrder, orders.leftOrder.signature, orders.rightOrder.signature, - { from: takerAddress }, + { from: takerAddress, gasPrice: constants.DEFAULT_GAS_PRICE, value }, ); } else { - actualMatchResults = await this.deployment.exchange.matchOrders.callAsync( + actualMatchResults = await this._deployment.exchange.matchOrders.callAsync( orders.leftOrder, orders.rightOrder, orders.leftOrder.signature, orders.rightOrder.signature, - { from: takerAddress }, + { from: takerAddress, gasPrice: constants.DEFAULT_GAS_PRICE, value }, ); - transactionReceipt = await this.deployment.exchange.matchOrders.awaitTransactionSuccessAsync( + transactionReceipt = await this._deployment.exchange.matchOrders.awaitTransactionSuccessAsync( orders.leftOrder, orders.rightOrder, orders.leftOrder.signature, orders.rightOrder.signature, - { from: takerAddress }, + { from: takerAddress, gasPrice: constants.DEFAULT_GAS_PRICE, value }, ); } + localBalanceStore.burnGas(takerAddress, constants.DEFAULT_GAS_PRICE * transactionReceipt.gasUsed); // Simulate the fill. const expectedMatchResults = await simulateMatchOrdersAsync( orders, takerAddress, + this._deployment.staking.stakingProxy.address, this._blockchainBalanceStore, toFullMatchTransferAmounts(expectedTransferAmounts), this._devUtils, - this._localBalanceStore, + localBalanceStore, ); const expectedResults = convertToMatchResults(expectedMatchResults); expect(actualMatchResults).to.be.eql(expectedResults); @@ -279,9 +256,9 @@ export class MatchOrderTester { await assertMatchResultsAsync( expectedMatchResults, transactionReceipt, - this._localBalanceStore, + localBalanceStore, this._blockchainBalanceStore, - this.deployment.exchange, + this._deployment.exchange, ); return expectedMatchResults; } @@ -321,6 +298,10 @@ function toFullMatchTransferAmounts(partial: Partial): Mat partial.leftTakerFeeAssetPaidByTakerAmount || ZERO, rightTakerFeeAssetPaidByTakerAmount: partial.rightTakerFeeAssetPaidByTakerAmount || ZERO, + leftProtocolFeePaidByTakerAmount: + partial.leftProtocolFeePaidByTakerAmount || ZERO, + rightProtocolFeePaidByTakerAmount: + partial.rightProtocolFeePaidByTakerAmount || ZERO, }; } @@ -336,6 +317,7 @@ function toFullMatchTransferAmounts(partial: Partial): Mat async function simulateBatchMatchOrdersAsync( orders: BatchMatchedOrders, takerAddress: string, + stakingProxyAddress: string, blockchainBalanceStore: BlockchainBalanceStore, localBalanceStore: LocalBalanceStore, matchPairs: Array<[number, number]>, @@ -401,6 +383,7 @@ async function simulateBatchMatchOrdersAsync( await simulateMatchOrdersAsync( matchedOrders, takerAddress, + stakingProxyAddress, blockchainBalanceStore, toFullMatchTransferAmounts(transferAmounts[i]), devUtils, @@ -464,6 +447,7 @@ async function simulateBatchMatchOrdersAsync( async function simulateMatchOrdersAsync( orders: MatchedOrders, takerAddress: string, + stakingProxyAddress: string, blockchainBalanceStore: BlockchainBalanceStore, // FIXME - Is this right? transferAmounts: MatchTransferAmounts, devUtils: DevUtilsContract, @@ -485,6 +469,7 @@ async function simulateMatchOrdersAsync( }, fills: simulateFillEvents(orders, takerAddress, transferAmounts), }; + // Right maker asset -> left maker localBalanceStore.transferAsset( orders.rightOrder.makerAddress, @@ -492,6 +477,7 @@ async function simulateMatchOrdersAsync( transferAmounts.rightMakerAssetBoughtByLeftMakerAmount, orders.rightOrder.makerAssetData, ); + // FIXME - Is this a necessary condition? if (orders.leftOrder.makerAddress !== orders.leftOrder.feeRecipientAddress) { // Left maker fees @@ -502,6 +488,8 @@ async function simulateMatchOrdersAsync( orders.leftOrder.makerFeeAssetData, ); } + + // FIXME - Is this a necessary condition? // Left maker asset -> right maker localBalanceStore.transferAsset( orders.leftOrder.makerAddress, @@ -509,6 +497,7 @@ async function simulateMatchOrdersAsync( transferAmounts.leftMakerAssetBoughtByRightMakerAmount, orders.leftOrder.makerAssetData, ); + // FIXME - Is this a necessary condition? if (orders.rightOrder.makerAddress !== orders.rightOrder.feeRecipientAddress) { // Right maker fees @@ -519,6 +508,7 @@ async function simulateMatchOrdersAsync( orders.rightOrder.makerFeeAssetData, ); } + // Left taker profit localBalanceStore.transferAsset( orders.leftOrder.makerAddress, @@ -526,6 +516,7 @@ async function simulateMatchOrdersAsync( transferAmounts.leftMakerAssetReceivedByTakerAmount, orders.leftOrder.makerAssetData, ); + // Right taker profit localBalanceStore.transferAsset( orders.rightOrder.makerAddress, @@ -533,6 +524,7 @@ async function simulateMatchOrdersAsync( transferAmounts.rightMakerAssetReceivedByTakerAmount, orders.rightOrder.makerAssetData, ); + // Left taker fees localBalanceStore.transferAsset( takerAddress, @@ -540,6 +532,7 @@ async function simulateMatchOrdersAsync( transferAmounts.leftTakerFeeAssetPaidByTakerAmount, orders.leftOrder.takerFeeAssetData, ); + // Right taker fees localBalanceStore.transferAsset( takerAddress, @@ -548,6 +541,13 @@ async function simulateMatchOrdersAsync( orders.rightOrder.takerFeeAssetData, ); + // Protocol Fee + localBalanceStore.sendEth( + takerAddress, + stakingProxyAddress, + transferAmounts.leftProtocolFeePaidByTakerAmount.plus(transferAmounts.rightProtocolFeePaidByTakerAmount), + ); + return matchResults; } @@ -574,6 +574,9 @@ async function assertBatchMatchResultsAsync( transactionReceipt, ); + // Update the blockchain balance store balances. + await blockchainBalanceStore.updateBalancesAsync(); + // Ensure that the actual and expected token balances are equivalent. localBalanceStore.assertEquals(blockchainBalanceStore); @@ -598,6 +601,9 @@ async function assertMatchResultsAsync( // Check the fill events. assertFillEvents(matchResults.fills, transactionReceipt); + // Update the blockchain balance store balances. + await blockchainBalanceStore.updateBalancesAsync(); + // Check the token balances. localBalanceStore.assertEquals(blockchainBalanceStore); @@ -654,6 +660,7 @@ function simulateFillEvents( takerAssetFilledAmount: transferAmounts.rightMakerAssetBoughtByLeftMakerAmount, makerFeePaid: transferAmounts.leftMakerFeeAssetPaidByLeftMakerAmount, takerFeePaid: transferAmounts.leftTakerFeeAssetPaidByTakerAmount, + protocolFeePaid: transferAmounts.leftProtocolFeePaidByTakerAmount, }, // Right order Fill { @@ -664,10 +671,12 @@ function simulateFillEvents( takerAssetFilledAmount: transferAmounts.leftMakerAssetBoughtByRightMakerAmount, makerFeePaid: transferAmounts.rightMakerFeeAssetPaidByRightMakerAmount, takerFeePaid: transferAmounts.rightTakerFeeAssetPaidByTakerAmount, + protocolFeePaid: transferAmounts.rightProtocolFeePaidByTakerAmount, }, ]; } +// FIXME - Refactor this to use filterToLogsArguments /** * Extract `Fill` events from a transaction receipt. */ @@ -680,6 +689,7 @@ function extractFillEventsfromReceipt(receipt: TransactionReceiptWithDecodedLogs takerAssetFilledAmount: string; makerFeePaid: string; takerFeePaid: string; + protocolFeePaid: string; } const actualFills = (_.filter(receipt.logs, ['event', 'Fill']) as any) as Array< LogWithDecodedArgs @@ -693,18 +703,10 @@ function extractFillEventsfromReceipt(receipt: TransactionReceiptWithDecodedLogs takerAssetFilledAmount: new BigNumber(fill.args.takerAssetFilledAmount), makerFeePaid: new BigNumber(fill.args.makerFeePaid), takerFeePaid: new BigNumber(fill.args.takerFeePaid), + protocolFeePaid: new BigNumber(fill.args.protocolFeePaid), })); } -/** - * Asserts that all expected token holdings match the actual holdings. - * @param expectedBalances Expected balances. - * @param actualBalances Actual balances. - */ -function assertBalances(expectedBalances: TokenBalances, actualBalances: TokenBalances): void { - expect(encodeTokenBalances(actualBalances)).to.deep.equal(encodeTokenBalances(expectedBalances)); -} - /** * Asserts the initial exchange state for batch matched orders. * @param orders Batch matched orders with intial filled amounts. @@ -819,64 +821,6 @@ async function assertOrderFilledAmountAsync( expect(actualStatus, `${side} order final status`).to.equal(expectedStatus); } -/** - * Retrieve the current token balances of all known addresses. - * @param erc20Wrapper The ERC20Wrapper instance. - * @param erc721Wrapper The ERC721Wrapper instance. - * @param erc1155Wrapper The ERC1155ProxyWrapper instance. - * @return A promise that resolves to a `TokenBalances`. - */ -export async function getTokenBalancesAsync( - erc20Wrapper: ERC20Wrapper, - erc721Wrapper: ERC721Wrapper, - erc1155ProxyWrapper: ERC1155ProxyWrapper, -): Promise { - const [erc20, erc721, erc1155] = await Promise.all([ - erc20Wrapper.getBalancesAsync(), - erc721Wrapper.getBalancesAsync(), - erc1155ProxyWrapper.getBalancesAsync(), - ]); - return { - erc20, - erc721, - erc1155: transformERC1155Holdings(erc1155), - }; -} - -/** - * Restructures `ERC1155HoldingsByOwner` to be compatible with `TokenBalances.erc1155`. - * @param erc1155HoldingsByOwner Holdings returned by `ERC1155ProxyWrapper.getBalancesAsync()`. - */ -function transformERC1155Holdings(erc1155HoldingsByOwner: ERC1155HoldingsByOwner): ERC1155Holdings { - const result = {}; - for (const owner of _.keys(erc1155HoldingsByOwner.fungible)) { - for (const contract of _.keys(erc1155HoldingsByOwner.fungible[owner])) { - _.set(result as any, [owner, contract, 'fungible'], erc1155HoldingsByOwner.fungible[owner][contract]); - } - } - for (const owner of _.keys(erc1155HoldingsByOwner.nonFungible)) { - for (const contract of _.keys(erc1155HoldingsByOwner.nonFungible[owner])) { - const tokenIds = _.flatten(_.values(erc1155HoldingsByOwner.nonFungible[owner][contract])); - _.set(result as any, [owner, contract, 'nonFungible'], _.uniqBy(tokenIds, v => v.toString(10))); - } - } - return result; -} - -function encodeTokenBalances(obj: any): any { - if (!_.isPlainObject(obj)) { - if (BigNumber.isBigNumber(obj)) { - return obj.toString(10); - } - if (_.isArray(obj)) { - return _.sortBy(obj, v => encodeTokenBalances(v)); - } - return obj; - } - const keys = _.keys(obj).sort(); - return _.zip(keys, keys.map(k => encodeTokenBalances(obj[k]))); -} - /** * Gets the last match in a BatchMatchResults object. * @param batchMatchResults The BatchMatchResults object. @@ -886,6 +830,7 @@ function getLastMatch(batchMatchResults: BatchMatchResults): MatchResults { return batchMatchResults.matches[batchMatchResults.matches.length - 1]; } +// FIXME - This can probably be removed in favor of the reference functions. /** * Add a new fill results object to a total fill results object destructively. * @param total The total fill results that should be updated. @@ -901,81 +846,7 @@ function addFillResults(total: FillEventArgs, fill: FillEventArgs): void { total.takerAssetFilledAmount = total.takerAssetFilledAmount.plus(fill.takerAssetFilledAmount); total.makerFeePaid = total.makerFeePaid.plus(fill.makerFeePaid); total.takerFeePaid = total.takerFeePaid.plus(fill.takerFeePaid); -} - -/** - * Takes a `totalBalances`, a `balances`, and an `initialBalances`, subtracts the `initialBalances - * from the `balances`, and then adds the result to `totalBalances`. - * @param totalBalances A set of balances to be updated with new results. - * @param balances A new set of results that deviate from the `initialBalances` by one matched - * order. Subtracting away the `initialBalances` leaves behind a diff of the - * matched orders effect on the `initialBalances`. - * @param initialBalances The token balances from before the call to `batchMatchOrders()`. - * @return The updated total balances using the derived balance difference. - */ -function aggregateBalances( - totalBalances: TokenBalances, - balances: TokenBalances, - initialBalances: TokenBalances, -): TokenBalances { - // ERC20 - for (const owner of _.keys(totalBalances.erc20)) { - for (const contract of _.keys(totalBalances.erc20[owner])) { - const difference = balances.erc20[owner][contract].minus(initialBalances.erc20[owner][contract]); - totalBalances.erc20[owner][contract] = totalBalances.erc20[owner][contract].plus(difference); - } - } - // ERC721 - for (const owner of _.keys(totalBalances.erc721)) { - for (const contract of _.keys(totalBalances.erc721[owner])) { - totalBalances.erc721[owner][contract] = _.zipWith( - totalBalances.erc721[owner][contract], - balances.erc721[owner][contract], - initialBalances.erc721[owner][contract], - (a: BigNumber, b: BigNumber, c: BigNumber) => a.plus(b.minus(c)), - ); - } - } - // ERC1155 - for (const owner of _.keys(totalBalances.erc1155)) { - for (const contract of _.keys(totalBalances.erc1155[owner])) { - // Fungible - for (const tokenId of _.keys(totalBalances.erc1155[owner][contract].fungible)) { - const difference = balances.erc1155[owner][contract].fungible[tokenId].minus( - initialBalances.erc1155[owner][contract].fungible[tokenId], - ); - totalBalances.erc1155[owner][contract].fungible[tokenId] = totalBalances.erc1155[owner][ - contract - ].fungible[tokenId].plus(difference); - } - - // Nonfungible - let isDuplicate = false; - for (const value of balances.erc1155[owner][contract].nonFungible) { - // If the value is in the initial balances or the total balances, skip the - // value since it will already be added. - for (const val of totalBalances.erc1155[owner][contract].nonFungible) { - if (value.isEqualTo(val)) { - isDuplicate = true; - } - } - - if (!isDuplicate) { - for (const val of initialBalances.erc1155[owner][contract].nonFungible) { - if (value.isEqualTo(val)) { - isDuplicate = true; - } - } - } - - if (!isDuplicate) { - totalBalances.erc1155[owner][contract].nonFungible.push(value); - } - isDuplicate = false; - } - } - } - return totalBalances; + total.protocolFeePaid = total.protocolFeePaid.plus(fill.protocolFeePaid); } /** @@ -1042,14 +913,14 @@ function convertToMatchResults(result: MatchResults): MatchedFillResults { takerAssetFilledAmount: result.fills[0].takerAssetFilledAmount, makerFeePaid: result.fills[0].makerFeePaid, takerFeePaid: result.fills[0].takerFeePaid, - protocolFeePaid: constants.ZERO_AMOUNT, + protocolFeePaid: result.fills[0].protocolFeePaid, }, right: { makerAssetFilledAmount: result.fills[1].makerAssetFilledAmount, takerAssetFilledAmount: result.fills[1].takerAssetFilledAmount, makerFeePaid: result.fills[1].makerFeePaid, takerFeePaid: result.fills[1].takerFeePaid, - protocolFeePaid: constants.ZERO_AMOUNT, + protocolFeePaid: result.fills[1].protocolFeePaid, }, profitInLeftMakerAsset, profitInRightMakerAsset, @@ -1068,7 +939,7 @@ function convertToFillResults(result: FillEventArgs): FillResults { takerAssetFilledAmount: result.takerAssetFilledAmount, makerFeePaid: result.makerFeePaid, takerFeePaid: result.takerFeePaid, - protocolFeePaid: constants.ZERO_AMOUNT, + protocolFeePaid: result.protocolFeePaid, }; return fillResults; } @@ -1082,10 +953,11 @@ function emptyFillEventArgs(): FillEventArgs { orderHash: '', makerAddress: '', takerAddress: '', - makerAssetFilledAmount: new BigNumber(0), - takerAssetFilledAmount: new BigNumber(0), - makerFeePaid: new BigNumber(0), - takerFeePaid: new BigNumber(0), + makerAssetFilledAmount: constants.ZERO_AMOUNT, + takerAssetFilledAmount: constants.ZERO_AMOUNT, + makerFeePaid: constants.ZERO_AMOUNT, + takerFeePaid: constants.ZERO_AMOUNT, + protocolFeePaid: constants.ZERO_AMOUNT, }; return empty; } diff --git a/contracts/staking/test/utils/number_utils.ts b/contracts/staking/test/utils/number_utils.ts index a404030f1c..0b76e2eb0d 100644 --- a/contracts/staking/test/utils/number_utils.ts +++ b/contracts/staking/test/utils/number_utils.ts @@ -110,6 +110,7 @@ export function assertIntegerRoughlyEquals(actual: Numberish, expected: Numberis */ export function toBaseUnitAmount(amount: Numberish, decimals?: number): BigNumber { const amountAsBigNumber = new BigNumber(amount); - const baseUnitAmount = Web3Wrapper.toBaseUnitAmount(amountAsBigNumber, decimals || 18); + const baseDecimals = decimals !== undefined ? decimals : 18; + const baseUnitAmount = Web3Wrapper.toBaseUnitAmount(amountAsBigNumber, baseDecimals); return baseUnitAmount; }