diff --git a/contracts/coordinator/test/coordinator_registry.ts b/contracts/coordinator/test/coordinator_registry.ts index ef20a0eaf8..743132fa7e 100644 --- a/contracts/coordinator/test/coordinator_registry.ts +++ b/contracts/coordinator/test/coordinator_registry.ts @@ -1,11 +1,6 @@ -import { blockchainTests, expect } from '@0x/contracts-test-utils'; +import { blockchainTests, expect, verifyEvents } from '@0x/contracts-test-utils'; -import { - artifacts, - CoordinatorRegistryContract, - CoordinatorRegistryCoordinatorEndpointSetEventArgs, - CoordinatorTestFactory, -} from '../src'; +import { artifacts, CoordinatorRegistryContract, CoordinatorRegistryCoordinatorEndpointSetEventArgs } from '../src'; // tslint:disable:no-unnecessary-type-assertion blockchainTests.resets('Coordinator Registry tests', env => { @@ -71,7 +66,7 @@ blockchainTests.resets('Coordinator Registry tests', env => { coordinatorOperator, coordinatorEndpoint, }; - CoordinatorTestFactory.verifyEvents(txReceipt, [expectedEvent], 'CoordinatorEndpointSet'); + verifyEvents(txReceipt, [expectedEvent], 'CoordinatorEndpointSet'); }); }); }); diff --git a/contracts/coordinator/test/utils/index.ts b/contracts/coordinator/test/utils/index.ts index a724673f47..bd5bd79dae 100644 --- a/contracts/coordinator/test/utils/index.ts +++ b/contracts/coordinator/test/utils/index.ts @@ -1,4 +1,3 @@ export { hashUtils } from './hash_utils'; export { ApprovalFactory } from './approval_factory'; -export { CoordinatorTestFactory } from './coordinator_test_factory'; export * from './types'; diff --git a/contracts/integrations/src/index.ts b/contracts/integrations/src/index.ts index a51a51959b..d55f08ea2d 100644 --- a/contracts/integrations/src/index.ts +++ b/contracts/integrations/src/index.ts @@ -1,3 +1,2 @@ export * from './artifacts'; export * from './wrappers'; -export * from './deployment_mananger'; diff --git a/contracts/integrations/test/actors/base.ts b/contracts/integrations/test/actors/base.ts new file mode 100644 index 0000000000..c3638c817d --- /dev/null +++ b/contracts/integrations/test/actors/base.ts @@ -0,0 +1,54 @@ +import { DummyERC20TokenContract, WETH9Contract } from '@0x/contracts-erc20'; +import { constants } from '@0x/contracts-test-utils'; +import { BigNumber } from '@0x/utils'; + +import { DeploymentManager } from '../deployment/deployment_mananger'; + +export type Constructor = new (...args: any[]) => T; + +export interface ActorConfig { + address: string; + name?: string; + deployment: DeploymentManager; + [mixinProperty: string]: any; +} + +export class Actor { + public readonly address: string; + public readonly name: string; + public readonly deployment: DeploymentManager; + + constructor(config: ActorConfig) { + this.address = config.address; + this.name = config.name || config.address; + this.deployment = config.deployment; + } + + /** + * Sets a balance for an ERC20 token and approves a spender (defaults to the ERC20 asset proxy) + * to transfer the token. + */ + public async configureERC20TokenAsync( + token: DummyERC20TokenContract | WETH9Contract, + spender?: string, + amount?: BigNumber, + ): Promise { + if (token instanceof DummyERC20TokenContract) { + await token.setBalance.awaitTransactionSuccessAsync( + this.address, + amount || constants.INITIAL_ERC20_BALANCE, + ); + } else { + await token.deposit.awaitTransactionSuccessAsync({ + from: this.address, + value: amount || constants.ONE_ETHER, + }); + } + + await token.approve.awaitTransactionSuccessAsync( + spender || this.deployment.assetProxies.erc20Proxy.address, + constants.MAX_UINT256, + { from: this.address }, + ); + } +} diff --git a/contracts/integrations/test/actors/hybrids.ts b/contracts/integrations/test/actors/hybrids.ts new file mode 100644 index 0000000000..bd55763de8 --- /dev/null +++ b/contracts/integrations/test/actors/hybrids.ts @@ -0,0 +1,5 @@ +import { Actor } from './base'; +import { MakerMixin } from './maker'; +import { PoolOperatorMixin } from './pool_operator'; + +export class OperatorMaker extends PoolOperatorMixin(MakerMixin(Actor)) {} diff --git a/contracts/integrations/test/actors/index.ts b/contracts/integrations/test/actors/index.ts new file mode 100644 index 0000000000..ab525a5a70 --- /dev/null +++ b/contracts/integrations/test/actors/index.ts @@ -0,0 +1,3 @@ +export { Maker } from './maker'; +export { PoolOperator } from './pool_operator'; +export * from './hybrids'; diff --git a/contracts/integrations/test/actors/maker.ts b/contracts/integrations/test/actors/maker.ts new file mode 100644 index 0000000000..870716c7d2 --- /dev/null +++ b/contracts/integrations/test/actors/maker.ts @@ -0,0 +1,59 @@ +import { constants, OrderFactory } from '@0x/contracts-test-utils'; +import { Order, SignedOrder } from '@0x/types'; +import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; + +import { Actor, ActorConfig, Constructor } from './base'; + +export interface MakerConfig extends ActorConfig { + orderConfig: Partial; +} + +export function MakerMixin(Base: TBase) { + return class extends Base { + public poolId?: string; + public readonly actor: Actor; + public readonly orderFactory: OrderFactory; + + /** + * The mixin pattern requires that this constructor uses `...args: any[]`, but this class + * really expects a single `MakerConfig` parameter (assuming `Actor` is used as the base + * class). + */ + constructor(...args: any[]) { + super(...args); + this.actor = (this as any) as Actor; + + const { orderConfig } = args[0] as MakerConfig; + const defaultOrderParams = { + ...constants.STATIC_ORDER_PARAMS, + makerAddress: this.actor.address, + exchangeAddress: this.actor.deployment.exchange.address, + chainId: this.actor.deployment.chainId, + ...orderConfig, + }; + const privateKey = + constants.TESTRPC_PRIVATE_KEYS[this.actor.deployment.accounts.indexOf(this.actor.address)]; + this.orderFactory = new OrderFactory(privateKey, defaultOrderParams); + } + + /** + * Signs an order (optionally, with custom parameters) as the maker. + */ + public async signOrderAsync(customOrderParams: Partial = {}): Promise { + return this.orderFactory.newSignedOrderAsync(customOrderParams); + } + + /** + * Joins the staking pool specified by the given ID. + */ + public async joinStakingPoolAsync(poolId: string): Promise { + const stakingContract = this.actor.deployment.staking.stakingWrapper; + this.poolId = poolId; + return stakingContract.joinStakingPoolAsMaker.awaitTransactionSuccessAsync(poolId, { + from: this.actor.address, + }); + } + }; +} + +export class Maker extends MakerMixin(Actor) {} diff --git a/contracts/integrations/test/actors/pool_operator.ts b/contracts/integrations/test/actors/pool_operator.ts new file mode 100644 index 0000000000..3f15b8a002 --- /dev/null +++ b/contracts/integrations/test/actors/pool_operator.ts @@ -0,0 +1,66 @@ +import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; + +import { Actor, ActorConfig, Constructor } from './base'; + +export interface PoolOperatorConfig extends ActorConfig { + operatorShare: number; +} + +export function PoolOperatorMixin(Base: TBase) { + return class extends Base { + public operatorShare: number; + public readonly poolIds: string[] = []; + public readonly actor: Actor; + + /** + * The mixin pattern requires that this constructor uses `...args: any[]`, but this class + * really expects a single `PoolOperatorConfig` parameter (assuming `Actor` is used as the + * base class). + */ + constructor(...args: any[]) { + super(...args); + this.actor = (this as any) as Actor; + + const { operatorShare } = args[0] as PoolOperatorConfig; + this.operatorShare = operatorShare; + } + + /** + * Creates a staking pool and returns the ID of the new pool. + */ + public async createStakingPoolAsync( + operatorShare: number, + addOperatorAsMaker: boolean = false, + ): Promise { + const stakingContract = this.actor.deployment.staking.stakingWrapper; + const txReceipt = await stakingContract.createStakingPool.awaitTransactionSuccessAsync( + operatorShare, + addOperatorAsMaker, + { from: this.actor.address }, + ); + + const createStakingPoolLog = txReceipt.logs[0]; + const poolId = (createStakingPoolLog as any).args.poolId; + this.poolIds.push(poolId); + return poolId; + } + + /** + * Decreases the operator share of a specified staking pool. + */ + public async decreaseOperatorShareAsync( + poolId: string, + newOperatorShare: number, + ): Promise { + const stakingContract = this.actor.deployment.staking.stakingWrapper; + this.operatorShare = newOperatorShare; + return stakingContract.decreaseStakingPoolOperatorShare.awaitTransactionSuccessAsync( + poolId, + newOperatorShare, + { from: this.actor.address }, + ); + } + }; +} + +export class PoolOperator extends PoolOperatorMixin(Actor) {} diff --git a/contracts/coordinator/test/coordinator.ts b/contracts/integrations/test/coordinator/coordinator.ts similarity index 99% rename from contracts/coordinator/test/coordinator.ts rename to contracts/integrations/test/coordinator/coordinator.ts index 02db8841e3..c4671a7994 100644 --- a/contracts/coordinator/test/coordinator.ts +++ b/contracts/integrations/test/coordinator/coordinator.ts @@ -1,4 +1,5 @@ import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy'; +import { ApprovalFactory, artifacts, CoordinatorContract } from '@0x/contracts-coordinator'; import { artifacts as erc20Artifacts, DummyERC20TokenContract, WETH9Contract } from '@0x/contracts-erc20'; import { artifacts as exchangeArtifacts, @@ -19,7 +20,7 @@ import { import { assetDataUtils, CoordinatorRevertErrors, transactionHashUtils } from '@0x/order-utils'; import { BigNumber } from '@0x/utils'; -import { ApprovalFactory, artifacts, CoordinatorContract, CoordinatorTestFactory } from '../src'; +import { CoordinatorTestFactory } from './coordinator_test_factory'; // tslint:disable:no-unnecessary-type-assertion blockchainTests.resets('Coordinator tests', env => { diff --git a/contracts/coordinator/test/utils/coordinator_test_factory.ts b/contracts/integrations/test/coordinator/coordinator_test_factory.ts similarity index 91% rename from contracts/coordinator/test/utils/coordinator_test_factory.ts rename to contracts/integrations/test/coordinator/coordinator_test_factory.ts index caca5877da..bd3ba81f2d 100644 --- a/contracts/coordinator/test/utils/coordinator_test_factory.ts +++ b/contracts/integrations/test/coordinator/coordinator_test_factory.ts @@ -1,4 +1,5 @@ import { ERC20Wrapper } from '@0x/contracts-asset-proxy'; +import { CoordinatorContract } from '@0x/contracts-coordinator'; import { ExchangeCancelEventArgs, ExchangeCancelUpToEventArgs, @@ -6,31 +7,17 @@ import { ExchangeFillEventArgs, ExchangeFunctionName, } from '@0x/contracts-exchange'; -import { expect, filterLogsToArguments, Numberish, TokenBalances, web3Wrapper } from '@0x/contracts-test-utils'; +import { expect, Numberish, TokenBalances, verifyEvents, web3Wrapper } from '@0x/contracts-test-utils'; import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; import { SignedOrder, SignedZeroExTransaction } from '@0x/types'; import { BigNumber, RevertError } from '@0x/utils'; import { TransactionReceiptWithDecodedLogs, TxData } from 'ethereum-types'; import * as _ from 'lodash'; -import { CoordinatorContract } from '../../src'; - export class CoordinatorTestFactory { private readonly _addresses: string[]; private readonly _protocolFee: BigNumber; - public static verifyEvents( - txReceipt: TransactionReceiptWithDecodedLogs, - expectedEvents: TEventArgs[], - eventName: string, - ): void { - const logs = filterLogsToArguments(txReceipt.logs, eventName); - expect(logs.length).to.eq(expectedEvents.length); - logs.forEach((log, index) => { - expect(log).to.deep.equal(expectedEvents[index]); - }); - } - private static _expectedCancelEvent(order: SignedOrder): ExchangeCancelEventArgs { return { makerAddress: order.makerAddress, @@ -89,11 +76,7 @@ export class CoordinatorTestFactory { } const transactionReceipt = await tx; - CoordinatorTestFactory.verifyEvents( - transactionReceipt, - orders.map(order => this._expectedFillEvent(order)), - ExchangeEvents.Fill, - ); + verifyEvents(transactionReceipt, orders.map(order => this._expectedFillEvent(order)), ExchangeEvents.Fill); const expectedBalances = this._getExpectedBalances(initBalances, orders, transactionReceipt, txData.value); await this._verifyBalancesAsync(expectedBalances); @@ -121,9 +104,9 @@ export class CoordinatorTestFactory { orderSenderAddress: this._coordinatorContract.address, orderEpoch: new BigNumber(1), }; - CoordinatorTestFactory.verifyEvents(transactionReceipt, [expectedEvent], ExchangeEvents.CancelUpTo); + verifyEvents(transactionReceipt, [expectedEvent], ExchangeEvents.CancelUpTo); } else { - CoordinatorTestFactory.verifyEvents( + verifyEvents( transactionReceipt, orders.map(order => CoordinatorTestFactory._expectedCancelEvent(order)), ExchangeEvents.Cancel, diff --git a/contracts/integrations/test/deployment_manager_test.ts b/contracts/integrations/test/deployment/deployment_manager_test.ts similarity index 98% rename from contracts/integrations/test/deployment_manager_test.ts rename to contracts/integrations/test/deployment/deployment_manager_test.ts index 5b3a06c51f..359f165922 100644 --- a/contracts/integrations/test/deployment_manager_test.ts +++ b/contracts/integrations/test/deployment/deployment_manager_test.ts @@ -1,9 +1,8 @@ import { Authorizable, Ownable } from '@0x/contracts-exchange'; import { constants as stakingConstants } from '@0x/contracts-staking'; -import { blockchainTests, constants, expect } from '@0x/contracts-test-utils'; -import { BigNumber } from '@0x/utils'; +import { blockchainTests, expect } from '@0x/contracts-test-utils'; -import { DeploymentManager } from '../src'; +import { DeploymentManager } from './deployment_mananger'; blockchainTests('Deployment Manager', env => { let owner: string; @@ -11,7 +10,6 @@ blockchainTests('Deployment Manager', env => { before(async () => { [owner] = await env.getAccountAddressesAsync(); - deploymentManager = await DeploymentManager.deployAsync(env); }); diff --git a/contracts/integrations/src/deployment_mananger.ts b/contracts/integrations/test/deployment/deployment_mananger.ts similarity index 77% rename from contracts/integrations/src/deployment_mananger.ts rename to contracts/integrations/test/deployment/deployment_mananger.ts index 8e29fdf58f..3a8002ce39 100644 --- a/contracts/integrations/src/deployment_mananger.ts +++ b/contracts/integrations/test/deployment/deployment_mananger.ts @@ -6,9 +6,14 @@ import { MultiAssetProxyContract, StaticCallProxyContract, } from '@0x/contracts-asset-proxy'; -import { artifacts as ERC1155Artifacts, ERC1155Contract } from '@0x/contracts-erc1155'; -import { artifacts as ERC20Artifacts, ERC20TokenContract, ZRXTokenContract, WETH9Contract } from '@0x/contracts-erc20'; -import { artifacts as ERC721Artifacts, ERC721TokenContract } from '@0x/contracts-erc721'; +import { artifacts as ERC1155Artifacts, ERC1155MintableContract } from '@0x/contracts-erc1155'; +import { + DummyERC20TokenContract, + artifacts as ERC20Artifacts, + ZRXTokenContract, + WETH9Contract, +} from '@0x/contracts-erc20'; +import { artifacts as ERC721Artifacts, DummyERC721TokenContract } from '@0x/contracts-erc721'; import { artifacts as exchangeArtifacts, AssetProxyDispatcher, @@ -20,18 +25,15 @@ import { artifacts as multisigArtifacts, ZeroExGovernorContract } from '@0x/cont import { artifacts as stakingArtifacts, ReadOnlyProxyContract, - StakingContract, StakingProxyContract, + TestStakingContract, ZrxVaultContract, } from '@0x/contracts-staking'; import { BlockchainTestsEnvironment, constants } from '@0x/contracts-test-utils'; -import { Web3ProviderEngine } from '@0x/subproviders'; import { BigNumber } from '@0x/utils'; import { TxData } from 'ethereum-types'; import * as _ from 'lodash'; -import { artifacts, TestStakingPlaceholderContract } from './'; - /** * Adds a batch of authorities to a list of authorizable contracts. * @param owner The owner of the authorizable contracts. @@ -96,45 +98,53 @@ interface AssetProxyContracts { // Contract wrappers for all of the staking contracts interface StakingContracts { readOnlyProxy: ReadOnlyProxyContract; - stakingLogic: TestStakingPlaceholderContract; + stakingLogic: TestStakingContract; stakingProxy: StakingProxyContract; - stakingWrapper: TestStakingPlaceholderContract; + stakingWrapper: TestStakingContract; zrxVault: ZrxVaultContract; } // Contract wrappers for tokens. interface TokenContracts { - erc1155: ERC1155Contract; - erc20: ERC20TokenContract; - erc721: ERC721TokenContract; + erc20: DummyERC20TokenContract[]; + erc721: DummyERC721TokenContract[]; + erc1155: ERC1155MintableContract[]; weth: WETH9Contract; zrx: ZRXTokenContract; } +// Options to be passed to `deployAsync` +export interface DeploymentOptions { + owner: string; + numErc1155TokensToDeploy: number; + numErc20TokensToDeploy: number; + numErc721TokensToDeploy: number; +} + export class DeploymentManager { public static protocolFeeMultiplier = new BigNumber(150000); - public assetProxies: AssetProxyContracts; - public governor: ZeroExGovernorContract; - public exchange: ExchangeContract; - public staking: StakingContracts; - public tokens: TokenContracts; - /** * Fully deploy the 0x exchange and staking contracts and configure the system with the * asset proxy owner multisig. * @param environment A blockchain test environment to use for contracts deployment. + * @param options Specifies the owner address and number of tokens to deploy. */ - public static async deployAsync(environment: BlockchainTestsEnvironment): Promise { + public static async deployAsync( + environment: BlockchainTestsEnvironment, + options: Partial = {}, + ): Promise { const chainId = await environment.getChainIdAsync(); - const [owner] = await environment.getAccountAddressesAsync(); + const accounts = await environment.getAccountAddressesAsync(); + + const owner = options.owner || (await environment.getAccountAddressesAsync())[0]; const txDefaults = { ...environment.txDefaults, from: owner, }; // Deploy the contracts using the same owner and environment. - const assetProxies = await DeploymentManager._deployAssetProxyContractsAsync(environment, owner, txDefaults); + const assetProxies = await DeploymentManager._deployAssetProxyContractsAsync(environment, txDefaults); const exchange = await ExchangeContract.deployFrom0xArtifactAsync( exchangeArtifacts.Exchange, environment.provider, @@ -154,7 +164,7 @@ export class DeploymentManager { new BigNumber(1), constants.ZERO_AMOUNT, ); - const tokens = await DeploymentManager._deployTokenContractsAsync(environment, txDefaults); + const tokens = await DeploymentManager._deployTokenContractsAsync(environment, txDefaults, options); const staking = await DeploymentManager._deployStakingContractsAsync( environment, owner, @@ -190,7 +200,7 @@ export class DeploymentManager { staking.stakingProxy, ]); - return new DeploymentManager(assetProxies, governor, exchange, staking, tokens); + return new DeploymentManager(assetProxies, governor, exchange, staking, tokens, chainId, accounts); } /** @@ -273,12 +283,10 @@ export class DeploymentManager { /** * Deploy a set of asset proxy contracts. * @param environment The blockchain environment to use. - * @param owner An owner address to use when configuring the asset proxies. * @param txDefaults Defaults to use when deploying the asset proxies. */ protected static async _deployAssetProxyContractsAsync( environment: BlockchainTestsEnvironment, - owner: string, txDefaults: Partial, ): Promise { const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync( @@ -349,8 +357,8 @@ export class DeploymentManager { txDefaults, stakingArtifacts, ); - const stakingLogic = await TestStakingPlaceholderContract.deployFrom0xArtifactAsync( - artifacts.TestStakingPlaceholder, + const stakingLogic = await TestStakingContract.deployFrom0xArtifactAsync( + stakingArtifacts.TestStaking, environment.provider, txDefaults, stakingArtifacts, @@ -365,7 +373,7 @@ export class DeploymentManager { stakingLogic.address, readOnlyProxy.address, ); - const stakingWrapper = new TestStakingPlaceholderContract(stakingProxy.address, environment.provider); + const stakingWrapper = new TestStakingContract(stakingProxy.address, environment.provider); // Add the zrx vault and the weth contract to the staking proxy. await stakingWrapper.setWethContract.awaitTransactionSuccessAsync(tokens.weth.address, { from: owner }); @@ -392,30 +400,67 @@ export class DeploymentManager { * Deploy a set of token contracts. * @param environment The blockchain environment to use. * @param txDefaults Defaults to use when deploying the asset proxies. + * @param options Specifies how many tokens of each standard to deploy. */ protected static async _deployTokenContractsAsync( environment: BlockchainTestsEnvironment, txDefaults: Partial, + options: Partial, ): Promise { - const erc20 = await ERC20TokenContract.deployFrom0xArtifactAsync( - ERC20Artifacts.ERC20Token, - environment.provider, - txDefaults, - ERC20Artifacts, - ); + const numErc20TokensToDeploy = + options.numErc20TokensToDeploy !== undefined + ? options.numErc20TokensToDeploy + : constants.NUM_DUMMY_ERC20_TO_DEPLOY; + const numErc721TokensToDeploy = + options.numErc721TokensToDeploy !== undefined + ? options.numErc721TokensToDeploy + : constants.NUM_DUMMY_ERC721_TO_DEPLOY; + const numErc1155TokensToDeploy = + options.numErc1155TokensToDeploy !== undefined + ? options.numErc1155TokensToDeploy + : constants.NUM_DUMMY_ERC1155_CONTRACTS_TO_DEPLOY; - const erc721 = await ERC721TokenContract.deployFrom0xArtifactAsync( - ERC721Artifacts.ERC721Token, - environment.provider, - txDefaults, - ERC721Artifacts, + const erc20 = await Promise.all( + _.times( + numErc20TokensToDeploy, + async () => + await DummyERC20TokenContract.deployFrom0xArtifactAsync( + ERC20Artifacts.DummyERC20Token, + environment.provider, + txDefaults, + ERC20Artifacts, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, + ), + ), ); - - const erc1155 = await ERC1155Contract.deployFrom0xArtifactAsync( - ERC1155Artifacts.ERC1155, - environment.provider, - txDefaults, - ERC1155Artifacts, + const erc721 = await Promise.all( + _.times( + numErc721TokensToDeploy, + async () => + await DummyERC721TokenContract.deployFrom0xArtifactAsync( + ERC721Artifacts.DummyERC721Token, + environment.provider, + txDefaults, + ERC721Artifacts, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + ), + ), + ); + const erc1155 = await Promise.all( + _.times( + numErc1155TokensToDeploy, + async () => + await ERC1155MintableContract.deployFrom0xArtifactAsync( + ERC1155Artifacts.ERC1155Mintable, + environment.provider, + txDefaults, + ERC1155Artifacts, + ), + ), ); const weth = await WETH9Contract.deployFrom0xArtifactAsync( @@ -424,7 +469,6 @@ export class DeploymentManager { txDefaults, ERC20Artifacts, ); - const zrx = await ZRXTokenContract.deployFrom0xArtifactAsync( ERC20Artifacts.ZRXToken, environment.provider, @@ -433,25 +477,21 @@ export class DeploymentManager { ); return { - erc1155, erc20, erc721, + erc1155, weth, zrx, }; } - private constructor( - assetProxies: AssetProxyContracts, - governor: ZeroExGovernorContract, - exchange: ExchangeContract, - staking: StakingContracts, - tokens: TokenContracts, - ) { - this.assetProxies = assetProxies; - this.governor = governor; - this.exchange = exchange; - this.staking = staking; - this.tokens = tokens; - } + protected constructor( + public assetProxies: AssetProxyContracts, + public governor: ZeroExGovernorContract, + public exchange: ExchangeContract, + public staking: StakingContracts, + public tokens: TokenContracts, + public chainId: number, + public accounts: string[], + ) {} } diff --git a/contracts/integrations/test/deployment_test.ts b/contracts/integrations/test/deployment/deployment_test.ts similarity index 100% rename from contracts/integrations/test/deployment_test.ts rename to contracts/integrations/test/deployment/deployment_test.ts diff --git a/contracts/test-utils/src/index.ts b/contracts/test-utils/src/index.ts index 1753c590c4..48121d3870 100644 --- a/contracts/test-utils/src/index.ts +++ b/contracts/test-utils/src/index.ts @@ -15,7 +15,7 @@ export { export { getLatestBlockTimestampAsync, increaseTimeAndMineBlockAsync } from './block_timestamp'; export { provider, txDefaults, web3Wrapper } from './web3_wrapper'; export { LogDecoder } from './log_decoder'; -export { filterLogs, filterLogsToArguments } from './log_utils'; +export { filterLogs, filterLogsToArguments, verifyEvents } from './log_utils'; export { signingUtils } from './signing_utils'; export { orderUtils } from './order_utils'; export { typeEncodingUtils } from './type_encoding_utils'; diff --git a/contracts/test-utils/src/log_utils.ts b/contracts/test-utils/src/log_utils.ts index ae95ace2f8..8c09add427 100644 --- a/contracts/test-utils/src/log_utils.ts +++ b/contracts/test-utils/src/log_utils.ts @@ -1,4 +1,6 @@ -import { LogEntry, LogWithDecodedArgs } from 'ethereum-types'; +import { LogEntry, LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from 'ethereum-types'; + +import { expect } from './chai_setup'; // tslint:disable no-unnecessary-type-assertion @@ -15,3 +17,18 @@ export function filterLogs(logs: LogEntry[], event: string): Array(logs: LogEntry[], event: string): TEventArgs[] { return filterLogs(logs, event).map(log => log.args); } + +/** + * Verifies that a transaction emitted the expected events of a particular type. + */ +export function verifyEvents( + txReceipt: TransactionReceiptWithDecodedLogs, + expectedEvents: TEventArgs[], + eventName: string, +): void { + const logs = filterLogsToArguments(txReceipt.logs, eventName); + expect(logs.length).to.eq(expectedEvents.length); + logs.forEach((log, index) => { + expect(log).to.deep.equal(expectedEvents[index]); + }); +}