diff options
Diffstat (limited to 'packages/contract-wrappers/test')
18 files changed, 505 insertions, 280 deletions
diff --git a/packages/contract-wrappers/test/artifacts_test.ts b/packages/contract-wrappers/test/artifacts_test.ts deleted file mode 100644 index c05d513b3..000000000 --- a/packages/contract-wrappers/test/artifacts_test.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { web3Factory } from '@0xproject/dev-utils'; - -import { ContractWrappers } from '../src'; - -import { chaiSetup } from './utils/chai_setup'; -import { constants } from './utils/constants'; - -chaiSetup.configure(); - -// Those tests are slower cause they're talking to a remote node -const TIMEOUT = 10000; - -// TODO: Re-enable those tests after final kovan and ropsten deployments are done. -describe.skip('Artifacts', () => { - describe('contracts are deployed on kovan', () => { - const kovanRpcUrl = constants.KOVAN_RPC_URL; - const provider = web3Factory.getRpcProvider({ rpcUrl: kovanRpcUrl }); - const config = { - networkId: constants.KOVAN_NETWORK_ID, - }; - const contractWrappers = new ContractWrappers(provider, config); - it('erc20 proxy contract is deployed', async () => { - await (contractWrappers.erc20Proxy as any)._getTokenTransferProxyContractAsync(); - }).timeout(TIMEOUT); - it('erc721 proxy contract is deployed', async () => { - await (contractWrappers.erc721Proxy as any)._getTokenTransferProxyContractAsync(); - }).timeout(TIMEOUT); - }); - describe('contracts are deployed on ropsten', () => { - const ropstenRpcUrl = constants.ROPSTEN_RPC_URL; - const provider = web3Factory.getRpcProvider({ rpcUrl: ropstenRpcUrl }); - const config = { - networkId: constants.ROPSTEN_NETWORK_ID, - }; - const contractWrappers = new ContractWrappers(provider, config); - it('erc20 proxy contract is deployed', async () => { - await (contractWrappers.erc20Proxy as any)._getTokenTransferProxyContractAsync(); - }).timeout(TIMEOUT); - it('erc721 proxy contract is deployed', async () => { - await (contractWrappers.erc721Proxy as any)._getTokenTransferProxyContractAsync(); - }).timeout(TIMEOUT); - }); -}); diff --git a/packages/contract-wrappers/test/calldata_optimization_utils_test.ts b/packages/contract-wrappers/test/calldata_optimization_utils_test.ts index a4cea772f..6cb8a669e 100644 --- a/packages/contract-wrappers/test/calldata_optimization_utils_test.ts +++ b/packages/contract-wrappers/test/calldata_optimization_utils_test.ts @@ -1,9 +1,8 @@ -import { orderFactory } from '@0xproject/order-utils'; +import { orderFactory } from '@0x/order-utils/lib/src/order_factory'; import * as chai from 'chai'; import * as _ from 'lodash'; import 'mocha'; -import { assert } from '../src/utils/assert'; import { calldataOptimizationUtils } from '../src/utils/calldata_optimization_utils'; import { constants } from '../src/utils/constants'; diff --git a/packages/contract-wrappers/test/erc20_proxy_wrapper_test.ts b/packages/contract-wrappers/test/erc20_proxy_wrapper_test.ts index 6bf9f1e25..d8dfa4204 100644 --- a/packages/contract-wrappers/test/erc20_proxy_wrapper_test.ts +++ b/packages/contract-wrappers/test/erc20_proxy_wrapper_test.ts @@ -4,6 +4,7 @@ import { ContractWrappers } from '../src'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; +import { migrateOnceAsync } from './utils/migrate'; import { provider } from './utils/web3_wrapper'; chaiSetup.configure(); @@ -11,10 +12,13 @@ const expect = chai.expect; describe('ERC20ProxyWrapper', () => { let contractWrappers: ContractWrappers; - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - }; before(async () => { + const contractAddresses = await migrateOnceAsync(); + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + blockPollingIntervalMs: 10, + }; contractWrappers = new ContractWrappers(provider, config); }); describe('#isAuthorizedAsync', () => { diff --git a/packages/contract-wrappers/test/erc20_wrapper_test.ts b/packages/contract-wrappers/test/erc20_wrapper_test.ts index cf7ac527e..15d3a9ead 100644 --- a/packages/contract-wrappers/test/erc20_wrapper_test.ts +++ b/packages/contract-wrappers/test/erc20_wrapper_test.ts @@ -1,7 +1,8 @@ -import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils'; -import { EmptyWalletSubprovider, Web3ProviderEngine } from '@0xproject/subproviders'; -import { DoneCallback } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +import { ContractAddresses } from '@0x/contract-addresses'; +import { BlockchainLifecycle, callbackErrorReporter } from '@0x/dev-utils'; +import { EmptyWalletSubprovider, Web3ProviderEngine } from '@0x/subproviders'; +import { DoneCallback } from '@0x/types'; +import { BigNumber } from '@0x/utils'; import * as chai from 'chai'; import { Provider } from 'ethereum-types'; import 'mocha'; @@ -10,6 +11,7 @@ import { BlockParamLiteral, BlockRange, ContractWrappers, + ContractWrappersConfig, ContractWrappersError, DecodedLogEvent, ERC20TokenApprovalEventArgs, @@ -19,6 +21,7 @@ import { import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; +import { migrateOnceAsync } from './utils/migrate'; import { tokenUtils } from './utils/token_utils'; import { provider, web3Wrapper } from './utils/web3_wrapper'; @@ -28,14 +31,20 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('ERC20Wrapper', () => { let contractWrappers: ContractWrappers; + let contractAddresses: ContractAddresses; let userAddresses: string[]; let tokens: string[]; let coinbase: string; let addressWithoutFunds: string; - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - }; + let config: ContractWrappersConfig; + before(async () => { + contractAddresses = await migrateOnceAsync(); + config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + blockPollingIntervalMs: 10, + }; contractWrappers = new ContractWrappers(provider, config); userAddresses = await web3Wrapper.getAvailableAddressesAsync(); tokens = tokenUtils.getDummyERC20TokenAddresses(); @@ -71,19 +80,6 @@ describe('ERC20Wrapper', () => { contractWrappers.erc20Token.transferAsync(tokenAddress, fromAddress, toAddress, transferAmount), ).to.be.rejectedWith(ContractWrappersError.InsufficientBalanceForTransfer); }); - it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => { - const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065'; - const fromAddress = coinbase; - const toAddress = coinbase; - return expect( - contractWrappers.erc20Token.transferAsync( - nonExistentTokenAddress, - fromAddress, - toAddress, - transferAmount, - ), - ).to.be.rejectedWith(ContractWrappersError.ERC20TokenContractDoesNotExist); - }); }); describe('#transferFromAsync', () => { let tokenAddress: string; @@ -188,19 +184,6 @@ describe('ERC20Wrapper', () => { const postBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, toAddress); return expect(postBalance).to.be.bignumber.equal(transferAmount); }); - it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => { - const fromAddress = coinbase; - const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065'; - return expect( - contractWrappers.erc20Token.transferFromAsync( - nonExistentTokenAddress, - fromAddress, - toAddress, - senderAddress, - new BigNumber(42), - ), - ).to.be.rejectedWith(ContractWrappersError.ERC20TokenContractDoesNotExist); - }); }); describe('#getBalanceAsync', () => { describe('With provider with accounts', () => { @@ -211,13 +194,6 @@ describe('ERC20Wrapper', () => { const expectedBalance = new BigNumber('1000000000000000000000000000'); return expect(balance).to.be.bignumber.equal(expectedBalance); }); - it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => { - const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065'; - const ownerAddress = coinbase; - return expect( - contractWrappers.erc20Token.getBalanceAsync(nonExistentTokenAddress, ownerAddress), - ).to.be.rejectedWith(ContractWrappersError.ERC20TokenContractDoesNotExist); - }); it('should return a balance of 0 for a non-existent owner address', async () => { const tokenAddress = tokens[0]; const nonExistentOwner = '0x198c6ad858f213fb31b6fe809e25040e6b964593'; @@ -293,7 +269,7 @@ describe('ERC20Wrapper', () => { }); it('should reduce the gas cost for transfers including tokens with unlimited allowance support', async () => { const transferAmount = new BigNumber(5); - const zrxAddress = tokenUtils.getProtocolTokenAddress(); + const zrxAddress = contractAddresses.zrxToken; const [, userWithNormalAllowance, userWithUnlimitedAllowance] = userAddresses; await contractWrappers.erc20Token.setAllowanceAsync( zrxAddress, @@ -524,7 +500,7 @@ describe('ERC20Wrapper', () => { ); })().catch(done); }); - it('Outstanding subscriptions are cancelled when contractWrappers.setProvider called', (done: DoneCallback) => { + it('Outstanding subscriptions are cancelled when contractWrappers.unsubscribeAll called', (done: DoneCallback) => { (async () => { const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( (_logEvent: DecodedLogEvent<ERC20TokenApprovalEventArgs>) => { @@ -538,7 +514,7 @@ describe('ERC20Wrapper', () => { callbackNeverToBeCalled, ); const callbackToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(); - contractWrappers.setProvider(provider, constants.TESTRPC_NETWORK_ID); + contractWrappers.unsubscribeAll(); contractWrappers.erc20Token.subscribe( tokenAddress, ERC20TokenEvents.Transfer, @@ -587,7 +563,7 @@ describe('ERC20Wrapper', () => { let txHash: string; before(() => { tokenAddress = tokens[0]; - tokenTransferProxyAddress = contractWrappers.erc20Proxy.getContractAddress(); + tokenTransferProxyAddress = contractWrappers.erc20Proxy.address; }); it('should get logs with decoded args emitted by Approval', async () => { txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase); diff --git a/packages/contract-wrappers/test/erc721_proxy_wrapper_test.ts b/packages/contract-wrappers/test/erc721_proxy_wrapper_test.ts index 9473d930b..9b0fe8817 100644 --- a/packages/contract-wrappers/test/erc721_proxy_wrapper_test.ts +++ b/packages/contract-wrappers/test/erc721_proxy_wrapper_test.ts @@ -4,6 +4,7 @@ import { ContractWrappers } from '../src'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; +import { migrateOnceAsync } from './utils/migrate'; import { provider } from './utils/web3_wrapper'; chaiSetup.configure(); @@ -11,10 +12,13 @@ const expect = chai.expect; describe('ERC721ProxyWrapper', () => { let contractWrappers: ContractWrappers; - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - }; before(async () => { + const contractAddresses = await migrateOnceAsync(); + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + blockPollingIntervalMs: 10, + }; contractWrappers = new ContractWrappers(provider, config); }); describe('#isAuthorizedAsync', () => { diff --git a/packages/contract-wrappers/test/erc721_wrapper_test.ts b/packages/contract-wrappers/test/erc721_wrapper_test.ts index f005ac2e0..a7f1e4c41 100644 --- a/packages/contract-wrappers/test/erc721_wrapper_test.ts +++ b/packages/contract-wrappers/test/erc721_wrapper_test.ts @@ -1,7 +1,7 @@ -import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils'; -import { EmptyWalletSubprovider, Web3ProviderEngine } from '@0xproject/subproviders'; -import { DoneCallback } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +import { BlockchainLifecycle, callbackErrorReporter } from '@0x/dev-utils'; +import { EmptyWalletSubprovider, Web3ProviderEngine } from '@0x/subproviders'; +import { DoneCallback } from '@0x/types'; +import { BigNumber } from '@0x/utils'; import * as chai from 'chai'; import { Provider } from 'ethereum-types'; import 'mocha'; @@ -10,6 +10,7 @@ import { BlockParamLiteral, BlockRange, ContractWrappers, + ContractWrappersConfig, ContractWrappersError, DecodedLogEvent, ERC721TokenApprovalEventArgs, @@ -20,6 +21,7 @@ import { import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; +import { migrateOnceAsync } from './utils/migrate'; import { tokenUtils } from './utils/token_utils'; import { provider, web3Wrapper } from './utils/web3_wrapper'; @@ -37,10 +39,15 @@ describe('ERC721Wrapper', () => { let operatorAddress: string; let approvedAddress: string; let receiverAddress: string; - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - }; + let config: ContractWrappersConfig; + before(async () => { + const contractAddresses = await migrateOnceAsync(); + config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + blockPollingIntervalMs: 10, + }; contractWrappers = new ContractWrappers(provider, config); userAddresses = await web3Wrapper.getAvailableAddressesAsync(); tokens = tokenUtils.getDummyERC721TokenAddresses(); @@ -108,12 +115,6 @@ describe('ERC721Wrapper', () => { tokenCount = await contractWrappers.erc721Token.getTokenCountAsync(tokenAddress, ownerAddress); expect(tokenCount).to.be.bignumber.equal(1); }); - it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => { - const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065'; - return expect( - contractWrappers.erc721Token.getTokenCountAsync(nonExistentTokenAddress, ownerAddress), - ).to.be.rejectedWith(ContractWrappersError.ERC721TokenContractDoesNotExist); - }); it('should return a balance of 0 for a non-existent owner address', async () => { const nonExistentOwner = '0x198c6ad858f213fb31b6fe809e25040e6b964593'; const balance = await contractWrappers.erc721Token.getTokenCountAsync(tokenAddress, nonExistentOwner); @@ -142,13 +143,6 @@ describe('ERC721Wrapper', () => { const tokenOwner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId); expect(tokenOwner).to.be.bignumber.equal(ownerAddress); }); - it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => { - const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065'; - const fakeTokenId = new BigNumber(42); - return expect( - contractWrappers.erc721Token.getOwnerOfAsync(nonExistentTokenAddress, fakeTokenId), - ).to.be.rejectedWith(ContractWrappersError.ERC721TokenContractDoesNotExist); - }); it('should return undefined not 0 for a non-existent ERC721', async () => { const fakeTokenId = new BigNumber(42); return expect(contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, fakeTokenId)).to.be.rejectedWith( @@ -229,11 +223,17 @@ describe('ERC721Wrapper', () => { it('should set the proxy approval', async () => { const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress); - const approvalBeforeSet = await contractWrappers.erc721Token.isProxyApprovedAsync(tokenAddress, tokenId); - expect(approvalBeforeSet).to.be.false(); + const isProxyApprovedBeforeSet = await contractWrappers.erc721Token.isProxyApprovedAsync( + tokenAddress, + tokenId, + ); + expect(isProxyApprovedBeforeSet).to.be.false(); await contractWrappers.erc721Token.setProxyApprovalAsync(tokenAddress, tokenId); - const approvalAfterSet = await contractWrappers.erc721Token.isProxyApprovedAsync(tokenAddress, tokenId); - expect(approvalAfterSet).to.be.true(); + const isProxyApprovedAfterSet = await contractWrappers.erc721Token.isProxyApprovedAsync( + tokenAddress, + tokenId, + ); + expect(isProxyApprovedAfterSet).to.be.true(); }); }); describe('#subscribe', () => { @@ -313,7 +313,7 @@ describe('ERC721Wrapper', () => { ); })().catch(done); }); - it('Outstanding subscriptions are cancelled when contractWrappers.setProvider called', (done: DoneCallback) => { + it('Outstanding subscriptions are cancelled when contractWrappers.unsubscribeAll called', (done: DoneCallback) => { (async () => { const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<ERC721TokenApprovalEventArgs>) => { @@ -327,7 +327,7 @@ describe('ERC721Wrapper', () => { callbackNeverToBeCalled, ); const callbackToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(); - contractWrappers.setProvider(provider, constants.TESTRPC_NETWORK_ID); + contractWrappers.unsubscribeAll(); contractWrappers.erc721Token.subscribe( tokenAddress, ERC721TokenEvents.Approval, @@ -357,7 +357,6 @@ describe('ERC721Wrapper', () => { ); contractWrappers.erc721Token.unsubscribe(subscriptionToken); - const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress); const isApproved = true; await web3Wrapper.awaitTransactionSuccessAsync( await contractWrappers.erc721Token.setApprovalForAllAsync( @@ -373,15 +372,11 @@ describe('ERC721Wrapper', () => { }); }); describe('#getLogsAsync', () => { - let tokenTransferProxyAddress: string; const blockRange: BlockRange = { fromBlock: 0, toBlock: BlockParamLiteral.Latest, }; let txHash: string; - before(() => { - tokenTransferProxyAddress = contractWrappers.erc721Proxy.getContractAddress(); - }); it('should get logs with decoded args emitted by ApprovalForAll', async () => { const isApprovedForAll = true; txHash = await contractWrappers.erc721Token.setApprovalForAllAsync( diff --git a/packages/contract-wrappers/test/ether_token_wrapper_test.ts b/packages/contract-wrappers/test/ether_token_wrapper_test.ts index 48bd6d3f6..e3efef19d 100644 --- a/packages/contract-wrappers/test/ether_token_wrapper_test.ts +++ b/packages/contract-wrappers/test/ether_token_wrapper_test.ts @@ -1,7 +1,8 @@ -import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils'; -import { DoneCallback } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import { ContractAddresses } from '@0x/contract-addresses'; +import { BlockchainLifecycle, callbackErrorReporter } from '@0x/dev-utils'; +import { DoneCallback } from '@0x/types'; +import { BigNumber } from '@0x/utils'; +import { Web3Wrapper } from '@0x/web3-wrapper'; import * as chai from 'chai'; import 'mocha'; @@ -10,17 +11,17 @@ import { BlockRange, ContractWrappers, ContractWrappersError, - DecodedLogEvent, WETH9ApprovalEventArgs, WETH9DepositEventArgs, WETH9Events, WETH9TransferEventArgs, WETH9WithdrawalEventArgs, } from '../src'; +import { DecodedLogEvent } from '../src/types'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; -import { tokenUtils } from './utils/token_utils'; +import { migrateOnceAsync } from './utils/migrate'; import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); @@ -35,6 +36,7 @@ const MAX_REASONABLE_GAS_COST_IN_WEI = 62517; describe('EtherTokenWrapper', () => { let contractWrappers: ContractWrappers; + let contractAddresses: ContractAddresses; let userAddresses: string[]; let addressWithETH: string; let wethContractAddress: string; @@ -42,19 +44,22 @@ describe('EtherTokenWrapper', () => { const decimalPlaces = 7; let addressWithoutFunds: string; const gasPrice = new BigNumber(1); - const zeroExConfig = { - gasPrice, - networkId: constants.TESTRPC_NETWORK_ID, - }; const transferAmount = new BigNumber(42); const allowanceAmount = new BigNumber(42); const depositAmount = new BigNumber(42); const withdrawalAmount = new BigNumber(42); before(async () => { - contractWrappers = new ContractWrappers(provider, zeroExConfig); + contractAddresses = await migrateOnceAsync(); + const config = { + gasPrice, + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + blockPollingIntervalMs: 10, + }; + contractWrappers = new ContractWrappers(provider, config); userAddresses = await web3Wrapper.getAvailableAddressesAsync(); addressWithETH = userAddresses[0]; - wethContractAddress = contractWrappers.etherToken.getContractAddressIfExists() as string; + wethContractAddress = contractAddresses.etherToken; depositWeiAmount = Web3Wrapper.toWei(new BigNumber(5)); addressWithoutFunds = userAddresses[1]; }); @@ -66,7 +71,7 @@ describe('EtherTokenWrapper', () => { }); describe('#getContractAddressIfExists', async () => { it('should return contract address if connected to a known network', () => { - const contractAddressIfExists = contractWrappers.etherToken.getContractAddressIfExists(); + const contractAddressIfExists = contractAddresses.etherToken; expect(contractAddressIfExists).to.not.be.undefined(); }); it('should throw if connected to a private network and contract addresses are not specified', () => { @@ -171,7 +176,7 @@ describe('EtherTokenWrapper', () => { const indexFilterValues = {}; let etherTokenAddress: string; before(async () => { - etherTokenAddress = tokenUtils.getWethTokenAddress(); + etherTokenAddress = contractAddresses.etherToken; }); afterEach(() => { contractWrappers.etherToken.unsubscribeAll(); @@ -278,7 +283,7 @@ describe('EtherTokenWrapper', () => { await contractWrappers.etherToken.withdrawAsync(etherTokenAddress, withdrawalAmount, addressWithETH); })().catch(done); }); - it('should cancel outstanding subscriptions when ZeroEx.setProvider is called', (done: DoneCallback) => { + it('should cancel outstanding subscriptions when contractWrappers.unsubscribeAll is called', (done: DoneCallback) => { (async () => { const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( (_logEvent: DecodedLogEvent<WETH9ApprovalEventArgs>) => { @@ -292,7 +297,7 @@ describe('EtherTokenWrapper', () => { callbackNeverToBeCalled, ); const callbackToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(); - contractWrappers.setProvider(provider, constants.TESTRPC_NETWORK_ID); + contractWrappers.unsubscribeAll(); await contractWrappers.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH); contractWrappers.etherToken.subscribe( etherTokenAddress, @@ -340,10 +345,10 @@ describe('EtherTokenWrapper', () => { let txHash: string; before(async () => { addressWithETH = userAddresses[0]; - etherTokenAddress = tokenUtils.getWethTokenAddress(); - erc20ProxyAddress = contractWrappers.erc20Proxy.getContractAddress(); + etherTokenAddress = contractAddresses.etherToken; + erc20ProxyAddress = contractWrappers.erc20Proxy.address; // Start the block range after all migrations to avoid unexpected logs - const currentBlock = await web3Wrapper.getBlockNumberAsync(); + const currentBlock: number = await web3Wrapper.getBlockNumberAsync(); const fromBlock = currentBlock + 1; blockRange = { fromBlock, diff --git a/packages/contract-wrappers/test/exchange_wrapper_test.ts b/packages/contract-wrappers/test/exchange_wrapper_test.ts index fa3b49eb9..0e537bd83 100644 --- a/packages/contract-wrappers/test/exchange_wrapper_test.ts +++ b/packages/contract-wrappers/test/exchange_wrapper_test.ts @@ -1,23 +1,18 @@ -import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils'; -import { FillScenarios } from '@0xproject/fill-scenarios'; -import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils'; -import { DoneCallback, SignedOrder } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +import { BlockchainLifecycle, callbackErrorReporter } from '@0x/dev-utils'; +import { FillScenarios } from '@0x/fill-scenarios'; +import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; +import { DoneCallback, SignedOrder } from '@0x/types'; +import { BigNumber } from '@0x/utils'; import * as chai from 'chai'; import { BlockParamLiteral } from 'ethereum-types'; import 'mocha'; -import { - ContractWrappers, - DecodedLogEvent, - ExchangeCancelEventArgs, - ExchangeEvents, - ExchangeFillEventArgs, - OrderStatus, -} from '../src'; +import { ContractWrappers, ExchangeCancelEventArgs, ExchangeEvents, ExchangeFillEventArgs, OrderStatus } from '../src'; +import { DecodedLogEvent } from '../src/types'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; +import { migrateOnceAsync } from './utils/migrate'; import { tokenUtils } from './utils/token_utils'; import { provider, web3Wrapper } from './utils/web3_wrapper'; @@ -33,37 +28,38 @@ describe('ExchangeWrapper', () => { let exchangeContractAddress: string; let makerTokenAddress: string; let takerTokenAddress: string; - let coinbase: string; let makerAddress: string; let anotherMakerAddress: string; let takerAddress: string; let makerAssetData: string; let takerAssetData: string; - let feeRecipient: string; let txHash: string; const fillableAmount = new BigNumber(5); const takerTokenFillAmount = new BigNumber(5); let signedOrder: SignedOrder; let anotherSignedOrder: SignedOrder; - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - blockPollingIntervalMs: 0, - }; + before(async () => { + const contractAddresses = await migrateOnceAsync(); await blockchainLifecycle.startAsync(); + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + blockPollingIntervalMs: 10, + }; contractWrappers = new ContractWrappers(provider, config); - exchangeContractAddress = contractWrappers.exchange.getContractAddress(); + exchangeContractAddress = contractWrappers.exchange.address; userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - zrxTokenAddress = tokenUtils.getProtocolTokenAddress(); + zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress; fillScenarios = new FillScenarios( provider, userAddresses, zrxTokenAddress, exchangeContractAddress, - contractWrappers.erc20Proxy.getContractAddress(), - contractWrappers.erc721Proxy.getContractAddress(), + contractWrappers.erc20Proxy.address, + contractWrappers.erc721Proxy.address, ); - [coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses; + [, makerAddress, takerAddress, , anotherMakerAddress] = userAddresses; [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); [makerAssetData, takerAssetData] = [ assetDataUtils.encodeERC20AssetData(makerTokenAddress), @@ -335,11 +331,11 @@ describe('ExchangeWrapper', () => { it('should fill or kill a valid order', async () => { const erc20ProxyId = await contractWrappers.erc20Proxy.getProxyIdAsync(); const erc20ProxyAddressById = await contractWrappers.exchange.getAssetProxyBySignatureAsync(erc20ProxyId); - const erc20ProxyAddress = contractWrappers.erc20Proxy.getContractAddress(); + const erc20ProxyAddress = contractWrappers.erc20Proxy.address; expect(erc20ProxyAddressById).to.be.equal(erc20ProxyAddress); const erc721ProxyId = await contractWrappers.erc721Proxy.getProxyIdAsync(); const erc721ProxyAddressById = await contractWrappers.exchange.getAssetProxyBySignatureAsync(erc721ProxyId); - const erc721ProxyAddress = contractWrappers.erc721Proxy.getContractAddress(); + const erc721ProxyAddress = contractWrappers.erc721Proxy.address; expect(erc721ProxyAddressById).to.be.equal(erc721ProxyAddress); }); }); @@ -364,7 +360,7 @@ describe('ExchangeWrapper', () => { describe('#getVersionAsync', () => { it('should return version the hash', async () => { const version = await contractWrappers.exchange.getVersionAsync(); - const VERSION = '2.0.1-alpha'; + const VERSION = '2.0.0'; expect(version).to.be.equal(VERSION); }); }); @@ -414,7 +410,7 @@ describe('ExchangeWrapper', () => { await contractWrappers.exchange.cancelOrderAsync(signedOrder); })().catch(done); }); - it('Outstanding subscriptions are cancelled when contractWrappers.setProvider called', (done: DoneCallback) => { + it('Outstanding subscriptions are cancelled when contractWrappers.unsubscribeAll called', (done: DoneCallback) => { (async () => { const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<ExchangeFillEventArgs>) => { @@ -423,7 +419,7 @@ describe('ExchangeWrapper', () => { ); contractWrappers.exchange.subscribe(ExchangeEvents.Fill, indexFilterValues, callbackNeverToBeCalled); - contractWrappers.setProvider(provider, constants.TESTRPC_NETWORK_ID); + contractWrappers.unsubscribeAll(); const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<ExchangeFillEventArgs>) => { @@ -460,13 +456,6 @@ describe('ExchangeWrapper', () => { })().catch(done); }); }); - describe('#getZRXTokenAddressAsync', () => { - it('gets the same token as is in token registry', () => { - const zrxAddressFromExchangeWrapper = contractWrappers.exchange.getZRXTokenAddress(); - const zrxAddress = tokenUtils.getProtocolTokenAddress(); - expect(zrxAddressFromExchangeWrapper).to.equal(zrxAddress); - }); - }); describe('#getLogsAsync', () => { const blockRange = { fromBlock: 0, diff --git a/packages/contract-wrappers/test/forwarder_wrapper_test.ts b/packages/contract-wrappers/test/forwarder_wrapper_test.ts index 3f3b40e0b..ff4ff8b67 100644 --- a/packages/contract-wrappers/test/forwarder_wrapper_test.ts +++ b/packages/contract-wrappers/test/forwarder_wrapper_test.ts @@ -1,23 +1,16 @@ -import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils'; -import { FillScenarios } from '@0xproject/fill-scenarios'; -import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils'; -import { DoneCallback, SignedOrder } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +import { BlockchainLifecycle } from '@0x/dev-utils'; +import { FillScenarios } from '@0x/fill-scenarios'; +import { assetDataUtils } from '@0x/order-utils'; +import { SignedOrder } from '@0x/types'; +import { BigNumber } from '@0x/utils'; import * as chai from 'chai'; -import { BlockParamLiteral } from 'ethereum-types'; import 'mocha'; -import { - ContractWrappers, - DecodedLogEvent, - ExchangeCancelEventArgs, - ExchangeEvents, - ExchangeFillEventArgs, - OrderStatus, -} from '../src'; +import { ContractWrappers, OrderStatus } from '../src'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; +import { migrateOnceAsync } from './utils/migrate'; import { tokenUtils } from './utils/token_utils'; import { provider, web3Wrapper } from './utils/web3_wrapper'; @@ -25,24 +18,16 @@ chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); +// tslint:disable:custom-no-magic-numbers describe('ForwarderWrapper', () => { - const contractWrappersConfig = { - networkId: constants.TESTRPC_NETWORK_ID, - blockPollingIntervalMs: 0, - }; const fillableAmount = new BigNumber(5); - const takerTokenFillAmount = new BigNumber(5); let contractWrappers: ContractWrappers; let fillScenarios: FillScenarios; - let forwarderContractAddress: string; let exchangeContractAddress: string; let zrxTokenAddress: string; let userAddresses: string[]; - let coinbase: string; let makerAddress: string; let takerAddress: string; - let feeRecipient: string; - let anotherMakerAddress: string; let makerTokenAddress: string; let takerTokenAddress: string; let makerAssetData: string; @@ -50,23 +35,28 @@ describe('ForwarderWrapper', () => { let signedOrder: SignedOrder; let anotherSignedOrder: SignedOrder; before(async () => { + const contractAddresses = await migrateOnceAsync(); await blockchainLifecycle.startAsync(); - contractWrappers = new ContractWrappers(provider, contractWrappersConfig); - forwarderContractAddress = contractWrappers.forwarder.getContractAddress(); - exchangeContractAddress = contractWrappers.exchange.getContractAddress(); + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + blockPollingIntervalMs: 10, + }; + contractWrappers = new ContractWrappers(provider, config); + exchangeContractAddress = contractWrappers.exchange.address; userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - zrxTokenAddress = tokenUtils.getProtocolTokenAddress(); + zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress; fillScenarios = new FillScenarios( provider, userAddresses, zrxTokenAddress, exchangeContractAddress, - contractWrappers.erc20Proxy.getContractAddress(), - contractWrappers.erc721Proxy.getContractAddress(), + contractWrappers.erc20Proxy.address, + contractWrappers.erc721Proxy.address, ); - [coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses; + [, makerAddress, takerAddress] = userAddresses; [makerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); - takerTokenAddress = tokenUtils.getWethTokenAddress(); + takerTokenAddress = contractWrappers.forwarder.etherTokenAddress; [makerAssetData, takerAssetData] = [ assetDataUtils.encodeERC20AssetData(makerTokenAddress), assetDataUtils.encodeERC20AssetData(takerTokenAddress), @@ -110,6 +100,25 @@ describe('ForwarderWrapper', () => { expect(ordersInfo[0].orderStatus).to.be.equal(OrderStatus.FULLY_FILLED); expect(ordersInfo[1].orderStatus).to.be.equal(OrderStatus.FULLY_FILLED); }); + it('should throw when invalid transaction and shouldValidate is true', async () => { + const signedOrders = [signedOrder]; + // request more makerAsset than what is available + const makerAssetFillAmount = signedOrder.makerAssetAmount.plus(100); + return expect( + contractWrappers.forwarder.marketBuyOrdersWithEthAsync( + signedOrders, + makerAssetFillAmount, + takerAddress, + makerAssetFillAmount, + [], + 0, + constants.NULL_ADDRESS, + { + shouldValidate: true, + }, + ), + ).to.be.rejectedWith('COMPLETE_FILL_FAILED'); + }); }); describe('#marketSellOrdersWithEthAsync', () => { it('should market sell orders with eth', async () => { @@ -126,5 +135,33 @@ describe('ForwarderWrapper', () => { expect(ordersInfo[1].orderStatus).to.be.equal(OrderStatus.FILLABLE); expect(ordersInfo[1].orderTakerAssetFilledAmount).to.be.bignumber.equal(new BigNumber(4)); // only 95% of ETH is sold }); + it('should throw when invalid transaction and shouldValidate is true', async () => { + // create an order with fees, we try to fill it but we do not provide enough ETH to cover the fees + const signedOrderWithFee = await fillScenarios.createFillableSignedOrderWithFeesAsync( + makerAssetData, + takerAssetData, + constants.ZERO_AMOUNT, + new BigNumber(100), + makerAddress, + constants.NULL_ADDRESS, + fillableAmount, + constants.NULL_ADDRESS, + ); + const signedOrders = [signedOrderWithFee]; + const makerAssetFillAmount = signedOrder.makerAssetAmount; + return expect( + contractWrappers.forwarder.marketSellOrdersWithEthAsync( + signedOrders, + takerAddress, + makerAssetFillAmount, + [], + 0, + constants.NULL_ADDRESS, + { + shouldValidate: true, + }, + ), + ).to.be.rejectedWith('COMPLETE_FILL_FAILED'); + }); }); }); diff --git a/packages/contract-wrappers/test/global_hooks.ts b/packages/contract-wrappers/test/global_hooks.ts index 8731318e7..e23739b59 100644 --- a/packages/contract-wrappers/test/global_hooks.ts +++ b/packages/contract-wrappers/test/global_hooks.ts @@ -1,17 +1,6 @@ -import { devConstants } from '@0xproject/dev-utils'; -import { runV2MigrationsAsync } from '@0xproject/migrations'; - -import { provider } from './utils/web3_wrapper'; - -before('migrate contracts', async function(): Promise<void> { +before('set up mocha', async function(): Promise<void> { // HACK: Since the migrations take longer then our global mocha timeout limit // we manually increase it for this before hook. const mochaTestTimeoutMs = 50000; this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this - const txDefaults = { - gas: devConstants.GAS_LIMIT, - from: devConstants.TESTRPC_FIRST_ADDRESS, - }; - const artifactsDir = `src/artifacts`; - await runV2MigrationsAsync(provider, artifactsDir, txDefaults); }); diff --git a/packages/contract-wrappers/test/order_validator_wrapper_test.ts b/packages/contract-wrappers/test/order_validator_wrapper_test.ts new file mode 100644 index 000000000..da3f99e72 --- /dev/null +++ b/packages/contract-wrappers/test/order_validator_wrapper_test.ts @@ -0,0 +1,146 @@ +import { ContractAddresses } from '@0x/contract-addresses'; +import { BlockchainLifecycle } from '@0x/dev-utils'; +import { FillScenarios } from '@0x/fill-scenarios'; +import { assetDataUtils } from '@0x/order-utils'; +import { SignedOrder } from '@0x/types'; +import { BigNumber } from '@0x/utils'; +import * as chai from 'chai'; +import * as _ from 'lodash'; +import 'mocha'; + +import { ContractWrappers, OrderStatus } from '../src'; +import { OrderInfo, TraderInfo } from '../src/types'; + +import { chaiSetup } from './utils/chai_setup'; +import { constants } from './utils/constants'; +import { migrateOnceAsync } from './utils/migrate'; +import { tokenUtils } from './utils/token_utils'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; + +chaiSetup.configure(); +const expect = chai.expect; +const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); + +describe('OrderValidator', () => { + const fillableAmount = new BigNumber(5); + let contractWrappers: ContractWrappers; + let fillScenarios: FillScenarios; + let exchangeContractAddress: string; + let zrxTokenAddress: string; + let zrxTokenAssetData: string; + let userAddresses: string[]; + let coinbase: string; + let makerAddress: string; + let takerAddress: string; + let feeRecipient: string; + let anotherMakerAddress: string; + let makerTokenAddress: string; + let takerTokenAddress: string; + let makerAssetData: string; + let takerAssetData: string; + let signedOrder: SignedOrder; + let anotherSignedOrder: SignedOrder; + let contractAddresses: ContractAddresses; + + before(async () => { + contractAddresses = await migrateOnceAsync(); + await blockchainLifecycle.startAsync(); + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + blockPollingIntervalMs: 10, + }; + contractWrappers = new ContractWrappers(provider, config); + exchangeContractAddress = contractWrappers.exchange.address; + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); + zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress; + zrxTokenAssetData = assetDataUtils.encodeERC20AssetData(zrxTokenAddress); + fillScenarios = new FillScenarios( + provider, + userAddresses, + zrxTokenAddress, + exchangeContractAddress, + contractWrappers.erc20Proxy.address, + contractWrappers.erc721Proxy.address, + ); + [coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses; + [makerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); + takerTokenAddress = contractAddresses.etherToken; + [makerAssetData, takerAssetData] = [ + assetDataUtils.encodeERC20AssetData(makerTokenAddress), + assetDataUtils.encodeERC20AssetData(takerTokenAddress), + ]; + + signedOrder = await fillScenarios.createFillableSignedOrderAsync( + makerAssetData, + takerAssetData, + makerAddress, + constants.NULL_ADDRESS, + fillableAmount, + ); + anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync( + zrxTokenAssetData, + takerAssetData, + makerAddress, + constants.NULL_ADDRESS, + fillableAmount, + ); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); + beforeEach(async () => { + await blockchainLifecycle.startAsync(); + }); + afterEach(async () => { + await blockchainLifecycle.revertAsync(); + }); + describe('#getOrdersAndTradersInfoAsync', () => { + let signedOrders: SignedOrder[]; + let takerAddresses: string[]; + let ordersInfo: OrderInfo[]; + let tradersInfo: TraderInfo[]; + beforeEach(async () => { + signedOrders = [signedOrder, anotherSignedOrder]; + takerAddresses = [takerAddress, takerAddress]; + const ordersAndTradersInfo = await contractWrappers.orderValidator.getOrdersAndTradersInfoAsync( + signedOrders, + takerAddresses, + ); + ordersInfo = _.map(ordersAndTradersInfo, orderAndTraderInfo => orderAndTraderInfo.orderInfo); + tradersInfo = _.map(ordersAndTradersInfo, orderAndTraderInfo => orderAndTraderInfo.traderInfo); + }); + it('should return the same number of order infos and trader infos as input orders', async () => { + expect(ordersInfo.length).to.be.equal(signedOrders.length); + expect(tradersInfo.length).to.be.equal(takerAddresses.length); + }); + it('should return correct on-chain order info for input orders', async () => { + const firstOrderInfo = ordersInfo[0]; + const secondOrderInfo = ordersInfo[1]; + expect(firstOrderInfo.orderStatus).to.be.equal(OrderStatus.FILLABLE); + expect(firstOrderInfo.orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT); + expect(secondOrderInfo.orderStatus).to.be.equal(OrderStatus.FILLABLE); + expect(secondOrderInfo.orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT); + }); + it('should return correct on-chain trader info for input takers', async () => { + const firstTraderInfo = tradersInfo[0]; + const secondTraderInfo = tradersInfo[1]; + expect(firstTraderInfo.makerBalance).to.bignumber.equal(new BigNumber(5)); + expect(firstTraderInfo.makerAllowance).to.bignumber.equal(new BigNumber(5)); + expect(firstTraderInfo.takerBalance).to.bignumber.equal(new BigNumber(0)); + expect(firstTraderInfo.takerAllowance).to.bignumber.equal(new BigNumber(0)); + expect(firstTraderInfo.makerZrxBalance).to.bignumber.equal(new BigNumber(5)); + expect(firstTraderInfo.makerZrxAllowance).to.bignumber.equal(new BigNumber(5)); + expect(firstTraderInfo.takerZrxBalance).to.bignumber.equal(new BigNumber(0)); + expect(firstTraderInfo.takerZrxAllowance).to.bignumber.equal(new BigNumber(0)); + expect(secondTraderInfo.makerBalance).to.bignumber.equal(new BigNumber(5)); + expect(secondTraderInfo.makerAllowance).to.bignumber.equal(new BigNumber(5)); + expect(secondTraderInfo.takerBalance).to.bignumber.equal(new BigNumber(0)); + expect(secondTraderInfo.takerAllowance).to.bignumber.equal(new BigNumber(0)); + expect(secondTraderInfo.makerZrxBalance).to.bignumber.equal(new BigNumber(5)); + expect(secondTraderInfo.makerZrxAllowance).to.bignumber.equal(new BigNumber(5)); + expect(secondTraderInfo.takerZrxBalance).to.bignumber.equal(new BigNumber(0)); + expect(secondTraderInfo.takerZrxAllowance).to.bignumber.equal(new BigNumber(0)); + }); + }); +}); diff --git a/packages/contract-wrappers/test/revert_validation_test.ts b/packages/contract-wrappers/test/revert_validation_test.ts new file mode 100644 index 000000000..efd5dd61f --- /dev/null +++ b/packages/contract-wrappers/test/revert_validation_test.ts @@ -0,0 +1,115 @@ +import { BlockchainLifecycle, devConstants, web3Factory } from '@0x/dev-utils'; +import { FillScenarios } from '@0x/fill-scenarios'; +import { runMigrationsAsync } from '@0x/migrations'; +import { assetDataUtils } from '@0x/order-utils'; +import { SignedOrder } from '@0x/types'; +import { BigNumber } from '@0x/utils'; +import { Web3Wrapper } from '@0x/web3-wrapper'; +import * as chai from 'chai'; +import 'mocha'; + +import { ContractWrappers } from '../src'; + +import { chaiSetup } from './utils/chai_setup'; +import { constants } from './utils/constants'; +import { tokenUtils } from './utils/token_utils'; + +chaiSetup.configure(); +const expect = chai.expect; + +describe('Revert Validation ExchangeWrapper', () => { + let contractWrappers: ContractWrappers; + let userAddresses: string[]; + let fillScenarios: FillScenarios; + let makerTokenAddress: string; + let takerTokenAddress: string; + let makerAddress: string; + let takerAddress: string; + let makerAssetData: string; + let takerAssetData: string; + let txHash: string; + let blockchainLifecycle: BlockchainLifecycle; + let web3Wrapper: Web3Wrapper; + const fillableAmount = new BigNumber(5); + const takerTokenFillAmount = new BigNumber(5); + let signedOrder: SignedOrder; + before(async () => { + // vmErrorsOnRPCResponse is useful for quick feedback and testing during development + // but is not the default behaviour in production. Here we ensure our failure cases + // are handled in an environment which behaves similar to production + const provider = web3Factory.getRpcProvider({ + shouldUseInProcessGanache: true, + shouldThrowErrorsOnGanacheRPCResponse: false, + }); + web3Wrapper = new Web3Wrapper(provider); + blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); + // Re-deploy the artifacts in this provider, rather than in the default provider exposed in + // the beforeAll hook. This is due to the fact that the default provider enabled vmErrorsOnRPCResponse + // and we are explicity testing with vmErrorsOnRPCResponse disabled. + const txDefaults = { + gas: devConstants.GAS_LIMIT, + from: devConstants.TESTRPC_FIRST_ADDRESS, + }; + await blockchainLifecycle.startAsync(); + const contractAddresses = await runMigrationsAsync(provider, txDefaults); + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + blockPollingIntervalMs: 10, + }; + contractWrappers = new ContractWrappers(provider, config); + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); + fillScenarios = new FillScenarios( + provider, + userAddresses, + contractAddresses.zrxToken, + contractAddresses.exchange, + contractAddresses.erc20Proxy, + contractAddresses.erc721Proxy, + ); + [, makerAddress, takerAddress] = userAddresses; + [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); + [makerAssetData, takerAssetData] = [ + assetDataUtils.encodeERC20AssetData(makerTokenAddress), + assetDataUtils.encodeERC20AssetData(takerTokenAddress), + ]; + signedOrder = await fillScenarios.createFillableSignedOrderAsync( + makerAssetData, + takerAssetData, + makerAddress, + takerAddress, + fillableAmount, + ); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); + beforeEach(async () => { + await blockchainLifecycle.startAsync(); + }); + afterEach(async () => { + await blockchainLifecycle.revertAsync(); + }); + describe('#fillOrderAsync', () => { + it('should throw the revert reason when shouldValidate is true and a fill would revert', async () => { + // Create a scenario where the fill will revert + const makerTokenBalance = await contractWrappers.erc20Token.getBalanceAsync( + makerTokenAddress, + makerAddress, + ); + // Transfer all of the tokens from maker to create a failure scenario + txHash = await contractWrappers.erc20Token.transferAsync( + makerTokenAddress, + makerAddress, + takerAddress, + makerTokenBalance, + ); + await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); + return expect( + contractWrappers.exchange.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress, { + shouldValidate: true, + }), + ).to.be.rejectedWith('TRANSFER_FAILED'); + }); + }); +}); diff --git a/packages/contract-wrappers/test/subscription_test.ts b/packages/contract-wrappers/test/subscription_test.ts index 80d17576f..0fa6af40d 100644 --- a/packages/contract-wrappers/test/subscription_test.ts +++ b/packages/contract-wrappers/test/subscription_test.ts @@ -1,14 +1,20 @@ -import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils'; -import { DoneCallback } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +import { BlockchainLifecycle } from '@0x/dev-utils'; +import { DoneCallback } from '@0x/types'; import * as _ from 'lodash'; import 'mocha'; import * as Sinon from 'sinon'; -import { ContractWrappers, DecodedLogEvent, ERC20TokenApprovalEventArgs, ERC20TokenEvents, Token } from '../src'; +import { + ContractWrappers, + ContractWrappersConfig, + DecodedLogEvent, + ERC20TokenApprovalEventArgs, + ERC20TokenEvents, +} from '../src'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; +import { migrateOnceAsync } from './utils/migrate'; import { tokenUtils } from './utils/token_utils'; import { provider, web3Wrapper } from './utils/web3_wrapper'; @@ -17,17 +23,15 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('SubscriptionTest', () => { let contractWrappers: ContractWrappers; - let userAddresses: string[]; - let coinbase: string; - let addressWithoutFunds: string; - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - }; + let config: ContractWrappersConfig; + before(async () => { + const contractAddresses = await migrateOnceAsync(); + config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + }; contractWrappers = new ContractWrappers(provider, config); - userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - coinbase = userAddresses[0]; - addressWithoutFunds = userAddresses[1]; }); beforeEach(async () => { await blockchainLifecycle.startAsync(); @@ -38,7 +42,6 @@ describe('SubscriptionTest', () => { describe('#subscribe', () => { const indexFilterValues = {}; let tokenAddress: string; - const allowanceAmount = new BigNumber(42); let stubs: Sinon.SinonStub[] = []; before(() => { const tokenAddresses = tokenUtils.getDummyERC20TokenAddresses(); @@ -52,7 +55,7 @@ describe('SubscriptionTest', () => { it('Should allow unsubscribeAll to be called successfully after an error', (done: DoneCallback) => { (async () => { const callback = (err: Error | null, _logEvent?: DecodedLogEvent<ERC20TokenApprovalEventArgs>) => - _.noop; + _.noop.bind(_); contractWrappers.erc20Token.subscribe( tokenAddress, ERC20TokenEvents.Approval, @@ -60,7 +63,7 @@ describe('SubscriptionTest', () => { callback, ); stubs = [ - Sinon.stub((contractWrappers as any)._web3Wrapper, 'getBlockAsync').throws( + Sinon.stub((contractWrappers as any)._web3Wrapper, 'getBlockIfExistsAsync').throws( new Error('JSON RPC error'), ), ]; diff --git a/packages/contract-wrappers/test/transaction_encoder_test.ts b/packages/contract-wrappers/test/transaction_encoder_test.ts index 10222dbc1..ef9eb2cf3 100644 --- a/packages/contract-wrappers/test/transaction_encoder_test.ts +++ b/packages/contract-wrappers/test/transaction_encoder_test.ts @@ -1,14 +1,15 @@ -import { BlockchainLifecycle } from '@0xproject/dev-utils'; -import { FillScenarios } from '@0xproject/fill-scenarios'; -import { assetDataUtils, ecSignOrderHashAsync, generatePseudoRandomSalt, orderHashUtils } from '@0xproject/order-utils'; -import { SignedOrder, SignerType } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +import { BlockchainLifecycle } from '@0x/dev-utils'; +import { FillScenarios } from '@0x/fill-scenarios'; +import { assetDataUtils, generatePseudoRandomSalt, orderHashUtils, signatureUtils } from '@0x/order-utils'; +import { SignedOrder } from '@0x/types'; +import { BigNumber } from '@0x/utils'; import 'mocha'; import { ContractWrappers } from '../src'; import { TransactionEncoder } from '../src/utils/transaction_encoder'; import { constants } from './utils/constants'; +import { migrateOnceAsync } from './utils/migrate'; import { tokenUtils } from './utils/token_utils'; import { provider, web3Wrapper } from './utils/web3_wrapper'; @@ -31,23 +32,26 @@ describe('TransactionEncoder', () => { const fillableAmount = new BigNumber(5); const takerTokenFillAmount = new BigNumber(5); let signedOrder: SignedOrder; - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - blockPollingIntervalMs: 0, - }; + before(async () => { + const contractAddresses = await migrateOnceAsync(); await blockchainLifecycle.startAsync(); + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + blockPollingIntervalMs: 10, + }; contractWrappers = new ContractWrappers(provider, config); - exchangeContractAddress = contractWrappers.exchange.getContractAddress(); + exchangeContractAddress = contractWrappers.exchange.address; userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - const zrxTokenAddress = tokenUtils.getProtocolTokenAddress(); + const zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress; fillScenarios = new FillScenarios( provider, userAddresses, zrxTokenAddress, exchangeContractAddress, - contractWrappers.erc20Proxy.getContractAddress(), - contractWrappers.erc721Proxy.getContractAddress(), + contractWrappers.erc20Proxy.address, + contractWrappers.erc721Proxy.address, ); [coinbase, makerAddress, takerAddress, senderAddress] = userAddresses; [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); @@ -80,12 +84,7 @@ describe('TransactionEncoder', () => { ): Promise<void> => { const salt = generatePseudoRandomSalt(); const encodedTransaction = encoder.getTransactionHex(data, salt, signerAddress); - const signature = await ecSignOrderHashAsync( - provider, - encodedTransaction, - signerAddress, - SignerType.Default, - ); + const signature = await signatureUtils.ecSignHashAsync(provider, encodedTransaction, signerAddress); txHash = await contractWrappers.exchange.executeTransactionAsync( salt, signerAddress, diff --git a/packages/contract-wrappers/test/utils/constants.ts b/packages/contract-wrappers/test/utils/constants.ts index 60c3370a2..ca6c574e4 100644 --- a/packages/contract-wrappers/test/utils/constants.ts +++ b/packages/contract-wrappers/test/utils/constants.ts @@ -1,4 +1,4 @@ -import { BigNumber } from '@0xproject/utils'; +import { BigNumber } from '@0x/utils'; export const constants = { NULL_ADDRESS: '0x0000000000000000000000000000000000000000', @@ -15,4 +15,5 @@ export const constants = { DUMMY_TOKEN_TOTAL_SUPPLY: new BigNumber(10 ** 27), // tslint:disable-line:custom-no-magic-numbers NUM_DUMMY_ERC20_TO_DEPLOY: 3, NUM_DUMMY_ERC721_TO_DEPLOY: 1, + ZERO_AMOUNT: new BigNumber(0), }; diff --git a/packages/contract-wrappers/test/utils/migrate.ts b/packages/contract-wrappers/test/utils/migrate.ts new file mode 100644 index 000000000..665ce0faa --- /dev/null +++ b/packages/contract-wrappers/test/utils/migrate.ts @@ -0,0 +1,18 @@ +import { ContractAddresses } from '@0x/contract-addresses'; +import { devConstants } from '@0x/dev-utils'; +import { runMigrationsOnceAsync } from '@0x/migrations'; + +import { provider } from './web3_wrapper'; + +/** + * Configures and runs the migrations exactly once. Any subsequent times this is + * called, it returns the cached addresses. + * @returns The addresses of contracts that were deployed during the migrations. + */ +export async function migrateOnceAsync(): Promise<ContractAddresses> { + const txDefaults = { + gas: devConstants.GAS_LIMIT, + from: devConstants.TESTRPC_FIRST_ADDRESS, + }; + return runMigrationsOnceAsync(provider, txDefaults); +} diff --git a/packages/contract-wrappers/test/utils/token_utils.ts b/packages/contract-wrappers/test/utils/token_utils.ts index 06a82ff6e..f8a88637f 100644 --- a/packages/contract-wrappers/test/utils/token_utils.ts +++ b/packages/contract-wrappers/test/utils/token_utils.ts @@ -1,14 +1,13 @@ -import { generatePseudoRandomSalt } from '@0xproject/order-utils'; -import { BigNumber } from '@0xproject/utils'; +import { DummyERC721TokenContract } from '@0x/abi-gen-wrappers'; +import { DummyERC721Token } from '@0x/contract-artifacts'; +import { generatePseudoRandomSalt } from '@0x/order-utils'; +import { BigNumber } from '@0x/utils'; -import { artifacts } from '../../src/artifacts'; -import { DummyERC721TokenContract } from '../../src/contract_wrappers/generated/dummy_erc721_token'; - -import { constants } from './constants'; import { provider, txDefaults, web3Wrapper } from './web3_wrapper'; // Those addresses come from migrations. They're deterministic so it's relatively safe to hard-code them here. // Before we were fetching them from the TokenRegistry but now we can't as it's deprecated and removed. +// TODO(albrow): Import these from the migrations package instead of hard-coding them. const DUMMY_ERC_20_ADRESSES = [ '0x6dfff22588be9b3ef8cf0ad6dc9b84796f9fb45f', '0xcfc18cec799fbd1793b5c43e773c98d4d61cc2db', @@ -20,12 +19,6 @@ const DUMMY_ERC_20_ADRESSES = [ const DUMMY_ERC_721_ADRESSES = ['0x131855dda0aaff096f6854854c55a4debf61077a']; export const tokenUtils = { - getProtocolTokenAddress(): string { - return artifacts.ZRXToken.networks[constants.TESTRPC_NETWORK_ID].address; - }, - getWethTokenAddress(): string { - return artifacts.EtherToken.networks[constants.TESTRPC_NETWORK_ID].address; - }, getDummyERC20TokenAddresses(): string[] { return DUMMY_ERC_20_ADRESSES; }, @@ -33,12 +26,7 @@ export const tokenUtils = { return DUMMY_ERC_721_ADRESSES; }, async mintDummyERC721Async(address: string, tokenOwner: string): Promise<BigNumber> { - const erc721 = new DummyERC721TokenContract( - artifacts.DummyERC721Token.compilerOutput.abi, - address, - provider, - txDefaults, - ); + const erc721 = new DummyERC721TokenContract(DummyERC721Token.compilerOutput.abi, address, provider, txDefaults); const tokenId = generatePseudoRandomSalt(); const txHash = await erc721.mint.sendTransactionAsync(tokenOwner, tokenId); web3Wrapper.awaitTransactionSuccessAsync(txHash); diff --git a/packages/contract-wrappers/test/utils/web3_wrapper.ts b/packages/contract-wrappers/test/utils/web3_wrapper.ts index 02c8c5918..4e86ebeba 100644 --- a/packages/contract-wrappers/test/utils/web3_wrapper.ts +++ b/packages/contract-wrappers/test/utils/web3_wrapper.ts @@ -1,5 +1,5 @@ -import { devConstants, web3Factory } from '@0xproject/dev-utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import { devConstants, web3Factory } from '@0x/dev-utils'; +import { Web3Wrapper } from '@0x/web3-wrapper'; import { Provider } from 'ethereum-types'; const txDefaults = { |