diff options
Diffstat (limited to 'contracts/core')
56 files changed, 259 insertions, 2296 deletions
diff --git a/contracts/core/compiler.json b/contracts/core/compiler.json index c824e4645..ea9e43f12 100644 --- a/contracts/core/compiler.json +++ b/contracts/core/compiler.json @@ -39,8 +39,6 @@ "IWallet", "MixinAuthorizable", "MultiAssetProxy", - "MultiSigWallet", - "MultiSigWalletWithTimeLock", "OrderValidator", "ReentrantERC20Token", "TestAssetProxyOwner", diff --git a/contracts/core/contracts/multisig/MultiSigWallet.sol b/contracts/core/contracts/multisig/MultiSigWallet.sol deleted file mode 100644 index 516e7391c..000000000 --- a/contracts/core/contracts/multisig/MultiSigWallet.sol +++ /dev/null @@ -1,393 +0,0 @@ -// solhint-disable -pragma solidity ^0.4.15; - - -/// @title Multisignature wallet - Allows multiple parties to agree on transactions before execution. -/// @author Stefan George - <stefan.george@consensys.net> -contract MultiSigWallet { - - /* - * Events - */ - event Confirmation(address indexed sender, uint indexed transactionId); - event Revocation(address indexed sender, uint indexed transactionId); - event Submission(uint indexed transactionId); - event Execution(uint indexed transactionId); - event ExecutionFailure(uint indexed transactionId); - event Deposit(address indexed sender, uint value); - event OwnerAddition(address indexed owner); - event OwnerRemoval(address indexed owner); - event RequirementChange(uint required); - - /* - * Constants - */ - uint constant public MAX_OWNER_COUNT = 50; - - /* - * Storage - */ - mapping (uint => Transaction) public transactions; - mapping (uint => mapping (address => bool)) public confirmations; - mapping (address => bool) public isOwner; - address[] public owners; - uint public required; - uint public transactionCount; - - struct Transaction { - address destination; - uint value; - bytes data; - bool executed; - } - - /* - * Modifiers - */ - modifier onlyWallet() { - require(msg.sender == address(this)); - _; - } - - modifier ownerDoesNotExist(address owner) { - require(!isOwner[owner]); - _; - } - - modifier ownerExists(address owner) { - require(isOwner[owner]); - _; - } - - modifier transactionExists(uint transactionId) { - require(transactions[transactionId].destination != 0); - _; - } - - modifier confirmed(uint transactionId, address owner) { - require(confirmations[transactionId][owner]); - _; - } - - modifier notConfirmed(uint transactionId, address owner) { - require(!confirmations[transactionId][owner]); - _; - } - - modifier notExecuted(uint transactionId) { - require(!transactions[transactionId].executed); - _; - } - - modifier notNull(address _address) { - require(_address != 0); - _; - } - - modifier validRequirement(uint ownerCount, uint _required) { - require(ownerCount <= MAX_OWNER_COUNT - && _required <= ownerCount - && _required != 0 - && ownerCount != 0); - _; - } - - /// @dev Fallback function allows to deposit ether. - function() - payable - { - if (msg.value > 0) - Deposit(msg.sender, msg.value); - } - - /* - * Public functions - */ - /// @dev Contract constructor sets initial owners and required number of confirmations. - /// @param _owners List of initial owners. - /// @param _required Number of required confirmations. - function MultiSigWallet(address[] _owners, uint _required) - public - validRequirement(_owners.length, _required) - { - for (uint i=0; i<_owners.length; i++) { - require(!isOwner[_owners[i]] && _owners[i] != 0); - isOwner[_owners[i]] = true; - } - owners = _owners; - required = _required; - } - - /// @dev Allows to add a new owner. Transaction has to be sent by wallet. - /// @param owner Address of new owner. - function addOwner(address owner) - public - onlyWallet - ownerDoesNotExist(owner) - notNull(owner) - validRequirement(owners.length + 1, required) - { - isOwner[owner] = true; - owners.push(owner); - OwnerAddition(owner); - } - - /// @dev Allows to remove an owner. Transaction has to be sent by wallet. - /// @param owner Address of owner. - function removeOwner(address owner) - public - onlyWallet - ownerExists(owner) - { - isOwner[owner] = false; - for (uint i=0; i<owners.length - 1; i++) - if (owners[i] == owner) { - owners[i] = owners[owners.length - 1]; - break; - } - owners.length -= 1; - if (required > owners.length) - changeRequirement(owners.length); - OwnerRemoval(owner); - } - - /// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet. - /// @param owner Address of owner to be replaced. - /// @param newOwner Address of new owner. - function replaceOwner(address owner, address newOwner) - public - onlyWallet - ownerExists(owner) - ownerDoesNotExist(newOwner) - { - for (uint i=0; i<owners.length; i++) - if (owners[i] == owner) { - owners[i] = newOwner; - break; - } - isOwner[owner] = false; - isOwner[newOwner] = true; - OwnerRemoval(owner); - OwnerAddition(newOwner); - } - - /// @dev Allows to change the number of required confirmations. Transaction has to be sent by wallet. - /// @param _required Number of required confirmations. - function changeRequirement(uint _required) - public - onlyWallet - validRequirement(owners.length, _required) - { - required = _required; - RequirementChange(_required); - } - - /// @dev Allows an owner to submit and confirm a transaction. - /// @param destination Transaction target address. - /// @param value Transaction ether value. - /// @param data Transaction data payload. - /// @return Returns transaction ID. - function submitTransaction(address destination, uint value, bytes data) - public - returns (uint transactionId) - { - transactionId = addTransaction(destination, value, data); - confirmTransaction(transactionId); - } - - /// @dev Allows an owner to confirm a transaction. - /// @param transactionId Transaction ID. - function confirmTransaction(uint transactionId) - public - ownerExists(msg.sender) - transactionExists(transactionId) - notConfirmed(transactionId, msg.sender) - { - confirmations[transactionId][msg.sender] = true; - Confirmation(msg.sender, transactionId); - executeTransaction(transactionId); - } - - /// @dev Allows an owner to revoke a confirmation for a transaction. - /// @param transactionId Transaction ID. - function revokeConfirmation(uint transactionId) - public - ownerExists(msg.sender) - confirmed(transactionId, msg.sender) - notExecuted(transactionId) - { - confirmations[transactionId][msg.sender] = false; - Revocation(msg.sender, transactionId); - } - - /// @dev Allows anyone to execute a confirmed transaction. - /// @param transactionId Transaction ID. - function executeTransaction(uint transactionId) - public - ownerExists(msg.sender) - confirmed(transactionId, msg.sender) - notExecuted(transactionId) - { - if (isConfirmed(transactionId)) { - Transaction storage txn = transactions[transactionId]; - txn.executed = true; - if (external_call(txn.destination, txn.value, txn.data.length, txn.data)) - Execution(transactionId); - else { - ExecutionFailure(transactionId); - txn.executed = false; - } - } - } - - // call has been separated into its own function in order to take advantage - // of the Solidity's code generator to produce a loop that copies tx.data into memory. - function external_call(address destination, uint value, uint dataLength, bytes data) internal returns (bool) { - bool result; - assembly { - let x := mload(0x40) // "Allocate" memory for output (0x40 is where "free memory" pointer is stored by convention) - let d := add(data, 32) // First 32 bytes are the padded length of data, so exclude that - result := call( - sub(gas, 34710), // 34710 is the value that solidity is currently emitting - // It includes callGas (700) + callVeryLow (3, to pay for SUB) + callValueTransferGas (9000) + - // callNewAccountGas (25000, in case the destination address does not exist and needs creating) - destination, - value, - d, - dataLength, // Size of the input (in bytes) - this is what fixes the padding problem - x, - 0 // Output is ignored, therefore the output size is zero - ) - } - return result; - } - - /// @dev Returns the confirmation status of a transaction. - /// @param transactionId Transaction ID. - /// @return Confirmation status. - function isConfirmed(uint transactionId) - public - constant - returns (bool) - { - uint count = 0; - for (uint i=0; i<owners.length; i++) { - if (confirmations[transactionId][owners[i]]) - count += 1; - if (count == required) - return true; - } - } - - /* - * Internal functions - */ - /// @dev Adds a new transaction to the transaction mapping, if transaction does not exist yet. - /// @param destination Transaction target address. - /// @param value Transaction ether value. - /// @param data Transaction data payload. - /// @return Returns transaction ID. - function addTransaction(address destination, uint value, bytes data) - internal - notNull(destination) - returns (uint transactionId) - { - transactionId = transactionCount; - transactions[transactionId] = Transaction({ - destination: destination, - value: value, - data: data, - executed: false - }); - transactionCount += 1; - Submission(transactionId); - } - - /* - * Web3 call functions - */ - /// @dev Returns number of confirmations of a transaction. - /// @param transactionId Transaction ID. - /// @return Number of confirmations. - function getConfirmationCount(uint transactionId) - public - constant - returns (uint count) - { - for (uint i=0; i<owners.length; i++) - if (confirmations[transactionId][owners[i]]) - count += 1; - } - - /// @dev Returns total number of transactions after filers are applied. - /// @param pending Include pending transactions. - /// @param executed Include executed transactions. - /// @return Total number of transactions after filters are applied. - function getTransactionCount(bool pending, bool executed) - public - constant - returns (uint count) - { - for (uint i=0; i<transactionCount; i++) - if ( pending && !transactions[i].executed - || executed && transactions[i].executed) - count += 1; - } - - /// @dev Returns list of owners. - /// @return List of owner addresses. - function getOwners() - public - constant - returns (address[]) - { - return owners; - } - - /// @dev Returns array with owner addresses, which confirmed transaction. - /// @param transactionId Transaction ID. - /// @return Returns array of owner addresses. - function getConfirmations(uint transactionId) - public - constant - returns (address[] _confirmations) - { - address[] memory confirmationsTemp = new address[](owners.length); - uint count = 0; - uint i; - for (i=0; i<owners.length; i++) - if (confirmations[transactionId][owners[i]]) { - confirmationsTemp[count] = owners[i]; - count += 1; - } - _confirmations = new address[](count); - for (i=0; i<count; i++) - _confirmations[i] = confirmationsTemp[i]; - } - - /// @dev Returns list of transaction IDs in defined range. - /// @param from Index start position of transaction array. - /// @param to Index end position of transaction array. - /// @param pending Include pending transactions. - /// @param executed Include executed transactions. - /// @return Returns array of transaction IDs. - function getTransactionIds(uint from, uint to, bool pending, bool executed) - public - constant - returns (uint[] _transactionIds) - { - uint[] memory transactionIdsTemp = new uint[](transactionCount); - uint count = 0; - uint i; - for (i=0; i<transactionCount; i++) - if ( pending && !transactions[i].executed - || executed && transactions[i].executed) - { - transactionIdsTemp[count] = i; - count += 1; - } - _transactionIds = new uint[](to - from); - for (i=from; i<to; i++) - _transactionIds[i - from] = transactionIdsTemp[i]; - } -}
\ No newline at end of file diff --git a/contracts/core/contracts/multisig/MultiSigWalletWithTimeLock.sol b/contracts/core/contracts/multisig/MultiSigWalletWithTimeLock.sol deleted file mode 100644 index 9513d3b30..000000000 --- a/contracts/core/contracts/multisig/MultiSigWalletWithTimeLock.sol +++ /dev/null @@ -1,127 +0,0 @@ -/* - - Copyright 2018 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.4.24; - -import "./MultiSigWallet.sol"; - - -/// @title Multisignature wallet with time lock- Allows multiple parties to execute a transaction after a time lock has passed. -/// @author Amir Bandeali - <amir@0xProject.com> -// solhint-disable not-rely-on-time -contract MultiSigWalletWithTimeLock is - MultiSigWallet -{ - event ConfirmationTimeSet(uint256 indexed transactionId, uint256 confirmationTime); - event TimeLockChange(uint256 secondsTimeLocked); - - uint256 public secondsTimeLocked; - - mapping (uint256 => uint256) public confirmationTimes; - - modifier notFullyConfirmed(uint256 transactionId) { - require( - !isConfirmed(transactionId), - "TX_FULLY_CONFIRMED" - ); - _; - } - - modifier fullyConfirmed(uint256 transactionId) { - require( - isConfirmed(transactionId), - "TX_NOT_FULLY_CONFIRMED" - ); - _; - } - - modifier pastTimeLock(uint256 transactionId) { - require( - block.timestamp >= confirmationTimes[transactionId] + secondsTimeLocked, - "TIME_LOCK_INCOMPLETE" - ); - _; - } - - /// @dev Contract constructor sets initial owners, required number of confirmations, and time lock. - /// @param _owners List of initial owners. - /// @param _required Number of required confirmations. - /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds. - constructor ( - address[] _owners, - uint256 _required, - uint256 _secondsTimeLocked - ) - public - MultiSigWallet(_owners, _required) - { - secondsTimeLocked = _secondsTimeLocked; - } - - /// @dev Changes the duration of the time lock for transactions. - /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds. - function changeTimeLock(uint256 _secondsTimeLocked) - public - onlyWallet - { - secondsTimeLocked = _secondsTimeLocked; - emit TimeLockChange(_secondsTimeLocked); - } - - /// @dev Allows an owner to confirm a transaction. - /// @param transactionId Transaction ID. - function confirmTransaction(uint256 transactionId) - public - ownerExists(msg.sender) - transactionExists(transactionId) - notConfirmed(transactionId, msg.sender) - notFullyConfirmed(transactionId) - { - confirmations[transactionId][msg.sender] = true; - emit Confirmation(msg.sender, transactionId); - if (isConfirmed(transactionId)) { - setConfirmationTime(transactionId, block.timestamp); - } - } - - /// @dev Allows anyone to execute a confirmed transaction. - /// @param transactionId Transaction ID. - function executeTransaction(uint256 transactionId) - public - notExecuted(transactionId) - fullyConfirmed(transactionId) - pastTimeLock(transactionId) - { - Transaction storage txn = transactions[transactionId]; - txn.executed = true; - if (external_call(txn.destination, txn.value, txn.data.length, txn.data)) { - emit Execution(transactionId); - } else { - emit ExecutionFailure(transactionId); - txn.executed = false; - } - } - - /// @dev Sets the time of when a submission first passed. - function setConfirmationTime(uint256 transactionId, uint256 confirmationTime) - internal - { - confirmationTimes[transactionId] = confirmationTime; - emit ConfirmationTimeSet(transactionId, confirmationTime); - } -} diff --git a/contracts/core/contracts/protocol/AssetProxyOwner/AssetProxyOwner.sol b/contracts/core/contracts/protocol/AssetProxyOwner/AssetProxyOwner.sol index edb788fab..3096340b9 100644 --- a/contracts/core/contracts/protocol/AssetProxyOwner/AssetProxyOwner.sol +++ b/contracts/core/contracts/protocol/AssetProxyOwner/AssetProxyOwner.sol @@ -18,7 +18,7 @@ pragma solidity 0.4.24; -import "../../multisig/MultiSigWalletWithTimeLock.sol"; +import "@0x/contracts-multisig/contracts/multisig/MultiSigWalletWithTimeLock.sol"; import "../../utils/LibBytes/LibBytes.sol"; diff --git a/contracts/core/package.json b/contracts/core/package.json index b20b0ef3f..bdfd7078f 100644 --- a/contracts/core/package.json +++ b/contracts/core/package.json @@ -1,6 +1,6 @@ { "private": true, - "name": "contracts", + "name": "@0x/contracts-core", "version": "2.1.56", "engines": { "node": ">=6.12" @@ -47,6 +47,7 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/contracts/core/README.md", "devDependencies": { + "@0x/contracts-test-utils": "^1.0.0", "@0x/abi-gen": "^1.0.17", "@0x/dev-utils": "^1.0.19", "@0x/sol-compiler": "^1.1.14", @@ -73,8 +74,14 @@ "yargs": "^10.0.3" }, "dependencies": { +<<<<<<< HEAD "@0x/base-contract": "^3.0.8", "@0x/order-utils": "^3.0.4", +======= + "@0x/contracts-multisig": "^1.0.0", + "@0x/base-contract": "^3.0.7", + "@0x/order-utils": "^3.0.3", +>>>>>>> Refactor contracts-core into contracts-multisig, contracts-core and contracts-test-utils "@0x/types": "^1.3.0", "@0x/typescript-typings": "^3.0.4", "@0x/utils": "^2.0.6", diff --git a/contracts/core/test/asset_proxy/authorizable.ts b/contracts/core/test/asset_proxy/authorizable.ts index e21af9b81..853d18be0 100644 --- a/contracts/core/test/asset_proxy/authorizable.ts +++ b/contracts/core/test/asset_proxy/authorizable.ts @@ -1,3 +1,11 @@ +import { + chaiSetup, + constants, + expectTransactionFailedAsync, + provider, + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { RevertReason } from '@0x/types'; import { BigNumber } from '@0x/utils'; @@ -6,10 +14,6 @@ import * as _ from 'lodash'; import { MixinAuthorizableContract } from '../../generated-wrappers/mixin_authorizable'; import { artifacts } from '../../src/artifacts'; -import { expectTransactionFailedAsync } from '../utils/assertions'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; diff --git a/contracts/core/test/asset_proxy/proxies.ts b/contracts/core/test/asset_proxy/proxies.ts index 8fa1e602a..2527b0fbf 100644 --- a/contracts/core/test/asset_proxy/proxies.ts +++ b/contracts/core/test/asset_proxy/proxies.ts @@ -1,3 +1,13 @@ +import { + chaiSetup, + constants, + expectTransactionFailedAsync, + expectTransactionFailedWithoutReasonAsync, + LogDecoder, + provider, + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { assetDataUtils } from '@0x/order-utils'; import { RevertReason } from '@0x/types'; @@ -16,13 +26,8 @@ import { IAssetDataContract } from '../../generated-wrappers/i_asset_data'; import { IAssetProxyContract } from '../../generated-wrappers/i_asset_proxy'; import { MultiAssetProxyContract } from '../../generated-wrappers/multi_asset_proxy'; import { artifacts } from '../../src/artifacts'; -import { expectTransactionFailedAsync, expectTransactionFailedWithoutReasonAsync } from '../utils/assertions'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; import { ERC20Wrapper } from '../utils/erc20_wrapper'; import { ERC721Wrapper } from '../utils/erc721_wrapper'; -import { LogDecoder } from '../utils/log_decoder'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -553,7 +558,7 @@ describe('Asset Transfer Proxies', () => { erc721Receiver.address, amount, ); - const logDecoder = new LogDecoder(web3Wrapper); + const logDecoder = new LogDecoder(web3Wrapper, artifacts); const tx = await logDecoder.getTxWithDecodedLogsAsync( await web3Wrapper.sendTransactionAsync({ to: erc721Proxy.address, diff --git a/contracts/core/test/exchange/core.ts b/contracts/core/test/exchange/core.ts index 9159b0d8f..fd6b9ee6b 100644 --- a/contracts/core/test/exchange/core.ts +++ b/contracts/core/test/exchange/core.ts @@ -1,3 +1,16 @@ +import { + chaiSetup, + constants, + ERC20BalancesByOwner, + expectTransactionFailedAsync, + getLatestBlockTimestampAsync, + increaseTimeAndMineBlockAsync, + OrderFactory, + OrderStatus, + provider, + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; import { RevertReason, SignatureType, SignedOrder } from '@0x/types'; @@ -19,16 +32,9 @@ import { MultiAssetProxyContract } from '../../generated-wrappers/multi_asset_pr import { ReentrantERC20TokenContract } from '../../generated-wrappers/reentrant_erc20_token'; import { TestStaticCallReceiverContract } from '../../generated-wrappers/test_static_call_receiver'; import { artifacts } from '../../src/artifacts'; -import { expectTransactionFailedAsync } from '../utils/assertions'; -import { getLatestBlockTimestampAsync, increaseTimeAndMineBlockAsync } from '../utils/block_timestamp'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; import { ERC20Wrapper } from '../utils/erc20_wrapper'; import { ERC721Wrapper } from '../utils/erc721_wrapper'; import { ExchangeWrapper } from '../utils/exchange_wrapper'; -import { OrderFactory } from '../utils/order_factory'; -import { ERC20BalancesByOwner, OrderStatus } from '../utils/types'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; diff --git a/contracts/core/test/exchange/dispatcher.ts b/contracts/core/test/exchange/dispatcher.ts index 3d3aa42c2..9bc5cbcce 100644 --- a/contracts/core/test/exchange/dispatcher.ts +++ b/contracts/core/test/exchange/dispatcher.ts @@ -1,3 +1,12 @@ +import { + chaiSetup, + constants, + expectTransactionFailedAsync, + LogDecoder, + provider, + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { assetDataUtils } from '@0x/order-utils'; import { AssetProxyId, RevertReason } from '@0x/types'; @@ -14,13 +23,8 @@ import { TestAssetProxyDispatcherContract, } from '../../generated-wrappers/test_asset_proxy_dispatcher'; import { artifacts } from '../../src/artifacts'; -import { expectTransactionFailedAsync } from '../utils/assertions'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; import { ERC20Wrapper } from '../utils/erc20_wrapper'; import { ERC721Wrapper } from '../utils/erc721_wrapper'; -import { LogDecoder } from '../utils/log_decoder'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -145,7 +149,7 @@ describe('AssetProxyDispatcher', () => { }); it('should log an event with correct arguments when an asset proxy is registered', async () => { - const logDecoder = new LogDecoder(web3Wrapper); + const logDecoder = new LogDecoder(web3Wrapper, artifacts); const txReceipt = await logDecoder.getTxWithDecodedLogsAsync( await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, { from: owner }), ); diff --git a/contracts/core/test/exchange/fill_order.ts b/contracts/core/test/exchange/fill_order.ts index 37efaad2b..2bdbe4855 100644 --- a/contracts/core/test/exchange/fill_order.ts +++ b/contracts/core/test/exchange/fill_order.ts @@ -1,23 +1,25 @@ -import { BlockchainLifecycle } from '@0x/dev-utils'; -import * as _ from 'lodash'; - -import { chaiSetup } from '../utils/chai_setup'; -import { - FillOrderCombinatorialUtils, - fillOrderCombinatorialUtilsFactoryAsync, -} from '../utils/fill_order_combinatorial_utils'; import { AllowanceAmountScenario, AssetDataScenario, BalanceAmountScenario, + chaiSetup, ExpirationTimeSecondsScenario, FeeRecipientAddressScenario, FillScenario, OrderAssetAmountScenario, + provider, TakerAssetFillAmountScenario, TakerScenario, -} from '../utils/types'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; +import { BlockchainLifecycle } from '@0x/dev-utils'; +import * as _ from 'lodash'; + +import { + FillOrderCombinatorialUtils, + fillOrderCombinatorialUtilsFactoryAsync, +} from '../utils/fill_order_combinatorial_utils'; chaiSetup.configure(); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); diff --git a/contracts/core/test/exchange/internal.ts b/contracts/core/test/exchange/internal.ts index 109be29c6..cff8f630c 100644 --- a/contracts/core/test/exchange/internal.ts +++ b/contracts/core/test/exchange/internal.ts @@ -1,3 +1,12 @@ +import { + chaiSetup, + constants, + FillResults, + getRevertReasonOrErrorMessageForSendTransactionAsync, + provider, + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { Order, RevertReason, SignedOrder } from '@0x/types'; import { BigNumber } from '@0x/utils'; @@ -6,12 +15,7 @@ import * as _ from 'lodash'; import { TestExchangeInternalsContract } from '../../generated-wrappers/test_exchange_internals'; import { artifacts } from '../../src/artifacts'; -import { getRevertReasonOrErrorMessageForSendTransactionAsync } from '../utils/assertions'; -import { chaiSetup } from '../utils/chai_setup'; import { bytes32Values, testCombinatoriallyWithReferenceFuncAsync, uint256Values } from '../utils/combinatorial_utils'; -import { constants } from '../utils/constants'; -import { FillResults } from '../utils/types'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; diff --git a/contracts/core/test/exchange/libs.ts b/contracts/core/test/exchange/libs.ts index 503ef0e0f..f52992c13 100644 --- a/contracts/core/test/exchange/libs.ts +++ b/contracts/core/test/exchange/libs.ts @@ -1,3 +1,12 @@ +import { + addressUtils, + chaiSetup, + constants, + OrderFactory, + provider, + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; import { SignedOrder } from '@0x/types'; @@ -7,11 +16,6 @@ import * as chai from 'chai'; import { TestConstantsContract } from '../../generated-wrappers/test_constants'; import { TestLibsContract } from '../../generated-wrappers/test_libs'; import { artifacts } from '../../src/artifacts'; -import { addressUtils } from '../utils/address_utils'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; -import { OrderFactory } from '../utils/order_factory'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; diff --git a/contracts/core/test/exchange/match_orders.ts b/contracts/core/test/exchange/match_orders.ts index eea9992d9..0e841b359 100644 --- a/contracts/core/test/exchange/match_orders.ts +++ b/contracts/core/test/exchange/match_orders.ts @@ -1,3 +1,14 @@ +import { + chaiSetup, + constants, + ERC20BalancesByOwner, + ERC721TokenIdsByOwner, + expectTransactionFailedAsync, + OrderFactory, + provider, + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { assetDataUtils } from '@0x/order-utils'; import { RevertReason } from '@0x/types'; @@ -14,16 +25,10 @@ import { ExchangeContract } from '../../generated-wrappers/exchange'; import { ReentrantERC20TokenContract } from '../../generated-wrappers/reentrant_erc20_token'; import { TestExchangeInternalsContract } from '../../generated-wrappers/test_exchange_internals'; import { artifacts } from '../../src/artifacts'; -import { expectTransactionFailedAsync } from '../utils/assertions'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; import { ERC20Wrapper } from '../utils/erc20_wrapper'; import { ERC721Wrapper } from '../utils/erc721_wrapper'; import { ExchangeWrapper } from '../utils/exchange_wrapper'; import { MatchOrderTester } from '../utils/match_order_tester'; -import { OrderFactory } from '../utils/order_factory'; -import { ERC20BalancesByOwner, ERC721TokenIdsByOwner } from '../utils/types'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); chaiSetup.configure(); diff --git a/contracts/core/test/exchange/signature_validator.ts b/contracts/core/test/exchange/signature_validator.ts index 756c72766..b84a488a1 100644 --- a/contracts/core/test/exchange/signature_validator.ts +++ b/contracts/core/test/exchange/signature_validator.ts @@ -1,3 +1,14 @@ +import { + addressUtils, + chaiSetup, + constants, + expectContractCallFailedAsync, + LogDecoder, + OrderFactory, + provider, + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { assetDataUtils, orderHashUtils, signatureUtils } from '@0x/order-utils'; import { RevertReason, SignatureType, SignedOrder } from '@0x/types'; @@ -13,13 +24,6 @@ import { TestStaticCallReceiverContract } from '../../generated-wrappers/test_st import { ValidatorContract } from '../../generated-wrappers/validator'; import { WalletContract } from '../../generated-wrappers/wallet'; import { artifacts } from '../../src/artifacts'; -import { addressUtils } from '../utils/address_utils'; -import { expectContractCallFailedAsync } from '../utils/assertions'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; -import { LogDecoder } from '../utils/log_decoder'; -import { OrderFactory } from '../utils/order_factory'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -73,7 +77,7 @@ describe('MixinSignatureValidator', () => { provider, txDefaults, ); - signatureValidatorLogDecoder = new LogDecoder(web3Wrapper); + signatureValidatorLogDecoder = new LogDecoder(web3Wrapper, artifacts); await web3Wrapper.awaitTransactionSuccessAsync( await signatureValidator.setSignatureValidatorApproval.sendTransactionAsync(testValidator.address, true, { from: signerAddress, diff --git a/contracts/core/test/exchange/transactions.ts b/contracts/core/test/exchange/transactions.ts index 1b5eef295..c4086d9be 100644 --- a/contracts/core/test/exchange/transactions.ts +++ b/contracts/core/test/exchange/transactions.ts @@ -1,3 +1,16 @@ +import { + chaiSetup, + constants, + ERC20BalancesByOwner, + expectTransactionFailedAsync, + OrderFactory, + orderUtils, + provider, + SignedTransaction, + TransactionFactory, + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils'; import { OrderWithoutExchangeAddress, RevertReason, SignedOrder } from '@0x/types'; @@ -11,16 +24,8 @@ import { ExchangeContract } from '../../generated-wrappers/exchange'; import { ExchangeWrapperContract } from '../../generated-wrappers/exchange_wrapper'; import { WhitelistContract } from '../../generated-wrappers/whitelist'; import { artifacts } from '../../src/artifacts'; -import { expectTransactionFailedAsync } from '../utils/assertions'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; import { ERC20Wrapper } from '../utils/erc20_wrapper'; import { ExchangeWrapper } from '../utils/exchange_wrapper'; -import { OrderFactory } from '../utils/order_factory'; -import { orderUtils } from '../utils/order_utils'; -import { TransactionFactory } from '../utils/transaction_factory'; -import { ERC20BalancesByOwner, SignedTransaction } from '../utils/types'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; diff --git a/contracts/core/test/exchange/wrapper.ts b/contracts/core/test/exchange/wrapper.ts index 6b660aac5..17cb7a3bb 100644 --- a/contracts/core/test/exchange/wrapper.ts +++ b/contracts/core/test/exchange/wrapper.ts @@ -1,3 +1,16 @@ +import { + chaiSetup, + constants, + ERC20BalancesByOwner, + expectTransactionFailedAsync, + getLatestBlockTimestampAsync, + increaseTimeAndMineBlockAsync, + OrderFactory, + OrderStatus, + provider, + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; import { RevertReason, SignedOrder } from '@0x/types'; @@ -13,16 +26,9 @@ import { ERC721ProxyContract } from '../../generated-wrappers/erc721_proxy'; import { ExchangeContract } from '../../generated-wrappers/exchange'; import { ReentrantERC20TokenContract } from '../../generated-wrappers/reentrant_erc20_token'; import { artifacts } from '../../src/artifacts'; -import { expectTransactionFailedAsync } from '../utils/assertions'; -import { getLatestBlockTimestampAsync, increaseTimeAndMineBlockAsync } from '../utils/block_timestamp'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; import { ERC20Wrapper } from '../utils/erc20_wrapper'; import { ERC721Wrapper } from '../utils/erc721_wrapper'; import { ExchangeWrapper } from '../utils/exchange_wrapper'; -import { OrderFactory } from '../utils/order_factory'; -import { ERC20BalancesByOwner, OrderStatus } from '../utils/types'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; diff --git a/contracts/core/test/extensions/forwarder.ts b/contracts/core/test/extensions/forwarder.ts index c006be0fe..44ad4d6ff 100644 --- a/contracts/core/test/extensions/forwarder.ts +++ b/contracts/core/test/extensions/forwarder.ts @@ -1,3 +1,16 @@ +import { + chaiSetup, + constants, + ContractName, + ERC20BalancesByOwner, + expectContractCreationFailedAsync, + expectTransactionFailedAsync, + OrderFactory, + provider, + sendTransactionResult, + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { assetDataUtils } from '@0x/order-utils'; import { RevertReason, SignedOrder } from '@0x/types'; @@ -12,20 +25,10 @@ import { ExchangeContract } from '../../generated-wrappers/exchange'; import { ForwarderContract } from '../../generated-wrappers/forwarder'; import { WETH9Contract } from '../../generated-wrappers/weth9'; import { artifacts } from '../../src/artifacts'; -import { - expectContractCreationFailedAsync, - expectTransactionFailedAsync, - sendTransactionResult, -} from '../utils/assertions'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; import { ERC20Wrapper } from '../utils/erc20_wrapper'; import { ERC721Wrapper } from '../utils/erc721_wrapper'; import { ExchangeWrapper } from '../utils/exchange_wrapper'; import { ForwarderWrapper } from '../utils/forwarder_wrapper'; -import { OrderFactory } from '../utils/order_factory'; -import { ContractName, ERC20BalancesByOwner } from '../utils/types'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; diff --git a/contracts/core/test/extensions/order_validator.ts b/contracts/core/test/extensions/order_validator.ts index 37d7c4c5a..3dbe76f6e 100644 --- a/contracts/core/test/extensions/order_validator.ts +++ b/contracts/core/test/extensions/order_validator.ts @@ -1,3 +1,12 @@ +import { + chaiSetup, + constants, + OrderFactory, + OrderStatus, + provider, + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; import { SignedOrder } from '@0x/types'; @@ -12,14 +21,9 @@ import { ERC721ProxyContract } from '../../generated-wrappers/erc721_proxy'; import { ExchangeContract } from '../../generated-wrappers/exchange'; import { OrderValidatorContract } from '../../generated-wrappers/order_validator'; import { artifacts } from '../../src/artifacts'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; import { ERC20Wrapper } from '../utils/erc20_wrapper'; import { ERC721Wrapper } from '../utils/erc721_wrapper'; import { ExchangeWrapper } from '../utils/exchange_wrapper'; -import { OrderFactory } from '../utils/order_factory'; -import { OrderStatus } from '../utils/types'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; diff --git a/contracts/core/test/global_hooks.ts b/contracts/core/test/global_hooks.ts index 2e9ac9e21..847b8ea91 100644 --- a/contracts/core/test/global_hooks.ts +++ b/contracts/core/test/global_hooks.ts @@ -1,7 +1,6 @@ import { env, EnvVars } from '@0x/dev-utils'; -import { coverage } from './utils/coverage'; -import { profiler } from './utils/profiler'; +import { coverage, profiler } from '@0x/contracts-test-utils'; after('generate coverage report', async () => { if (env.parseBoolean(EnvVars.SolidityCoverage)) { diff --git a/contracts/core/test/libraries/lib_bytes.ts b/contracts/core/test/libraries/lib_bytes.ts index b1a389f00..9338e6e7f 100644 --- a/contracts/core/test/libraries/lib_bytes.ts +++ b/contracts/core/test/libraries/lib_bytes.ts @@ -1,3 +1,12 @@ +import { + chaiSetup, + constants, + expectContractCallFailedAsync, + provider, + txDefaults, + typeEncodingUtils, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { generatePseudoRandomSalt } from '@0x/order-utils'; import { RevertReason } from '@0x/types'; @@ -9,11 +18,6 @@ import * as _ from 'lodash'; import { TestLibBytesContract } from '../../generated-wrappers/test_lib_bytes'; import { artifacts } from '../../src/artifacts'; -import { expectContractCallFailedAsync } from '../utils/assertions'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; -import { typeEncodingUtils } from '../utils/type_encoding_utils'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; diff --git a/contracts/core/test/multisig/asset_proxy_owner.ts b/contracts/core/test/multisig/asset_proxy_owner.ts index 087152316..f9ff9fe1e 100644 --- a/contracts/core/test/multisig/asset_proxy_owner.ts +++ b/contracts/core/test/multisig/asset_proxy_owner.ts @@ -1,3 +1,16 @@ +import { + chaiSetup, + constants, + expectContractCallFailedAsync, + expectContractCreationFailedAsync, + expectTransactionFailedAsync, + expectTransactionFailedWithoutReasonAsync, + increaseTimeAndMineBlockAsync, + provider, + sendTransactionResult, + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { RevertReason } from '@0x/types'; import { BigNumber } from '@0x/utils'; @@ -14,18 +27,7 @@ import { import { MixinAuthorizableContract } from '../../generated-wrappers/mixin_authorizable'; import { TestAssetProxyOwnerContract } from '../../generated-wrappers/test_asset_proxy_owner'; import { artifacts } from '../../src/artifacts'; -import { - expectContractCallFailedAsync, - expectContractCreationFailedAsync, - expectTransactionFailedAsync, - expectTransactionFailedWithoutReasonAsync, - sendTransactionResult, -} from '../utils/assertions'; -import { increaseTimeAndMineBlockAsync } from '../utils/block_timestamp'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; import { MultiSigWrapper } from '../utils/multi_sig_wrapper'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -495,4 +497,3 @@ describe('AssetProxyOwner', () => { }); }); }); -// tslint:enable:no-unnecessary-type-assertion diff --git a/contracts/core/test/multisig/multi_sig_with_time_lock.ts b/contracts/core/test/multisig/multi_sig_with_time_lock.ts deleted file mode 100644 index 1c0cb0515..000000000 --- a/contracts/core/test/multisig/multi_sig_with_time_lock.ts +++ /dev/null @@ -1,347 +0,0 @@ -import { BlockchainLifecycle } from '@0x/dev-utils'; -import { RevertReason } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; -import { LogWithDecodedArgs } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { DummyERC20TokenContract } from '../../generated-wrappers/dummy_erc20_token'; -import { - MultiSigWalletWithTimeLockConfirmationEventArgs, - MultiSigWalletWithTimeLockConfirmationTimeSetEventArgs, - MultiSigWalletWithTimeLockContract, - MultiSigWalletWithTimeLockExecutionEventArgs, - MultiSigWalletWithTimeLockExecutionFailureEventArgs, - MultiSigWalletWithTimeLockSubmissionEventArgs, -} from '../../generated-wrappers/multi_sig_wallet_with_time_lock'; -import { artifacts } from '../../src/artifacts'; -import { expectTransactionFailedAsync, expectTransactionFailedWithoutReasonAsync } from '../utils/assertions'; -import { increaseTimeAndMineBlockAsync } from '../utils/block_timestamp'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; -import { MultiSigWrapper } from '../utils/multi_sig_wrapper'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; - -chaiSetup.configure(); -const expect = chai.expect; -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); -// tslint:disable:no-unnecessary-type-assertion -describe('MultiSigWalletWithTimeLock', () => { - let owners: string[]; - let notOwner: string; - const REQUIRED_APPROVALS = new BigNumber(2); - const SECONDS_TIME_LOCKED = new BigNumber(1000000); - - before(async () => { - await blockchainLifecycle.startAsync(); - }); - after(async () => { - await blockchainLifecycle.revertAsync(); - }); - before(async () => { - const accounts = await web3Wrapper.getAvailableAddressesAsync(); - owners = [accounts[0], accounts[1], accounts[2]]; - notOwner = accounts[3]; - }); - - let multiSig: MultiSigWalletWithTimeLockContract; - let multiSigWrapper: MultiSigWrapper; - - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); - - describe('external_call', () => { - it('should be internal', async () => { - const secondsTimeLocked = new BigNumber(0); - multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync( - artifacts.MultiSigWalletWithTimeLock, - provider, - txDefaults, - owners, - REQUIRED_APPROVALS, - secondsTimeLocked, - ); - expect(_.isUndefined((multiSig as any).external_call)).to.be.equal(true); - }); - }); - describe('confirmTransaction', () => { - let txId: BigNumber; - beforeEach(async () => { - const secondsTimeLocked = new BigNumber(0); - multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync( - artifacts.MultiSigWalletWithTimeLock, - provider, - txDefaults, - owners, - REQUIRED_APPROVALS, - secondsTimeLocked, - ); - multiSigWrapper = new MultiSigWrapper(multiSig, provider); - const destination = notOwner; - const data = constants.NULL_BYTES; - const txReceipt = await multiSigWrapper.submitTransactionAsync(destination, data, owners[0]); - txId = (txReceipt.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockSubmissionEventArgs>).args - .transactionId; - }); - it('should revert if called by a non-owner', async () => { - await expectTransactionFailedWithoutReasonAsync(multiSigWrapper.confirmTransactionAsync(txId, notOwner)); - }); - it('should revert if transaction does not exist', async () => { - const nonexistentTxId = new BigNumber(123456789); - await expectTransactionFailedWithoutReasonAsync( - multiSigWrapper.confirmTransactionAsync(nonexistentTxId, owners[1]), - ); - }); - it('should revert if transaction is already confirmed by caller', async () => { - await expectTransactionFailedWithoutReasonAsync(multiSigWrapper.confirmTransactionAsync(txId, owners[0])); - }); - it('should confirm transaction for caller and log a Confirmation event', async () => { - const txReceipt = await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); - const log = txReceipt.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockConfirmationEventArgs>; - expect(log.event).to.be.equal('Confirmation'); - expect(log.args.sender).to.be.equal(owners[1]); - expect(log.args.transactionId).to.be.bignumber.equal(txId); - }); - it('should revert if fully confirmed', async () => { - await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); - await expectTransactionFailedAsync( - multiSigWrapper.confirmTransactionAsync(txId, owners[2]), - RevertReason.TxFullyConfirmed, - ); - }); - it('should set the confirmation time of the transaction if it becomes fully confirmed', async () => { - const txReceipt = await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); - const blockNum = await web3Wrapper.getBlockNumberAsync(); - const timestamp = new BigNumber(await web3Wrapper.getBlockTimestampAsync(blockNum)); - const log = txReceipt.logs[1] as LogWithDecodedArgs<MultiSigWalletWithTimeLockConfirmationTimeSetEventArgs>; - expect(log.args.confirmationTime).to.be.bignumber.equal(timestamp); - expect(log.args.transactionId).to.be.bignumber.equal(txId); - }); - }); - describe('executeTransaction', () => { - let txId: BigNumber; - const secondsTimeLocked = new BigNumber(1000000); - beforeEach(async () => { - multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync( - artifacts.MultiSigWalletWithTimeLock, - provider, - txDefaults, - owners, - REQUIRED_APPROVALS, - secondsTimeLocked, - ); - multiSigWrapper = new MultiSigWrapper(multiSig, provider); - const destination = notOwner; - const data = constants.NULL_BYTES; - const txReceipt = await multiSigWrapper.submitTransactionAsync(destination, data, owners[0]); - txId = (txReceipt.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockSubmissionEventArgs>).args - .transactionId; - }); - it('should revert if transaction has not been fully confirmed', async () => { - await increaseTimeAndMineBlockAsync(secondsTimeLocked.toNumber()); - await expectTransactionFailedAsync( - multiSigWrapper.executeTransactionAsync(txId, owners[1]), - RevertReason.TxNotFullyConfirmed, - ); - }); - it('should revert if time lock has not passed', async () => { - await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); - await expectTransactionFailedAsync( - multiSigWrapper.executeTransactionAsync(txId, owners[1]), - RevertReason.TimeLockIncomplete, - ); - }); - it('should execute a transaction and log an Execution event if successful and called by owner', async () => { - await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); - await increaseTimeAndMineBlockAsync(secondsTimeLocked.toNumber()); - const txReceipt = await multiSigWrapper.executeTransactionAsync(txId, owners[1]); - const log = txReceipt.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockExecutionEventArgs>; - expect(log.event).to.be.equal('Execution'); - expect(log.args.transactionId).to.be.bignumber.equal(txId); - }); - it('should execute a transaction and log an Execution event if successful and called by non-owner', async () => { - await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); - await increaseTimeAndMineBlockAsync(secondsTimeLocked.toNumber()); - const txReceipt = await multiSigWrapper.executeTransactionAsync(txId, notOwner); - const log = txReceipt.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockExecutionEventArgs>; - expect(log.event).to.be.equal('Execution'); - expect(log.args.transactionId).to.be.bignumber.equal(txId); - }); - it('should revert if a required confirmation is revoked before executeTransaction is called', async () => { - await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); - await increaseTimeAndMineBlockAsync(secondsTimeLocked.toNumber()); - await multiSigWrapper.revokeConfirmationAsync(txId, owners[0]); - await expectTransactionFailedAsync( - multiSigWrapper.executeTransactionAsync(txId, owners[1]), - RevertReason.TxNotFullyConfirmed, - ); - }); - it('should revert if transaction has been executed', async () => { - await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); - await increaseTimeAndMineBlockAsync(secondsTimeLocked.toNumber()); - const txReceipt = await multiSigWrapper.executeTransactionAsync(txId, owners[1]); - const log = txReceipt.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockExecutionEventArgs>; - expect(log.args.transactionId).to.be.bignumber.equal(txId); - await expectTransactionFailedWithoutReasonAsync(multiSigWrapper.executeTransactionAsync(txId, owners[1])); - }); - it("should log an ExecutionFailure event and not update the transaction's execution state if unsuccessful", async () => { - const contractWithoutFallback = await DummyERC20TokenContract.deployFrom0xArtifactAsync( - artifacts.DummyERC20Token, - provider, - txDefaults, - constants.DUMMY_TOKEN_NAME, - constants.DUMMY_TOKEN_SYMBOL, - constants.DUMMY_TOKEN_DECIMALS, - constants.DUMMY_TOKEN_TOTAL_SUPPLY, - ); - const data = constants.NULL_BYTES; - const value = new BigNumber(10); - const submissionTxReceipt = await multiSigWrapper.submitTransactionAsync( - contractWithoutFallback.address, - data, - owners[0], - { value }, - ); - const newTxId = (submissionTxReceipt.logs[0] as LogWithDecodedArgs< - MultiSigWalletWithTimeLockSubmissionEventArgs - >).args.transactionId; - await multiSigWrapper.confirmTransactionAsync(newTxId, owners[1]); - await increaseTimeAndMineBlockAsync(secondsTimeLocked.toNumber()); - const txReceipt = await multiSigWrapper.executeTransactionAsync(newTxId, owners[1]); - const executionFailureLog = txReceipt.logs[0] as LogWithDecodedArgs< - MultiSigWalletWithTimeLockExecutionFailureEventArgs - >; - expect(executionFailureLog.event).to.be.equal('ExecutionFailure'); - expect(executionFailureLog.args.transactionId).to.be.bignumber.equal(newTxId); - }); - }); - describe('changeTimeLock', () => { - describe('initially non-time-locked', async () => { - before(async () => { - await blockchainLifecycle.startAsync(); - }); - after(async () => { - await blockchainLifecycle.revertAsync(); - }); - before('deploy a wallet', async () => { - const secondsTimeLocked = new BigNumber(0); - multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync( - artifacts.MultiSigWalletWithTimeLock, - provider, - txDefaults, - owners, - REQUIRED_APPROVALS, - secondsTimeLocked, - ); - multiSigWrapper = new MultiSigWrapper(multiSig, provider); - }); - - it('should throw when not called by wallet', async () => { - return expectTransactionFailedWithoutReasonAsync( - multiSig.changeTimeLock.sendTransactionAsync(SECONDS_TIME_LOCKED, { from: owners[0] }), - ); - }); - - it('should throw without enough confirmations', async () => { - const destination = multiSig.address; - const changeTimeLockData = multiSig.changeTimeLock.getABIEncodedTransactionData(SECONDS_TIME_LOCKED); - const res = await multiSigWrapper.submitTransactionAsync(destination, changeTimeLockData, owners[0]); - const log = res.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockSubmissionEventArgs>; - const txId = log.args.transactionId; - return expectTransactionFailedAsync( - multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }), - RevertReason.TxNotFullyConfirmed, - ); - }); - - it('should set confirmation time with enough confirmations', async () => { - const destination = multiSig.address; - const changeTimeLockData = multiSig.changeTimeLock.getABIEncodedTransactionData(SECONDS_TIME_LOCKED); - const subRes = await multiSigWrapper.submitTransactionAsync(destination, changeTimeLockData, owners[0]); - const subLog = subRes.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockSubmissionEventArgs>; - const txId = subLog.args.transactionId; - - const confirmRes = await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); - expect(confirmRes.logs).to.have.length(2); - - const blockNum = await web3Wrapper.getBlockNumberAsync(); - const blockInfo = await web3Wrapper.getBlockIfExistsAsync(blockNum); - if (_.isUndefined(blockInfo)) { - throw new Error(`Unexpectedly failed to fetch block at #${blockNum}`); - } - const timestamp = new BigNumber(blockInfo.timestamp); - const confirmationTimeBigNum = new BigNumber(await multiSig.confirmationTimes.callAsync(txId)); - - expect(timestamp).to.be.bignumber.equal(confirmationTimeBigNum); - }); - - it('should be executable with enough confirmations and secondsTimeLocked of 0', async () => { - const destination = multiSig.address; - const changeTimeLockData = multiSig.changeTimeLock.getABIEncodedTransactionData(SECONDS_TIME_LOCKED); - const subRes = await multiSigWrapper.submitTransactionAsync(destination, changeTimeLockData, owners[0]); - const subLog = subRes.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockSubmissionEventArgs>; - const txId = subLog.args.transactionId; - - await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); - await multiSigWrapper.executeTransactionAsync(txId, owners[1]); - - const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.callAsync()); - expect(secondsTimeLocked).to.be.bignumber.equal(SECONDS_TIME_LOCKED); - }); - }); - describe('initially time-locked', async () => { - before(async () => { - await blockchainLifecycle.startAsync(); - }); - after(async () => { - await blockchainLifecycle.revertAsync(); - }); - let txId: BigNumber; - const newSecondsTimeLocked = new BigNumber(0); - before('deploy a wallet, submit transaction to change timelock, and confirm the transaction', async () => { - multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync( - artifacts.MultiSigWalletWithTimeLock, - provider, - txDefaults, - owners, - REQUIRED_APPROVALS, - SECONDS_TIME_LOCKED, - ); - multiSigWrapper = new MultiSigWrapper(multiSig, provider); - - const changeTimeLockData = multiSig.changeTimeLock.getABIEncodedTransactionData(newSecondsTimeLocked); - const res = await multiSigWrapper.submitTransactionAsync( - multiSig.address, - changeTimeLockData, - owners[0], - ); - const log = res.logs[0] as LogWithDecodedArgs<MultiSigWalletWithTimeLockSubmissionEventArgs>; - txId = log.args.transactionId; - await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); - }); - - it('should throw if it has enough confirmations but is not past the time lock', async () => { - return expectTransactionFailedAsync( - multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }), - RevertReason.TimeLockIncomplete, - ); - }); - - it('should execute if it has enough confirmations and is past the time lock', async () => { - await increaseTimeAndMineBlockAsync(SECONDS_TIME_LOCKED.toNumber()); - await web3Wrapper.awaitTransactionSuccessAsync( - await multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }), - constants.AWAIT_TRANSACTION_MINED_MS, - ); - - const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.callAsync()); - expect(secondsTimeLocked).to.be.bignumber.equal(newSecondsTimeLocked); - }); - }); - }); -}); -// tslint:enable:no-unnecessary-type-assertion diff --git a/contracts/core/test/tokens/erc721_token.ts b/contracts/core/test/tokens/erc721_token.ts index 72407748f..3b0a5f001 100644 --- a/contracts/core/test/tokens/erc721_token.ts +++ b/contracts/core/test/tokens/erc721_token.ts @@ -1,3 +1,13 @@ +import { + chaiSetup, + constants, + expectTransactionFailedAsync, + expectTransactionFailedWithoutReasonAsync, + LogDecoder, + provider, + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { RevertReason } from '@0x/types'; import { BigNumber } from '@0x/utils'; @@ -14,11 +24,6 @@ import { } from '../../generated-wrappers/dummy_erc721_token'; import { InvalidERC721ReceiverContract } from '../../generated-wrappers/invalid_erc721_receiver'; import { artifacts } from '../../src/artifacts'; -import { expectTransactionFailedAsync, expectTransactionFailedWithoutReasonAsync } from '../utils/assertions'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; -import { LogDecoder } from '../utils/log_decoder'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -53,7 +58,7 @@ describe('ERC721Token', () => { provider, txDefaults, ); - logDecoder = new LogDecoder(web3Wrapper); + logDecoder = new LogDecoder(web3Wrapper, artifacts); await web3Wrapper.awaitTransactionSuccessAsync( await token.mint.sendTransactionAsync(owner, tokenId, { from: owner }), constants.AWAIT_TRANSACTION_MINED_MS, diff --git a/contracts/core/test/tokens/unlimited_allowance_token.ts b/contracts/core/test/tokens/unlimited_allowance_token.ts index ea5a50522..c3e4072c5 100644 --- a/contracts/core/test/tokens/unlimited_allowance_token.ts +++ b/contracts/core/test/tokens/unlimited_allowance_token.ts @@ -1,3 +1,11 @@ +import { + chaiSetup, + constants, + expectContractCallFailedAsync, + provider, + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { RevertReason } from '@0x/types'; import { BigNumber } from '@0x/utils'; @@ -5,10 +13,6 @@ import * as chai from 'chai'; import { DummyERC20TokenContract } from '../../generated-wrappers/dummy_erc20_token'; import { artifacts } from '../../src/artifacts'; -import { expectContractCallFailedAsync } from '../utils/assertions'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; diff --git a/contracts/core/test/tokens/weth9.ts b/contracts/core/test/tokens/weth9.ts index 9a31dc3f2..225481904 100644 --- a/contracts/core/test/tokens/weth9.ts +++ b/contracts/core/test/tokens/weth9.ts @@ -1,3 +1,12 @@ +import { + chaiSetup, + constants, + expectInsufficientFundsAsync, + expectTransactionFailedWithoutReasonAsync, + provider, + txDefaults, + web3Wrapper, +} from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { BigNumber } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; @@ -5,10 +14,6 @@ import * as chai from 'chai'; import { WETH9Contract } from '../../generated-wrappers/weth9'; import { artifacts } from '../../src/artifacts'; -import { expectInsufficientFundsAsync, expectTransactionFailedWithoutReasonAsync } from '../utils/assertions'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; diff --git a/contracts/core/test/tokens/zrx_token.ts b/contracts/core/test/tokens/zrx_token.ts index cab62c205..6bc5e164c 100644 --- a/contracts/core/test/tokens/zrx_token.ts +++ b/contracts/core/test/tokens/zrx_token.ts @@ -1,3 +1,4 @@ +import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { BigNumber } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; @@ -5,9 +6,6 @@ import * as chai from 'chai'; import { ZRXTokenContract } from '../../generated-wrappers/zrx_token'; import { artifacts } from '../../src/artifacts'; -import { chaiSetup } from '../utils/chai_setup'; -import { constants } from '../utils/constants'; -import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; diff --git a/contracts/core/test/utils/abstract_asset_wrapper.ts b/contracts/core/test/utils/abstract_asset_wrapper.ts deleted file mode 100644 index 4b56a8502..000000000 --- a/contracts/core/test/utils/abstract_asset_wrapper.ts +++ /dev/null @@ -1,3 +0,0 @@ -export abstract class AbstractAssetWrapper { - public abstract getProxyId(): string; -} diff --git a/contracts/core/test/utils/address_utils.ts b/contracts/core/test/utils/address_utils.ts deleted file mode 100644 index 634da0c16..000000000 --- a/contracts/core/test/utils/address_utils.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { generatePseudoRandomSalt } from '@0x/order-utils'; -import { crypto } from '@0x/order-utils/lib/src/crypto'; - -export const addressUtils = { - generatePseudoRandomAddress(): string { - const randomBigNum = generatePseudoRandomSalt(); - const randomBuff = crypto.solSHA3([randomBigNum]); - const randomAddress = `0x${randomBuff.slice(0, 20).toString('hex')}`; - return randomAddress; - }, -}; diff --git a/contracts/core/test/utils/assertions.ts b/contracts/core/test/utils/assertions.ts deleted file mode 100644 index 5b1cedfcc..000000000 --- a/contracts/core/test/utils/assertions.ts +++ /dev/null @@ -1,199 +0,0 @@ -import { RevertReason } from '@0x/types'; -import { logUtils } from '@0x/utils'; -import { NodeType } from '@0x/web3-wrapper'; -import * as chai from 'chai'; -import { TransactionReceipt, TransactionReceiptStatus, TransactionReceiptWithDecodedLogs } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { web3Wrapper } from './web3_wrapper'; - -const expect = chai.expect; - -let nodeType: NodeType | undefined; - -// Represents the return value of a `sendTransaction` call. The Promise should -// resolve with either a transaction receipt or a transaction hash. -export type sendTransactionResult = Promise<TransactionReceipt | TransactionReceiptWithDecodedLogs | string>; - -/** - * Returns ganacheError if the backing Ethereum node is Ganache and gethError - * if it is Geth. - * @param ganacheError the error to be returned if the backing node is Ganache. - * @param gethError the error to be returned if the backing node is Geth. - * @returns either the given ganacheError or gethError depending on the backing - * node. - */ -async function _getGanacheOrGethError(ganacheError: string, gethError: string): Promise<string> { - if (_.isUndefined(nodeType)) { - nodeType = await web3Wrapper.getNodeTypeAsync(); - } - switch (nodeType) { - case NodeType.Ganache: - return ganacheError; - case NodeType.Geth: - return gethError; - default: - throw new Error(`Unknown node type: ${nodeType}`); - } -} - -async function _getInsufficientFundsErrorMessageAsync(): Promise<string> { - return _getGanacheOrGethError("sender doesn't have enough funds", 'insufficient funds'); -} - -async function _getTransactionFailedErrorMessageAsync(): Promise<string> { - return _getGanacheOrGethError('revert', 'always failing transaction'); -} - -async function _getContractCallFailedErrorMessageAsync(): Promise<string> { - return _getGanacheOrGethError('revert', 'Contract call failed'); -} - -/** - * Returns the expected error message for an 'invalid opcode' resulting from a - * contract call. The exact error message depends on the backing Ethereum node. - */ -export async function getInvalidOpcodeErrorMessageForCallAsync(): Promise<string> { - return _getGanacheOrGethError('invalid opcode', 'Contract call failed'); -} - -/** - * Returns the expected error message for the given revert reason resulting from - * a sendTransaction call. The exact error message depends on the backing - * Ethereum node and whether it supports revert reasons. - * @param reason a specific revert reason. - * @returns the expected error message. - */ -export async function getRevertReasonOrErrorMessageForSendTransactionAsync(reason: RevertReason): Promise<string> { - return _getGanacheOrGethError(reason, 'always failing transaction'); -} - -/** - * Rejects if the given Promise does not reject with an error indicating - * insufficient funds. - * @param p a promise resulting from a contract call or sendTransaction call. - * @returns a new Promise which will reject if the conditions are not met and - * otherwise resolve with no value. - */ -export async function expectInsufficientFundsAsync<T>(p: Promise<T>): Promise<void> { - const errMessage = await _getInsufficientFundsErrorMessageAsync(); - return expect(p).to.be.rejectedWith(errMessage); -} - -/** - * Resolves if the the sendTransaction call fails with the given revert reason. - * However, since Geth does not support revert reasons for sendTransaction, this - * falls back to expectTransactionFailedWithoutReasonAsync if the backing - * Ethereum node is Geth. - * @param p a Promise resulting from a sendTransaction call - * @param reason a specific revert reason - * @returns a new Promise which will reject if the conditions are not met and - * otherwise resolve with no value. - */ -export async function expectTransactionFailedAsync(p: sendTransactionResult, reason: RevertReason): Promise<void> { - // HACK(albrow): This dummy `catch` should not be necessary, but if you - // remove it, there is an uncaught exception and the Node process will - // forcibly exit. It's possible this is a false positive in - // make-promises-safe. - p.catch(e => { - _.noop(e); - }); - - if (_.isUndefined(nodeType)) { - nodeType = await web3Wrapper.getNodeTypeAsync(); - } - switch (nodeType) { - case NodeType.Ganache: - return expect(p).to.be.rejectedWith(reason); - case NodeType.Geth: - logUtils.warn( - 'WARNING: Geth does not support revert reasons for sendTransaction. This test will pass if the transaction fails for any reason.', - ); - return expectTransactionFailedWithoutReasonAsync(p); - default: - throw new Error(`Unknown node type: ${nodeType}`); - } -} - -/** - * Resolves if the transaction fails without a revert reason, or if the - * corresponding transactionReceipt has a status of 0 or '0', indicating - * failure. - * @param p a Promise resulting from a sendTransaction call - * @returns a new Promise which will reject if the conditions are not met and - * otherwise resolve with no value. - */ -export async function expectTransactionFailedWithoutReasonAsync(p: sendTransactionResult): Promise<void> { - return p - .then(async result => { - let txReceiptStatus: TransactionReceiptStatus; - if (_.isString(result)) { - // Result is a txHash. We need to make a web3 call to get the - // receipt, then get the status from the receipt. - const txReceipt = await web3Wrapper.awaitTransactionMinedAsync(result); - txReceiptStatus = txReceipt.status; - } else if ('status' in result) { - // Result is a transaction receipt, so we can get the status - // directly. - txReceiptStatus = result.status; - } else { - throw new Error('Unexpected result type: ' + typeof result); - } - expect(_.toString(txReceiptStatus)).to.equal( - '0', - 'Expected transaction to fail but receipt had a non-zero status, indicating success', - ); - }) - .catch(async err => { - // If the promise rejects, we expect a specific error message, - // depending on the backing Ethereum node type. - const errMessage = await _getTransactionFailedErrorMessageAsync(); - expect(err.message).to.include(errMessage); - }); -} - -/** - * Resolves if the the contract call fails with the given revert reason. - * @param p a Promise resulting from a contract call - * @param reason a specific revert reason - * @returns a new Promise which will reject if the conditions are not met and - * otherwise resolve with no value. - */ -export async function expectContractCallFailedAsync<T>(p: Promise<T>, reason: RevertReason): Promise<void> { - return expect(p).to.be.rejectedWith(reason); -} - -/** - * Resolves if the contract call fails without a revert reason. - * @param p a Promise resulting from a contract call - * @returns a new Promise which will reject if the conditions are not met and - * otherwise resolve with no value. - */ -export async function expectContractCallFailedWithoutReasonAsync<T>(p: Promise<T>): Promise<void> { - const errMessage = await _getContractCallFailedErrorMessageAsync(); - return expect(p).to.be.rejectedWith(errMessage); -} - -/** - * Resolves if the contract creation/deployment fails without a revert reason. - * @param p a Promise resulting from a contract creation/deployment - * @returns a new Promise which will reject if the conditions are not met and - * otherwise resolve with no value. - */ -export async function expectContractCreationFailedAsync<T>( - p: sendTransactionResult, - reason: RevertReason, -): Promise<void> { - return expectTransactionFailedAsync(p, reason); -} - -/** - * Resolves if the contract creation/deployment fails without a revert reason. - * @param p a Promise resulting from a contract creation/deployment - * @returns a new Promise which will reject if the conditions are not met and - * otherwise resolve with no value. - */ -export async function expectContractCreationFailedWithoutReasonAsync<T>(p: Promise<T>): Promise<void> { - const errMessage = await _getTransactionFailedErrorMessageAsync(); - return expect(p).to.be.rejectedWith(errMessage); -} diff --git a/contracts/core/test/utils/asset_wrapper.ts b/contracts/core/test/utils/asset_wrapper.ts index 4e7696066..e4090ad74 100644 --- a/contracts/core/test/utils/asset_wrapper.ts +++ b/contracts/core/test/utils/asset_wrapper.ts @@ -1,10 +1,9 @@ +import { AbstractAssetWrapper, constants } from '@0x/contracts-test-utils'; import { assetDataUtils } from '@0x/order-utils'; import { AssetProxyId } from '@0x/types'; import { BigNumber, errorUtils } from '@0x/utils'; import * as _ from 'lodash'; -import { AbstractAssetWrapper } from './abstract_asset_wrapper'; -import { constants } from './constants'; import { ERC20Wrapper } from './erc20_wrapper'; import { ERC721Wrapper } from './erc721_wrapper'; diff --git a/contracts/core/test/utils/block_timestamp.ts b/contracts/core/test/utils/block_timestamp.ts deleted file mode 100644 index 66c13eed1..000000000 --- a/contracts/core/test/utils/block_timestamp.ts +++ /dev/null @@ -1,43 +0,0 @@ -import * as _ from 'lodash'; - -import { constants } from './constants'; -import { web3Wrapper } from './web3_wrapper'; - -let firstAccount: string | undefined; - -/** - * Increases time by the given number of seconds and then mines a block so that - * the current block timestamp has the offset applied. - * @param seconds the number of seconds by which to incrase the time offset. - * @returns a new Promise which will resolve with the new total time offset or - * reject if the time could not be increased. - */ -export async function increaseTimeAndMineBlockAsync(seconds: number): Promise<number> { - if (_.isUndefined(firstAccount)) { - const accounts = await web3Wrapper.getAvailableAddressesAsync(); - firstAccount = accounts[0]; - } - - const offset = await web3Wrapper.increaseTimeAsync(seconds); - // Note: we need to send a transaction after increasing time so - // that a block is actually mined. The contract looks at the - // last mined block for the timestamp. - await web3Wrapper.awaitTransactionSuccessAsync( - await web3Wrapper.sendTransactionAsync({ from: firstAccount, to: firstAccount, value: 0 }), - constants.AWAIT_TRANSACTION_MINED_MS, - ); - - return offset; -} - -/** - * Returns the timestamp of the latest block in seconds since the Unix epoch. - * @returns a new Promise which will resolve with the timestamp in seconds. - */ -export async function getLatestBlockTimestampAsync(): Promise<number> { - const currentBlockIfExists = await web3Wrapper.getBlockIfExistsAsync('latest'); - if (_.isUndefined(currentBlockIfExists)) { - throw new Error(`Unable to fetch latest block.`); - } - return currentBlockIfExists.timestamp; -} diff --git a/contracts/core/test/utils/chai_setup.ts b/contracts/core/test/utils/chai_setup.ts deleted file mode 100644 index 1a8733093..000000000 --- a/contracts/core/test/utils/chai_setup.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as chai from 'chai'; -import chaiAsPromised = require('chai-as-promised'); -import ChaiBigNumber = require('chai-bignumber'); -import * as dirtyChai from 'dirty-chai'; - -export const chaiSetup = { - configure(): void { - chai.config.includeStack = true; - chai.use(ChaiBigNumber()); - chai.use(dirtyChai); - chai.use(chaiAsPromised); - }, -}; diff --git a/contracts/core/test/utils/combinatorial_utils.ts b/contracts/core/test/utils/combinatorial_utils.ts index bb1b55b4d..d6e339f94 100644 --- a/contracts/core/test/utils/combinatorial_utils.ts +++ b/contracts/core/test/utils/combinatorial_utils.ts @@ -1,7 +1,7 @@ import { BigNumber } from '@0x/utils'; import * as combinatorics from 'js-combinatorics'; -import { testWithReferenceFuncAsync } from './test_with_reference'; +import { testWithReferenceFuncAsync } from '@0x/contracts-test-utils'; // A set of values corresponding to the uint256 type in Solidity. This set // contains some notable edge cases, including some values which will overflow diff --git a/contracts/core/test/utils/constants.ts b/contracts/core/test/utils/constants.ts deleted file mode 100644 index d2c3ab512..000000000 --- a/contracts/core/test/utils/constants.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -const TESTRPC_PRIVATE_KEYS_STRINGS = [ - '0xf2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e0164837257d', - '0x5d862464fe9303452126c8bc94274b8c5f9874cbd219789b3eb2128075a76f72', - '0xdf02719c4df8b9b8ac7f551fcb5d9ef48fa27eef7a66453879f4d8fdc6e78fb1', - '0xff12e391b79415e941a94de3bf3a9aee577aed0731e297d5cfa0b8a1e02fa1d0', - '0x752dd9cf65e68cfaba7d60225cbdbc1f4729dd5e5507def72815ed0d8abc6249', - '0xefb595a0178eb79a8df953f87c5148402a224cdf725e88c0146727c6aceadccd', - '0x83c6d2cc5ddcf9711a6d59b417dc20eb48afd58d45290099e5987e3d768f328f', - '0xbb2d3f7c9583780a7d3904a2f55d792707c345f21de1bacb2d389934d82796b2', - '0xb2fd4d29c1390b71b8795ae81196bfd60293adf99f9d32a0aff06288fcdac55f', - '0x23cb7121166b9a2f93ae0b7c05bde02eae50d64449b2cbb42bc84e9d38d6cc89', -]; - -export const constants = { - BASE_16: 16, - INVALID_OPCODE: 'invalid opcode', - TESTRPC_NETWORK_ID: 50, - // Note(albrow): In practice V8 and most other engines limit the minimum - // interval for setInterval to 10ms. We still set it to 0 here in order to - // ensure we always use the minimum interval. - AWAIT_TRANSACTION_MINED_MS: 0, - MAX_ETHERTOKEN_WITHDRAW_GAS: 43000, - MAX_EXECUTE_TRANSACTION_GAS: 1000000, - MAX_TOKEN_TRANSFERFROM_GAS: 80000, - MAX_TOKEN_APPROVE_GAS: 60000, - MAX_TRANSFER_FROM_GAS: 150000, - DUMMY_TOKEN_NAME: '', - DUMMY_TOKEN_SYMBOL: '', - DUMMY_TOKEN_DECIMALS: new BigNumber(18), - DUMMY_TOKEN_TOTAL_SUPPLY: new BigNumber(0), - NULL_BYTES: '0x', - NUM_DUMMY_ERC20_TO_DEPLOY: 3, - NUM_DUMMY_ERC721_TO_DEPLOY: 2, - NUM_ERC721_TOKENS_TO_MINT: 2, - NULL_ADDRESS: '0x0000000000000000000000000000000000000000', - UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1), - TESTRPC_PRIVATE_KEYS: _.map(TESTRPC_PRIVATE_KEYS_STRINGS, privateKeyString => ethUtil.toBuffer(privateKeyString)), - INITIAL_ERC20_BALANCE: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18), - INITIAL_ERC20_ALLOWANCE: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18), - STATIC_ORDER_PARAMS: { - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), - makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), - takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), - }, - WORD_LENGTH: 32, - ZERO_AMOUNT: new BigNumber(0), - PERCENTAGE_DENOMINATOR: new BigNumber(10).pow(18), - FUNCTIONS_WITH_MUTEX: [ - 'FILL_ORDER', - 'FILL_OR_KILL_ORDER', - 'BATCH_FILL_ORDERS', - 'BATCH_FILL_OR_KILL_ORDERS', - 'MARKET_BUY_ORDERS', - 'MARKET_SELL_ORDERS', - 'MATCH_ORDERS', - 'CANCEL_ORDER', - 'BATCH_CANCEL_ORDERS', - 'CANCEL_ORDERS_UP_TO', - 'SET_SIGNATURE_VALIDATOR_APPROVAL', - ], -}; diff --git a/contracts/core/test/utils/coverage.ts b/contracts/core/test/utils/coverage.ts deleted file mode 100644 index 5becfa1b6..000000000 --- a/contracts/core/test/utils/coverage.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { devConstants } from '@0x/dev-utils'; -import { CoverageSubprovider, SolCompilerArtifactAdapter } from '@0x/sol-cov'; -import * as _ from 'lodash'; - -let coverageSubprovider: CoverageSubprovider; - -export const coverage = { - getCoverageSubproviderSingleton(): CoverageSubprovider { - if (_.isUndefined(coverageSubprovider)) { - coverageSubprovider = coverage._getCoverageSubprovider(); - } - return coverageSubprovider; - }, - _getCoverageSubprovider(): CoverageSubprovider { - const defaultFromAddress = devConstants.TESTRPC_FIRST_ADDRESS; - const solCompilerArtifactAdapter = new SolCompilerArtifactAdapter(); - const isVerbose = true; - const subprovider = new CoverageSubprovider(solCompilerArtifactAdapter, defaultFromAddress, isVerbose); - return subprovider; - }, -}; diff --git a/contracts/core/test/utils/erc20_wrapper.ts b/contracts/core/test/utils/erc20_wrapper.ts index c281a2abf..d6210646c 100644 --- a/contracts/core/test/utils/erc20_wrapper.ts +++ b/contracts/core/test/utils/erc20_wrapper.ts @@ -1,3 +1,4 @@ +import { constants, ERC20BalancesByOwner, txDefaults } from '@0x/contracts-test-utils'; import { assetDataUtils } from '@0x/order-utils'; import { BigNumber } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; @@ -8,10 +9,6 @@ import { DummyERC20TokenContract } from '../../generated-wrappers/dummy_erc20_to import { ERC20ProxyContract } from '../../generated-wrappers/erc20_proxy'; import { artifacts } from '../../src/artifacts'; -import { constants } from './constants'; -import { ERC20BalancesByOwner } from './types'; -import { txDefaults } from './web3_wrapper'; - export class ERC20Wrapper { private readonly _tokenOwnerAddresses: string[]; private readonly _contractOwnerAddress: string; diff --git a/contracts/core/test/utils/erc721_wrapper.ts b/contracts/core/test/utils/erc721_wrapper.ts index e9da553d0..b5ae34e60 100644 --- a/contracts/core/test/utils/erc721_wrapper.ts +++ b/contracts/core/test/utils/erc721_wrapper.ts @@ -1,3 +1,4 @@ +import { constants, ERC721TokenIdsByOwner, txDefaults } from '@0x/contracts-test-utils'; import { generatePseudoRandomSalt } from '@0x/order-utils'; import { BigNumber } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; @@ -8,10 +9,6 @@ import { DummyERC721TokenContract } from '../../generated-wrappers/dummy_erc721_ import { ERC721ProxyContract } from '../../generated-wrappers/erc721_proxy'; import { artifacts } from '../../src/artifacts'; -import { constants } from './constants'; -import { ERC721TokenIdsByOwner } from './types'; -import { txDefaults } from './web3_wrapper'; - export class ERC721Wrapper { private readonly _tokenOwnerAddresses: string[]; private readonly _contractOwnerAddress: string; diff --git a/contracts/core/test/utils/exchange_wrapper.ts b/contracts/core/test/utils/exchange_wrapper.ts index c28989d3f..2a24b880f 100644 --- a/contracts/core/test/utils/exchange_wrapper.ts +++ b/contracts/core/test/utils/exchange_wrapper.ts @@ -1,14 +1,18 @@ +import { + FillResults, + formatters, + LogDecoder, + OrderInfo, + orderUtils, + SignedTransaction, +} from '@0x/contracts-test-utils'; import { SignedOrder } from '@0x/types'; import { BigNumber } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import { ExchangeContract } from '../../generated-wrappers/exchange'; - -import { formatters } from './formatters'; -import { LogDecoder } from './log_decoder'; -import { orderUtils } from './order_utils'; -import { FillResults, OrderInfo, SignedTransaction } from './types'; +import { artifacts } from '../../src/artifacts'; export class ExchangeWrapper { private readonly _exchange: ExchangeContract; @@ -17,7 +21,7 @@ export class ExchangeWrapper { constructor(exchangeContract: ExchangeContract, provider: Provider) { this._exchange = exchangeContract; this._web3Wrapper = new Web3Wrapper(provider); - this._logDecoder = new LogDecoder(this._web3Wrapper); + this._logDecoder = new LogDecoder(this._web3Wrapper, artifacts); } public async fillOrderAsync( signedOrder: SignedOrder, diff --git a/contracts/core/test/utils/fill_order_combinatorial_utils.ts b/contracts/core/test/utils/fill_order_combinatorial_utils.ts index 8046771f9..6372ad29a 100644 --- a/contracts/core/test/utils/fill_order_combinatorial_utils.ts +++ b/contracts/core/test/utils/fill_order_combinatorial_utils.ts @@ -1,4 +1,21 @@ import { + AllowanceAmountScenario, + AssetDataScenario, + BalanceAmountScenario, + chaiSetup, + constants, + expectTransactionFailedAsync, + ExpirationTimeSecondsScenario, + FeeRecipientAddressScenario, + FillScenario, + OrderAssetAmountScenario, + orderUtils, + signingUtils, + TakerAssetFillAmountScenario, + TakerScenario, + TraderStateScenario, +} from '@0x/contracts-test-utils'; +import { assetDataUtils, BalanceAndProxyAllowanceLazyStore, ExchangeTransferSimulator, @@ -18,30 +35,13 @@ import { ExchangeContract, ExchangeFillEventArgs } from '../../generated-wrapper import { TestLibsContract } from '../../generated-wrappers/test_libs'; import { artifacts } from '../../src/artifacts'; -import { expectTransactionFailedAsync } from './assertions'; import { AssetWrapper } from './asset_wrapper'; -import { chaiSetup } from './chai_setup'; -import { constants } from './constants'; import { ERC20Wrapper } from './erc20_wrapper'; import { ERC721Wrapper } from './erc721_wrapper'; import { ExchangeWrapper } from './exchange_wrapper'; import { OrderFactoryFromScenario } from './order_factory_from_scenario'; -import { orderUtils } from './order_utils'; -import { signingUtils } from './signing_utils'; import { SimpleAssetBalanceAndProxyAllowanceFetcher } from './simple_asset_balance_and_proxy_allowance_fetcher'; import { SimpleOrderFilledCancelledFetcher } from './simple_order_filled_cancelled_fetcher'; -import { - AllowanceAmountScenario, - AssetDataScenario, - BalanceAmountScenario, - ExpirationTimeSecondsScenario, - FeeRecipientAddressScenario, - FillScenario, - OrderAssetAmountScenario, - TakerAssetFillAmountScenario, - TakerScenario, - TraderStateScenario, -} from './types'; chaiSetup.configure(); const expect = chai.expect; diff --git a/contracts/core/test/utils/formatters.ts b/contracts/core/test/utils/formatters.ts deleted file mode 100644 index 813eb45db..000000000 --- a/contracts/core/test/utils/formatters.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; - -import { constants } from './constants'; -import { orderUtils } from './order_utils'; -import { BatchCancelOrders, BatchFillOrders, MarketBuyOrders, MarketSellOrders } from './types'; - -export const formatters = { - createBatchFill(signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[] = []): BatchFillOrders { - const batchFill: BatchFillOrders = { - orders: [], - signatures: [], - takerAssetFillAmounts, - }; - _.forEach(signedOrders, signedOrder => { - const orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder); - batchFill.orders.push(orderWithoutExchangeAddress); - batchFill.signatures.push(signedOrder.signature); - if (takerAssetFillAmounts.length < signedOrders.length) { - batchFill.takerAssetFillAmounts.push(signedOrder.takerAssetAmount); - } - }); - return batchFill; - }, - createMarketSellOrders(signedOrders: SignedOrder[], takerAssetFillAmount: BigNumber): MarketSellOrders { - const marketSellOrders: MarketSellOrders = { - orders: [], - signatures: [], - takerAssetFillAmount, - }; - _.forEach(signedOrders, (signedOrder, i) => { - const orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder); - if (i !== 0) { - orderWithoutExchangeAddress.takerAssetData = constants.NULL_BYTES; - } - marketSellOrders.orders.push(orderWithoutExchangeAddress); - marketSellOrders.signatures.push(signedOrder.signature); - }); - return marketSellOrders; - }, - createMarketBuyOrders(signedOrders: SignedOrder[], makerAssetFillAmount: BigNumber): MarketBuyOrders { - const marketBuyOrders: MarketBuyOrders = { - orders: [], - signatures: [], - makerAssetFillAmount, - }; - _.forEach(signedOrders, (signedOrder, i) => { - const orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder); - if (i !== 0) { - orderWithoutExchangeAddress.makerAssetData = constants.NULL_BYTES; - } - marketBuyOrders.orders.push(orderWithoutExchangeAddress); - marketBuyOrders.signatures.push(signedOrder.signature); - }); - return marketBuyOrders; - }, - createBatchCancel(signedOrders: SignedOrder[]): BatchCancelOrders { - const batchCancel: BatchCancelOrders = { - orders: [], - }; - _.forEach(signedOrders, signedOrder => { - const orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder); - batchCancel.orders.push(orderWithoutExchangeAddress); - }); - return batchCancel; - }, -}; diff --git a/contracts/core/test/utils/forwarder_wrapper.ts b/contracts/core/test/utils/forwarder_wrapper.ts index a0bfcfe1d..9c5560381 100644 --- a/contracts/core/test/utils/forwarder_wrapper.ts +++ b/contracts/core/test/utils/forwarder_wrapper.ts @@ -1,3 +1,4 @@ +import { constants, formatters, LogDecoder, MarketSellOrders } from '@0x/contracts-test-utils'; import { SignedOrder } from '@0x/types'; import { BigNumber } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; @@ -5,11 +6,7 @@ import { Provider, TransactionReceiptWithDecodedLogs, TxDataPayable } from 'ethe import * as _ from 'lodash'; import { ForwarderContract } from '../../generated-wrappers/forwarder'; - -import { constants } from './constants'; -import { formatters } from './formatters'; -import { LogDecoder } from './log_decoder'; -import { MarketSellOrders } from './types'; +import { artifacts } from '../../src/artifacts'; export class ForwarderWrapper { private readonly _web3Wrapper: Web3Wrapper; @@ -61,7 +58,7 @@ export class ForwarderWrapper { constructor(contractInstance: ForwarderContract, provider: Provider) { this._forwarderContract = contractInstance; this._web3Wrapper = new Web3Wrapper(provider); - this._logDecoder = new LogDecoder(this._web3Wrapper); + this._logDecoder = new LogDecoder(this._web3Wrapper, artifacts); } public async marketSellOrdersWithEthAsync( orders: SignedOrder[], diff --git a/contracts/core/test/utils/log_decoder.ts b/contracts/core/test/utils/log_decoder.ts deleted file mode 100644 index 05b0a9204..000000000 --- a/contracts/core/test/utils/log_decoder.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { AbiDecoder, BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { - AbiDefinition, - ContractArtifact, - DecodedLogArgs, - LogEntry, - LogWithDecodedArgs, - RawLog, - TransactionReceiptWithDecodedLogs, -} from 'ethereum-types'; -import * as _ from 'lodash'; - -import { artifacts } from '../../src/artifacts'; - -import { constants } from './constants'; - -export class LogDecoder { - private readonly _web3Wrapper: Web3Wrapper; - private readonly _abiDecoder: AbiDecoder; - public static wrapLogBigNumbers(log: any): any { - const argNames = _.keys(log.args); - for (const argName of argNames) { - const isWeb3BigNumber = _.startsWith(log.args[argName].constructor.toString(), 'function BigNumber('); - if (isWeb3BigNumber) { - log.args[argName] = new BigNumber(log.args[argName]); - } - } - } - constructor(web3Wrapper: Web3Wrapper) { - this._web3Wrapper = web3Wrapper; - const abiArrays: AbiDefinition[][] = []; - _.forEach(artifacts, (artifact: ContractArtifact) => { - const compilerOutput = artifact.compilerOutput; - abiArrays.push(compilerOutput.abi); - }); - this._abiDecoder = new AbiDecoder(abiArrays); - } - public decodeLogOrThrow<ArgsType extends DecodedLogArgs>(log: LogEntry): LogWithDecodedArgs<ArgsType> | RawLog { - const logWithDecodedArgsOrLog = this._abiDecoder.tryToDecodeLogOrNoop(log); - // tslint:disable-next-line:no-unnecessary-type-assertion - if (_.isUndefined((logWithDecodedArgsOrLog as LogWithDecodedArgs<ArgsType>).args)) { - throw new Error(`Unable to decode log: ${JSON.stringify(log)}`); - } - LogDecoder.wrapLogBigNumbers(logWithDecodedArgsOrLog); - return logWithDecodedArgsOrLog; - } - public async getTxWithDecodedLogsAsync(txHash: string): Promise<TransactionReceiptWithDecodedLogs> { - const tx = await this._web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - tx.logs = _.map(tx.logs, log => this.decodeLogOrThrow(log)); - return tx; - } -} diff --git a/contracts/core/test/utils/match_order_tester.ts b/contracts/core/test/utils/match_order_tester.ts index 6c2c84959..8f574704e 100644 --- a/contracts/core/test/utils/match_order_tester.ts +++ b/contracts/core/test/utils/match_order_tester.ts @@ -1,3 +1,12 @@ +import { + chaiSetup, + ERC20BalancesByOwner, + ERC721TokenIdsByOwner, + OrderInfo, + OrderStatus, + TransferAmountsByMatchOrders as TransferAmounts, + TransferAmountsLoggedByMatchOrders as LoggedTransferAmounts, +} from '@0x/contracts-test-utils'; import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; import { AssetProxyId, SignedOrder } from '@0x/types'; import { BigNumber } from '@0x/utils'; @@ -6,18 +15,9 @@ import * as _ from 'lodash'; import { TransactionReceiptWithDecodedLogs } from '../../../../node_modules/ethereum-types'; -import { chaiSetup } from './chai_setup'; import { ERC20Wrapper } from './erc20_wrapper'; import { ERC721Wrapper } from './erc721_wrapper'; import { ExchangeWrapper } from './exchange_wrapper'; -import { - ERC20BalancesByOwner, - ERC721TokenIdsByOwner, - OrderInfo, - OrderStatus, - TransferAmountsByMatchOrders as TransferAmounts, - TransferAmountsLoggedByMatchOrders as LoggedTransferAmounts, -} from './types'; chaiSetup.configure(); const expect = chai.expect; @@ -270,18 +270,14 @@ export class MatchOrderTester { const leftExpectedStatus = expectedTransferAmounts.amountBoughtByLeftMaker.equals(maxAmountBoughtByLeftMaker) ? OrderStatus.FULLY_FILLED : OrderStatus.FILLABLE; - expect(leftOrderInfo.orderStatus as OrderStatus, 'Checking exchange status for left order').to.be.equal( - leftExpectedStatus, - ); + expect(leftOrderInfo.orderStatus, 'Checking exchange status for left order').to.be.equal(leftExpectedStatus); // Assert right order status const maxAmountBoughtByRightMaker = signedOrderRight.takerAssetAmount.minus(initialRightOrderFilledAmount); const rightOrderInfo: OrderInfo = await this._exchangeWrapper.getOrderInfoAsync(signedOrderRight); const rightExpectedStatus = expectedTransferAmounts.amountBoughtByRightMaker.equals(maxAmountBoughtByRightMaker) ? OrderStatus.FULLY_FILLED : OrderStatus.FILLABLE; - expect(rightOrderInfo.orderStatus as OrderStatus, 'Checking exchange status for right order').to.be.equal( - rightExpectedStatus, - ); + expect(rightOrderInfo.orderStatus, 'Checking exchange status for right order').to.be.equal(rightExpectedStatus); } /// @dev Asserts account balances after matching orders. /// @param signedOrderLeft First matched order. diff --git a/contracts/core/test/utils/multi_sig_wrapper.ts b/contracts/core/test/utils/multi_sig_wrapper.ts index 74fd3b4d6..34c9c2578 100644 --- a/contracts/core/test/utils/multi_sig_wrapper.ts +++ b/contracts/core/test/utils/multi_sig_wrapper.ts @@ -1,3 +1,4 @@ +import { LogDecoder } from '@0x/contracts-test-utils'; import { BigNumber } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types'; @@ -5,8 +6,7 @@ import * as _ from 'lodash'; import { AssetProxyOwnerContract } from '../../generated-wrappers/asset_proxy_owner'; import { MultiSigWalletContract } from '../../generated-wrappers/multi_sig_wallet'; - -import { LogDecoder } from './log_decoder'; +import { artifacts } from '../../src/artifacts'; export class MultiSigWrapper { private readonly _multiSig: MultiSigWalletContract; @@ -15,7 +15,7 @@ export class MultiSigWrapper { constructor(multiSigContract: MultiSigWalletContract, provider: Provider) { this._multiSig = multiSigContract; this._web3Wrapper = new Web3Wrapper(provider); - this._logDecoder = new LogDecoder(this._web3Wrapper); + this._logDecoder = new LogDecoder(this._web3Wrapper, artifacts); } public async submitTransactionAsync( destination: string, diff --git a/contracts/core/test/utils/order_factory.ts b/contracts/core/test/utils/order_factory.ts deleted file mode 100644 index 2449d1a8a..000000000 --- a/contracts/core/test/utils/order_factory.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { generatePseudoRandomSalt, orderHashUtils } from '@0x/order-utils'; -import { Order, SignatureType, SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; - -import { getLatestBlockTimestampAsync } from './block_timestamp'; -import { constants } from './constants'; -import { signingUtils } from './signing_utils'; - -export class OrderFactory { - private readonly _defaultOrderParams: Partial<Order>; - private readonly _privateKey: Buffer; - constructor(privateKey: Buffer, defaultOrderParams: Partial<Order>) { - this._defaultOrderParams = defaultOrderParams; - this._privateKey = privateKey; - } - public async newSignedOrderAsync( - customOrderParams: Partial<Order> = {}, - signatureType: SignatureType = SignatureType.EthSign, - ): Promise<SignedOrder> { - const tenMinutesInSeconds = 10 * 60; - const currentBlockTimestamp = await getLatestBlockTimestampAsync(); - const order = ({ - senderAddress: constants.NULL_ADDRESS, - expirationTimeSeconds: new BigNumber(currentBlockTimestamp).add(tenMinutesInSeconds), - salt: generatePseudoRandomSalt(), - takerAddress: constants.NULL_ADDRESS, - ...this._defaultOrderParams, - ...customOrderParams, - } as any) as Order; - const orderHashBuff = orderHashUtils.getOrderHashBuffer(order); - const signature = signingUtils.signMessage(orderHashBuff, this._privateKey, signatureType); - const signedOrder = { - ...order, - signature: `0x${signature.toString('hex')}`, - }; - return signedOrder; - } -} diff --git a/contracts/core/test/utils/order_factory_from_scenario.ts b/contracts/core/test/utils/order_factory_from_scenario.ts index 60c8606c4..1cc962020 100644 --- a/contracts/core/test/utils/order_factory_from_scenario.ts +++ b/contracts/core/test/utils/order_factory_from_scenario.ts @@ -1,19 +1,18 @@ -import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils'; -import { Order } from '@0x/types'; -import { BigNumber, errorUtils } from '@0x/utils'; - -import { DummyERC721TokenContract } from '../../generated-wrappers/dummy_erc721_token'; - -import { constants } from './constants'; import { AssetDataScenario, + constants, ERC721TokenIdsByOwner, ExpirationTimeSecondsScenario, FeeRecipientAddressScenario, OrderAssetAmountScenario, OrderScenario, TakerScenario, -} from './types'; +} from '@0x/contracts-test-utils'; +import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils'; +import { Order } from '@0x/types'; +import { BigNumber, errorUtils } from '@0x/utils'; + +import { DummyERC721TokenContract } from '../../generated-wrappers/dummy_erc721_token'; const TEN_UNITS_EIGHTEEN_DECIMALS = new BigNumber(10_000_000_000_000_000_000); const FIVE_UNITS_EIGHTEEN_DECIMALS = new BigNumber(5_000_000_000_000_000_000); diff --git a/contracts/core/test/utils/order_utils.ts b/contracts/core/test/utils/order_utils.ts deleted file mode 100644 index 4f7a34011..000000000 --- a/contracts/core/test/utils/order_utils.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { OrderWithoutExchangeAddress, SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; - -import { constants } from './constants'; -import { CancelOrder, MatchOrder } from './types'; - -export const orderUtils = { - getPartialAmountFloor(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber { - const partialAmount = numerator - .mul(target) - .div(denominator) - .floor(); - return partialAmount; - }, - createFill: (signedOrder: SignedOrder, takerAssetFillAmount?: BigNumber) => { - const fill = { - order: orderUtils.getOrderWithoutExchangeAddress(signedOrder), - takerAssetFillAmount: takerAssetFillAmount || signedOrder.takerAssetAmount, - signature: signedOrder.signature, - }; - return fill; - }, - createCancel(signedOrder: SignedOrder, takerAssetCancelAmount?: BigNumber): CancelOrder { - const cancel = { - order: orderUtils.getOrderWithoutExchangeAddress(signedOrder), - takerAssetCancelAmount: takerAssetCancelAmount || signedOrder.takerAssetAmount, - }; - return cancel; - }, - getOrderWithoutExchangeAddress(signedOrder: SignedOrder): OrderWithoutExchangeAddress { - const orderStruct = { - senderAddress: signedOrder.senderAddress, - makerAddress: signedOrder.makerAddress, - takerAddress: signedOrder.takerAddress, - feeRecipientAddress: signedOrder.feeRecipientAddress, - makerAssetAmount: signedOrder.makerAssetAmount, - takerAssetAmount: signedOrder.takerAssetAmount, - makerFee: signedOrder.makerFee, - takerFee: signedOrder.takerFee, - expirationTimeSeconds: signedOrder.expirationTimeSeconds, - salt: signedOrder.salt, - makerAssetData: signedOrder.makerAssetData, - takerAssetData: signedOrder.takerAssetData, - }; - return orderStruct; - }, - createMatchOrders(signedOrderLeft: SignedOrder, signedOrderRight: SignedOrder): MatchOrder { - const fill = { - left: orderUtils.getOrderWithoutExchangeAddress(signedOrderLeft), - right: orderUtils.getOrderWithoutExchangeAddress(signedOrderRight), - leftSignature: signedOrderLeft.signature, - rightSignature: signedOrderRight.signature, - }; - fill.right.makerAssetData = constants.NULL_BYTES; - fill.right.takerAssetData = constants.NULL_BYTES; - return fill; - }, -}; diff --git a/contracts/core/test/utils/profiler.ts b/contracts/core/test/utils/profiler.ts deleted file mode 100644 index 2c7c1d66c..000000000 --- a/contracts/core/test/utils/profiler.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { devConstants } from '@0x/dev-utils'; -import { ProfilerSubprovider, SolCompilerArtifactAdapter } from '@0x/sol-cov'; -import * as _ from 'lodash'; - -let profilerSubprovider: ProfilerSubprovider; - -export const profiler = { - start(): void { - profiler.getProfilerSubproviderSingleton().start(); - }, - stop(): void { - profiler.getProfilerSubproviderSingleton().stop(); - }, - getProfilerSubproviderSingleton(): ProfilerSubprovider { - if (_.isUndefined(profilerSubprovider)) { - profilerSubprovider = profiler._getProfilerSubprovider(); - } - return profilerSubprovider; - }, - _getProfilerSubprovider(): ProfilerSubprovider { - const defaultFromAddress = devConstants.TESTRPC_FIRST_ADDRESS; - const solCompilerArtifactAdapter = new SolCompilerArtifactAdapter(); - const isVerbose = true; - const subprovider = new ProfilerSubprovider(solCompilerArtifactAdapter, defaultFromAddress, isVerbose); - return subprovider; - }, -}; diff --git a/contracts/core/test/utils/revert_trace.ts b/contracts/core/test/utils/revert_trace.ts deleted file mode 100644 index 3f74fd28b..000000000 --- a/contracts/core/test/utils/revert_trace.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { devConstants } from '@0x/dev-utils'; -import { RevertTraceSubprovider, SolCompilerArtifactAdapter } from '@0x/sol-cov'; -import * as _ from 'lodash'; - -let revertTraceSubprovider: RevertTraceSubprovider; - -export const revertTrace = { - getRevertTraceSubproviderSingleton(): RevertTraceSubprovider { - if (_.isUndefined(revertTraceSubprovider)) { - revertTraceSubprovider = revertTrace._getRevertTraceSubprovider(); - } - return revertTraceSubprovider; - }, - _getRevertTraceSubprovider(): RevertTraceSubprovider { - const defaultFromAddress = devConstants.TESTRPC_FIRST_ADDRESS; - const solCompilerArtifactAdapter = new SolCompilerArtifactAdapter(); - const isVerbose = true; - const subprovider = new RevertTraceSubprovider(solCompilerArtifactAdapter, defaultFromAddress, isVerbose); - return subprovider; - }, -}; diff --git a/contracts/core/test/utils/signing_utils.ts b/contracts/core/test/utils/signing_utils.ts deleted file mode 100644 index 21f864bfa..000000000 --- a/contracts/core/test/utils/signing_utils.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { SignatureType } from '@0x/types'; -import * as ethUtil from 'ethereumjs-util'; - -export const signingUtils = { - signMessage(message: Buffer, privateKey: Buffer, signatureType: SignatureType): Buffer { - if (signatureType === SignatureType.EthSign) { - const prefixedMessage = ethUtil.hashPersonalMessage(message); - const ecSignature = ethUtil.ecsign(prefixedMessage, privateKey); - const signature = Buffer.concat([ - ethUtil.toBuffer(ecSignature.v), - ecSignature.r, - ecSignature.s, - ethUtil.toBuffer(signatureType), - ]); - return signature; - } else if (signatureType === SignatureType.EIP712) { - const ecSignature = ethUtil.ecsign(message, privateKey); - const signature = Buffer.concat([ - ethUtil.toBuffer(ecSignature.v), - ecSignature.r, - ecSignature.s, - ethUtil.toBuffer(signatureType), - ]); - return signature; - } else { - throw new Error(`${signatureType} is not a valid signature type`); - } - }, -}; diff --git a/contracts/core/test/utils/test_with_reference.ts b/contracts/core/test/utils/test_with_reference.ts deleted file mode 100644 index b80be4a6c..000000000 --- a/contracts/core/test/utils/test_with_reference.ts +++ /dev/null @@ -1,139 +0,0 @@ -import * as chai from 'chai'; -import * as _ from 'lodash'; - -import { chaiSetup } from './chai_setup'; - -chaiSetup.configure(); -const expect = chai.expect; - -class Value<T> { - public value: T; - constructor(value: T) { - this.value = value; - } -} - -// tslint:disable-next-line: max-classes-per-file -class ErrorMessage { - public error: string; - constructor(message: string) { - this.error = message; - } -} - -type PromiseResult<T> = Value<T> | ErrorMessage; - -// TODO(albrow): This seems like a generic utility function that could exist in -// lodash. We should replace it by a library implementation, or move it to our -// own. -async function evaluatePromise<T>(promise: Promise<T>): Promise<PromiseResult<T>> { - try { - return new Value<T>(await promise); - } catch (e) { - return new ErrorMessage(e.message); - } -} - -export async function testWithReferenceFuncAsync<P0, R>( - referenceFunc: (p0: P0) => Promise<R>, - testFunc: (p0: P0) => Promise<R>, - values: [P0], -): Promise<void>; -export async function testWithReferenceFuncAsync<P0, P1, R>( - referenceFunc: (p0: P0, p1: P1) => Promise<R>, - testFunc: (p0: P0, p1: P1) => Promise<R>, - values: [P0, P1], -): Promise<void>; -export async function testWithReferenceFuncAsync<P0, P1, P2, R>( - referenceFunc: (p0: P0, p1: P1, p2: P2) => Promise<R>, - testFunc: (p0: P0, p1: P1, p2: P2) => Promise<R>, - values: [P0, P1, P2], -): Promise<void>; -export async function testWithReferenceFuncAsync<P0, P1, P2, P3, R>( - referenceFunc: (p0: P0, p1: P1, p2: P2, p3: P3) => Promise<R>, - testFunc: (p0: P0, p1: P1, p2: P2, p3: P3) => Promise<R>, - values: [P0, P1, P2, P3], -): Promise<void>; -export async function testWithReferenceFuncAsync<P0, P1, P2, P3, P4, R>( - referenceFunc: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4) => Promise<R>, - testFunc: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4) => Promise<R>, - values: [P0, P1, P2, P3, P4], -): Promise<void>; - -/** - * Tests the behavior of a test function by comparing it to the expected - * behavior (defined by a reference function). - * - * First the reference function will be called to obtain an "expected result", - * or if the reference function throws/rejects, an "expected error". Next, the - * test function will be called to obtain an "actual result", or if the test - * function throws/rejects, an "actual error". The test passes if at least one - * of the following conditions is met: - * - * 1) Neither the reference function or the test function throw and the - * "expected result" equals the "actual result". - * - * 2) Both the reference function and the test function throw and the "actual - * error" message *contains* the "expected error" message. - * - * @param referenceFuncAsync a reference function implemented in pure - * JavaScript/TypeScript which accepts N arguments and returns the "expected - * result" or throws/rejects with the "expected error". - * @param testFuncAsync a test function which, e.g., makes a call or sends a - * transaction to a contract. It accepts the same N arguments returns the - * "actual result" or throws/rejects with the "actual error". - * @param values an array of N values, where each value corresponds in-order to - * an argument to both the test function and the reference function. - * @return A Promise that resolves if the test passes and rejects if the test - * fails, according to the rules described above. - */ -export async function testWithReferenceFuncAsync( - referenceFuncAsync: (...args: any[]) => Promise<any>, - testFuncAsync: (...args: any[]) => Promise<any>, - values: any[], -): Promise<void> { - // Measure correct behaviour - const expected = await evaluatePromise(referenceFuncAsync(...values)); - - // Measure actual behaviour - const actual = await evaluatePromise(testFuncAsync(...values)); - - // Compare behaviour - if (expected instanceof ErrorMessage) { - // If we expected an error, check if the actual error message contains the - // expected error message. - if (!(actual instanceof ErrorMessage)) { - throw new Error( - `Expected error containing ${expected.error} but got no error\n\tTest case: ${_getTestCaseString( - referenceFuncAsync, - values, - )}`, - ); - } - expect(actual.error).to.contain( - expected.error, - `${actual.error}\n\tTest case: ${_getTestCaseString(referenceFuncAsync, values)}`, - ); - } else { - // If we do not expect an error, compare actual and expected directly. - expect(actual).to.deep.equal(expected, `Test case ${_getTestCaseString(referenceFuncAsync, values)}`); - } -} - -function _getTestCaseString(referenceFuncAsync: (...args: any[]) => Promise<any>, values: any[]): string { - const paramNames = _getParameterNames(referenceFuncAsync); - return JSON.stringify(_.zipObject(paramNames, values)); -} - -// Source: https://stackoverflow.com/questions/1007981/how-to-get-function-parameter-names-values-dynamically -function _getParameterNames(func: (...args: any[]) => any): string[] { - return _.toString(func) - .replace(/[/][/].*$/gm, '') // strip single-line comments - .replace(/\s+/g, '') // strip white space - .replace(/[/][*][^/*]*[*][/]/g, '') // strip multi-line comments - .split('){', 1)[0] - .replace(/^[^(]*[(]/, '') // extract the parameters - .replace(/=[^,]+/g, '') // strip any ES6 defaults - .split(',') - .filter(Boolean); // split & filter [""] -} diff --git a/contracts/core/test/utils/transaction_factory.ts b/contracts/core/test/utils/transaction_factory.ts deleted file mode 100644 index dbab3ade4..000000000 --- a/contracts/core/test/utils/transaction_factory.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { eip712Utils, generatePseudoRandomSalt } from '@0x/order-utils'; -import { SignatureType } from '@0x/types'; -import { signTypedDataUtils } from '@0x/utils'; -import * as ethUtil from 'ethereumjs-util'; - -import { signingUtils } from './signing_utils'; -import { SignedTransaction } from './types'; - -export class TransactionFactory { - private readonly _signerBuff: Buffer; - private readonly _exchangeAddress: string; - private readonly _privateKey: Buffer; - constructor(privateKey: Buffer, exchangeAddress: string) { - this._privateKey = privateKey; - this._exchangeAddress = exchangeAddress; - this._signerBuff = ethUtil.privateToAddress(this._privateKey); - } - public newSignedTransaction(data: string, signatureType: SignatureType = SignatureType.EthSign): SignedTransaction { - const salt = generatePseudoRandomSalt(); - const signerAddress = `0x${this._signerBuff.toString('hex')}`; - const executeTransactionData = { - salt, - signerAddress, - data, - }; - - const typedData = eip712Utils.createZeroExTransactionTypedData(executeTransactionData, this._exchangeAddress); - const eip712MessageBuffer = signTypedDataUtils.generateTypedDataHash(typedData); - const signature = signingUtils.signMessage(eip712MessageBuffer, this._privateKey, signatureType); - const signedTx = { - exchangeAddress: this._exchangeAddress, - signature: `0x${signature.toString('hex')}`, - ...executeTransactionData, - }; - return signedTx; - } -} diff --git a/contracts/core/test/utils/type_encoding_utils.ts b/contracts/core/test/utils/type_encoding_utils.ts deleted file mode 100644 index bfd9c9ef5..000000000 --- a/contracts/core/test/utils/type_encoding_utils.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import BN = require('bn.js'); -import ethUtil = require('ethereumjs-util'); - -import { constants } from './constants'; - -export const typeEncodingUtils = { - encodeUint256(value: BigNumber): Buffer { - const base = 10; - const formattedValue = new BN(value.toString(base)); - const encodedValue = ethUtil.toBuffer(formattedValue); - // tslint:disable-next-line:custom-no-magic-numbers - const paddedValue = ethUtil.setLengthLeft(encodedValue, constants.WORD_LENGTH); - return paddedValue; - }, - decodeUint256(encodedValue: Buffer): BigNumber { - const formattedValue = ethUtil.bufferToHex(encodedValue); - const value = new BigNumber(formattedValue, constants.BASE_16); - return value; - }, -}; diff --git a/contracts/core/test/utils/types.ts b/contracts/core/test/utils/types.ts deleted file mode 100644 index 9fc9e1570..000000000 --- a/contracts/core/test/utils/types.ts +++ /dev/null @@ -1,241 +0,0 @@ -import { OrderWithoutExchangeAddress } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import { AbiDefinition } from 'ethereum-types'; - -export interface ERC20BalancesByOwner { - [ownerAddress: string]: { - [tokenAddress: string]: BigNumber; - }; -} - -export interface ERC721TokenIdsByOwner { - [ownerAddress: string]: { - [tokenAddress: string]: BigNumber[]; - }; -} - -export interface SubmissionContractEventArgs { - transactionId: BigNumber; -} - -export interface BatchFillOrders { - orders: OrderWithoutExchangeAddress[]; - signatures: string[]; - takerAssetFillAmounts: BigNumber[]; -} - -export interface MarketSellOrders { - orders: OrderWithoutExchangeAddress[]; - signatures: string[]; - takerAssetFillAmount: BigNumber; -} - -export interface MarketBuyOrders { - orders: OrderWithoutExchangeAddress[]; - signatures: string[]; - makerAssetFillAmount: BigNumber; -} - -export interface BatchCancelOrders { - orders: OrderWithoutExchangeAddress[]; -} - -export interface CancelOrdersBefore { - salt: BigNumber; -} - -export interface TransactionDataParams { - name: string; - abi: AbiDefinition[]; - args: any[]; -} - -export interface MultiSigConfig { - owners: string[]; - confirmationsRequired: number; - secondsRequired: number; -} - -export interface MultiSigConfigByNetwork { - [networkName: string]: MultiSigConfig; -} - -export interface Token { - address?: string; - name: string; - symbol: string; - decimals: number; - ipfsHash: string; - swarmHash: string; -} - -export enum OrderStatus { - INVALID, - INVALID_MAKER_ASSET_AMOUNT, - INVALID_TAKER_ASSET_AMOUNT, - FILLABLE, - EXPIRED, - FULLY_FILLED, - CANCELLED, -} - -export enum ContractName { - TokenRegistry = 'TokenRegistry', - MultiSigWalletWithTimeLock = 'MultiSigWalletWithTimeLock', - Exchange = 'Exchange', - ZRXToken = 'ZRXToken', - DummyERC20Token = 'DummyERC20Token', - EtherToken = 'WETH9', - AssetProxyOwner = 'AssetProxyOwner', - AccountLevels = 'AccountLevels', - EtherDelta = 'EtherDelta', - Arbitrage = 'Arbitrage', - TestAssetDataDecoders = 'TestAssetDataDecoders', - TestAssetProxyDispatcher = 'TestAssetProxyDispatcher', - TestLibs = 'TestLibs', - TestSignatureValidator = 'TestSignatureValidator', - ERC20Proxy = 'ERC20Proxy', - ERC721Proxy = 'ERC721Proxy', - DummyERC721Receiver = 'DummyERC721Receiver', - DummyERC721Token = 'DummyERC721Token', - TestLibBytes = 'TestLibBytes', - TestWallet = 'TestWallet', - Authorizable = 'Authorizable', - Whitelist = 'Whitelist', - Forwarder = 'Forwarder', -} - -export interface SignedTransaction { - exchangeAddress: string; - salt: BigNumber; - signerAddress: string; - data: string; - signature: string; -} - -export interface TransferAmountsByMatchOrders { - // Left Maker - amountBoughtByLeftMaker: BigNumber; - amountSoldByLeftMaker: BigNumber; - feePaidByLeftMaker: BigNumber; - // Right Maker - amountBoughtByRightMaker: BigNumber; - amountSoldByRightMaker: BigNumber; - feePaidByRightMaker: BigNumber; - // Taker - amountReceivedByTaker: BigNumber; - feePaidByTakerLeft: BigNumber; - feePaidByTakerRight: BigNumber; -} - -export interface TransferAmountsLoggedByMatchOrders { - makerAddress: string; - takerAddress: string; - makerAssetFilledAmount: string; - takerAssetFilledAmount: string; - makerFeePaid: string; - takerFeePaid: string; -} - -export interface OrderInfo { - orderStatus: number; - orderHash: string; - orderTakerAssetFilledAmount: BigNumber; -} - -export interface CancelOrder { - order: OrderWithoutExchangeAddress; - takerAssetCancelAmount: BigNumber; -} - -export interface MatchOrder { - left: OrderWithoutExchangeAddress; - right: OrderWithoutExchangeAddress; - leftSignature: string; - rightSignature: string; -} - -// Combinatorial testing types - -export enum FeeRecipientAddressScenario { - BurnAddress = 'BURN_ADDRESS', - EthUserAddress = 'ETH_USER_ADDRESS', -} - -export enum OrderAssetAmountScenario { - Zero = 'ZERO', - Large = 'LARGE', - Small = 'SMALL', -} - -export enum TakerScenario { - CorrectlySpecified = 'CORRECTLY_SPECIFIED', - IncorrectlySpecified = 'INCORRECTLY_SPECIFIED', - Unspecified = 'UNSPECIFIED', -} - -export enum ExpirationTimeSecondsScenario { - InPast = 'IN_PAST', - InFuture = 'IN_FUTURE', -} - -export enum AssetDataScenario { - ERC20ZeroDecimals = 'ERC20_ZERO_DECIMALS', - ZRXFeeToken = 'ZRX_FEE_TOKEN', - ERC20FiveDecimals = 'ERC20_FIVE_DECIMALS', - ERC20NonZRXEighteenDecimals = 'ERC20_NON_ZRX_EIGHTEEN_DECIMALS', - ERC721 = 'ERC721', -} - -export enum TakerAssetFillAmountScenario { - Zero = 'ZERO', - GreaterThanRemainingFillableTakerAssetAmount = 'GREATER_THAN_REMAINING_FILLABLE_TAKER_ASSET_AMOUNT', - LessThanRemainingFillableTakerAssetAmount = 'LESS_THAN_REMAINING_FILLABLE_TAKER_ASSET_AMOUNT', - ExactlyRemainingFillableTakerAssetAmount = 'EXACTLY_REMAINING_FILLABLE_TAKER_ASSET_AMOUNT', -} - -export interface OrderScenario { - takerScenario: TakerScenario; - feeRecipientScenario: FeeRecipientAddressScenario; - makerAssetAmountScenario: OrderAssetAmountScenario; - takerAssetAmountScenario: OrderAssetAmountScenario; - makerFeeScenario: OrderAssetAmountScenario; - takerFeeScenario: OrderAssetAmountScenario; - expirationTimeSecondsScenario: ExpirationTimeSecondsScenario; - makerAssetDataScenario: AssetDataScenario; - takerAssetDataScenario: AssetDataScenario; -} - -export enum BalanceAmountScenario { - Exact = 'EXACT', - TooLow = 'TOO_LOW', - Higher = 'HIGHER', -} - -export enum AllowanceAmountScenario { - Exact = 'EXACT', - TooLow = 'TOO_LOW', - Higher = 'HIGHER', - Unlimited = 'UNLIMITED', -} - -export interface TraderStateScenario { - traderAssetBalance: BalanceAmountScenario; - traderAssetAllowance: AllowanceAmountScenario; - zrxFeeBalance: BalanceAmountScenario; - zrxFeeAllowance: AllowanceAmountScenario; -} - -export interface FillScenario { - orderScenario: OrderScenario; - takerAssetFillAmountScenario: TakerAssetFillAmountScenario; - makerStateScenario: TraderStateScenario; - takerStateScenario: TraderStateScenario; -} - -export interface FillResults { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; -} diff --git a/contracts/core/test/utils/web3_wrapper.ts b/contracts/core/test/utils/web3_wrapper.ts deleted file mode 100644 index f7b1a732a..000000000 --- a/contracts/core/test/utils/web3_wrapper.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { devConstants, env, EnvVars, web3Factory } from '@0x/dev-utils'; -import { prependSubprovider, Web3ProviderEngine } from '@0x/subproviders'; -import { logUtils } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import * as _ from 'lodash'; - -import { coverage } from './coverage'; -import { profiler } from './profiler'; -import { revertTrace } from './revert_trace'; - -enum ProviderType { - Ganache = 'ganache', - Geth = 'geth', -} - -let testProvider: ProviderType; -switch (process.env.TEST_PROVIDER) { - case undefined: - testProvider = ProviderType.Ganache; - break; - case 'ganache': - testProvider = ProviderType.Ganache; - break; - case 'geth': - testProvider = ProviderType.Geth; - break; - default: - throw new Error(`Unknown TEST_PROVIDER: ${process.env.TEST_PROVIDER}`); -} - -const ganacheTxDefaults = { - from: devConstants.TESTRPC_FIRST_ADDRESS, - gas: devConstants.GAS_LIMIT, -}; -const gethTxDefaults = { - from: devConstants.TESTRPC_FIRST_ADDRESS, -}; -export const txDefaults = testProvider === ProviderType.Ganache ? ganacheTxDefaults : gethTxDefaults; - -const gethConfigs = { - shouldUseInProcessGanache: false, - rpcUrl: 'http://localhost:8501', - shouldUseFakeGasEstimate: false, -}; -const ganacheConfigs = { - shouldUseInProcessGanache: true, -}; -const providerConfigs = testProvider === ProviderType.Ganache ? ganacheConfigs : gethConfigs; - -export const provider: Web3ProviderEngine = web3Factory.getRpcProvider(providerConfigs); -const isCoverageEnabled = env.parseBoolean(EnvVars.SolidityCoverage); -const isProfilerEnabled = env.parseBoolean(EnvVars.SolidityProfiler); -const isRevertTraceEnabled = env.parseBoolean(EnvVars.SolidityRevertTrace); -const enabledSubproviderCount = _.filter( - [isCoverageEnabled, isProfilerEnabled, isRevertTraceEnabled], - _.identity.bind(_), -).length; -if (enabledSubproviderCount > 1) { - throw new Error(`Only one of coverage, profiler, or revert trace subproviders can be enabled at a time`); -} -if (isCoverageEnabled) { - const coverageSubprovider = coverage.getCoverageSubproviderSingleton(); - prependSubprovider(provider, coverageSubprovider); -} -if (isProfilerEnabled) { - if (testProvider === ProviderType.Ganache) { - logUtils.warn( - "Gas costs in Ganache traces are incorrect and we don't recommend using it for profiling. Please switch to Geth", - ); - process.exit(1); - } - const profilerSubprovider = profiler.getProfilerSubproviderSingleton(); - logUtils.log( - "By default profilerSubprovider is stopped so that you don't get noise from setup code. Don't forget to start it before the code you want to profile and stop it afterwards", - ); - profilerSubprovider.stop(); - prependSubprovider(provider, profilerSubprovider); -} -if (isRevertTraceEnabled) { - const revertTraceSubprovider = revertTrace.getRevertTraceSubproviderSingleton(); - prependSubprovider(provider, revertTraceSubprovider); -} - -export const web3Wrapper = new Web3Wrapper(provider); diff --git a/contracts/core/test/utils_test/test_with_reference.ts b/contracts/core/test/utils_test/test_with_reference.ts deleted file mode 100644 index 8d633cd1f..000000000 --- a/contracts/core/test/utils_test/test_with_reference.ts +++ /dev/null @@ -1,63 +0,0 @@ -import * as chai from 'chai'; - -import { chaiSetup } from '../utils/chai_setup'; -import { testWithReferenceFuncAsync } from '../utils/test_with_reference'; - -chaiSetup.configure(); -const expect = chai.expect; - -async function divAsync(x: number, y: number): Promise<number> { - if (y === 0) { - throw new Error('MathError: divide by zero'); - } - return x / y; -} - -// returns an async function that always returns the given value. -function alwaysValueFunc(value: number): (x: number, y: number) => Promise<number> { - return async (x: number, y: number) => value; -} - -// returns an async function which always throws/rejects with the given error -// message. -function alwaysFailFunc(errMessage: string): (x: number, y: number) => Promise<number> { - return async (x: number, y: number) => { - throw new Error(errMessage); - }; -} - -describe('testWithReferenceFuncAsync', () => { - it('passes when both succeed and actual === expected', async () => { - await testWithReferenceFuncAsync(alwaysValueFunc(0.5), divAsync, [1, 2]); - }); - - it('passes when both fail and actual error contains expected error', async () => { - await testWithReferenceFuncAsync(alwaysFailFunc('divide by zero'), divAsync, [1, 0]); - }); - - it('fails when both succeed and actual !== expected', async () => { - expect(testWithReferenceFuncAsync(alwaysValueFunc(3), divAsync, [1, 2])).to.be.rejectedWith( - 'Test case {"x":1,"y":2}: expected { value: 0.5 } to deeply equal { value: 3 }', - ); - }); - - it('fails when both fail and actual error does not contain expected error', async () => { - expect( - testWithReferenceFuncAsync(alwaysFailFunc('Unexpected math error'), divAsync, [1, 0]), - ).to.be.rejectedWith( - 'MathError: divide by zero\n\tTest case: {"x":1,"y":0}: expected \'MathError: divide by zero\' to include \'Unexpected math error\'', - ); - }); - - it('fails when referenceFunc succeeds and testFunc fails', async () => { - expect(testWithReferenceFuncAsync(alwaysValueFunc(0), divAsync, [1, 0])).to.be.rejectedWith( - 'Test case {"x":1,"y":0}: expected { error: \'MathError: divide by zero\' } to deeply equal { value: 0 }', - ); - }); - - it('fails when referenceFunc fails and testFunc succeeds', async () => { - expect(testWithReferenceFuncAsync(alwaysFailFunc('divide by zero'), divAsync, [1, 2])).to.be.rejectedWith( - 'Expected error containing divide by zero but got no error\n\tTest case: {"x":1,"y":2}', - ); - }); -}); |