diff --git a/contracts/exchange/contracts/test/TestSignatureValidator.sol b/contracts/exchange/contracts/test/TestSignatureValidator.sol deleted file mode 100644 index 600e06523a..0000000000 --- a/contracts/exchange/contracts/test/TestSignatureValidator.sol +++ /dev/null @@ -1,37 +0,0 @@ -/* - - Copyright 2019 ZeroEx Intl. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pragma solidity ^0.5.5; -pragma experimental ABIEncoderV2; - -import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol"; -import "../src/MixinSignatureValidator.sol"; -import "../src/MixinTransactions.sol"; - - -contract TestSignatureValidator is - LibEIP712ExchangeDomain, - MixinSignatureValidator -{ - - // solhint-disable no-empty-blocks - constructor (uint256 chainId) - public - LibEIP712ExchangeDomain(chainId, address(0)) - {} -} diff --git a/contracts/exchange/src/index.ts b/contracts/exchange/src/index.ts index 7d80a4e498..d3b1d4e71c 100644 --- a/contracts/exchange/src/index.ts +++ b/contracts/exchange/src/index.ts @@ -1,6 +1,4 @@ export * from './artifacts'; export * from './wrappers'; export import ExchangeRevertErrors = require('./revert_errors'); -export { BlockchainBalanceStore } from './balance_stores/blockchain_balance_store'; -export { LocalBalanceStore } from './balance_stores/local_balance_store'; export { exchangeDataEncoder } from './exchange_data_encoder'; diff --git a/contracts/exchange/test/artifacts.ts b/contracts/exchange/test/artifacts.ts index 89075160f7..d3fb1e0506 100644 --- a/contracts/exchange/test/artifacts.ts +++ b/contracts/exchange/test/artifacts.ts @@ -37,7 +37,6 @@ import * as TestLibExchangeRichErrorDecoder from '../test/generated-artifacts/Te import * as TestProtocolFeeCollector from '../test/generated-artifacts/TestProtocolFeeCollector.json'; import * as TestProtocolFees from '../test/generated-artifacts/TestProtocolFees.json'; import * as TestProtocolFeesReceiver from '../test/generated-artifacts/TestProtocolFeesReceiver.json'; -import * as TestSignatureValidator from '../test/generated-artifacts/TestSignatureValidator.json'; import * as TestTransactions from '../test/generated-artifacts/TestTransactions.json'; import * as TestValidatorWallet from '../test/generated-artifacts/TestValidatorWallet.json'; import * as TestWrapperFunctions from '../test/generated-artifacts/TestWrapperFunctions.json'; @@ -74,7 +73,6 @@ export const artifacts = { TestProtocolFeeCollector: TestProtocolFeeCollector as ContractArtifact, TestProtocolFees: TestProtocolFees as ContractArtifact, TestProtocolFeesReceiver: TestProtocolFeesReceiver as ContractArtifact, - TestSignatureValidator: TestSignatureValidator as ContractArtifact, TestTransactions: TestTransactions as ContractArtifact, TestValidatorWallet: TestValidatorWallet as ContractArtifact, TestWrapperFunctions: TestWrapperFunctions as ContractArtifact, diff --git a/contracts/exchange/test/signature_validator.ts b/contracts/exchange/test/signature_validator.ts index 2de6fa2642..0d5c1a775e 100644 --- a/contracts/exchange/test/signature_validator.ts +++ b/contracts/exchange/test/signature_validator.ts @@ -1,4 +1,6 @@ +import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy'; import { DevUtilsContract } from '@0x/contracts-dev-utils'; +import { DummyERC20TokenContract } from '@0x/contracts-erc20'; import { blockchainTests, constants, @@ -12,6 +14,7 @@ import { randomAddress, TransactionFactory, transactionHashUtils, + ValidatorWalletAction, } from '@0x/contracts-test-utils'; import { SignatureType, SignedOrder, SignedZeroExTransaction } from '@0x/types'; import { BigNumber, StringRevertError } from '@0x/utils'; @@ -22,33 +25,35 @@ import ExchangeRevertErrors = require('../src/revert_errors'); import { artifacts } from './artifacts'; import { + ExchangeContract, + ExchangeSignatureValidatorApprovalEventArgs, IEIP1271DataContract, - TestSignatureValidatorContract, - TestSignatureValidatorSignatureValidatorApprovalEventArgs, TestValidatorWalletContract, } from './wrappers'; -import { ValidatorWalletAction } from './utils/constants'; - // tslint:disable:no-unnecessary-type-assertion blockchainTests.resets('MixinSignatureValidator', env => { let chainId: number; - let signatureValidator: TestSignatureValidatorContract; + let exchange: ExchangeContract; let validatorWallet: TestValidatorWalletContract; let validatorWalletRevertReason: string; let signerAddress: string; let signerPrivateKey: Buffer; let notSignerAddress: string; + let accounts: string[]; + let owner: string; + let makerAddress: string; + let takerAddress: string; + let feeRecipientAddress: string; const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, env.provider, env.txDefaults); const eip1271Data = new IEIP1271DataContract(constants.NULL_ADDRESS, env.provider, env.txDefaults); before(async () => { chainId = await env.getChainIdAsync(); - const accounts = await env.getAccountAddressesAsync(); - signerAddress = accounts[0]; - notSignerAddress = accounts[1]; - signatureValidator = await TestSignatureValidatorContract.deployFrom0xArtifactAsync( - artifacts.TestSignatureValidator, + accounts = await env.getAccountAddressesAsync(); + [owner, signerAddress, notSignerAddress, makerAddress, takerAddress, feeRecipientAddress] = accounts; + exchange = await ExchangeContract.deployFrom0xArtifactAsync( + artifacts.Exchange, env.provider, env.txDefaults, {}, @@ -59,14 +64,14 @@ blockchainTests.resets('MixinSignatureValidator', env => { env.provider, env.txDefaults, {}, - signatureValidator.address, + exchange.address, ); validatorWalletRevertReason = await validatorWallet.REVERT_REASON().callAsync(); // Approve the validator for both signers. await Promise.all( [signerAddress, notSignerAddress].map(async (addr: string) => { - return signatureValidator + return exchange .setSignatureValidatorApproval(validatorWallet.address, true) .awaitTransactionSuccessAsync({ from: addr }); }), @@ -300,7 +305,7 @@ blockchainTests.resets('MixinSignatureValidator', env => { it('should return true when SignatureType=Presigned and signer has presigned hash', async () => { const hashHex = getCurrentHashHex(); // Presign the hash - await signatureValidator.preSign(hashHex).awaitTransactionSuccessAsync({ from: signerAddress }); + await exchange.preSign(hashHex).awaitTransactionSuccessAsync({ from: signerAddress }); // Validate presigned signature const signatureHex = hexConcat(SignatureType.PreSigned); const isValidSignature = await validateAsync(hashHex, signerAddress, signatureHex); @@ -338,7 +343,7 @@ blockchainTests.resets('MixinSignatureValidator', env => { .prepare(_hashHex, validatorAction, expectedSignatureHashHex) .awaitTransactionSuccessAsync(); } - return signatureValidator.isValidHashSignature(_hashHex, _signerAddress, signatureHex).callAsync(); + return exchange.isValidHashSignature(_hashHex, _signerAddress, signatureHex).callAsync(); }; it('should revert when signerAddress == 0', async () => { @@ -387,9 +392,7 @@ blockchainTests.resets('MixinSignatureValidator', env => { const trezorSignatureType = ethUtil.toBuffer(`0x${SignatureType.EthSign}`); const signature = Buffer.concat([v, r, s, trezorSignatureType]); const signatureHex = ethUtil.bufferToHex(signature); - const isValidSignature = await signatureValidator - .isValidHashSignature(messageHash, signer, signatureHex) - .callAsync(); + const isValidSignature = await exchange.isValidHashSignature(messageHash, signer, signatureHex).callAsync(); expect(isValidSignature).to.be.true(); }); @@ -403,9 +406,7 @@ blockchainTests.resets('MixinSignatureValidator', env => { const trezorSignatureType = ethUtil.toBuffer(`0x${SignatureType.EthSign}`); const signature = Buffer.concat([v, r, s, trezorSignatureType]); const signatureHex = ethUtil.bufferToHex(signature); - const isValidSignature = await signatureValidator - .isValidHashSignature(messageHash, signer, signatureHex) - .callAsync(); + const isValidSignature = await exchange.isValidHashSignature(messageHash, signer, signatureHex).callAsync(); expect(isValidSignature).to.be.true(); }); @@ -417,10 +418,9 @@ blockchainTests.resets('MixinSignatureValidator', env => { let signedOrder: SignedOrder; before(async () => { - const makerAddress = signerAddress; const defaultOrderParams = { ...constants.STATIC_ORDER_PARAMS, - makerAddress, + makerAddress: signerAddress, feeRecipientAddress: randomAddress(), makerAssetData: await devUtils.encodeERC20AssetData(randomAddress()).callAsync(), takerAssetData: await devUtils.encodeERC20AssetData(randomAddress()).callAsync(), @@ -428,7 +428,7 @@ blockchainTests.resets('MixinSignatureValidator', env => { takerFeeAssetData: await devUtils.encodeERC20AssetData(randomAddress()).callAsync(), makerFee: constants.ZERO_AMOUNT, takerFee: constants.ZERO_AMOUNT, - exchangeAddress: signatureValidator.address, + exchangeAddress: exchange.address, chainId, }; orderFactory = new OrderFactory(signerPrivateKey, defaultOrderParams); @@ -454,7 +454,7 @@ blockchainTests.resets('MixinSignatureValidator', env => { .prepare(orderHashHex, validatorAction, expectedSignatureHashHex) .awaitTransactionSuccessAsync(); } - return signatureValidator.isValidOrderSignature(order, signatureHex).callAsync(); + return exchange.isValidOrderSignature(order, signatureHex).callAsync(); }; it('should revert when signerAddress == 0', async () => { @@ -470,7 +470,7 @@ blockchainTests.resets('MixinSignatureValidator', env => { constants.NULL_ADDRESS, signatureHex, ); - const tx = signatureValidator.isValidOrderSignature(nullMakerOrder, signatureHex).callAsync(); + const tx = exchange.isValidOrderSignature(nullMakerOrder, signatureHex).callAsync(); return expect(tx).to.revertWith(expectedError); }); @@ -566,7 +566,7 @@ blockchainTests.resets('MixinSignatureValidator', env => { it('should revert when SignatureType=Validator and signature is shorter than 21 bytes', async () => { // Set approval of signature validator to false - await signatureValidator + await exchange .setSignatureValidatorApproval(validatorWallet.address, false) .awaitTransactionSuccessAsync({ from: signedOrder.makerAddress }); // Doesn't have to contain a real signature since our wallet contract @@ -585,7 +585,7 @@ blockchainTests.resets('MixinSignatureValidator', env => { it('should revert when SignatureType=Validator, signature is valid and validator is not approved', async () => { // Set approval of signature validator to false - await signatureValidator + await exchange .setSignatureValidatorApproval(validatorWallet.address, false) .awaitTransactionSuccessAsync({ from: signedOrder.makerAddress }); // Doesn't have to contain a real signature since our wallet contract @@ -706,7 +706,7 @@ blockchainTests.resets('MixinSignatureValidator', env => { signatureHex, constants.NULL_BYTES, ); - const tx = signatureValidator.isValidOrderSignature(signedOrder, signatureHex).callAsync(); + const tx = exchange.isValidOrderSignature(signedOrder, signatureHex).callAsync(); return expect(tx).to.revertWith(expectedError); }); @@ -721,16 +721,16 @@ blockchainTests.resets('MixinSignatureValidator', env => { constants.NULL_BYTES, ); // Register an EOA as a validator. - await signatureValidator + await exchange .setSignatureValidatorApproval(notSignerAddress, true) .awaitTransactionSuccessAsync({ from: signerAddress }); - const tx = signatureValidator.isValidOrderSignature(signedOrder, signatureHex).callAsync(); + const tx = exchange.isValidOrderSignature(signedOrder, signatureHex).callAsync(); return expect(tx).to.revertWith(expectedError); }); // Run hash-only signature type tests as well. const validateOrderHashAsync = async ( - hashHex: string, + _hashHex: string, _signerAddress: string, signatureHex: string, validatorAction?: ValidatorWalletAction, @@ -751,7 +751,7 @@ blockchainTests.resets('MixinSignatureValidator', env => { const TRANSACTION_DATA_LENGTH = 100; before(async () => { - transactionFactory = new TransactionFactory(signerPrivateKey, signatureValidator.address, chainId); + transactionFactory = new TransactionFactory(signerPrivateKey, exchange.address, chainId); }); beforeEach(async () => { @@ -778,7 +778,7 @@ blockchainTests.resets('MixinSignatureValidator', env => { .prepare(transactionHashHex, validatorAction, expectedSignatureHashHex) .awaitTransactionSuccessAsync(); } - return signatureValidator.isValidTransactionSignature(transaction, signatureHex).callAsync(); + return exchange.isValidTransactionSignature(transaction, signatureHex).callAsync(); }; it('should revert when signerAddress == 0', async () => { @@ -794,7 +794,7 @@ blockchainTests.resets('MixinSignatureValidator', env => { constants.NULL_ADDRESS, signatureHex, ); - const tx = signatureValidator.isValidTransactionSignature(nullSignerTransaction, signatureHex).callAsync(); + const tx = exchange.isValidTransactionSignature(nullSignerTransaction, signatureHex).callAsync(); return expect(tx).to.revertWith(expectedError); }); @@ -841,7 +841,7 @@ blockchainTests.resets('MixinSignatureValidator', env => { it('should revert when SignatureType=Validator and signature is shorter than 21 bytes', async () => { // Set approval of signature validator to false - await signatureValidator + await exchange .setSignatureValidatorApproval(validatorWallet.address, false) .awaitTransactionSuccessAsync({ from: signedTransaction.signerAddress }); // Doesn't have to contain a real signature since our wallet contract @@ -920,7 +920,7 @@ blockchainTests.resets('MixinSignatureValidator', env => { it('should revert when SignatureType=Validator, signature is valid and validator is not approved', async () => { // Set approval of signature validator to false - await signatureValidator + await exchange .setSignatureValidatorApproval(validatorWallet.address, false) .awaitTransactionSuccessAsync({ from: signedTransaction.signerAddress }); // Doesn't have to contain a real signature since our wallet contract @@ -1055,7 +1055,7 @@ blockchainTests.resets('MixinSignatureValidator', env => { signatureHex, constants.NULL_BYTES, ); - const tx = signatureValidator.isValidTransactionSignature(signedTransaction, signatureHex).callAsync(); + const tx = exchange.isValidTransactionSignature(signedTransaction, signatureHex).callAsync(); return expect(tx).to.revertWith(expectedError); }); @@ -1072,16 +1072,16 @@ blockchainTests.resets('MixinSignatureValidator', env => { constants.NULL_BYTES, ); // Register an EOA as a validator. - await signatureValidator + await exchange .setSignatureValidatorApproval(notSignerAddress, true) .awaitTransactionSuccessAsync({ from: signerAddress }); - const tx = signatureValidator.isValidTransactionSignature(signedTransaction, signatureHex).callAsync(); + const tx = exchange.isValidTransactionSignature(signedTransaction, signatureHex).callAsync(); return expect(tx).to.revertWith(expectedError); }); // Run hash-only signature type tests as well. const validateOrderHashAsync = async ( - hashHex: string, + _hashHex: string, _signerAddress: string, signatureHex: string, validatorAction?: ValidatorWalletAction, @@ -1105,14 +1105,14 @@ blockchainTests.resets('MixinSignatureValidator', env => { it('should emit a SignatureValidatorApprovalSet with correct args when a validator is approved', async () => { const approval = true; - const res = await signatureValidator + const res = await exchange .setSignatureValidatorApproval(validatorWallet.address, approval) .awaitTransactionSuccessAsync({ from: signerAddress, }); expect(res.logs.length).to.equal(1); const log = signatureValidatorLogDecoder.decodeLogOrThrow(res.logs[0]) as LogWithDecodedArgs< - TestSignatureValidatorSignatureValidatorApprovalEventArgs + ExchangeSignatureValidatorApprovalEventArgs >; const logArgs = log.args; expect(logArgs.signerAddress).to.equal(signerAddress); @@ -1121,14 +1121,14 @@ blockchainTests.resets('MixinSignatureValidator', env => { }); it('should emit a SignatureValidatorApprovalSet with correct args when a validator is disapproved', async () => { const approval = false; - const res = await signatureValidator + const res = await exchange .setSignatureValidatorApproval(validatorWallet.address, approval) .awaitTransactionSuccessAsync({ from: signerAddress, }); expect(res.logs.length).to.equal(1); const log = signatureValidatorLogDecoder.decodeLogOrThrow(res.logs[0]) as LogWithDecodedArgs< - TestSignatureValidatorSignatureValidatorApprovalEventArgs + ExchangeSignatureValidatorApprovalEventArgs >; const logArgs = log.args; expect(logArgs.signerAddress).to.equal(signerAddress); @@ -1136,6 +1136,153 @@ blockchainTests.resets('MixinSignatureValidator', env => { expect(logArgs.isApproved).to.equal(approval); }); }); + + describe('fillOrder integration tests', () => { + let erc20Wrapper: ERC20Wrapper; + let erc20Proxy: ERC20ProxyContract; + let erc20TokenA: DummyERC20TokenContract; + let erc20TokenB: DummyERC20TokenContract; + let feeToken: DummyERC20TokenContract; + let orderFactory: OrderFactory; + let signedOrder: SignedOrder; + + before(async () => { + // Deploy ERC20 proxy and tokens + erc20Wrapper = new ERC20Wrapper(env.provider, accounts, owner); + erc20Proxy = await erc20Wrapper.deployProxyAsync(); + const numDummyErc20ToDeploy = 3; + [erc20TokenA, erc20TokenB, feeToken] = await erc20Wrapper.deployDummyTokensAsync( + numDummyErc20ToDeploy, + constants.DUMMY_TOKEN_DECIMALS, + ); + await erc20Wrapper.setBalancesAndAllowancesAsync(); + + // Configure ERC20 proxy and exchange + await erc20Proxy.addAuthorizedAddress(exchange.address).awaitTransactionSuccessAsync({ from: owner }); + await exchange.registerAssetProxy(erc20Proxy.address).awaitTransactionSuccessAsync({ from: owner }); + + // Configure order defaults + const defaultMakerAssetAddress = erc20TokenA.address; + const defaultTakerAssetAddress = erc20TokenB.address; + const defaultFeeAssetAddress = feeToken.address; + const defaultOrderParams = { + ...constants.STATIC_ORDER_PARAMS, + makerAddress, + feeRecipientAddress, + makerAssetData: await devUtils.encodeERC20AssetData(defaultMakerAssetAddress).callAsync(), + takerAssetData: await devUtils.encodeERC20AssetData(defaultTakerAssetAddress).callAsync(), + makerFeeAssetData: await devUtils.encodeERC20AssetData(defaultFeeAssetAddress).callAsync(), + takerFeeAssetData: await devUtils.encodeERC20AssetData(defaultFeeAssetAddress).callAsync(), + exchangeAddress: exchange.address, + chainId, + }; + const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)]; + orderFactory = new OrderFactory(privateKey, defaultOrderParams); + + // Approve the ERC20 proxy with the test validator wallet. + await validatorWallet + .approveERC20(erc20TokenA.address, erc20Proxy.address, constants.INITIAL_ERC20_ALLOWANCE) + .awaitTransactionSuccessAsync(); + // Mint some ERC20 tokens to the test validator wallet. + await erc20TokenA + .setBalance(validatorWallet.address, constants.INITIAL_ERC20_BALANCE) + .awaitTransactionSuccessAsync(); + // Approve the validator. + await exchange.setSignatureValidatorApproval(validatorWallet.address, true).awaitTransactionSuccessAsync({ + from: makerAddress, + }); + signedOrder = await orderFactory.newSignedOrderAsync({ + makerFee: constants.ZERO_AMOUNT, + takerFee: constants.ZERO_AMOUNT, + }); + }); + + it('should revert if `Validator` signature type rejects during a second fill', async () => { + const signatureHex = hexConcat(validatorWallet.address, SignatureType.Validator); + signedOrder.signature = signatureHex; + const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); + // Allow the signature check for the first fill. + await validatorWallet + .prepare(orderHashHex, ValidatorWalletAction.Accept, constants.NULL_BYTES) + .awaitTransactionSuccessAsync(); + const fillAmount = signedOrder.takerAssetAmount.div(10); + await exchange.fillOrder(signedOrder, fillAmount, signedOrder.signature).awaitTransactionSuccessAsync({ + from: takerAddress, + }); + // Reject the signature check for the second fill. + await validatorWallet + .prepare(orderHashHex, ValidatorWalletAction.Reject, constants.NULL_BYTES) + .awaitTransactionSuccessAsync(); + const tx = exchange.fillOrder(signedOrder, fillAmount, signedOrder.signature).awaitTransactionSuccessAsync({ + from: takerAddress, + }); + const expectedError = new ExchangeRevertErrors.SignatureError( + ExchangeRevertErrors.SignatureErrorCode.BadOrderSignature, + orderHashHex, + signedOrder.makerAddress, + signedOrder.signature, + ); + return expect(tx).to.revertWith(expectedError); + }); + + it('should revert if `Wallet` signature type rejects during a second fill', async () => { + const signatureHex = hexConcat(SignatureType.Wallet); + signedOrder.makerAddress = validatorWallet.address; + signedOrder.signature = signatureHex; + const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); + // Allow the signature check for the first fill. + await validatorWallet + .prepare(orderHashHex, ValidatorWalletAction.Accept, constants.NULL_BYTES) + .awaitTransactionSuccessAsync(); + const fillAmount = signedOrder.takerAssetAmount.div(10); + await exchange.fillOrder(signedOrder, fillAmount, signedOrder.signature).awaitTransactionSuccessAsync({ + from: takerAddress, + }); + // Reject the signature check for the second fill. + await validatorWallet + .prepare(orderHashHex, ValidatorWalletAction.Reject, constants.NULL_BYTES) + .awaitTransactionSuccessAsync(); + const tx = exchange.fillOrder(signedOrder, fillAmount, signedOrder.signature).awaitTransactionSuccessAsync({ + from: takerAddress, + }); + const expectedError = new ExchangeRevertErrors.SignatureError( + ExchangeRevertErrors.SignatureErrorCode.BadOrderSignature, + orderHashHex, + signedOrder.makerAddress, + signedOrder.signature, + ); + return expect(tx).to.revertWith(expectedError); + }); + + it('should revert if `EIP1271Wallet` signature type rejects during a second fill', async () => { + const signatureHex = hexConcat(SignatureType.EIP1271Wallet); + signedOrder.makerAddress = validatorWallet.address; + signedOrder.signature = signatureHex; + const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); + // Allow the signature check for the first fill. + await validatorWallet + .prepare(orderHashHex, ValidatorWalletAction.Accept, constants.NULL_BYTES) + .awaitTransactionSuccessAsync(); + const fillAmount = signedOrder.takerAssetAmount.div(10); + await exchange.fillOrder(signedOrder, fillAmount, signedOrder.signature).awaitTransactionSuccessAsync({ + from: takerAddress, + }); + // Reject the signature check for the second fill. + await validatorWallet + .prepare(orderHashHex, ValidatorWalletAction.Reject, constants.NULL_BYTES) + .awaitTransactionSuccessAsync(); + const tx = exchange.fillOrder(signedOrder, fillAmount, signedOrder.signature).awaitTransactionSuccessAsync({ + from: takerAddress, + }); + const expectedError = new ExchangeRevertErrors.SignatureError( + ExchangeRevertErrors.SignatureErrorCode.BadOrderSignature, + orderHashHex, + signedOrder.makerAddress, + signedOrder.signature, + ); + return expect(tx).to.revertWith(expectedError); + }); + }); }); // tslint:disable:max-file-line-count // tslint:enable:no-unnecessary-type-assertion diff --git a/contracts/exchange/test/utils/constants.ts b/contracts/exchange/test/utils/constants.ts index cee5450e2a..903ebe75c0 100644 --- a/contracts/exchange/test/utils/constants.ts +++ b/contracts/exchange/test/utils/constants.ts @@ -14,14 +14,3 @@ export const constants = { ExchangeFunctionName.DetachProtocolFeeCollector, ], }; - -export enum ValidatorWalletAction { - Reject = 0, - Accept = 1, - Revert = 2, - UpdateState = 3, - MatchSignatureHash = 4, - ReturnTrue = 5, - ReturnNothing = 6, - NTypes = 7, -} diff --git a/contracts/exchange/test/wrappers.ts b/contracts/exchange/test/wrappers.ts index d38276dee5..cfc716abe1 100644 --- a/contracts/exchange/test/wrappers.ts +++ b/contracts/exchange/test/wrappers.ts @@ -35,7 +35,6 @@ export * from '../test/generated-wrappers/test_lib_exchange_rich_error_decoder'; export * from '../test/generated-wrappers/test_protocol_fee_collector'; export * from '../test/generated-wrappers/test_protocol_fees'; export * from '../test/generated-wrappers/test_protocol_fees_receiver'; -export * from '../test/generated-wrappers/test_signature_validator'; export * from '../test/generated-wrappers/test_transactions'; export * from '../test/generated-wrappers/test_validator_wallet'; export * from '../test/generated-wrappers/test_wrapper_functions'; diff --git a/contracts/exchange/tsconfig.json b/contracts/exchange/tsconfig.json index b5598e3af5..e4bbba0643 100644 --- a/contracts/exchange/tsconfig.json +++ b/contracts/exchange/tsconfig.json @@ -37,7 +37,6 @@ "test/generated-artifacts/TestProtocolFeeCollector.json", "test/generated-artifacts/TestProtocolFees.json", "test/generated-artifacts/TestProtocolFeesReceiver.json", - "test/generated-artifacts/TestSignatureValidator.json", "test/generated-artifacts/TestTransactions.json", "test/generated-artifacts/TestValidatorWallet.json", "test/generated-artifacts/TestWrapperFunctions.json" diff --git a/contracts/integrations/package.json b/contracts/integrations/package.json index 8a216ccaaf..4f354bf486 100644 --- a/contracts/integrations/package.json +++ b/contracts/integrations/package.json @@ -70,6 +70,7 @@ "chai-as-promised": "^7.1.0", "chai-bignumber": "^3.0.0", "dirty-chai": "^2.0.1", + "js-combinatorics": "^0.5.3", "make-promises-safe": "^1.1.0", "mocha": "^6.2.0", "npm-run-all": "^4.1.2", diff --git a/contracts/integrations/src/index.ts b/contracts/integrations/src/index.ts index d595a9f090..d55f08ea2d 100644 --- a/contracts/integrations/src/index.ts +++ b/contracts/integrations/src/index.ts @@ -1,3 +1,2 @@ export * from './artifacts'; export * from './wrappers'; -export * from './function_assertions'; diff --git a/contracts/integrations/test/actors/index.ts b/contracts/integrations/test/actors/index.ts deleted file mode 100644 index d712eb0efd..0000000000 --- a/contracts/integrations/test/actors/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export { Actor } from './base'; -export { Maker } from './maker'; -export { PoolOperator } from './pool_operator'; -export { FeeRecipient } from './fee_recipient'; -export { Staker } from './staker'; -export { Keeper } from './keeper'; -export { Taker } from './taker'; -export * from './hybrids'; -export * from './utils'; diff --git a/contracts/integrations/test/coordinator/coordinator_test.ts b/contracts/integrations/test/coordinator/coordinator_test.ts index 711c77b22c..71204c26b0 100644 --- a/contracts/integrations/test/coordinator/coordinator_test.ts +++ b/contracts/integrations/test/coordinator/coordinator_test.ts @@ -1,13 +1,11 @@ import { CoordinatorContract, CoordinatorRevertErrors, SignedCoordinatorApproval } from '@0x/contracts-coordinator'; import { DevUtilsContract } from '@0x/contracts-dev-utils'; import { - BlockchainBalanceStore, ExchangeCancelEventArgs, ExchangeCancelUpToEventArgs, exchangeDataEncoder, ExchangeEvents, ExchangeFillEventArgs, - LocalBalanceStore, } from '@0x/contracts-exchange'; import { blockchainTests, @@ -25,8 +23,13 @@ import { SignedOrder, SignedZeroExTransaction } from '@0x/types'; import { BigNumber } from '@0x/utils'; import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; -import { Actor, actorAddressesByName, FeeRecipient, Maker } from '../actors'; -import { DeploymentManager } from '../deployment_manager'; +import { Actor } from '../framework/actors/base'; +import { FeeRecipient } from '../framework/actors/fee_recipient'; +import { Maker } from '../framework/actors/maker'; +import { actorAddressesByName } from '../framework/actors/utils'; +import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store'; +import { LocalBalanceStore } from '../framework/balances/local_balance_store'; +import { DeploymentManager } from '../framework/deployment_manager'; import { deployCoordinatorAsync } from './deploy_coordinator'; diff --git a/contracts/integrations/test/coordinator/deploy_coordinator.ts b/contracts/integrations/test/coordinator/deploy_coordinator.ts index 90b274da60..b393c962c0 100644 --- a/contracts/integrations/test/coordinator/deploy_coordinator.ts +++ b/contracts/integrations/test/coordinator/deploy_coordinator.ts @@ -3,7 +3,7 @@ import { artifacts as exchangeArtifacts } from '@0x/contracts-exchange'; import { BlockchainTestsEnvironment } from '@0x/contracts-test-utils'; import { BigNumber } from '@0x/utils'; -import { DeploymentManager } from '../deployment_manager'; +import { DeploymentManager } from '../framework/deployment_manager'; /** * Deploys a Coordinator contract configured to work alongside the provided `deployment`. diff --git a/contracts/integrations/test/internal-integration-tests/deployment_test.ts b/contracts/integrations/test/deployment_test.ts similarity index 99% rename from contracts/integrations/test/internal-integration-tests/deployment_test.ts rename to contracts/integrations/test/deployment_test.ts index 22d9109d39..5cc02e5f40 100644 --- a/contracts/integrations/test/internal-integration-tests/deployment_test.ts +++ b/contracts/integrations/test/deployment_test.ts @@ -33,7 +33,7 @@ import { AssetProxyId } from '@0x/types'; import { BigNumber } from '@0x/utils'; import { TxData } from 'ethereum-types'; -import { AssetProxyDispatcher, Authorizable, Ownable } from '../wrapper_interfaces'; +import { AssetProxyDispatcher, Authorizable, Ownable } from './framework/wrapper_interfaces'; // tslint:disable:no-unnecessary-type-assertion blockchainTests('Deployment and Configuration End to End Tests', env => { diff --git a/contracts/exchange/test/core.ts b/contracts/integrations/test/exchange/core_test.ts similarity index 84% rename from contracts/exchange/test/core.ts rename to contracts/integrations/test/exchange/core_test.ts index e07332edf1..4200d4dece 100644 --- a/contracts/exchange/test/core.ts +++ b/contracts/integrations/test/exchange/core_test.ts @@ -18,6 +18,7 @@ import { DummyNoReturnERC20TokenContract, } from '@0x/contracts-erc20'; import { DummyERC721TokenContract } from '@0x/contracts-erc721'; +import { artifacts, ExchangeCancelEventArgs, ExchangeContract, ExchangeRevertErrors } from '@0x/contracts-exchange'; import { LibMathRevertErrors } from '@0x/contracts-exchange-libs'; import { blockchainTests, @@ -26,7 +27,6 @@ import { ERC20BalancesByOwner, expect, getLatestBlockTimestampAsync, - hexConcat, increaseTimeAndMineBlockAsync, OrderFactory, orderHashUtils, @@ -35,20 +35,13 @@ import { txDefaults, web3Wrapper, } from '@0x/contracts-test-utils'; -import { RevertReason, SignatureType, SignedOrder } from '@0x/types'; +import { RevertReason, SignedOrder } from '@0x/types'; import { BigNumber, providerUtils, StringRevertError } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { LogWithDecodedArgs } from 'ethereum-types'; import * as _ from 'lodash'; -import ExchangeRevertErrors = require('../src/revert_errors'); - -import { ValidatorWalletAction } from './utils/constants'; -import { ExchangeWrapper } from './utils/exchange_wrapper'; - -import { artifacts } from './artifacts'; -import { FillOrderWrapper } from './assertion_wrappers/fill_order_wrapper'; -import { ExchangeCancelEventArgs, ExchangeContract, TestValidatorWalletContract } from './wrappers'; +import { FillOrderWrapper } from './fill_order_wrapper'; // tslint:disable:no-unnecessary-type-assertion blockchainTests.resets('Exchange core', () => { @@ -69,14 +62,12 @@ blockchainTests.resets('Exchange core', () => { let erc721Proxy: ERC721ProxyContract; let erc1155Proxy: ERC1155ProxyContract; let multiAssetProxy: MultiAssetProxyContract; - let validatorWallet: TestValidatorWalletContract; let erc1155Contract: ERC1155MintableContract; let staticCallProxy: StaticCallProxyContract; let staticCallTarget: TestStaticCallTargetContract; let signedOrder: SignedOrder; let erc20Balances: ERC20BalancesByOwner; - let exchangeWrapper: ExchangeWrapper; let erc20Wrapper: ERC20Wrapper; let erc721Wrapper: ERC721Wrapper; let erc1155Wrapper: Erc1155Wrapper; @@ -147,13 +138,6 @@ blockchainTests.resets('Exchange core', () => { {}, new BigNumber(chainId), ); - validatorWallet = await TestValidatorWalletContract.deployFrom0xArtifactAsync( - artifacts.TestValidatorWallet, - provider, - txDefaults, - {}, - exchange.address, - ); // Configure ERC20Proxy await erc20Proxy.addAuthorizedAddress(exchange.address).awaitTransactionSuccessAsync({ from: owner }); await erc20Proxy.addAuthorizedAddress(multiAssetProxy.address).awaitTransactionSuccessAsync({ from: owner }); @@ -173,12 +157,9 @@ blockchainTests.resets('Exchange core', () => { await multiAssetProxy.registerAssetProxy(staticCallProxy.address).awaitTransactionSuccessAsync({ from: owner }); // Configure Exchange - exchangeWrapper = new ExchangeWrapper(exchange); - await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner); - await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner); - await exchangeWrapper.registerAssetProxyAsync(erc1155Proxy.address, owner); - await exchangeWrapper.registerAssetProxyAsync(multiAssetProxy.address, owner); - await exchangeWrapper.registerAssetProxyAsync(staticCallProxy.address, owner); + for (const proxy of [erc20Proxy, erc721Proxy, erc1155Proxy, multiAssetProxy, staticCallProxy]) { + await exchange.registerAssetProxy(proxy.address).awaitTransactionSuccessAsync({ from: owner }); + } // Configure ERC20 tokens await erc20Wrapper.setBalancesAndAllowancesAsync(); @@ -252,115 +233,16 @@ blockchainTests.resets('Exchange core', () => { signedOrder = await orderFactory.newSignedOrderAsync(); }); - describe('callback signature types', () => { - beforeEach(async () => { - // Approve the ERC20 proxy with the test validator wallet. - await validatorWallet - .approveERC20(erc20TokenA.address, erc20Proxy.address, constants.INITIAL_ERC20_ALLOWANCE) - .awaitTransactionSuccessAsync(); - // Mint some ERC20 tokens to the test validator wallet. - await erc20TokenA - .setBalance(validatorWallet.address, constants.INITIAL_ERC20_BALANCE) - .awaitTransactionSuccessAsync(); - // Approve the validator. - await exchange - .setSignatureValidatorApproval(validatorWallet.address, true) - .awaitTransactionSuccessAsync({ - from: makerAddress, - }); - signedOrder = await orderFactory.newSignedOrderAsync({ - makerFee: constants.ZERO_AMOUNT, - takerFee: constants.ZERO_AMOUNT, - }); - }); - - it('should revert if `Validator` signature type rejects during a second fill', async () => { - const signatureHex = hexConcat(validatorWallet.address, SignatureType.Validator); - signedOrder.signature = signatureHex; - const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); - // Allow the signature check for the first fill. - await validatorWallet - .prepare(orderHashHex, ValidatorWalletAction.Accept, constants.NULL_BYTES) - .awaitTransactionSuccessAsync(); - const fillAmount = signedOrder.takerAssetAmount.div(10); - await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount: fillAmount }); - // Reject the signature check for the second fill. - await validatorWallet - .prepare(orderHashHex, ValidatorWalletAction.Reject, constants.NULL_BYTES) - .awaitTransactionSuccessAsync(); - const tx = exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { - takerAssetFillAmount: fillAmount, - }); - const expectedError = new ExchangeRevertErrors.SignatureError( - ExchangeRevertErrors.SignatureErrorCode.BadOrderSignature, - orderHashHex, - signedOrder.makerAddress, - signedOrder.signature, - ); - return expect(tx).to.revertWith(expectedError); - }); - - it('should revert if `Wallet` signature type rejects during a second fill', async () => { - const signatureHex = hexConcat(SignatureType.Wallet); - signedOrder.makerAddress = validatorWallet.address; - signedOrder.signature = signatureHex; - const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); - // Allow the signature check for the first fill. - await validatorWallet - .prepare(orderHashHex, ValidatorWalletAction.Accept, constants.NULL_BYTES) - .awaitTransactionSuccessAsync(); - const fillAmount = signedOrder.takerAssetAmount.div(10); - await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount: fillAmount }); - // Reject the signature check for the second fill. - await validatorWallet - .prepare(orderHashHex, ValidatorWalletAction.Reject, constants.NULL_BYTES) - .awaitTransactionSuccessAsync(); - const tx = exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { - takerAssetFillAmount: fillAmount, - }); - const expectedError = new ExchangeRevertErrors.SignatureError( - ExchangeRevertErrors.SignatureErrorCode.BadOrderSignature, - orderHashHex, - signedOrder.makerAddress, - signedOrder.signature, - ); - return expect(tx).to.revertWith(expectedError); - }); - - it('should revert if `EIP1271Wallet` signature type rejects during a second fill', async () => { - const signatureHex = hexConcat(SignatureType.EIP1271Wallet); - signedOrder.makerAddress = validatorWallet.address; - signedOrder.signature = signatureHex; - const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); - // Allow the signature check for the first fill. - await validatorWallet - .prepare(orderHashHex, ValidatorWalletAction.Accept, constants.NULL_BYTES) - .awaitTransactionSuccessAsync(); - const fillAmount = signedOrder.takerAssetAmount.div(10); - await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount: fillAmount }); - // Reject the signature check for the second fill. - await validatorWallet - .prepare(orderHashHex, ValidatorWalletAction.Reject, constants.NULL_BYTES) - .awaitTransactionSuccessAsync(); - const tx = exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { - takerAssetFillAmount: fillAmount, - }); - const expectedError = new ExchangeRevertErrors.SignatureError( - ExchangeRevertErrors.SignatureErrorCode.BadOrderSignature, - orderHashHex, - signedOrder.makerAddress, - signedOrder.signature, - ); - return expect(tx).to.revertWith(expectedError); - }); - }); - it('should revert if fully filled', async () => { signedOrder = await orderFactory.newSignedOrderAsync(); const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); - await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress); + await exchange + .fillOrder(signedOrder, signedOrder.takerAssetAmount, signedOrder.signature) + .awaitTransactionSuccessAsync({ from: takerAddress }); const expectedError = new ExchangeRevertErrors.OrderStatusError(orderHashHex, OrderStatus.FullyFilled); - const tx = exchangeWrapper.fillOrderAsync(signedOrder, takerAddress); + const tx = exchange + .fillOrder(signedOrder, signedOrder.takerAssetAmount, signedOrder.signature) + .awaitTransactionSuccessAsync({ from: takerAddress }); return expect(tx).to.revertWith(expectedError); }); @@ -375,7 +257,9 @@ blockchainTests.resets('Exchange core', () => { }); const orderHash = orderHashUtils.getOrderHashHex(signedOrder); const expectedError = new ExchangeRevertErrors.OrderStatusError(orderHash, OrderStatus.Expired); - const tx = exchangeWrapper.fillOrderAsync(signedOrder, takerAddress); + const tx = exchange + .fillOrder(signedOrder, signedOrder.takerAssetAmount, signedOrder.signature) + .awaitTransactionSuccessAsync({ from: takerAddress }); return expect(tx).to.revertWith(expectedError); }); @@ -386,9 +270,9 @@ blockchainTests.resets('Exchange core', () => { }); const fillTakerAssetAmount1 = new BigNumber(2); - await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { - takerAssetFillAmount: fillTakerAssetAmount1, - }); + await exchange + .fillOrder(signedOrder, fillTakerAssetAmount1, signedOrder.signature) + .awaitTransactionSuccessAsync({ from: takerAddress }); const fillTakerAssetAmount2 = new BigNumber(1); const expectedError = new LibMathRevertErrors.RoundingError( @@ -396,9 +280,9 @@ blockchainTests.resets('Exchange core', () => { new BigNumber(3), new BigNumber(1001), ); - const tx = exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { - takerAssetFillAmount: fillTakerAssetAmount2, - }); + const tx = exchange + .fillOrder(signedOrder, fillTakerAssetAmount2, signedOrder.signature) + .awaitTransactionSuccessAsync({ from: takerAddress }); return expect(tx).to.revertWith(expectedError); }); }); @@ -500,7 +384,7 @@ blockchainTests.resets('Exchange core', () => { orderHash, takerAddress, ); - const tx = exchangeWrapper.cancelOrderAsync(signedOrder, takerAddress); + const tx = exchange.cancelOrder(signedOrder).awaitTransactionSuccessAsync({ from: takerAddress }); return expect(tx).to.revertWith(expectedError); }); @@ -508,7 +392,7 @@ blockchainTests.resets('Exchange core', () => { signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(0), }); - const tx = await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress); + const tx = await exchange.cancelOrder(signedOrder).awaitTransactionSuccessAsync({ from: makerAddress }); expect(tx.logs.length).to.equal(0); }); @@ -516,22 +400,22 @@ blockchainTests.resets('Exchange core', () => { signedOrder = await orderFactory.newSignedOrderAsync({ takerAssetAmount: new BigNumber(0), }); - const tx = await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress); + const tx = await exchange.cancelOrder(signedOrder).awaitTransactionSuccessAsync({ from: makerAddress }); expect(tx.logs.length).to.equal(0); }); it('should be able to cancel an order', async () => { - await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress); + await exchange.cancelOrder(signedOrder).awaitTransactionSuccessAsync({ from: makerAddress }); const orderHash = orderHashUtils.getOrderHashHex(signedOrder); const expectedError = new ExchangeRevertErrors.OrderStatusError(orderHash, OrderStatus.Cancelled); - const tx = exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { - takerAssetFillAmount: signedOrder.takerAssetAmount.div(2), - }); + const tx = exchange + .fillOrder(signedOrder, signedOrder.takerAssetAmount.div(2), signedOrder.signature) + .awaitTransactionSuccessAsync({ from: takerAddress }); return expect(tx).to.revertWith(expectedError); }); it('should log 1 event with correct arguments if cancelled successfully', async () => { - const res = await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress); + const res = await exchange.cancelOrder(signedOrder).awaitTransactionSuccessAsync({ from: makerAddress }); expect(res.logs).to.have.length(1); const log = res.logs[0] as LogWithDecodedArgs; @@ -546,8 +430,8 @@ blockchainTests.resets('Exchange core', () => { }); it('should noop if already cancelled', async () => { - await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress); - const tx = await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress); + await exchange.cancelOrder(signedOrder).awaitTransactionSuccessAsync({ from: makerAddress }); + const tx = await exchange.cancelOrder(signedOrder).awaitTransactionSuccessAsync({ from: makerAddress }); expect(tx.logs.length).to.equal(0); }); @@ -556,7 +440,7 @@ blockchainTests.resets('Exchange core', () => { signedOrder = await orderFactory.newSignedOrderAsync({ expirationTimeSeconds: new BigNumber(currentTimestamp).minus(10), }); - const tx = await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress); + const tx = await exchange.cancelOrder(signedOrder).awaitTransactionSuccessAsync({ from: makerAddress }); expect(tx.logs.length).to.equal(0); }); }); @@ -564,33 +448,33 @@ blockchainTests.resets('Exchange core', () => { describe('cancelOrdersUpTo', () => { it('should fail to set orderEpoch less than current orderEpoch', async () => { const orderEpoch = new BigNumber(1); - await exchangeWrapper.cancelOrdersUpToAsync(orderEpoch, makerAddress); + await exchange.cancelOrdersUpTo(orderEpoch).awaitTransactionSuccessAsync({ from: makerAddress }); const lesserOrderEpoch = new BigNumber(0); const expectedError = new ExchangeRevertErrors.OrderEpochError( makerAddress, constants.NULL_ADDRESS, orderEpoch.plus(1), ); - const tx = exchangeWrapper.cancelOrdersUpToAsync(lesserOrderEpoch, makerAddress); + const tx = exchange.cancelOrdersUpTo(lesserOrderEpoch).awaitTransactionSuccessAsync({ from: makerAddress }); return expect(tx).to.revertWith(expectedError); }); it('should fail to set orderEpoch equal to existing orderEpoch', async () => { const orderEpoch = new BigNumber(1); - await exchangeWrapper.cancelOrdersUpToAsync(orderEpoch, makerAddress); + await exchange.cancelOrdersUpTo(orderEpoch).awaitTransactionSuccessAsync({ from: makerAddress }); const expectedError = new ExchangeRevertErrors.OrderEpochError( makerAddress, constants.NULL_ADDRESS, orderEpoch.plus(1), ); - const tx = exchangeWrapper.cancelOrdersUpToAsync(orderEpoch, makerAddress); + const tx = exchange.cancelOrdersUpTo(orderEpoch).awaitTransactionSuccessAsync({ from: makerAddress }); return expect(tx).to.revertWith(expectedError); }); it('should cancel only orders with a orderEpoch less than existing orderEpoch', async () => { // Cancel all transactions with a orderEpoch less than 2 const orderEpoch = new BigNumber(1); - await exchangeWrapper.cancelOrdersUpToAsync(orderEpoch, makerAddress); + await exchange.cancelOrdersUpTo(orderEpoch).awaitTransactionSuccessAsync({ from: makerAddress }); // Create 4 orders with orderEpoch values: 0,1,2,3 // Since we cancelled with orderEpoch=1, orders with orderEpoch<=1 will not be processed @@ -617,8 +501,13 @@ blockchainTests.resets('Exchange core', () => { salt: new BigNumber(3), }), ]; - await exchangeWrapper.batchFillOrdersNoThrowAsync(signedOrders, takerAddress); - + await exchange + .batchFillOrdersNoThrow( + signedOrders, + signedOrders.map(order => order.takerAssetAmount), + signedOrders.map(order => order.signature), + ) + .awaitTransactionSuccessAsync({ from: takerAddress }); const newBalances = await erc20Wrapper.getBalancesAsync(); const fillMakerAssetAmount = signedOrders[2].makerAssetAmount.plus(signedOrders[3].makerAssetAmount); const fillTakerAssetAmount = signedOrders[2].takerAssetAmount.plus(signedOrders[3].takerAssetAmount); @@ -672,7 +561,9 @@ blockchainTests.resets('Exchange core', () => { signedOrder.makerAssetData, new StringRevertError(RevertReason.TransferFailed).encode(), ); - const tx = exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }); + const tx = exchange + .fillOrder(signedOrder, takerAssetFillAmount, signedOrder.signature) + .awaitTransactionSuccessAsync({ from: takerAddress }); return expect(tx).to.revertWith(expectedError); }); @@ -699,7 +590,9 @@ blockchainTests.resets('Exchange core', () => { signedOrder.takerAssetData, new StringRevertError(RevertReason.TransferFailed).encode(), ); - const tx = exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }); + const tx = exchange + .fillOrder(signedOrder, takerAssetFillAmount, signedOrder.signature) + .awaitTransactionSuccessAsync({ from: takerAddress }); return expect(tx).to.revertWith(expectedError); }); @@ -726,7 +619,9 @@ blockchainTests.resets('Exchange core', () => { signedOrder.makerAssetData, new StringRevertError(RevertReason.InvalidAmount).encode(), ); - const tx = exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }); + const tx = exchange + .fillOrder(signedOrder, takerAssetFillAmount, signedOrder.signature) + .awaitTransactionSuccessAsync({ from: takerAddress }); return expect(tx).to.revertWith(expectedError); }); @@ -753,7 +648,9 @@ blockchainTests.resets('Exchange core', () => { signedOrder.takerAssetData, new StringRevertError(RevertReason.InvalidAmount).encode(), ); - const tx = exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }); + const tx = exchange + .fillOrder(signedOrder, takerAssetFillAmount, signedOrder.signature) + .awaitTransactionSuccessAsync({ from: takerAddress }); return expect(tx).to.revertWith(expectedError); }); @@ -773,7 +670,9 @@ blockchainTests.resets('Exchange core', () => { signedOrder.takerAssetAmount, signedOrder.makerAssetAmount, ); - const tx = exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }); + const tx = exchange + .fillOrder(signedOrder, takerAssetFillAmount, signedOrder.signature) + .awaitTransactionSuccessAsync({ from: takerAddress }); return expect(tx).to.revertWith(expectedError); }); }); @@ -1102,7 +1001,9 @@ blockchainTests.resets('Exchange core', () => { assetData, new StringRevertError(RevertReason.TargetNotEven).encode(), ); - const tx = exchangeWrapper.fillOrderAsync(signedOrder, takerAddress); + const tx = exchange + .fillOrder(signedOrder, signedOrder.takerAssetAmount, signedOrder.signature) + .awaitTransactionSuccessAsync({ from: takerAddress }); return expect(tx).to.revertWith(expectedError); }); it('should fill the order if the staticcall is successful', async () => { @@ -1133,7 +1034,9 @@ blockchainTests.resets('Exchange core', () => { assetData, new StringRevertError(RevertReason.TargetNotEven).encode(), ); - const tx = exchangeWrapper.fillOrderAsync(signedOrder, takerAddress); + const tx = exchange + .fillOrder(signedOrder, signedOrder.takerAssetAmount, signedOrder.signature) + .awaitTransactionSuccessAsync({ from: takerAddress }); return expect(tx).to.revertWith(expectedError); }); it('should fill the order is the staticcall is successful using the MultiAssetProxy', async () => { @@ -1159,7 +1062,7 @@ blockchainTests.resets('Exchange core', () => { signedOrder = await orderFactory.newSignedOrderAsync(); }); it('should return the correct orderInfo for an unfilled valid order', async () => { - const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const orderInfo = await exchange.getOrderInfo(signedOrder).callAsync(); const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); const expectedTakerAssetFilledAmount = new BigNumber(0); const expectedOrderStatus = OrderStatus.Fillable; @@ -1175,8 +1078,8 @@ blockchainTests.resets('Exchange core', () => { await fillOrderWrapper.fillOrderAndAssertEffectsAsync(signedOrder, takerAddress, { takerAssetFillAmount }); }); it('should return the correct orderInfo for a cancelled and unfilled order', async () => { - await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress); - const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + await exchange.cancelOrder(signedOrder).awaitTransactionSuccessAsync({ from: makerAddress }); + const orderInfo = await exchange.getOrderInfo(signedOrder).callAsync(); const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); const expectedTakerAssetFilledAmount = new BigNumber(0); const expectedOrderStatus = OrderStatus.Cancelled; @@ -1186,9 +1089,11 @@ blockchainTests.resets('Exchange core', () => { }); it('should return the correct orderInfo for a cancelled and partially filled order', async () => { const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2); - await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }); - await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress); - const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + await exchange + .fillOrder(signedOrder, takerAssetFillAmount, signedOrder.signature) + .awaitTransactionSuccessAsync({ from: takerAddress }); + await exchange.cancelOrder(signedOrder).awaitTransactionSuccessAsync({ from: makerAddress }); + const orderInfo = await exchange.getOrderInfo(signedOrder).callAsync(); const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); const expectedTakerAssetFilledAmount = takerAssetFillAmount; const expectedOrderStatus = OrderStatus.Cancelled; @@ -1200,7 +1105,7 @@ blockchainTests.resets('Exchange core', () => { const currentTimestamp = await getLatestBlockTimestampAsync(); const timeUntilExpiration = signedOrder.expirationTimeSeconds.minus(currentTimestamp).toNumber(); await increaseTimeAndMineBlockAsync(timeUntilExpiration); - const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const orderInfo = await exchange.getOrderInfo(signedOrder).callAsync(); const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); const expectedTakerAssetFilledAmount = new BigNumber(0); const expectedOrderStatus = OrderStatus.Expired; @@ -1210,11 +1115,13 @@ blockchainTests.resets('Exchange core', () => { }); it('should return the correct orderInfo for an expired and partially filled order', async () => { const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2); - await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }); + await exchange + .fillOrder(signedOrder, takerAssetFillAmount, signedOrder.signature) + .awaitTransactionSuccessAsync({ from: takerAddress }); const currentTimestamp = await getLatestBlockTimestampAsync(); const timeUntilExpiration = signedOrder.expirationTimeSeconds.minus(currentTimestamp).toNumber(); await increaseTimeAndMineBlockAsync(timeUntilExpiration); - const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const orderInfo = await exchange.getOrderInfo(signedOrder).callAsync(); const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); const expectedTakerAssetFilledAmount = takerAssetFillAmount; const expectedOrderStatus = OrderStatus.Expired; @@ -1223,11 +1130,13 @@ blockchainTests.resets('Exchange core', () => { expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); }); it('should return the correct orderInfo for an expired and fully filled order', async () => { - await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress); + await exchange + .fillOrder(signedOrder, signedOrder.takerAssetAmount, signedOrder.signature) + .awaitTransactionSuccessAsync({ from: takerAddress }); const currentTimestamp = await getLatestBlockTimestampAsync(); const timeUntilExpiration = signedOrder.expirationTimeSeconds.minus(currentTimestamp).toNumber(); await increaseTimeAndMineBlockAsync(timeUntilExpiration); - const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const orderInfo = await exchange.getOrderInfo(signedOrder).callAsync(); const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount; // FULLY_FILLED takes precedence over EXPIRED @@ -1238,7 +1147,7 @@ blockchainTests.resets('Exchange core', () => { }); it('should return the correct orderInfo for an order with a makerAssetAmount of 0', async () => { signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(0) }); - const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const orderInfo = await exchange.getOrderInfo(signedOrder).callAsync(); const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); const expectedTakerAssetFilledAmount = new BigNumber(0); const expectedOrderStatus = OrderStatus.InvalidMakerAssetAmount; @@ -1248,7 +1157,7 @@ blockchainTests.resets('Exchange core', () => { }); it('should return the correct orderInfo for an order with a takerAssetAmount of 0', async () => { signedOrder = await orderFactory.newSignedOrderAsync({ takerAssetAmount: new BigNumber(0) }); - const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const orderInfo = await exchange.getOrderInfo(signedOrder).callAsync(); const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); const expectedTakerAssetFilledAmount = new BigNumber(0); const expectedOrderStatus = OrderStatus.InvalidTakerAssetAmount; diff --git a/contracts/integrations/test/internal-integration-tests/exchange_wrapper_test.ts b/contracts/integrations/test/exchange/exchange_wrapper_test.ts similarity index 99% rename from contracts/integrations/test/internal-integration-tests/exchange_wrapper_test.ts rename to contracts/integrations/test/exchange/exchange_wrapper_test.ts index 9d28130067..7013877749 100644 --- a/contracts/integrations/test/internal-integration-tests/exchange_wrapper_test.ts +++ b/contracts/integrations/test/exchange/exchange_wrapper_test.ts @@ -1,12 +1,6 @@ import { DevUtilsContract } from '@0x/contracts-dev-utils'; import { ERC20TokenEvents, ERC20TokenTransferEventArgs } from '@0x/contracts-erc20'; -import { - BlockchainBalanceStore, - ExchangeRevertErrors, - IExchangeEvents, - IExchangeFillEventArgs, - LocalBalanceStore, -} from '@0x/contracts-exchange'; +import { ExchangeRevertErrors, IExchangeEvents, IExchangeFillEventArgs } from '@0x/contracts-exchange'; import { ReferenceFunctions } from '@0x/contracts-exchange-libs'; import { blockchainTests, @@ -25,9 +19,11 @@ import { BigNumber } from '@0x/utils'; import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import * as _ from 'lodash'; -import { Actor } from '../actors/base'; -import { Maker } from '../actors/maker'; -import { DeploymentManager } from '../deployment_manager'; +import { Actor } from '../framework/actors/base'; +import { Maker } from '../framework/actors/maker'; +import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store'; +import { LocalBalanceStore } from '../framework/balances/local_balance_store'; +import { DeploymentManager } from '../framework/deployment_manager'; const { addFillResults, safeGetPartialAmountFloor } = ReferenceFunctions; diff --git a/contracts/exchange/test/assertion_wrappers/fill_order_wrapper.ts b/contracts/integrations/test/exchange/fill_order_wrapper.ts similarity index 96% rename from contracts/exchange/test/assertion_wrappers/fill_order_wrapper.ts rename to contracts/integrations/test/exchange/fill_order_wrapper.ts index c93c3037bb..cd58ca98cb 100644 --- a/contracts/exchange/test/assertion_wrappers/fill_order_wrapper.ts +++ b/contracts/integrations/test/exchange/fill_order_wrapper.ts @@ -1,4 +1,5 @@ import { DevUtilsContract } from '@0x/contracts-dev-utils'; +import { ExchangeContract } from '@0x/contracts-exchange'; import { ReferenceFunctions as LibReferenceFunctions } from '@0x/contracts-exchange-libs'; import { constants, @@ -14,12 +15,10 @@ import { BigNumber } from '@0x/utils'; import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import * as _ from 'lodash'; -import { ExchangeContract } from '../wrappers'; - -import { BalanceStore } from '../../src/balance_stores/balance_store'; -import { BlockchainBalanceStore } from '../../src/balance_stores/blockchain_balance_store'; -import { LocalBalanceStore } from '../../src/balance_stores/local_balance_store'; -import { TokenContractsByName, TokenIds, TokenOwnersByName } from '../../src/balance_stores/types'; +import { BalanceStore } from '../framework/balances/balance_store'; +import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store'; +import { LocalBalanceStore } from '../framework/balances/local_balance_store'; +import { TokenContractsByName, TokenIds, TokenOwnersByName } from '../framework/balances/types'; export class FillOrderWrapper { private readonly _blockchainBalanceStore: BlockchainBalanceStore; diff --git a/contracts/integrations/test/internal-integration-tests/fillorder_test.ts b/contracts/integrations/test/exchange/fillorder_test.ts similarity index 96% rename from contracts/integrations/test/internal-integration-tests/fillorder_test.ts rename to contracts/integrations/test/exchange/fillorder_test.ts index b8631ee80d..e99da18614 100644 --- a/contracts/integrations/test/internal-integration-tests/fillorder_test.ts +++ b/contracts/integrations/test/exchange/fillorder_test.ts @@ -1,11 +1,6 @@ import { DevUtilsContract } from '@0x/contracts-dev-utils'; import { ERC20TokenEvents, ERC20TokenTransferEventArgs } from '@0x/contracts-erc20'; -import { - BlockchainBalanceStore, - ExchangeEvents, - ExchangeFillEventArgs, - LocalBalanceStore, -} from '@0x/contracts-exchange'; +import { ExchangeEvents, ExchangeFillEventArgs } from '@0x/contracts-exchange'; import { ReferenceFunctions } from '@0x/contracts-exchange-libs'; import { constants as stakingConstants, @@ -28,8 +23,14 @@ import { SignedOrder } from '@0x/types'; import { BigNumber } from '@0x/utils'; import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; -import { actorAddressesByName, FeeRecipient, Maker, OperatorStakerMaker, StakerKeeper, Taker } from '../actors'; -import { DeploymentManager } from '../deployment_manager'; +import { FeeRecipient } from '../framework/actors/fee_recipient'; +import { OperatorStakerMaker, StakerKeeper } from '../framework/actors/hybrids'; +import { Maker } from '../framework/actors/maker'; +import { Taker } from '../framework/actors/taker'; +import { actorAddressesByName } from '../framework/actors/utils'; +import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store'; +import { LocalBalanceStore } from '../framework/balances/local_balance_store'; +import { DeploymentManager } from '../framework/deployment_manager'; const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider); blockchainTests.resets('fillOrder integration tests', env => { diff --git a/contracts/integrations/test/forwarder/deploy_forwarder.ts b/contracts/integrations/test/forwarder/deploy_forwarder.ts index 27630b441c..8e06c9b83e 100644 --- a/contracts/integrations/test/forwarder/deploy_forwarder.ts +++ b/contracts/integrations/test/forwarder/deploy_forwarder.ts @@ -3,7 +3,7 @@ import { artifacts, ForwarderContract } from '@0x/contracts-exchange-forwarder'; import { BlockchainTestsEnvironment } from '@0x/contracts-test-utils'; import { assetDataUtils } from '@0x/order-utils'; -import { DeploymentManager } from '../deployment_manager'; +import { DeploymentManager } from '../framework/deployment_manager'; /** * Deploys a Forwarder contract configured to work alongside the provided `deployment`. diff --git a/contracts/integrations/test/forwarder/forwarder_test.ts b/contracts/integrations/test/forwarder/forwarder_test.ts index 6067d3eec9..4719169c42 100644 --- a/contracts/integrations/test/forwarder/forwarder_test.ts +++ b/contracts/integrations/test/forwarder/forwarder_test.ts @@ -1,12 +1,7 @@ import { DevUtilsContract } from '@0x/contracts-dev-utils'; import { DummyERC20TokenContract } from '@0x/contracts-erc20'; import { DummyERC721TokenContract } from '@0x/contracts-erc721'; -import { - artifacts as exchangeArtifacts, - BlockchainBalanceStore, - ExchangeContract, - LocalBalanceStore, -} from '@0x/contracts-exchange'; +import { artifacts as exchangeArtifacts, ExchangeContract } from '@0x/contracts-exchange'; import { artifacts, ForwarderContract, ForwarderRevertErrors } from '@0x/contracts-exchange-forwarder'; import { blockchainTests, @@ -19,8 +14,13 @@ import { } from '@0x/contracts-test-utils'; import { BigNumber } from '@0x/utils'; -import { Actor, actorAddressesByName, FeeRecipient, Maker } from '../actors'; -import { DeploymentManager } from '../deployment_manager'; +import { FeeRecipient } from '../framework/actors/fee_recipient'; +import { Maker } from '../framework/actors/maker'; +import { Taker } from '../framework/actors/taker'; +import { actorAddressesByName } from '../framework/actors/utils'; +import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store'; +import { LocalBalanceStore } from '../framework/balances/local_balance_store'; +import { DeploymentManager } from '../framework/deployment_manager'; import { deployForwarderAsync } from './deploy_forwarder'; import { ForwarderTestFactory } from './forwarder_test_factory'; @@ -42,7 +42,7 @@ blockchainTests('Forwarder integration tests', env => { let makerAssetData: string; let maker: Maker; - let taker: Actor; + let taker: Taker; let orderFeeRecipient: FeeRecipient; let forwarderFeeRecipient: FeeRecipient; @@ -59,7 +59,7 @@ blockchainTests('Forwarder integration tests', env => { wethAssetData = await devUtils.encodeERC20AssetData(deployment.tokens.weth.address).callAsync(); makerAssetData = await devUtils.encodeERC20AssetData(makerToken.address).callAsync(); - taker = new Actor({ name: 'Taker', deployment }); + taker = new Taker({ name: 'Taker', deployment }); orderFeeRecipient = new FeeRecipient({ name: 'Order fee recipient', deployment, @@ -560,14 +560,24 @@ blockchainTests('Forwarder integration tests', env => { // Compute expected balances const expectedBalances = LocalBalanceStore.create(devUtils, balanceStore); - expectedBalances.transferAssetAsync(maker.address, taker.address, makerAssetFillAmount, makerAssetData); + await expectedBalances.transferAssetAsync( + maker.address, + taker.address, + makerAssetFillAmount, + makerAssetData, + ); expectedBalances.wrapEth( taker.address, deployment.tokens.weth.address, takerAssetFillAmount.plus(DeploymentManager.protocolFee), ); - expectedBalances.transferAssetAsync(taker.address, maker.address, takerAssetFillAmount, wethAssetData); - expectedBalances.transferAssetAsync( + await expectedBalances.transferAssetAsync( + taker.address, + maker.address, + takerAssetFillAmount, + wethAssetData, + ); + await expectedBalances.transferAssetAsync( taker.address, deployment.staking.stakingProxy.address, DeploymentManager.protocolFee, diff --git a/contracts/integrations/test/forwarder/forwarder_test_factory.ts b/contracts/integrations/test/forwarder/forwarder_test_factory.ts index a0f7dcf872..dfaf8e4d13 100644 --- a/contracts/integrations/test/forwarder/forwarder_test_factory.ts +++ b/contracts/integrations/test/forwarder/forwarder_test_factory.ts @@ -1,13 +1,16 @@ import { DevUtilsContract } from '@0x/contracts-dev-utils'; -import { BlockchainBalanceStore, LocalBalanceStore } from '@0x/contracts-exchange'; import { ForwarderContract } from '@0x/contracts-exchange-forwarder'; import { constants, expect, getPercentageOfValue, OrderStatus } from '@0x/contracts-test-utils'; import { OrderInfo, SignedOrder } from '@0x/types'; import { BigNumber, RevertError } from '@0x/utils'; import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; -import { Actor, FeeRecipient, Maker } from '../actors'; -import { DeploymentManager } from '../deployment_manager'; +import { FeeRecipient } from '../framework/actors/fee_recipient'; +import { Maker } from '../framework/actors/maker'; +import { Taker } from '../framework/actors/taker'; +import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store'; +import { LocalBalanceStore } from '../framework/balances/local_balance_store'; +import { DeploymentManager } from '../framework/deployment_manager'; // Necessary bookkeeping to validate Forwarder results interface ForwarderFillState { @@ -31,7 +34,7 @@ export class ForwarderTestFactory { private readonly _deployment: DeploymentManager, private readonly _balanceStore: BlockchainBalanceStore, private readonly _maker: Maker, - private readonly _taker: Actor, + private readonly _taker: Taker, private readonly _orderFeeRecipient: FeeRecipient, private readonly _forwarderFeeRecipient: FeeRecipient, private readonly _devUtils: DevUtilsContract, diff --git a/contracts/integrations/test/actors/base.ts b/contracts/integrations/test/framework/actors/base.ts similarity index 96% rename from contracts/integrations/test/actors/base.ts rename to contracts/integrations/test/framework/actors/base.ts index 5447f15dfb..63deb6bc4e 100644 --- a/contracts/integrations/test/actors/base.ts +++ b/contracts/integrations/test/framework/actors/base.ts @@ -5,9 +5,9 @@ import { SignatureType, SignedZeroExTransaction, ZeroExTransaction } from '@0x/t import { BigNumber } from '@0x/utils'; import * as _ from 'lodash'; -import { AssertionResult } from '../../src/function_assertions'; +import { AssertionResult } from '../assertions/function_assertion'; import { DeploymentManager } from '../deployment_manager'; -import { SimulationEnvironment } from '../simulation/simulation'; +import { SimulationEnvironment } from '../simulation'; export type Constructor = new (...args: any[]) => T; diff --git a/contracts/integrations/test/actors/fee_recipient.ts b/contracts/integrations/test/framework/actors/fee_recipient.ts similarity index 100% rename from contracts/integrations/test/actors/fee_recipient.ts rename to contracts/integrations/test/framework/actors/fee_recipient.ts diff --git a/contracts/integrations/test/actors/hybrids.ts b/contracts/integrations/test/framework/actors/hybrids.ts similarity index 100% rename from contracts/integrations/test/actors/hybrids.ts rename to contracts/integrations/test/framework/actors/hybrids.ts diff --git a/contracts/integrations/test/actors/keeper.ts b/contracts/integrations/test/framework/actors/keeper.ts similarity index 100% rename from contracts/integrations/test/actors/keeper.ts rename to contracts/integrations/test/framework/actors/keeper.ts diff --git a/contracts/integrations/test/actors/maker.ts b/contracts/integrations/test/framework/actors/maker.ts similarity index 100% rename from contracts/integrations/test/actors/maker.ts rename to contracts/integrations/test/framework/actors/maker.ts diff --git a/contracts/integrations/test/actors/pool_operator.ts b/contracts/integrations/test/framework/actors/pool_operator.ts similarity index 94% rename from contracts/integrations/test/actors/pool_operator.ts rename to contracts/integrations/test/framework/actors/pool_operator.ts index b6492d84bc..19d9e06d12 100644 --- a/contracts/integrations/test/actors/pool_operator.ts +++ b/contracts/integrations/test/framework/actors/pool_operator.ts @@ -4,11 +4,9 @@ import '@azure/core-asynciterator-polyfill'; import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import * as _ from 'lodash'; -import { AssertionResult } from '../../src/function_assertions'; -import { - validCreateStakingPoolAssertion, - validDecreaseStakingPoolOperatorShareAssertion, -} from '../function-assertions'; +import { validCreateStakingPoolAssertion } from '../assertions/createStakingPool'; +import { validDecreaseStakingPoolOperatorShareAssertion } from '../assertions/decreaseStakingPoolOperatorShare'; +import { AssertionResult } from '../assertions/function_assertion'; import { Actor, Constructor } from './base'; diff --git a/contracts/integrations/test/actors/staker.ts b/contracts/integrations/test/framework/actors/staker.ts similarity index 95% rename from contracts/integrations/test/actors/staker.ts rename to contracts/integrations/test/framework/actors/staker.ts index 5954e8dbc6..1261933b85 100644 --- a/contracts/integrations/test/actors/staker.ts +++ b/contracts/integrations/test/framework/actors/staker.ts @@ -4,8 +4,10 @@ import { BigNumber } from '@0x/utils'; import '@azure/core-asynciterator-polyfill'; import * as _ from 'lodash'; -import { AssertionResult } from '../../src/function_assertions'; -import { validMoveStakeAssertion, validStakeAssertion, validUnstakeAssertion } from '../function-assertions'; +import { AssertionResult } from '../assertions/function_assertion'; +import { validMoveStakeAssertion } from '../assertions/moveStake'; +import { validStakeAssertion } from '../assertions/stake'; +import { validUnstakeAssertion } from '../assertions/unstake'; import { Actor, Constructor } from './base'; diff --git a/contracts/integrations/test/actors/taker.ts b/contracts/integrations/test/framework/actors/taker.ts similarity index 100% rename from contracts/integrations/test/actors/taker.ts rename to contracts/integrations/test/framework/actors/taker.ts diff --git a/contracts/integrations/test/actors/tslint.json b/contracts/integrations/test/framework/actors/tslint.json similarity index 100% rename from contracts/integrations/test/actors/tslint.json rename to contracts/integrations/test/framework/actors/tslint.json diff --git a/contracts/integrations/test/actors/utils.ts b/contracts/integrations/test/framework/actors/utils.ts similarity index 100% rename from contracts/integrations/test/actors/utils.ts rename to contracts/integrations/test/framework/actors/utils.ts diff --git a/contracts/integrations/test/function-assertions/createStakingPool.ts b/contracts/integrations/test/framework/assertions/createStakingPool.ts similarity index 96% rename from contracts/integrations/test/function-assertions/createStakingPool.ts rename to contracts/integrations/test/framework/assertions/createStakingPool.ts index b2cd793fe9..a1829a0e62 100644 --- a/contracts/integrations/test/function-assertions/createStakingPool.ts +++ b/contracts/integrations/test/framework/assertions/createStakingPool.ts @@ -3,9 +3,10 @@ import { expect } from '@0x/contracts-test-utils'; import { BigNumber, logUtils } from '@0x/utils'; import { TxData } from 'ethereum-types'; -import { FunctionAssertion, FunctionResult } from '../../src/function_assertions'; import { DeploymentManager } from '../deployment_manager'; +import { FunctionAssertion, FunctionResult } from './function_assertion'; + // tslint:disable:no-unnecessary-type-assertion /** diff --git a/contracts/integrations/test/function-assertions/decreaseStakingPoolOperatorShare.ts b/contracts/integrations/test/framework/assertions/decreaseStakingPoolOperatorShare.ts similarity index 93% rename from contracts/integrations/test/function-assertions/decreaseStakingPoolOperatorShare.ts rename to contracts/integrations/test/framework/assertions/decreaseStakingPoolOperatorShare.ts index f27816c59c..dfcee98ad2 100644 --- a/contracts/integrations/test/function-assertions/decreaseStakingPoolOperatorShare.ts +++ b/contracts/integrations/test/framework/assertions/decreaseStakingPoolOperatorShare.ts @@ -2,9 +2,10 @@ import { StakingPoolById } from '@0x/contracts-staking'; import { expect } from '@0x/contracts-test-utils'; import { logUtils } from '@0x/utils'; -import { FunctionAssertion, FunctionResult } from '../../src/function_assertions'; import { DeploymentManager } from '../deployment_manager'; +import { FunctionAssertion, FunctionResult } from './function_assertion'; + /** * Returns a FunctionAssertion for `decreaseStakingPoolOperatorShare` which assumes valid input is * provided. The FunctionAssertion checks that the operator share actually gets updated. diff --git a/contracts/integrations/src/function_assertions.ts b/contracts/integrations/test/framework/assertions/function_assertion.ts similarity index 59% rename from contracts/integrations/src/function_assertions.ts rename to contracts/integrations/test/framework/assertions/function_assertion.ts index 371ab84230..541e57ce12 100644 --- a/contracts/integrations/src/function_assertions.ts +++ b/contracts/integrations/test/framework/assertions/function_assertion.ts @@ -106,79 +106,3 @@ export class FunctionAssertion implements Assertion { }; } } - -export type IndexGenerator = () => number; - -export type InputGenerator = () => Promise; - -export interface AssertionGenerator { - assertion: Assertion; - generator: InputGenerator; -} - -/** - * This class is an abstract way to represent collections of function assertions. - * Using this, we can use closures to build up many useful collections with different - * properties. Notably, this abstraction supports function assertion collections - * that can be run continuously and also those that terminate in a finite number - * of steps. - */ -class MetaAssertion implements Assertion { - constructor( - protected readonly assertionGenerators: AssertionGenerator[], - protected readonly indexGenerator: IndexGenerator, - ) {} - - public async executeAsync(): Promise { - let idx = this.indexGenerator(); - while (idx > 0) { - const args = await this.assertionGenerators[idx].generator(); - await this.assertionGenerators[idx].assertion.executeAsync(...args); - idx = this.indexGenerator(); - } - } -} - -/** - * Returns a class that can execute a set of function assertions in sequence. - * @param assertionGenerators A set of assertion generators to run in sequence. - */ -export function FunctionAssertionSequence(assertionGenerators: AssertionGenerator[]): MetaAssertion { - let idx = 0; - return new MetaAssertion(assertionGenerators, () => { - if (idx < assertionGenerators.length) { - return idx++; - } else { - idx = 0; - return -1; - } - }); -} - -export interface WeightedAssertionGenerator extends AssertionGenerator { - weight?: number; -} - -/** - * Returns a class that can execute a set of function assertions at random continuously. - * This will not terminate unless the process that called `runAsync` terminates. - * @param weightedAssertionGenerators A set of function assertions that have been - * assigned weights. - */ -export function ContinuousFunctionAssertionSet( - weightedAssertionGenerators: WeightedAssertionGenerator[], -): MetaAssertion { - // Construct an array of assertion generators that allows random sampling from a - // uniform distribution to correctly bias assertion selection. - let assertionGenerators: AssertionGenerator[] = []; - for (const { assertion, generator, weight } of weightedAssertionGenerators) { - const weightedAssertions: AssertionGenerator[] = []; - _.fill(weightedAssertions, { assertion, generator }, 0, weight || 1); - assertionGenerators = assertionGenerators.concat(weightedAssertions); - } - - // The index generator simply needs to sample from a uniform distribution. - const indexGenerator = () => Math.round(Math.random() * (assertionGenerators.length - 1)); - - return new MetaAssertion(assertionGenerators, indexGenerator); -} diff --git a/contracts/integrations/test/function-assertions/moveStake.ts b/contracts/integrations/test/framework/assertions/moveStake.ts similarity index 98% rename from contracts/integrations/test/function-assertions/moveStake.ts rename to contracts/integrations/test/framework/assertions/moveStake.ts index 2404e06240..08d27627fe 100644 --- a/contracts/integrations/test/function-assertions/moveStake.ts +++ b/contracts/integrations/test/framework/assertions/moveStake.ts @@ -11,9 +11,10 @@ import { BigNumber, logUtils } from '@0x/utils'; import { TxData } from 'ethereum-types'; import * as _ from 'lodash'; -import { FunctionAssertion } from '../../src/function_assertions'; import { DeploymentManager } from '../deployment_manager'; +import { FunctionAssertion } from './function_assertion'; + function incrementNextEpochBalance(stakeBalance: StoredBalance, amount: BigNumber): void { _.update(stakeBalance, ['nextEpochBalance'], balance => (balance || constants.ZERO_AMOUNT).plus(amount)); } diff --git a/contracts/integrations/test/function-assertions/stake.ts b/contracts/integrations/test/framework/assertions/stake.ts similarity index 94% rename from contracts/integrations/test/function-assertions/stake.ts rename to contracts/integrations/test/framework/assertions/stake.ts index f1893d82ed..9c643c7ecc 100644 --- a/contracts/integrations/test/function-assertions/stake.ts +++ b/contracts/integrations/test/framework/assertions/stake.ts @@ -1,12 +1,14 @@ -import { BlockchainBalanceStore, LocalBalanceStore } from '@0x/contracts-exchange'; import { GlobalStakeByStatus, OwnerStakeByStatus, StakeStatus, StoredBalance } from '@0x/contracts-staking'; import { expect } from '@0x/contracts-test-utils'; import { BigNumber, logUtils } from '@0x/utils'; import { TxData } from 'ethereum-types'; -import { FunctionAssertion, FunctionResult } from '../../src/function_assertions'; +import { BlockchainBalanceStore } from '../balances/blockchain_balance_store'; +import { LocalBalanceStore } from '../balances/local_balance_store'; import { DeploymentManager } from '../deployment_manager'; +import { FunctionAssertion, FunctionResult } from './function_assertion'; + function expectedUndelegatedStake( initStake: OwnerStakeByStatus | GlobalStakeByStatus, amount: BigNumber, diff --git a/contracts/integrations/test/function-assertions/unstake.ts b/contracts/integrations/test/framework/assertions/unstake.ts similarity index 94% rename from contracts/integrations/test/function-assertions/unstake.ts rename to contracts/integrations/test/framework/assertions/unstake.ts index 64709cbeee..1930777899 100644 --- a/contracts/integrations/test/function-assertions/unstake.ts +++ b/contracts/integrations/test/framework/assertions/unstake.ts @@ -1,12 +1,14 @@ -import { BlockchainBalanceStore, LocalBalanceStore } from '@0x/contracts-exchange'; import { GlobalStakeByStatus, OwnerStakeByStatus, StakeStatus, StoredBalance } from '@0x/contracts-staking'; import { expect } from '@0x/contracts-test-utils'; import { BigNumber, logUtils } from '@0x/utils'; import { TxData } from 'ethereum-types'; -import { FunctionAssertion, FunctionResult } from '../../src/function_assertions'; +import { BlockchainBalanceStore } from '../balances/blockchain_balance_store'; +import { LocalBalanceStore } from '../balances/local_balance_store'; import { DeploymentManager } from '../deployment_manager'; +import { FunctionAssertion, FunctionResult } from './function_assertion'; + function expectedUndelegatedStake( initStake: OwnerStakeByStatus | GlobalStakeByStatus, amount: BigNumber, diff --git a/contracts/exchange/src/balance_stores/balance_store.ts b/contracts/integrations/test/framework/balances/balance_store.ts similarity index 100% rename from contracts/exchange/src/balance_stores/balance_store.ts rename to contracts/integrations/test/framework/balances/balance_store.ts diff --git a/contracts/exchange/src/balance_stores/blockchain_balance_store.ts b/contracts/integrations/test/framework/balances/blockchain_balance_store.ts similarity index 100% rename from contracts/exchange/src/balance_stores/blockchain_balance_store.ts rename to contracts/integrations/test/framework/balances/blockchain_balance_store.ts diff --git a/contracts/exchange/src/balance_stores/local_balance_store.ts b/contracts/integrations/test/framework/balances/local_balance_store.ts similarity index 100% rename from contracts/exchange/src/balance_stores/local_balance_store.ts rename to contracts/integrations/test/framework/balances/local_balance_store.ts diff --git a/contracts/exchange/src/balance_stores/types.ts b/contracts/integrations/test/framework/balances/types.ts similarity index 100% rename from contracts/exchange/src/balance_stores/types.ts rename to contracts/integrations/test/framework/balances/types.ts diff --git a/contracts/integrations/test/deployment_manager.ts b/contracts/integrations/test/framework/deployment_manager.ts similarity index 100% rename from contracts/integrations/test/deployment_manager.ts rename to contracts/integrations/test/framework/deployment_manager.ts diff --git a/contracts/integrations/test/simulation/simulation.ts b/contracts/integrations/test/framework/simulation.ts similarity index 84% rename from contracts/integrations/test/simulation/simulation.ts rename to contracts/integrations/test/framework/simulation.ts index 12b38284ab..5bc94a6625 100644 --- a/contracts/integrations/test/simulation/simulation.ts +++ b/contracts/integrations/test/framework/simulation.ts @@ -1,9 +1,9 @@ -import { BlockchainBalanceStore } from '@0x/contracts-exchange'; import { GlobalStakeByStatus, StakeStatus, StakingPoolById, StoredBalance } from '@0x/contracts-staking'; import * as _ from 'lodash'; -import { AssertionResult } from '../../src/function_assertions'; -import { DeploymentManager } from '../deployment_manager'; +import { AssertionResult } from './assertions/function_assertion'; +import { BlockchainBalanceStore } from './balances/blockchain_balance_store'; +import { DeploymentManager } from './deployment_manager'; // tslint:disable:max-classes-per-file diff --git a/contracts/integrations/test/framework-unit-tests/deployment_manager_test.ts b/contracts/integrations/test/framework/tests/deployment_manager_test.ts similarity index 100% rename from contracts/integrations/test/framework-unit-tests/deployment_manager_test.ts rename to contracts/integrations/test/framework/tests/deployment_manager_test.ts diff --git a/contracts/integrations/test/framework-unit-tests/function_assertion_test.ts b/contracts/integrations/test/framework/tests/function_assertion_test.ts similarity index 97% rename from contracts/integrations/test/framework-unit-tests/function_assertion_test.ts rename to contracts/integrations/test/framework/tests/function_assertion_test.ts index 34de637869..e585d17d1c 100644 --- a/contracts/integrations/test/framework-unit-tests/function_assertion_test.ts +++ b/contracts/integrations/test/framework/tests/function_assertion_test.ts @@ -2,10 +2,9 @@ import { blockchainTests, constants, expect, filterLogsToArguments, getRandomInt import { BigNumber, StringRevertError } from '@0x/utils'; import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; -import { FunctionAssertion, FunctionResult } from '../../src/function_assertions'; - -import { artifacts } from '../artifacts'; -import { TestFrameworkContract, TestFrameworkEventEventArgs, TestFrameworkEvents } from '../wrappers'; +import { artifacts } from '../../artifacts'; +import { TestFrameworkContract, TestFrameworkEventEventArgs, TestFrameworkEvents } from '../../wrappers'; +import { FunctionAssertion, FunctionResult } from '../assertions/function_assertion'; const { ZERO_AMOUNT, MAX_UINT256 } = constants; diff --git a/contracts/integrations/test/wrapper_interfaces.ts b/contracts/integrations/test/framework/wrapper_interfaces.ts similarity index 100% rename from contracts/integrations/test/wrapper_interfaces.ts rename to contracts/integrations/test/framework/wrapper_interfaces.ts diff --git a/contracts/integrations/test/function-assertions/index.ts b/contracts/integrations/test/function-assertions/index.ts deleted file mode 100644 index 6f5728d778..0000000000 --- a/contracts/integrations/test/function-assertions/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './stake'; -export * from './unstake'; -export * from './createStakingPool'; -export * from './decreaseStakingPoolOperatorShare'; -export * from './moveStake'; diff --git a/contracts/integrations/test/simulation/pool_management_test.ts b/contracts/integrations/test/fuzz_tests/pool_management_test.ts similarity index 78% rename from contracts/integrations/test/simulation/pool_management_test.ts rename to contracts/integrations/test/fuzz_tests/pool_management_test.ts index 4b7606156c..a922b02f3f 100644 --- a/contracts/integrations/test/simulation/pool_management_test.ts +++ b/contracts/integrations/test/fuzz_tests/pool_management_test.ts @@ -1,12 +1,11 @@ -import { BlockchainBalanceStore } from '@0x/contracts-exchange'; import { blockchainTests } from '@0x/contracts-test-utils'; import * as _ from 'lodash'; -import { AssertionResult } from '../../src/function_assertions'; -import { PoolOperator } from '../actors'; -import { DeploymentManager } from '../deployment_manager'; - -import { Simulation, SimulationEnvironment } from './simulation'; +import { PoolOperator } from '../framework/actors/pool_operator'; +import { AssertionResult } from '../framework/assertions/function_assertion'; +import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store'; +import { DeploymentManager } from '../framework/deployment_manager'; +import { Simulation, SimulationEnvironment } from '../framework/simulation'; export class PoolManagementSimulation extends Simulation { protected async *_assertionGenerator(): AsyncIterableIterator { diff --git a/contracts/integrations/test/simulation/stake_management_test.ts b/contracts/integrations/test/fuzz_tests/stake_management_test.ts similarity index 83% rename from contracts/integrations/test/simulation/stake_management_test.ts rename to contracts/integrations/test/fuzz_tests/stake_management_test.ts index a6e12d5ea2..e2051f059d 100644 --- a/contracts/integrations/test/simulation/stake_management_test.ts +++ b/contracts/integrations/test/fuzz_tests/stake_management_test.ts @@ -1,13 +1,13 @@ -import { BlockchainBalanceStore } from '@0x/contracts-exchange'; import { blockchainTests } from '@0x/contracts-test-utils'; import * as _ from 'lodash'; -import { AssertionResult } from '../../src/function_assertions'; -import { Staker } from '../actors'; -import { DeploymentManager } from '../deployment_manager'; +import { Staker } from '../framework/actors/staker'; +import { AssertionResult } from '../framework/assertions/function_assertion'; +import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store'; +import { DeploymentManager } from '../framework/deployment_manager'; +import { Simulation, SimulationEnvironment } from '../framework/simulation'; import { PoolManagementSimulation } from './pool_management_test'; -import { Simulation, SimulationEnvironment } from './simulation'; export class StakeManagementSimulation extends Simulation { protected async *_assertionGenerator(): AsyncIterableIterator { diff --git a/contracts/test-utils/src/index.ts b/contracts/test-utils/src/index.ts index ea304a3afe..bc670d2373 100644 --- a/contracts/test-utils/src/index.ts +++ b/contracts/test-utils/src/index.ts @@ -57,6 +57,7 @@ export { TokenBalances, TransactionDataParams, ExchangeFunctionName, + ValidatorWalletAction, } from './types'; export { blockchainTests, BlockchainTestsEnvironment, describe } from './mocha_blockchain'; export { chaiSetup, expect } from './chai_setup'; diff --git a/contracts/test-utils/src/types.ts b/contracts/test-utils/src/types.ts index 2db80a1437..20cb8ddc37 100644 --- a/contracts/test-utils/src/types.ts +++ b/contracts/test-utils/src/types.ts @@ -201,3 +201,14 @@ export enum ExchangeFunctionName { SetProtocolFeeCollectorAddress = 'setProtocolFeeCollectorAddress', DetachProtocolFeeCollector = 'detachProtocolFeeCollector', } + +export enum ValidatorWalletAction { + Reject = 0, + Accept = 1, + Revert = 2, + UpdateState = 3, + MatchSignatureHash = 4, + ReturnTrue = 5, + ReturnNothing = 6, + NTypes = 7, +}