@0x:contracts-integrations
Wrote a simple integration test and AddressManager
This commit is contained in:
parent
6cba9fd77f
commit
01aee08c02
@ -2,3 +2,4 @@ export * from './artifacts';
|
|||||||
export * from './wrappers';
|
export * from './wrappers';
|
||||||
export * from '../test/utils/function_assertions';
|
export * from '../test/utils/function_assertions';
|
||||||
export * from '../test/utils/deployment_manager';
|
export * from '../test/utils/deployment_manager';
|
||||||
|
export * from '../test/utils/address_manager';
|
||||||
|
@ -0,0 +1,138 @@
|
|||||||
|
import { blockchainTests, constants, expect, filterLogsToArguments, OrderFactory } from '@0x/contracts-test-utils';
|
||||||
|
import { DummyERC20TokenContract, IERC20TokenEvents, IERC20TokenTransferEventArgs } from '@0x/contracts-erc20';
|
||||||
|
import { IExchangeEvents, IExchangeFillEventArgs } from '@0x/contracts-exchange';
|
||||||
|
import { IStakingEventsEvents, IStakingEventsStakingPoolActivatedEventArgs } from '@0x/contracts-staking';
|
||||||
|
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
|
||||||
|
import { BigNumber } from '@0x/utils';
|
||||||
|
|
||||||
|
import { DeploymentManager, AddressManager } from '../../src';
|
||||||
|
|
||||||
|
blockchainTests('Exchange & Staking', async env => {
|
||||||
|
let accounts: string[];
|
||||||
|
let makerAddress: string;
|
||||||
|
let takers: string[];
|
||||||
|
let delegators: string[];
|
||||||
|
let feeRecipientAddress: string;
|
||||||
|
let addressManager: AddressManager;
|
||||||
|
let deploymentManager: DeploymentManager;
|
||||||
|
let orderFactory: OrderFactory;
|
||||||
|
let makerAsset: DummyERC20TokenContract;
|
||||||
|
let takerAsset: DummyERC20TokenContract;
|
||||||
|
let feeAsset: DummyERC20TokenContract;
|
||||||
|
|
||||||
|
const gasPrice = 1e9;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
const chainId = await env.getChainIdAsync();
|
||||||
|
accounts = await env.getAccountAddressesAsync();
|
||||||
|
makerAddress = accounts[1];
|
||||||
|
feeRecipientAddress = accounts[2];
|
||||||
|
takers = [accounts[3], accounts[4]];
|
||||||
|
delegators = [accounts[5], accounts[6], accounts[7]];
|
||||||
|
deploymentManager = await DeploymentManager.deployAsync(env);
|
||||||
|
|
||||||
|
// Create a staking pool with the operator as a maker address.
|
||||||
|
await deploymentManager.staking.stakingWrapper.createStakingPool.awaitTransactionSuccessAsync(
|
||||||
|
constants.ZERO_AMOUNT,
|
||||||
|
true,
|
||||||
|
{ from: makerAddress },
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set up an address for market making.
|
||||||
|
addressManager = new AddressManager();
|
||||||
|
await addressManager.addMakerAsync(
|
||||||
|
deploymentManager,
|
||||||
|
{
|
||||||
|
address: makerAddress,
|
||||||
|
mainToken: deploymentManager.tokens.erc20[0],
|
||||||
|
feeToken: deploymentManager.tokens.erc20[2],
|
||||||
|
},
|
||||||
|
env,
|
||||||
|
deploymentManager.tokens.erc20[1],
|
||||||
|
feeRecipientAddress,
|
||||||
|
chainId,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set up two addresses for taking orders.
|
||||||
|
await addressManager.addTakersAsync(
|
||||||
|
deploymentManager,
|
||||||
|
takers.map(takerAddress => {
|
||||||
|
return {
|
||||||
|
address: takerAddress,
|
||||||
|
mainToken: deploymentManager.tokens.erc20[1],
|
||||||
|
feeToken: deploymentManager.tokens.erc20[2],
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('fillOrder', () => {
|
||||||
|
it('should be able to fill an order', async () => {
|
||||||
|
const order = await addressManager.makerAddresses[0].orderFactory.newSignedOrderAsync({
|
||||||
|
makerAddress,
|
||||||
|
makerAssetAmount: new BigNumber(1),
|
||||||
|
takerAssetAmount: new BigNumber(1),
|
||||||
|
makerFee: constants.ZERO_AMOUNT,
|
||||||
|
takerFee: constants.ZERO_AMOUNT,
|
||||||
|
feeRecipientAddress,
|
||||||
|
});
|
||||||
|
|
||||||
|
const receipt = await deploymentManager.exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||||
|
order,
|
||||||
|
new BigNumber(1),
|
||||||
|
order.signature,
|
||||||
|
{
|
||||||
|
from: takers[0],
|
||||||
|
gasPrice,
|
||||||
|
value: DeploymentManager.protocolFeeMultiplier.times(gasPrice),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Ensure that the number of emitted logs is equal to 3. There should have been a fill event
|
||||||
|
// and two transfer events. A 'StakingPoolActivated' event should not be expected because
|
||||||
|
// the only staking pool that was created does not have enough stake.
|
||||||
|
expect(receipt.logs.length).to.be.eq(3);
|
||||||
|
|
||||||
|
// Ensure that the fill event was correct.
|
||||||
|
const fillArgs = filterLogsToArguments<IExchangeFillEventArgs>(receipt.logs, IExchangeEvents.Fill);
|
||||||
|
expect(fillArgs.length).to.be.eq(1);
|
||||||
|
expect(fillArgs).to.be.deep.eq([
|
||||||
|
{
|
||||||
|
makerAddress,
|
||||||
|
feeRecipientAddress,
|
||||||
|
makerAssetData: order.makerAssetData,
|
||||||
|
takerAssetData: order.takerAssetData,
|
||||||
|
makerFeeAssetData: order.makerFeeAssetData,
|
||||||
|
takerFeeAssetData: order.takerFeeAssetData,
|
||||||
|
orderHash: orderHashUtils.getOrderHashHex(order),
|
||||||
|
takerAddress: takers[0],
|
||||||
|
senderAddress: takers[0],
|
||||||
|
makerAssetFilledAmount: order.makerAssetAmount,
|
||||||
|
takerAssetFilledAmount: order.takerAssetAmount,
|
||||||
|
makerFeePaid: constants.ZERO_AMOUNT,
|
||||||
|
takerFeePaid: constants.ZERO_AMOUNT,
|
||||||
|
protocolFeePaid: DeploymentManager.protocolFeeMultiplier.times(gasPrice),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Ensure that the transfer events were correctly emitted.
|
||||||
|
const transferArgs = filterLogsToArguments<IERC20TokenTransferEventArgs>(
|
||||||
|
receipt.logs,
|
||||||
|
IERC20TokenEvents.Transfer,
|
||||||
|
);
|
||||||
|
expect(transferArgs.length).to.be.eq(2);
|
||||||
|
expect(transferArgs).to.be.deep.eq([
|
||||||
|
{
|
||||||
|
_from: takers[0],
|
||||||
|
_to: makerAddress,
|
||||||
|
_value: order.takerAssetAmount,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_from: makerAddress,
|
||||||
|
_to: takers[0],
|
||||||
|
_value: order.makerAssetAmount,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,50 +0,0 @@
|
|||||||
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils';
|
|
||||||
import { assetDataUtils } from '@0x/order-utils';
|
|
||||||
import { BigNumber } from '@0x/utils';
|
|
||||||
|
|
||||||
import { DeploymentManager } from '../../src';
|
|
||||||
|
|
||||||
blockchainTests('Exchange & Staking', env => {
|
|
||||||
let accounts: string[];
|
|
||||||
let deploymentManager: DeploymentManager;
|
|
||||||
|
|
||||||
before(async () => {
|
|
||||||
accounts = await env.getAccountAddressesAsync();
|
|
||||||
deploymentManager = await DeploymentManager.deployAsync(env);
|
|
||||||
|
|
||||||
// Create a staking pool with the operator as a maker address.
|
|
||||||
await deploymentManager.staking.stakingWrapper.createStakingPool.awaitTransactionSuccessAsync(
|
|
||||||
constants.ZERO_AMOUNT,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
// TODO(jalextowle): I will eventually want these utilities to be in the deployment manager.
|
|
||||||
// Create default order parameters
|
|
||||||
// const defaultOrderParams = {
|
|
||||||
// ...constants.STATIC_ORDER_PARAMS,
|
|
||||||
// makerAddress: accounts[1],
|
|
||||||
// makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
|
|
||||||
// takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
|
|
||||||
// makerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultFeeTokenAddress),
|
|
||||||
// takerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultFeeTokenAddress),
|
|
||||||
// feeRecipientAddress: feeRecipientAddressLeft,
|
|
||||||
// exchangeAddress: exchange.address,
|
|
||||||
// chainId,
|
|
||||||
// };
|
|
||||||
});
|
|
||||||
|
|
||||||
// Function assertions for all of the functions involved in
|
|
||||||
// (1) Creating a staking pool
|
|
||||||
// - At first, this can be isolated.
|
|
||||||
// (2) Joining a staking pool as a maker
|
|
||||||
// - This can be isolated too, and we can assume a limited number
|
|
||||||
// of market makers to make things easy.
|
|
||||||
// (3) Paying a protocol fee
|
|
||||||
// - I'm personally of the opinion that we should write integration
|
|
||||||
// tests for the exchange and the staking contracts to interoperate.
|
|
||||||
// (4) Going to the next epoch
|
|
||||||
// - This might be something that just get's called every certain number of itterations
|
|
||||||
// for simple tests.
|
|
||||||
// (5) Finalizing a pool in the epoch
|
|
||||||
// - Ditto
|
|
||||||
});
|
|
122
contracts/integrations/test/utils/address_manager.ts
Normal file
122
contracts/integrations/test/utils/address_manager.ts
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
|
||||||
|
import { constants, OrderFactory, BlockchainTestsEnvironment } from '@0x/contracts-test-utils';
|
||||||
|
import { assetDataUtils, Order, SignatureType, SignedOrder } from '@0x/order-utils';
|
||||||
|
|
||||||
|
import { DeploymentManager } from '../../src';
|
||||||
|
|
||||||
|
interface MarketMaker {
|
||||||
|
address: string;
|
||||||
|
orderFactory: OrderFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ConfigurationArgs {
|
||||||
|
address: string;
|
||||||
|
mainToken: DummyERC20TokenContract;
|
||||||
|
feeToken: DummyERC20TokenContract;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AddressManager {
|
||||||
|
// A set of addresses that have been configured for market making.
|
||||||
|
public makerAddresses: MarketMaker[];
|
||||||
|
|
||||||
|
// A set of addresses that have been configured to take orders.
|
||||||
|
public takerAddresses: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up an address to take orders.
|
||||||
|
*/
|
||||||
|
public async addTakerAsync(deploymentManager: DeploymentManager, configArgs: ConfigurationArgs): Promise<void> {
|
||||||
|
// Configure the taker address with the taker and fee tokens.
|
||||||
|
await this._configureTokenForAddressAsync(deploymentManager, configArgs.address, configArgs.mainToken);
|
||||||
|
await this._configureTokenForAddressAsync(deploymentManager, configArgs.address, configArgs.feeToken);
|
||||||
|
|
||||||
|
// Add the taker to the list of configured taker addresses.
|
||||||
|
this.takerAddresses.push(configArgs.address);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up a list of addresses to take orders.
|
||||||
|
*/
|
||||||
|
public async addTakersAsync(deploymentManager: DeploymentManager, configArgs: ConfigurationArgs[]): Promise<void> {
|
||||||
|
for (const args of configArgs) {
|
||||||
|
await this.addTakerAsync(deploymentManager, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up an address for market making.
|
||||||
|
*/
|
||||||
|
public async addMakerAsync(
|
||||||
|
deploymentManager: DeploymentManager,
|
||||||
|
configArgs: ConfigurationArgs,
|
||||||
|
environment: BlockchainTestsEnvironment,
|
||||||
|
takerToken: DummyERC20TokenContract,
|
||||||
|
feeRecipientAddress: string,
|
||||||
|
chainId: number,
|
||||||
|
): Promise<void> {
|
||||||
|
const accounts = await environment.getAccountAddressesAsync();
|
||||||
|
|
||||||
|
// Set up order signing for the maker address.
|
||||||
|
const defaultOrderParams = {
|
||||||
|
...constants.STATIC_ORDER_PARAMS,
|
||||||
|
makerAddress: configArgs.address,
|
||||||
|
makerAssetData: assetDataUtils.encodeERC20AssetData(configArgs.mainToken.address),
|
||||||
|
takerAssetData: assetDataUtils.encodeERC20AssetData(takerToken.address),
|
||||||
|
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(configArgs.feeToken.address),
|
||||||
|
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(configArgs.feeToken.address),
|
||||||
|
feeRecipientAddress,
|
||||||
|
exchangeAddress: deploymentManager.exchange.address,
|
||||||
|
chainId,
|
||||||
|
};
|
||||||
|
const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(configArgs.address)];
|
||||||
|
const orderFactory = new OrderFactory(privateKey, defaultOrderParams);
|
||||||
|
|
||||||
|
// Configure the maker address with the maker and fee tokens.
|
||||||
|
await this._configureTokenForAddressAsync(deploymentManager, configArgs.address, configArgs.mainToken);
|
||||||
|
await this._configureTokenForAddressAsync(deploymentManager, configArgs.address, configArgs.feeToken);
|
||||||
|
|
||||||
|
// Add the maker to the list of configured maker addresses.
|
||||||
|
this.makerAddresses.push({
|
||||||
|
address: configArgs.address,
|
||||||
|
orderFactory,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up several market makers.
|
||||||
|
*/
|
||||||
|
public async addMakersAsync(
|
||||||
|
deploymentManager: DeploymentManager,
|
||||||
|
configArgs: ConfigurationArgs[],
|
||||||
|
environment: BlockchainTestsEnvironment,
|
||||||
|
takerToken: DummyERC20TokenContract,
|
||||||
|
feeRecipientAddress: string,
|
||||||
|
chainId: number,
|
||||||
|
): Promise<void> {
|
||||||
|
for (const args of configArgs) {
|
||||||
|
await this.addMakerAsync(deploymentManager, args, environment, takerToken, feeRecipientAddress, chainId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up initial account balances for a token and approves the ERC20 asset proxy
|
||||||
|
* to transfer the token.
|
||||||
|
*/
|
||||||
|
protected async _configureTokenForAddressAsync(
|
||||||
|
deploymentManager: DeploymentManager,
|
||||||
|
address: string,
|
||||||
|
token: DummyERC20TokenContract,
|
||||||
|
): Promise<void> {
|
||||||
|
await token.setBalance.awaitTransactionSuccessAsync(address, constants.INITIAL_ERC20_BALANCE);
|
||||||
|
await token.approve.awaitTransactionSuccessAsync(
|
||||||
|
deploymentManager.assetProxies.erc20Proxy.address,
|
||||||
|
constants.MAX_UINT256,
|
||||||
|
{ from: address },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(makers?: MarketMaker[], takers?: string[]) {
|
||||||
|
this.makerAddresses = [];
|
||||||
|
this.takerAddresses = [];
|
||||||
|
}
|
||||||
|
}
|
@ -34,11 +34,6 @@ import { BigNumber } from '@0x/utils';
|
|||||||
import { TxData } from 'ethereum-types';
|
import { TxData } from 'ethereum-types';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
<<<<<<< HEAD:contracts/integrations/test/deployment/deployment_mananger.ts
|
|
||||||
=======
|
|
||||||
import { artifacts, TestStakingPlaceholderContract } from '../../src';
|
|
||||||
|
|
||||||
>>>>>>> `@0x/contracts-integrations` Created the FunctionAssertion class and examples:contracts/integrations/test/utils/deployment_mananger.ts
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
@ -111,15 +106,9 @@ interface StakingContracts {
|
|||||||
|
|
||||||
// Contract wrappers for tokens.
|
// Contract wrappers for tokens.
|
||||||
interface TokenContracts {
|
interface TokenContracts {
|
||||||
<<<<<<< HEAD:contracts/integrations/test/deployment/deployment_mananger.ts
|
|
||||||
erc20: DummyERC20TokenContract[];
|
erc20: DummyERC20TokenContract[];
|
||||||
erc721: DummyERC721TokenContract[];
|
erc721: DummyERC721TokenContract[];
|
||||||
erc1155: ERC1155MintableContract[];
|
erc1155: ERC1155MintableContract[];
|
||||||
=======
|
|
||||||
erc1155: ERC1155Contract;
|
|
||||||
erc20: ERC20TokenContract[];
|
|
||||||
erc721: ERC721TokenContract;
|
|
||||||
>>>>>>> `@0x/contracts-integrations` Created the FunctionAssertion class and examples:contracts/integrations/test/utils/deployment_mananger.ts
|
|
||||||
weth: WETH9Contract;
|
weth: WETH9Contract;
|
||||||
zrx: ZRXTokenContract;
|
zrx: ZRXTokenContract;
|
||||||
}
|
}
|
||||||
@ -160,7 +149,7 @@ export class DeploymentManager {
|
|||||||
exchangeArtifacts.Exchange,
|
exchangeArtifacts.Exchange,
|
||||||
environment.provider,
|
environment.provider,
|
||||||
environment.txDefaults,
|
environment.txDefaults,
|
||||||
exchangeArtifacts,
|
{ ...ERC20Artifacts, ...exchangeArtifacts },
|
||||||
new BigNumber(chainId),
|
new BigNumber(chainId),
|
||||||
);
|
);
|
||||||
const governor = await ZeroExGovernorContract.deployFrom0xArtifactAsync(
|
const governor = await ZeroExGovernorContract.deployFrom0xArtifactAsync(
|
||||||
@ -418,7 +407,6 @@ export class DeploymentManager {
|
|||||||
txDefaults: Partial<TxData>,
|
txDefaults: Partial<TxData>,
|
||||||
options: Partial<DeploymentOptions>,
|
options: Partial<DeploymentOptions>,
|
||||||
): Promise<TokenContracts> {
|
): Promise<TokenContracts> {
|
||||||
<<<<<<< HEAD:contracts/integrations/test/deployment/deployment_mananger.ts
|
|
||||||
const numErc20TokensToDeploy =
|
const numErc20TokensToDeploy =
|
||||||
options.numErc20TokensToDeploy !== undefined
|
options.numErc20TokensToDeploy !== undefined
|
||||||
? options.numErc20TokensToDeploy
|
? options.numErc20TokensToDeploy
|
||||||
@ -447,26 +435,6 @@ export class DeploymentManager {
|
|||||||
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
|
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
=======
|
|
||||||
const erc20 = [];
|
|
||||||
erc20[0] = await ERC20TokenContract.deployFrom0xArtifactAsync(
|
|
||||||
ERC20Artifacts.ERC20Token,
|
|
||||||
environment.provider,
|
|
||||||
txDefaults,
|
|
||||||
ERC20Artifacts,
|
|
||||||
);
|
|
||||||
erc20[1] = await ERC20TokenContract.deployFrom0xArtifactAsync(
|
|
||||||
ERC20Artifacts.ERC20Token,
|
|
||||||
environment.provider,
|
|
||||||
txDefaults,
|
|
||||||
ERC20Artifacts,
|
|
||||||
);
|
|
||||||
erc20[2] = await ERC20TokenContract.deployFrom0xArtifactAsync(
|
|
||||||
ERC20Artifacts.ERC20Token,
|
|
||||||
environment.provider,
|
|
||||||
txDefaults,
|
|
||||||
ERC20Artifacts,
|
|
||||||
>>>>>>> `@0x/contracts-integrations` Created the FunctionAssertion class and examples:contracts/integrations/test/utils/deployment_mananger.ts
|
|
||||||
);
|
);
|
||||||
const erc721 = await Promise.all(
|
const erc721 = await Promise.all(
|
||||||
_.times(
|
_.times(
|
||||||
|
@ -9,10 +9,12 @@ import { signingUtils } from './signing_utils';
|
|||||||
export class OrderFactory {
|
export class OrderFactory {
|
||||||
private readonly _defaultOrderParams: Partial<Order>;
|
private readonly _defaultOrderParams: Partial<Order>;
|
||||||
private readonly _privateKey: Buffer;
|
private readonly _privateKey: Buffer;
|
||||||
|
|
||||||
constructor(privateKey: Buffer, defaultOrderParams: Partial<Order>) {
|
constructor(privateKey: Buffer, defaultOrderParams: Partial<Order>) {
|
||||||
this._defaultOrderParams = defaultOrderParams;
|
this._defaultOrderParams = defaultOrderParams;
|
||||||
this._privateKey = privateKey;
|
this._privateKey = privateKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async newSignedOrderAsync(
|
public async newSignedOrderAsync(
|
||||||
customOrderParams: Partial<Order> = {},
|
customOrderParams: Partial<Order> = {},
|
||||||
signatureType: SignatureType = SignatureType.EthSign,
|
signatureType: SignatureType = SignatureType.EthSign,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user