Merge pull request #2273 from 0xProject/refactor/integrations/coordinator-tests
Coordinator test refactor [1/2] + actor mixin pattern
This commit is contained in:
commit
673d45361f
@ -1,11 +1,6 @@
|
|||||||
import { blockchainTests, expect } from '@0x/contracts-test-utils';
|
import { blockchainTests, expect, verifyEvents } from '@0x/contracts-test-utils';
|
||||||
|
|
||||||
import {
|
import { artifacts, CoordinatorRegistryContract, CoordinatorRegistryCoordinatorEndpointSetEventArgs } from '../src';
|
||||||
artifacts,
|
|
||||||
CoordinatorRegistryContract,
|
|
||||||
CoordinatorRegistryCoordinatorEndpointSetEventArgs,
|
|
||||||
CoordinatorTestFactory,
|
|
||||||
} from '../src';
|
|
||||||
|
|
||||||
// tslint:disable:no-unnecessary-type-assertion
|
// tslint:disable:no-unnecessary-type-assertion
|
||||||
blockchainTests.resets('Coordinator Registry tests', env => {
|
blockchainTests.resets('Coordinator Registry tests', env => {
|
||||||
@ -71,7 +66,7 @@ blockchainTests.resets('Coordinator Registry tests', env => {
|
|||||||
coordinatorOperator,
|
coordinatorOperator,
|
||||||
coordinatorEndpoint,
|
coordinatorEndpoint,
|
||||||
};
|
};
|
||||||
CoordinatorTestFactory.verifyEvents(txReceipt, [expectedEvent], 'CoordinatorEndpointSet');
|
verifyEvents(txReceipt, [expectedEvent], 'CoordinatorEndpointSet');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
export { hashUtils } from './hash_utils';
|
export { hashUtils } from './hash_utils';
|
||||||
export { ApprovalFactory } from './approval_factory';
|
export { ApprovalFactory } from './approval_factory';
|
||||||
export { CoordinatorTestFactory } from './coordinator_test_factory';
|
|
||||||
export * from './types';
|
export * from './types';
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
export * from './artifacts';
|
export * from './artifacts';
|
||||||
export * from './wrappers';
|
export * from './wrappers';
|
||||||
export * from './deployment_mananger';
|
|
||||||
|
54
contracts/integrations/test/actors/base.ts
Normal file
54
contracts/integrations/test/actors/base.ts
Normal file
@ -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<T = {}> = 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<void> {
|
||||||
|
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 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
5
contracts/integrations/test/actors/hybrids.ts
Normal file
5
contracts/integrations/test/actors/hybrids.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { Actor } from './base';
|
||||||
|
import { MakerMixin } from './maker';
|
||||||
|
import { PoolOperatorMixin } from './pool_operator';
|
||||||
|
|
||||||
|
export class OperatorMaker extends PoolOperatorMixin(MakerMixin(Actor)) {}
|
3
contracts/integrations/test/actors/index.ts
Normal file
3
contracts/integrations/test/actors/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export { Maker } from './maker';
|
||||||
|
export { PoolOperator } from './pool_operator';
|
||||||
|
export * from './hybrids';
|
59
contracts/integrations/test/actors/maker.ts
Normal file
59
contracts/integrations/test/actors/maker.ts
Normal file
@ -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<Order>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MakerMixin<TBase extends Constructor>(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<Order> = {}): Promise<SignedOrder> {
|
||||||
|
return this.orderFactory.newSignedOrderAsync(customOrderParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Joins the staking pool specified by the given ID.
|
||||||
|
*/
|
||||||
|
public async joinStakingPoolAsync(poolId: string): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
|
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) {}
|
66
contracts/integrations/test/actors/pool_operator.ts
Normal file
66
contracts/integrations/test/actors/pool_operator.ts
Normal file
@ -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<TBase extends Constructor>(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<string> {
|
||||||
|
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<TransactionReceiptWithDecodedLogs> {
|
||||||
|
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) {}
|
@ -1,4 +1,5 @@
|
|||||||
import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy';
|
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 erc20Artifacts, DummyERC20TokenContract, WETH9Contract } from '@0x/contracts-erc20';
|
||||||
import {
|
import {
|
||||||
artifacts as exchangeArtifacts,
|
artifacts as exchangeArtifacts,
|
||||||
@ -19,7 +20,7 @@ import {
|
|||||||
import { assetDataUtils, CoordinatorRevertErrors, transactionHashUtils } from '@0x/order-utils';
|
import { assetDataUtils, CoordinatorRevertErrors, transactionHashUtils } from '@0x/order-utils';
|
||||||
import { BigNumber } from '@0x/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
|
// tslint:disable:no-unnecessary-type-assertion
|
||||||
blockchainTests.resets('Coordinator tests', env => {
|
blockchainTests.resets('Coordinator tests', env => {
|
@ -1,4 +1,5 @@
|
|||||||
import { ERC20Wrapper } from '@0x/contracts-asset-proxy';
|
import { ERC20Wrapper } from '@0x/contracts-asset-proxy';
|
||||||
|
import { CoordinatorContract } from '@0x/contracts-coordinator';
|
||||||
import {
|
import {
|
||||||
ExchangeCancelEventArgs,
|
ExchangeCancelEventArgs,
|
||||||
ExchangeCancelUpToEventArgs,
|
ExchangeCancelUpToEventArgs,
|
||||||
@ -6,31 +7,17 @@ import {
|
|||||||
ExchangeFillEventArgs,
|
ExchangeFillEventArgs,
|
||||||
ExchangeFunctionName,
|
ExchangeFunctionName,
|
||||||
} from '@0x/contracts-exchange';
|
} 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 { assetDataUtils, orderHashUtils } from '@0x/order-utils';
|
||||||
import { SignedOrder, SignedZeroExTransaction } from '@0x/types';
|
import { SignedOrder, SignedZeroExTransaction } from '@0x/types';
|
||||||
import { BigNumber, RevertError } from '@0x/utils';
|
import { BigNumber, RevertError } from '@0x/utils';
|
||||||
import { TransactionReceiptWithDecodedLogs, TxData } from 'ethereum-types';
|
import { TransactionReceiptWithDecodedLogs, TxData } from 'ethereum-types';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { CoordinatorContract } from '../../src';
|
|
||||||
|
|
||||||
export class CoordinatorTestFactory {
|
export class CoordinatorTestFactory {
|
||||||
private readonly _addresses: string[];
|
private readonly _addresses: string[];
|
||||||
private readonly _protocolFee: BigNumber;
|
private readonly _protocolFee: BigNumber;
|
||||||
|
|
||||||
public static verifyEvents<TEventArgs>(
|
|
||||||
txReceipt: TransactionReceiptWithDecodedLogs,
|
|
||||||
expectedEvents: TEventArgs[],
|
|
||||||
eventName: string,
|
|
||||||
): void {
|
|
||||||
const logs = filterLogsToArguments<TEventArgs>(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 {
|
private static _expectedCancelEvent(order: SignedOrder): ExchangeCancelEventArgs {
|
||||||
return {
|
return {
|
||||||
makerAddress: order.makerAddress,
|
makerAddress: order.makerAddress,
|
||||||
@ -89,11 +76,7 @@ export class CoordinatorTestFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const transactionReceipt = await tx;
|
const transactionReceipt = await tx;
|
||||||
CoordinatorTestFactory.verifyEvents(
|
verifyEvents(transactionReceipt, orders.map(order => this._expectedFillEvent(order)), ExchangeEvents.Fill);
|
||||||
transactionReceipt,
|
|
||||||
orders.map(order => this._expectedFillEvent(order)),
|
|
||||||
ExchangeEvents.Fill,
|
|
||||||
);
|
|
||||||
|
|
||||||
const expectedBalances = this._getExpectedBalances(initBalances, orders, transactionReceipt, txData.value);
|
const expectedBalances = this._getExpectedBalances(initBalances, orders, transactionReceipt, txData.value);
|
||||||
await this._verifyBalancesAsync(expectedBalances);
|
await this._verifyBalancesAsync(expectedBalances);
|
||||||
@ -121,9 +104,9 @@ export class CoordinatorTestFactory {
|
|||||||
orderSenderAddress: this._coordinatorContract.address,
|
orderSenderAddress: this._coordinatorContract.address,
|
||||||
orderEpoch: new BigNumber(1),
|
orderEpoch: new BigNumber(1),
|
||||||
};
|
};
|
||||||
CoordinatorTestFactory.verifyEvents(transactionReceipt, [expectedEvent], ExchangeEvents.CancelUpTo);
|
verifyEvents(transactionReceipt, [expectedEvent], ExchangeEvents.CancelUpTo);
|
||||||
} else {
|
} else {
|
||||||
CoordinatorTestFactory.verifyEvents(
|
verifyEvents(
|
||||||
transactionReceipt,
|
transactionReceipt,
|
||||||
orders.map(order => CoordinatorTestFactory._expectedCancelEvent(order)),
|
orders.map(order => CoordinatorTestFactory._expectedCancelEvent(order)),
|
||||||
ExchangeEvents.Cancel,
|
ExchangeEvents.Cancel,
|
@ -1,9 +1,8 @@
|
|||||||
import { Authorizable, Ownable } from '@0x/contracts-exchange';
|
import { Authorizable, Ownable } from '@0x/contracts-exchange';
|
||||||
import { constants as stakingConstants } from '@0x/contracts-staking';
|
import { constants as stakingConstants } from '@0x/contracts-staking';
|
||||||
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils';
|
import { blockchainTests, expect } from '@0x/contracts-test-utils';
|
||||||
import { BigNumber } from '@0x/utils';
|
|
||||||
|
|
||||||
import { DeploymentManager } from '../src';
|
import { DeploymentManager } from './deployment_mananger';
|
||||||
|
|
||||||
blockchainTests('Deployment Manager', env => {
|
blockchainTests('Deployment Manager', env => {
|
||||||
let owner: string;
|
let owner: string;
|
||||||
@ -11,7 +10,6 @@ blockchainTests('Deployment Manager', env => {
|
|||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
[owner] = await env.getAccountAddressesAsync();
|
[owner] = await env.getAccountAddressesAsync();
|
||||||
|
|
||||||
deploymentManager = await DeploymentManager.deployAsync(env);
|
deploymentManager = await DeploymentManager.deployAsync(env);
|
||||||
});
|
});
|
||||||
|
|
@ -6,9 +6,14 @@ import {
|
|||||||
MultiAssetProxyContract,
|
MultiAssetProxyContract,
|
||||||
StaticCallProxyContract,
|
StaticCallProxyContract,
|
||||||
} from '@0x/contracts-asset-proxy';
|
} from '@0x/contracts-asset-proxy';
|
||||||
import { artifacts as ERC1155Artifacts, ERC1155Contract } from '@0x/contracts-erc1155';
|
import { artifacts as ERC1155Artifacts, ERC1155MintableContract } from '@0x/contracts-erc1155';
|
||||||
import { artifacts as ERC20Artifacts, ERC20TokenContract, ZRXTokenContract, WETH9Contract } from '@0x/contracts-erc20';
|
import {
|
||||||
import { artifacts as ERC721Artifacts, ERC721TokenContract } from '@0x/contracts-erc721';
|
DummyERC20TokenContract,
|
||||||
|
artifacts as ERC20Artifacts,
|
||||||
|
ZRXTokenContract,
|
||||||
|
WETH9Contract,
|
||||||
|
} from '@0x/contracts-erc20';
|
||||||
|
import { artifacts as ERC721Artifacts, DummyERC721TokenContract } from '@0x/contracts-erc721';
|
||||||
import {
|
import {
|
||||||
artifacts as exchangeArtifacts,
|
artifacts as exchangeArtifacts,
|
||||||
AssetProxyDispatcher,
|
AssetProxyDispatcher,
|
||||||
@ -20,18 +25,15 @@ import { artifacts as multisigArtifacts, ZeroExGovernorContract } from '@0x/cont
|
|||||||
import {
|
import {
|
||||||
artifacts as stakingArtifacts,
|
artifacts as stakingArtifacts,
|
||||||
ReadOnlyProxyContract,
|
ReadOnlyProxyContract,
|
||||||
StakingContract,
|
|
||||||
StakingProxyContract,
|
StakingProxyContract,
|
||||||
|
TestStakingContract,
|
||||||
ZrxVaultContract,
|
ZrxVaultContract,
|
||||||
} from '@0x/contracts-staking';
|
} from '@0x/contracts-staking';
|
||||||
import { BlockchainTestsEnvironment, constants } from '@0x/contracts-test-utils';
|
import { BlockchainTestsEnvironment, constants } from '@0x/contracts-test-utils';
|
||||||
import { Web3ProviderEngine } from '@0x/subproviders';
|
|
||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
import { TxData } from 'ethereum-types';
|
import { TxData } from 'ethereum-types';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { artifacts, TestStakingPlaceholderContract } from './';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a batch of authorities to a list of authorizable contracts.
|
* Adds a batch of authorities to a list of authorizable contracts.
|
||||||
* @param owner The owner of the authorizable contracts.
|
* @param owner The owner of the authorizable contracts.
|
||||||
@ -96,45 +98,53 @@ interface AssetProxyContracts {
|
|||||||
// Contract wrappers for all of the staking contracts
|
// Contract wrappers for all of the staking contracts
|
||||||
interface StakingContracts {
|
interface StakingContracts {
|
||||||
readOnlyProxy: ReadOnlyProxyContract;
|
readOnlyProxy: ReadOnlyProxyContract;
|
||||||
stakingLogic: TestStakingPlaceholderContract;
|
stakingLogic: TestStakingContract;
|
||||||
stakingProxy: StakingProxyContract;
|
stakingProxy: StakingProxyContract;
|
||||||
stakingWrapper: TestStakingPlaceholderContract;
|
stakingWrapper: TestStakingContract;
|
||||||
zrxVault: ZrxVaultContract;
|
zrxVault: ZrxVaultContract;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Contract wrappers for tokens.
|
// Contract wrappers for tokens.
|
||||||
interface TokenContracts {
|
interface TokenContracts {
|
||||||
erc1155: ERC1155Contract;
|
erc20: DummyERC20TokenContract[];
|
||||||
erc20: ERC20TokenContract;
|
erc721: DummyERC721TokenContract[];
|
||||||
erc721: ERC721TokenContract;
|
erc1155: ERC1155MintableContract[];
|
||||||
weth: WETH9Contract;
|
weth: WETH9Contract;
|
||||||
zrx: ZRXTokenContract;
|
zrx: ZRXTokenContract;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Options to be passed to `deployAsync`
|
||||||
|
export interface DeploymentOptions {
|
||||||
|
owner: string;
|
||||||
|
numErc1155TokensToDeploy: number;
|
||||||
|
numErc20TokensToDeploy: number;
|
||||||
|
numErc721TokensToDeploy: number;
|
||||||
|
}
|
||||||
|
|
||||||
export class DeploymentManager {
|
export class DeploymentManager {
|
||||||
public static protocolFeeMultiplier = new BigNumber(150000);
|
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
|
* Fully deploy the 0x exchange and staking contracts and configure the system with the
|
||||||
* asset proxy owner multisig.
|
* asset proxy owner multisig.
|
||||||
* @param environment A blockchain test environment to use for contracts deployment.
|
* @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<DeploymentManager> {
|
public static async deployAsync(
|
||||||
|
environment: BlockchainTestsEnvironment,
|
||||||
|
options: Partial<DeploymentOptions> = {},
|
||||||
|
): Promise<DeploymentManager> {
|
||||||
const chainId = await environment.getChainIdAsync();
|
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 = {
|
const txDefaults = {
|
||||||
...environment.txDefaults,
|
...environment.txDefaults,
|
||||||
from: owner,
|
from: owner,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Deploy the contracts using the same owner and environment.
|
// 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(
|
const exchange = await ExchangeContract.deployFrom0xArtifactAsync(
|
||||||
exchangeArtifacts.Exchange,
|
exchangeArtifacts.Exchange,
|
||||||
environment.provider,
|
environment.provider,
|
||||||
@ -154,7 +164,7 @@ export class DeploymentManager {
|
|||||||
new BigNumber(1),
|
new BigNumber(1),
|
||||||
constants.ZERO_AMOUNT,
|
constants.ZERO_AMOUNT,
|
||||||
);
|
);
|
||||||
const tokens = await DeploymentManager._deployTokenContractsAsync(environment, txDefaults);
|
const tokens = await DeploymentManager._deployTokenContractsAsync(environment, txDefaults, options);
|
||||||
const staking = await DeploymentManager._deployStakingContractsAsync(
|
const staking = await DeploymentManager._deployStakingContractsAsync(
|
||||||
environment,
|
environment,
|
||||||
owner,
|
owner,
|
||||||
@ -190,7 +200,7 @@ export class DeploymentManager {
|
|||||||
staking.stakingProxy,
|
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.
|
* Deploy a set of asset proxy contracts.
|
||||||
* @param environment The blockchain environment to use.
|
* @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.
|
* @param txDefaults Defaults to use when deploying the asset proxies.
|
||||||
*/
|
*/
|
||||||
protected static async _deployAssetProxyContractsAsync(
|
protected static async _deployAssetProxyContractsAsync(
|
||||||
environment: BlockchainTestsEnvironment,
|
environment: BlockchainTestsEnvironment,
|
||||||
owner: string,
|
|
||||||
txDefaults: Partial<TxData>,
|
txDefaults: Partial<TxData>,
|
||||||
): Promise<AssetProxyContracts> {
|
): Promise<AssetProxyContracts> {
|
||||||
const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync(
|
const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync(
|
||||||
@ -349,8 +357,8 @@ export class DeploymentManager {
|
|||||||
txDefaults,
|
txDefaults,
|
||||||
stakingArtifacts,
|
stakingArtifacts,
|
||||||
);
|
);
|
||||||
const stakingLogic = await TestStakingPlaceholderContract.deployFrom0xArtifactAsync(
|
const stakingLogic = await TestStakingContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.TestStakingPlaceholder,
|
stakingArtifacts.TestStaking,
|
||||||
environment.provider,
|
environment.provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
stakingArtifacts,
|
stakingArtifacts,
|
||||||
@ -365,7 +373,7 @@ export class DeploymentManager {
|
|||||||
stakingLogic.address,
|
stakingLogic.address,
|
||||||
readOnlyProxy.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.
|
// Add the zrx vault and the weth contract to the staking proxy.
|
||||||
await stakingWrapper.setWethContract.awaitTransactionSuccessAsync(tokens.weth.address, { from: owner });
|
await stakingWrapper.setWethContract.awaitTransactionSuccessAsync(tokens.weth.address, { from: owner });
|
||||||
@ -392,30 +400,67 @@ export class DeploymentManager {
|
|||||||
* Deploy a set of token contracts.
|
* Deploy a set of token contracts.
|
||||||
* @param environment The blockchain environment to use.
|
* @param environment The blockchain environment to use.
|
||||||
* @param txDefaults Defaults to use when deploying the asset proxies.
|
* @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(
|
protected static async _deployTokenContractsAsync(
|
||||||
environment: BlockchainTestsEnvironment,
|
environment: BlockchainTestsEnvironment,
|
||||||
txDefaults: Partial<TxData>,
|
txDefaults: Partial<TxData>,
|
||||||
|
options: Partial<DeploymentOptions>,
|
||||||
): Promise<TokenContracts> {
|
): Promise<TokenContracts> {
|
||||||
const erc20 = await ERC20TokenContract.deployFrom0xArtifactAsync(
|
const numErc20TokensToDeploy =
|
||||||
ERC20Artifacts.ERC20Token,
|
options.numErc20TokensToDeploy !== undefined
|
||||||
environment.provider,
|
? options.numErc20TokensToDeploy
|
||||||
txDefaults,
|
: constants.NUM_DUMMY_ERC20_TO_DEPLOY;
|
||||||
ERC20Artifacts,
|
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(
|
const erc20 = await Promise.all(
|
||||||
ERC721Artifacts.ERC721Token,
|
_.times(
|
||||||
environment.provider,
|
numErc20TokensToDeploy,
|
||||||
txDefaults,
|
async () =>
|
||||||
ERC721Artifacts,
|
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 erc721 = await Promise.all(
|
||||||
const erc1155 = await ERC1155Contract.deployFrom0xArtifactAsync(
|
_.times(
|
||||||
ERC1155Artifacts.ERC1155,
|
numErc721TokensToDeploy,
|
||||||
environment.provider,
|
async () =>
|
||||||
txDefaults,
|
await DummyERC721TokenContract.deployFrom0xArtifactAsync(
|
||||||
ERC1155Artifacts,
|
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(
|
const weth = await WETH9Contract.deployFrom0xArtifactAsync(
|
||||||
@ -424,7 +469,6 @@ export class DeploymentManager {
|
|||||||
txDefaults,
|
txDefaults,
|
||||||
ERC20Artifacts,
|
ERC20Artifacts,
|
||||||
);
|
);
|
||||||
|
|
||||||
const zrx = await ZRXTokenContract.deployFrom0xArtifactAsync(
|
const zrx = await ZRXTokenContract.deployFrom0xArtifactAsync(
|
||||||
ERC20Artifacts.ZRXToken,
|
ERC20Artifacts.ZRXToken,
|
||||||
environment.provider,
|
environment.provider,
|
||||||
@ -433,25 +477,21 @@ export class DeploymentManager {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
erc1155,
|
|
||||||
erc20,
|
erc20,
|
||||||
erc721,
|
erc721,
|
||||||
|
erc1155,
|
||||||
weth,
|
weth,
|
||||||
zrx,
|
zrx,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private constructor(
|
protected constructor(
|
||||||
assetProxies: AssetProxyContracts,
|
public assetProxies: AssetProxyContracts,
|
||||||
governor: ZeroExGovernorContract,
|
public governor: ZeroExGovernorContract,
|
||||||
exchange: ExchangeContract,
|
public exchange: ExchangeContract,
|
||||||
staking: StakingContracts,
|
public staking: StakingContracts,
|
||||||
tokens: TokenContracts,
|
public tokens: TokenContracts,
|
||||||
) {
|
public chainId: number,
|
||||||
this.assetProxies = assetProxies;
|
public accounts: string[],
|
||||||
this.governor = governor;
|
) {}
|
||||||
this.exchange = exchange;
|
|
||||||
this.staking = staking;
|
|
||||||
this.tokens = tokens;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -15,7 +15,7 @@ export {
|
|||||||
export { getLatestBlockTimestampAsync, increaseTimeAndMineBlockAsync } from './block_timestamp';
|
export { getLatestBlockTimestampAsync, increaseTimeAndMineBlockAsync } from './block_timestamp';
|
||||||
export { provider, txDefaults, web3Wrapper } from './web3_wrapper';
|
export { provider, txDefaults, web3Wrapper } from './web3_wrapper';
|
||||||
export { LogDecoder } from './log_decoder';
|
export { LogDecoder } from './log_decoder';
|
||||||
export { filterLogs, filterLogsToArguments } from './log_utils';
|
export { filterLogs, filterLogsToArguments, verifyEvents } from './log_utils';
|
||||||
export { signingUtils } from './signing_utils';
|
export { signingUtils } from './signing_utils';
|
||||||
export { orderUtils } from './order_utils';
|
export { orderUtils } from './order_utils';
|
||||||
export { typeEncodingUtils } from './type_encoding_utils';
|
export { typeEncodingUtils } from './type_encoding_utils';
|
||||||
|
@ -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
|
// tslint:disable no-unnecessary-type-assertion
|
||||||
|
|
||||||
@ -15,3 +17,18 @@ export function filterLogs<TEventArgs>(logs: LogEntry[], event: string): Array<L
|
|||||||
export function filterLogsToArguments<TEventArgs>(logs: LogEntry[], event: string): TEventArgs[] {
|
export function filterLogsToArguments<TEventArgs>(logs: LogEntry[], event: string): TEventArgs[] {
|
||||||
return filterLogs<TEventArgs>(logs, event).map(log => log.args);
|
return filterLogs<TEventArgs>(logs, event).map(log => log.args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that a transaction emitted the expected events of a particular type.
|
||||||
|
*/
|
||||||
|
export function verifyEvents<TEventArgs>(
|
||||||
|
txReceipt: TransactionReceiptWithDecodedLogs,
|
||||||
|
expectedEvents: TEventArgs[],
|
||||||
|
eventName: string,
|
||||||
|
): void {
|
||||||
|
const logs = filterLogsToArguments<TEventArgs>(txReceipt.logs, eventName);
|
||||||
|
expect(logs.length).to.eq(expectedEvents.length);
|
||||||
|
logs.forEach((log, index) => {
|
||||||
|
expect(log).to.deep.equal(expectedEvents[index]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user