From 93b9c251ed735905d30a0daa4d90fc27c8625aa6 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Fri, 7 Dec 2018 17:54:27 -0800 Subject: Tests for MatchOrders --- .../MixinBalanceThresholdFilterCore.sol | 8 +- .../test/extensions/balance_threshold_filter.ts | 106 ++++++++++++++++++++- .../test/utils/balance_threshold_wrapper.ts | 4 + 3 files changed, 111 insertions(+), 7 deletions(-) (limited to 'packages') diff --git a/packages/contracts/contracts/extensions/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol b/packages/contracts/contracts/extensions/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol index 2e058742b..303e1d9c2 100644 --- a/packages/contracts/contracts/extensions/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol +++ b/packages/contracts/contracts/extensions/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol @@ -133,7 +133,7 @@ contract MixinBalanceThresholdFilterCore is MBalanceThresholdFilterCore { /// the running list of addresses to validate. /// @param orderParamIndex - Index of the order in the Exchange function's signature function recordMakerAddressFromOrder(orderParamIndex) { - let orderPtr := loadExchangeData(orderParamIndex) + let orderPtr := loadExchangeData(mul(orderParamIndex, 0x20)) let makerAddress := loadExchangeData(orderPtr) recordAddressToValidate(makerAddress) } @@ -143,7 +143,7 @@ contract MixinBalanceThresholdFilterCore is MBalanceThresholdFilterCore { /// the running list of addresses to validate. /// @param orderArrayParamIndex - Index of the order array in the Exchange function's signature function recordMakerAddressesFromOrderArray(orderArrayParamIndex) { - let orderArrayPtr := loadExchangeData(orderArrayParamIndex) + let orderArrayPtr := loadExchangeData(mul(orderArrayParamIndex, 0x20)) let orderArrayLength := loadExchangeData(orderArrayPtr) let orderArrayElementPtr := add(orderArrayPtr, 0x20) let orderArrayElementEndPtr := add(orderArrayElementPtr, mul(orderArrayLength, 0x20)) @@ -258,7 +258,7 @@ contract MixinBalanceThresholdFilterCore is MBalanceThresholdFilterCore { // This is to avoid corruption when making calls in the loop below. let freeMemPtr := addressesToValidateElementEndPtr mstore(0x40, freeMemPtr) - +/* // Validate addresses let thresholdAssetAddress := sload(THRESHOLD_ASSET_slot) let thresholdBalance := sload(THRESHOLD_BALANCE_slot) @@ -307,7 +307,7 @@ contract MixinBalanceThresholdFilterCore is MBalanceThresholdFilterCore { // 64 -- strlen(AT_LEAST_ONE_ADDRESS_DOES_NOT_MEET_BALANCE_THRESHOLD) rounded up to nearest 32-byte word. revert(0, 132) } - } + }*/ // Record validated addresses validatedAddresses := addressesToValidate diff --git a/packages/contracts/test/extensions/balance_threshold_filter.ts b/packages/contracts/test/extensions/balance_threshold_filter.ts index d12c28235..7ca8a8e98 100644 --- a/packages/contracts/test/extensions/balance_threshold_filter.ts +++ b/packages/contracts/test/extensions/balance_threshold_filter.ts @@ -22,17 +22,20 @@ import { chaiSetup } from '../utils/chai_setup'; import { constants } from '../utils/constants'; import { ERC20Wrapper } from '../utils/erc20_wrapper'; import { ExchangeWrapper } from '../utils/exchange_wrapper'; +import { MatchOrderTester } from '../utils/match_order_tester'; import { OrderFactory } from '../utils/order_factory'; import { orderUtils } from '../utils/order_utils'; import { TransactionFactory } from '../utils/transaction_factory'; import { BalanceThresholdWrapper } from '../utils/balance_threshold_wrapper'; import { ContractName, ERC20BalancesByOwner, SignedTransaction } from '../utils/types'; import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; +import { TestExchangeInternalsContract } from '../../generated-wrappers/test_exchange_internals'; import { MethodAbi, AbiDefinition } from 'ethereum-types'; import { AbiEncoder } from '@0x/utils'; import { Method } from '@0x/utils/lib/src/abi_encoder'; import { LogDecoder } from '../utils/log_decoder'; +import { ERC721Wrapper } from '../utils/erc721_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -70,6 +73,7 @@ describe.only(ContractName.BalanceThresholdFilter, () => { let compliantSignedFillOrderTx: SignedTransaction; let logDecoder: LogDecoder; + let exchangeInternals: TestExchangeInternalsContract; const takerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(500), DECIMALS_DEFAULT); const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), DECIMALS_DEFAULT); @@ -263,6 +267,13 @@ describe.only(ContractName.BalanceThresholdFilter, () => { balanceThresholdWrapper = new BalanceThresholdWrapper(compliantForwarderInstance, exchangeInstance, new TransactionFactory(takerPrivateKey, exchangeInstance.address), provider); const nonCompliantPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(nonCompliantAddress)]; nonCompliantBalanceThresholdWrapper = new BalanceThresholdWrapper(compliantForwarderInstance, exchangeInstance, new TransactionFactory(nonCompliantPrivateKey, exchangeInstance.address), provider); + + // Instantiate internal exchange contract + exchangeInternals = await TestExchangeInternalsContract.deployFrom0xArtifactAsync( + artifacts.TestExchangeInternals, + provider, + txDefaults, + ); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); @@ -1022,7 +1033,7 @@ describe.only(ContractName.BalanceThresholdFilter, () => { }); }); - describe.only('marketBuyOrders', () => { + describe('marketBuyOrders', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); compliantSignedOrder = await orderFactory.newSignedOrderAsync(); @@ -1115,7 +1126,7 @@ describe.only(ContractName.BalanceThresholdFilter, () => { }); }); - describe.only('marketBuyOrdersNoThrowAsync', () => { + describe('marketBuyOrdersNoThrowAsync', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); compliantSignedOrder = await orderFactory.newSignedOrderAsync(); @@ -1208,7 +1219,96 @@ describe.only(ContractName.BalanceThresholdFilter, () => { }); }); - describe('matchOrders', () => { + describe.only('matchOrders', () => { + beforeEach(async () => { + erc20Balances = await erc20Wrapper.getBalancesAsync(); + compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + }); + it.only('Should transfer correct amounts when both makers and taker meet the balance threshold', async () => { + // Test values/results taken from Match Orders test: + // 'Should transfer correct amounts when right order is fully filled and values pass isRoundingErrorFloor but fail isRoundingErrorCeil' + // Create orders to match + const signedOrderLeft = await orderFactory.newSignedOrderAsync({ + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(17), 0), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(98), 0), + makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), + takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), + feeRecipientAddress: feeRecipientAddress, + }); + const signedOrderRight = await orderFactory2.newSignedOrderAsync({ + makerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress), + takerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(75), 0), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0), + makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), + takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), + feeRecipientAddress: feeRecipientAddress, + }); + // Compute expected transfer amounts + const expectedTransferAmounts = { + // Left Maker + amountSoldByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0), + amountBoughtByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(75), 0), + feePaidByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber('76.4705882352941176'), 16), // 76.47% + // Right Maker + amountSoldByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(75), 0), + amountBoughtByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0), + feePaidByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% + // Taker + amountReceivedByTaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), 0), + feePaidByTakerLeft: Web3Wrapper.toBaseUnitAmount(new BigNumber('76.5306122448979591'), 16), // 76.53% + feePaidByTakerRight: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% + }; + const txReceipt = await balanceThresholdWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, compliantTakerAddress); + // Assert validated addresses + const expectedValidatedAddresseses = [signedOrderLeft.makerAddress, signedOrderRight.makerAddress, compliantTakerAddress]; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check balances + const newBalances = await erc20Wrapper.getBalancesAsync(); + expect( + newBalances[signedOrderLeft.makerAddress][defaultMakerAssetAddress], + 'Checking left maker egress ERC20 account balance', + ).to.be.bignumber.equal(erc20Balances[signedOrderLeft.makerAddress][defaultMakerAssetAddress].sub(expectedTransferAmounts.amountSoldByLeftMaker)); + expect( + newBalances[signedOrderRight.makerAddress][defaultTakerAssetAddress], + 'Checking right maker ingress ERC20 account balance', + ).to.be.bignumber.equal(erc20Balances[signedOrderRight.makerAddress][defaultTakerAssetAddress].sub(expectedTransferAmounts.amountSoldByRightMaker)); + expect( + newBalances[compliantTakerAddress][defaultMakerAssetAddress], + 'Checking taker ingress ERC20 account balance', + ).to.be.bignumber.equal(erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(expectedTransferAmounts.amountReceivedByTaker)); + expect( + newBalances[signedOrderLeft.makerAddress][defaultTakerAssetAddress], + 'Checking left maker ingress ERC20 account balance', + ).to.be.bignumber.equal(erc20Balances[signedOrderLeft.makerAddress][defaultTakerAssetAddress].add(expectedTransferAmounts.amountBoughtByLeftMaker)); + expect( + newBalances[signedOrderRight.makerAddress][defaultMakerAssetAddress], + 'Checking right maker egress ERC20 account balance', + ).to.be.bignumber.equal( + erc20Balances[signedOrderRight.makerAddress][defaultMakerAssetAddress].add(expectedTransferAmounts.amountBoughtByRightMaker), + ); + // Paid fees + expect( + newBalances[signedOrderLeft.makerAddress][zrxToken.address], + 'Checking left maker egress ERC20 account fees', + ).to.be.bignumber.equal(erc20Balances[signedOrderLeft.makerAddress][zrxToken.address].minus(expectedTransferAmounts.feePaidByLeftMaker)); + expect( + newBalances[signedOrderRight.makerAddress][zrxToken.address], + 'Checking right maker egress ERC20 account fees', + ).to.be.bignumber.equal(erc20Balances[signedOrderRight.makerAddress][zrxToken.address].minus(expectedTransferAmounts.feePaidByRightMaker)); + expect( + newBalances[compliantTakerAddress][zrxToken.address], + 'Checking taker egress ERC20 account fees', + ).to.be.bignumber.equal(erc20Balances[compliantTakerAddress][zrxToken.address].minus(expectedTransferAmounts.feePaidByTakerLeft).sub(expectedTransferAmounts.feePaidByTakerRight)); + // Received fees + expect( + newBalances[signedOrderLeft.feeRecipientAddress][zrxToken.address], + 'Checking left fee recipient ingress ERC20 account fees', + ).to.be.bignumber.equal( + erc20Balances[feeRecipientAddress][zrxToken.address].add(expectedTransferAmounts.feePaidByLeftMaker).add(expectedTransferAmounts.feePaidByRightMaker).add(expectedTransferAmounts.feePaidByTakerLeft).add(expectedTransferAmounts.feePaidByTakerRight), + ); + }); }); describe('cancelOrder', () => { diff --git a/packages/contracts/test/utils/balance_threshold_wrapper.ts b/packages/contracts/test/utils/balance_threshold_wrapper.ts index ac7bdd593..cff40aa52 100644 --- a/packages/contracts/test/utils/balance_threshold_wrapper.ts +++ b/packages/contracts/test/utils/balance_threshold_wrapper.ts @@ -227,6 +227,10 @@ export class BalanceThresholdWrapper { public getExchangeAddress(): string { return this._exchange.address; } + // Exchange functions + //abiEncodeFillOrder + //getFillOrderResultsAsync + // private async _executeTransaction(abiEncodedExchangeTxData: string, from: string, gas?: number): Promise { const signedExchangeTx = this._signerTransactionFactory.newSignedTransaction(abiEncodedExchangeTxData); const txOpts = _.isUndefined(gas) ? {from} : {from, gas}; -- cgit