@0x:contracts-exchange Moved the deployment test to the exchange and addressed other review comments

This commit is contained in:
Alex Towle 2019-09-30 16:59:59 -07:00
parent 9282684d93
commit 6ca8edbf19
6 changed files with 149 additions and 92 deletions

View File

@ -50,6 +50,8 @@
"devDependencies": { "devDependencies": {
"@0x/abi-gen": "^4.2.1", "@0x/abi-gen": "^4.2.1",
"@0x/contracts-gen": "^1.0.15", "@0x/contracts-gen": "^1.0.15",
"@0x/contracts-multisig": "^3.1.14",
"@0x/contracts-staking": "^1.0.0",
"@0x/contracts-test-utils": "^3.1.16", "@0x/contracts-test-utils": "^3.1.16",
"@0x/dev-utils": "^2.3.3", "@0x/dev-utils": "^2.3.3",
"@0x/sol-compiler": "^3.1.15", "@0x/sol-compiler": "^3.1.15",

View File

@ -1,3 +1,4 @@
export * from './artifacts'; export * from './artifacts';
export * from './wrappers'; export * from './wrappers';
export * from '../test/utils'; export * from '../test/utils';
export * from './wrapper_interfaces';

View File

@ -0,0 +1,53 @@
import { PromiseWithTransactionHash } from '@0x/base-contract';
import { BlockParam, CallData, TransactionReceiptWithDecodedLogs, TxData } from 'ethereum-types';
// Generated Wrapper Interfaces
export interface AssetProxyDispatcher {
registerAssetProxy: {
awaitTransactionSuccessAsync: (
assetProxy: string,
txData?: Partial<TxData>,
pollingIntervalMs?: number,
timeoutMs?: number,
) => PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs>;
};
getAssetProxy: {
callAsync(assetProxyId: string, callData?: Partial<CallData>, defaultBlock?: BlockParam): Promise<string>;
};
}
export interface Authorizable extends Ownable {
addAuthorizedAddress: {
awaitTransactionSuccessAsync: (
target: string,
txData?: Partial<TxData>,
pollingIntervalMs?: number,
timeoutMs?: number,
) => PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs>;
};
removeAuthorizedAddress: {
awaitTransactionSuccessAsync: (
target: string,
txData?: Partial<TxData>,
pollingIntervalMs?: number,
timeoutMs?: number,
) => PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs>;
};
authorized: {
callAsync(authority: string, callData?: Partial<CallData>, defaultBlock?: BlockParam): Promise<boolean>;
};
}
export interface Ownable {
transferOwnership: {
awaitTransactionSuccessAsync: (
newOwner: string,
txData?: Partial<TxData>,
pollingIntervalMs?: number,
timeoutMs?: number,
) => PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs>;
};
owner: {
callAsync(callData?: Partial<CallData>, defaultBlock?: BlockParam): Promise<string>;
};
}

View File

@ -6,28 +6,35 @@ import {
MultiAssetProxyContract, MultiAssetProxyContract,
StaticCallProxyContract, StaticCallProxyContract,
} from '@0x/contracts-asset-proxy'; } from '@0x/contracts-asset-proxy';
import {
artifacts as exchangeArtifacts,
ExchangeContract,
MixinAssetProxyDispatcherAssetProxyRegisteredEventArgs,
MixinProtocolFeesProtocolFeeCollectorAddressEventArgs,
MixinProtocolFeesProtocolFeeMultiplierEventArgs,
} from '@0x/contracts-exchange';
import { artifacts as multisigArtifacts, AssetProxyOwnerContract } from '@0x/contracts-multisig'; import { artifacts as multisigArtifacts, AssetProxyOwnerContract } from '@0x/contracts-multisig';
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils'; import {
artifacts as stakingArtifacts,
ReadOnlyProxyContract,
StakingContract,
StakingEvents,
StakingExchangeAddedEventArgs,
StakingProxyContract,
} from '@0x/contracts-staking';
import { blockchainTests, constants, expect, filterLogsToArguments } from '@0x/contracts-test-utils';
import { import {
AuthorizableAuthorizedAddressAddedEventArgs, AuthorizableAuthorizedAddressAddedEventArgs,
AuthorizableAuthorizedAddressRemovedEventArgs, AuthorizableAuthorizedAddressRemovedEventArgs,
AuthorizableEvents,
} from '@0x/contracts-utils'; } from '@0x/contracts-utils';
import { AssetProxyId } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import { LogWithDecodedArgs, TxData } from 'ethereum-types'; import { TxData } from 'ethereum-types';
import { import {
artifacts as stakingArtifacts, artifacts as exchangeArtifacts,
MixinExchangeManagerExchangeAddedEventArgs, AssetProxyDispatcher,
ReadOnlyProxyContract, Authorizable,
StakingContract, ExchangeAssetProxyRegisteredEventArgs,
StakingProxyContract, ExchangeContract,
ExchangeEvents,
ExchangeProtocolFeeCollectorAddressEventArgs,
ExchangeProtocolFeeMultiplierEventArgs,
Ownable,
} from '../../src'; } from '../../src';
// tslint:disable:no-unnecessary-type-assertion // tslint:disable:no-unnecessary-type-assertion
@ -160,7 +167,7 @@ blockchainTests('Deployment and Configuration End to End Tests', env => {
describe('exchange specific', () => { describe('exchange specific', () => {
// Registers an asset proxy in the exchange contract and ensure that the correct state changes occurred. // Registers an asset proxy in the exchange contract and ensure that the correct state changes occurred.
async function registerAssetProxyAndAssertSuccessAsync( async function registerAssetProxyAndAssertSuccessAsync(
registrationContract: any, // TODO(jalextowle): Express this in a type-safe way (during a debt-demolition) registrationContract: AssetProxyDispatcher,
assetProxyAddress: string, assetProxyAddress: string,
assetProxyId: string, assetProxyId: string,
): Promise<void> { ): Promise<void> {
@ -173,13 +180,11 @@ blockchainTests('Deployment and Configuration End to End Tests', env => {
); );
// Ensure that the correct event was logged. // Ensure that the correct event was logged.
expect(receipt.logs.length).to.be.eq(1); const logs = filterLogsToArguments<ExchangeAssetProxyRegisteredEventArgs>(
const log = receipt.logs[0] as LogWithDecodedArgs< receipt.logs,
MixinAssetProxyDispatcherAssetProxyRegisteredEventArgs ExchangeEvents.AssetProxyRegistered,
>; );
expect(log.event).to.be.eq('AssetProxyRegistered'); expect(logs).to.be.deep.eq([{ id: assetProxyId, assetProxy: assetProxyAddress }]);
expect(log.args.id).to.be.eq(assetProxyId);
expect(log.args.assetProxy).to.be.eq(assetProxyAddress);
// Ensure that the asset proxy was actually registered. // Ensure that the asset proxy was actually registered.
const proxyAddress = await registrationContract.getAssetProxy.callAsync(assetProxyId); const proxyAddress = await registrationContract.getAssetProxy.callAsync(assetProxyId);
@ -188,7 +193,7 @@ blockchainTests('Deployment and Configuration End to End Tests', env => {
// Authorizes an address for a given asset proxy using the owner address. // Authorizes an address for a given asset proxy using the owner address.
async function authorizeAddressAndAssertSuccessAsync( async function authorizeAddressAndAssertSuccessAsync(
authorizable: any, // TODO(jalextowle): Express this in a type-safe way (during a debt-demolition) authorizable: Authorizable,
newAuthorityAddress: string, newAuthorityAddress: string,
): Promise<void> { ): Promise<void> {
// Authorize the address. // Authorize the address.
@ -198,11 +203,11 @@ blockchainTests('Deployment and Configuration End to End Tests', env => {
); );
// Ensure that the correct log was emitted. // Ensure that the correct log was emitted.
expect(receipt.logs.length).to.be.eq(1); const logs = filterLogsToArguments<AuthorizableAuthorizedAddressAddedEventArgs>(
const log = receipt.logs[0] as LogWithDecodedArgs<AuthorizableAuthorizedAddressAddedEventArgs>; receipt.logs,
expect(log.event).to.be.eq('AuthorizedAddressAdded'); AuthorizableEvents.AuthorizedAddressAdded,
expect(log.args.target).to.be.eq(newAuthorityAddress); );
expect(log.args.caller).to.be.eq(owner); expect(logs).to.be.deep.eq([{ target: newAuthorityAddress, caller: owner }]);
// Ensure that the address was actually authorized. // Ensure that the address was actually authorized.
const wasAuthorized = await authorizable.authorized.callAsync(newAuthorityAddress); const wasAuthorized = await authorizable.authorized.callAsync(newAuthorityAddress);
@ -211,46 +216,38 @@ blockchainTests('Deployment and Configuration End to End Tests', env => {
it('should successfully register the asset proxies in the exchange', async () => { it('should successfully register the asset proxies in the exchange', async () => {
// Register the asset proxies in the exchange. // Register the asset proxies in the exchange.
await registerAssetProxyAndAssertSuccessAsync(exchange, erc20Proxy.address, constants.ERC20_PROXY_ID); await registerAssetProxyAndAssertSuccessAsync(exchange, erc20Proxy.address, AssetProxyId.ERC20);
await registerAssetProxyAndAssertSuccessAsync(exchange, erc721Proxy.address, constants.ERC721_PROXY_ID); await registerAssetProxyAndAssertSuccessAsync(exchange, erc721Proxy.address, AssetProxyId.ERC721);
await registerAssetProxyAndAssertSuccessAsync( await registerAssetProxyAndAssertSuccessAsync(exchange, erc1155Proxy.address, AssetProxyId.ERC1155);
exchange,
erc1155Proxy.address,
constants.ERC1155_PROXY_ID,
);
await registerAssetProxyAndAssertSuccessAsync( await registerAssetProxyAndAssertSuccessAsync(
exchange, exchange,
multiAssetProxy.address, multiAssetProxy.address,
constants.MULTI_ASSET_PROXY_ID, AssetProxyId.MultiAsset,
); );
await registerAssetProxyAndAssertSuccessAsync( await registerAssetProxyAndAssertSuccessAsync(
exchange, exchange,
staticCallProxy.address, staticCallProxy.address,
constants.STATIC_CALL_PROXY_ID, AssetProxyId.StaticCall,
); );
}); });
it('should successfully register the asset proxies in the multi-asset proxy', async () => { it('should successfully register the asset proxies in the multi-asset proxy', async () => {
// Register the asset proxies in the multi-asset proxy. // Register the asset proxies in the multi-asset proxy.
await registerAssetProxyAndAssertSuccessAsync( await registerAssetProxyAndAssertSuccessAsync(multiAssetProxy, erc20Proxy.address, AssetProxyId.ERC20);
multiAssetProxy,
erc20Proxy.address,
constants.ERC20_PROXY_ID,
);
await registerAssetProxyAndAssertSuccessAsync( await registerAssetProxyAndAssertSuccessAsync(
multiAssetProxy, multiAssetProxy,
erc721Proxy.address, erc721Proxy.address,
constants.ERC721_PROXY_ID, AssetProxyId.ERC721,
); );
await registerAssetProxyAndAssertSuccessAsync( await registerAssetProxyAndAssertSuccessAsync(
multiAssetProxy, multiAssetProxy,
erc1155Proxy.address, erc1155Proxy.address,
constants.ERC1155_PROXY_ID, AssetProxyId.ERC1155,
); );
await registerAssetProxyAndAssertSuccessAsync( await registerAssetProxyAndAssertSuccessAsync(
multiAssetProxy, multiAssetProxy,
staticCallProxy.address, staticCallProxy.address,
constants.STATIC_CALL_PROXY_ID, AssetProxyId.StaticCall,
); );
}); });
@ -273,12 +270,12 @@ blockchainTests('Deployment and Configuration End to End Tests', env => {
describe('staking specific', () => { describe('staking specific', () => {
it('should have properly configured the staking proxy with the logic contract and read-only proxy', async () => { it('should have properly configured the staking proxy with the logic contract and read-only proxy', async () => {
// Ensure that the registered read-only proxy is correct. // Ensure that the registered read-only proxy is correct.
const readOnlyProxyAddres = await stakingProxy.readOnlyProxy.callAsync(); const readOnlyProxyAddress = await stakingProxy.readOnlyProxy.callAsync();
expect(readOnlyProxyAddres).to.be.eq(readOnlyProxy.address); expect(readOnlyProxyAddress).to.be.eq(readOnlyProxy.address);
// Ensure that the registered read-only proxy callee is correct. // Ensure that the registered read-only proxy callee is correct.
const readOnlyProxyCalleeAddres = await stakingProxy.readOnlyProxyCallee.callAsync(); const readOnlyProxyCalleeAddress = await stakingProxy.readOnlyProxyCallee.callAsync();
expect(readOnlyProxyCalleeAddres).to.be.eq(staking.address); expect(readOnlyProxyCalleeAddress).to.be.eq(staking.address);
// Ensure that the registered staking contract is correct. // Ensure that the registered staking contract is correct.
const stakingAddress = await stakingProxy.stakingContract.callAsync(); const stakingAddress = await stakingProxy.stakingContract.callAsync();
@ -288,13 +285,16 @@ blockchainTests('Deployment and Configuration End to End Tests', env => {
it('should have initialized the correct parameters in the staking proxy', async () => { it('should have initialized the correct parameters in the staking proxy', async () => {
// Ensure that the correct parameters were set. // Ensure that the correct parameters were set.
const params = await stakingWrapper.getParams.callAsync(); const params = await stakingWrapper.getParams.callAsync();
expect(params.length).to.be.eq(6); expect(params).to.be.deep.eq(
expect(params[0]).bignumber.to.be.eq(new BigNumber(864000)); // epochDurationInSeconds [
expect(params[1]).bignumber.to.be.eq(new BigNumber(900000)); // rewardDelegatedStakeWeight 864000, // epochDurationInSeconds
expect(params[2]).bignumber.to.be.eq(new BigNumber(100000000000000000000)); // minimumPoolStake 900000, // rewardDelegatedStakeWeight
expect(params[3]).bignumber.to.be.eq(10); // maximumMakerInPool 100000000000000000000, // minimumPoolStake
expect(params[4]).bignumber.to.be.eq(1); // cobbDouglasAlphaNumerator 10, // maximumMakerInPool
expect(params[5]).bignumber.to.be.eq(2); // cobbDouglasAlphaDenominator 1, // cobbDouglasAlphaNumerator
2, // cobbDouglasAlphaDenominator
].map(value => new BigNumber(value)),
);
}); });
}); });
@ -306,10 +306,11 @@ blockchainTests('Deployment and Configuration End to End Tests', env => {
}); });
// Ensure that the correct events were logged. // Ensure that the correct events were logged.
expect(receipt.logs.length).to.be.eq(1); const logs = filterLogsToArguments<StakingExchangeAddedEventArgs>(
const log = receipt.logs[0] as LogWithDecodedArgs<MixinExchangeManagerExchangeAddedEventArgs>; receipt.logs,
expect(log.event).to.be.eq('ExchangeAdded'); StakingEvents.ExchangeAdded,
expect(log.args.exchangeAddress).to.be.eq(exchange.address); );
expect(logs).to.be.deep.eq([{ exchangeAddress: exchange.address }]);
// Ensure that the exchange was registered. // Ensure that the exchange was registered.
const wasRegistered = await stakingWrapper.validExchanges.callAsync(exchange.address); const wasRegistered = await stakingWrapper.validExchanges.callAsync(exchange.address);
@ -326,13 +327,16 @@ blockchainTests('Deployment and Configuration End to End Tests', env => {
); );
// Ensure that the correct events were logged. // Ensure that the correct events were logged.
expect(receipt.logs.length).to.be.eq(1); const logs = filterLogsToArguments<ExchangeProtocolFeeCollectorAddressEventArgs>(
const log = receipt.logs[0] as LogWithDecodedArgs< receipt.logs,
MixinProtocolFeesProtocolFeeCollectorAddressEventArgs ExchangeEvents.ProtocolFeeCollectorAddress,
>; );
expect(log.event).to.be.eq('ProtocolFeeCollectorAddress'); expect(logs).to.be.deep.eq([
expect(log.args.oldProtocolFeeCollector).bignumber.to.be.eq(constants.NULL_ADDRESS); {
expect(log.args.updatedProtocolFeeCollector).bignumber.to.be.eq(stakingProxy.address); oldProtocolFeeCollector: constants.NULL_ADDRESS,
updatedProtocolFeeCollector: stakingProxy.address,
},
]);
// Ensure that the staking contract was registered. // Ensure that the staking contract was registered.
const feeCollector = await exchange.protocolFeeCollector.callAsync(); const feeCollector = await exchange.protocolFeeCollector.callAsync();
@ -346,11 +350,16 @@ blockchainTests('Deployment and Configuration End to End Tests', env => {
); );
// Ensure that the correct events were logged. // Ensure that the correct events were logged.
expect(receipt.logs.length).to.be.eq(1); const logs = filterLogsToArguments<ExchangeProtocolFeeMultiplierEventArgs>(
const log = receipt.logs[0] as LogWithDecodedArgs<MixinProtocolFeesProtocolFeeMultiplierEventArgs>; receipt.logs,
expect(log.event).to.be.eq('ProtocolFeeMultiplier'); ExchangeEvents.ProtocolFeeMultiplier,
expect(log.args.oldProtocolFeeMultiplier).bignumber.to.be.eq(constants.ZERO_AMOUNT); );
expect(log.args.updatedProtocolFeeMultiplier).bignumber.to.be.eq(protocolFeeMultiplier); expect(logs).to.be.deep.eq([
{
oldProtocolFeeMultiplier: constants.ZERO_AMOUNT,
updatedProtocolFeeMultiplier: protocolFeeMultiplier,
},
]);
// Ensure that the protocol fee multiplier was set correctly. // Ensure that the protocol fee multiplier was set correctly.
const multiplier = await exchange.protocolFeeMultiplier.callAsync(); const multiplier = await exchange.protocolFeeMultiplier.callAsync();
@ -360,19 +369,18 @@ blockchainTests('Deployment and Configuration End to End Tests', env => {
}); });
describe('transferring ownership', () => { describe('transferring ownership', () => {
// TODO(jalextowle): Express this in a type-safe way (during a debt-demolition)
// Removes authorization of the "externally owned address" owner and transfers the authorization // Removes authorization of the "externally owned address" owner and transfers the authorization
// to the asset proxy owner. // to the asset proxy owner.
async function transferAuthorizationAndAssertSuccessAsync(contract: any): Promise<void> { async function transferAuthorizationAndAssertSuccessAsync(contract: Authorizable): Promise<void> {
// Remove authorization from the old owner. // Remove authorization from the old owner.
let receipt = await contract.removeAuthorizedAddress.awaitTransactionSuccessAsync(owner, { from: owner }); let receipt = await contract.removeAuthorizedAddress.awaitTransactionSuccessAsync(owner, { from: owner });
// Ensure that the correct log was recorded. // Ensure that the correct log was recorded.
expect(receipt.logs.length).to.be.eq(1); let logs = filterLogsToArguments<AuthorizableAuthorizedAddressRemovedEventArgs>(
let log = receipt.logs[0] as LogWithDecodedArgs<AuthorizableAuthorizedAddressRemovedEventArgs>; receipt.logs,
expect(log.event).to.be.eq('AuthorizedAddressRemoved'); AuthorizableEvents.AuthorizedAddressRemoved,
expect(log.args.target).to.be.eq(owner); );
expect(log.args.caller).to.be.eq(owner); expect(logs).to.be.deep.eq([{ target: owner, caller: owner }]);
// Ensure that the owner was actually removed. // Ensure that the owner was actually removed.
let isAuthorized = await contract.authorized.callAsync(owner); let isAuthorized = await contract.authorized.callAsync(owner);
@ -384,20 +392,19 @@ blockchainTests('Deployment and Configuration End to End Tests', env => {
}); });
// Ensure that the correct log was recorded. // Ensure that the correct log was recorded.
expect(receipt.logs.length).to.be.eq(1); logs = filterLogsToArguments<AuthorizableAuthorizedAddressAddedEventArgs>(
log = receipt.logs[0] as LogWithDecodedArgs<AuthorizableAuthorizedAddressRemovedEventArgs>; receipt.logs,
expect(log.event).to.be.eq('AuthorizedAddressAdded'); AuthorizableEvents.AuthorizedAddressAdded,
expect(log.args.target).to.be.eq(assetProxyOwner.address); );
expect(log.args.caller).to.be.eq(owner); expect(logs).to.be.deep.eq([{ target: assetProxyOwner.address, caller: owner }]);
// Ensure that the asset-proxy owner was actually authorized. // Ensure that the asset-proxy owner was actually authorized.
isAuthorized = await contract.authorized.callAsync(assetProxyOwner.address); isAuthorized = await contract.authorized.callAsync(assetProxyOwner.address);
expect(isAuthorized).to.be.true(); expect(isAuthorized).to.be.true();
} }
// TODO(jalextowle): Express this in a type-safe way (during a debt-demolition)
// Transfers ownership of a contract to the asset-proxy owner, and ensures that the change was actually made. // Transfers ownership of a contract to the asset-proxy owner, and ensures that the change was actually made.
async function transferOwnershipAndAssertSuccessAsync(contract: any): Promise<void> { async function transferOwnershipAndAssertSuccessAsync(contract: Ownable): Promise<void> {
// Transfer ownership to the new owner. // Transfer ownership to the new owner.
await contract.transferOwnership.awaitTransactionSuccessAsync(assetProxyOwner.address, { from: owner }); await contract.transferOwnership.awaitTransactionSuccessAsync(assetProxyOwner.address, { from: owner });

View File

@ -51,7 +51,6 @@
"devDependencies": { "devDependencies": {
"@0x/abi-gen": "^4.1.0", "@0x/abi-gen": "^4.1.0",
"@0x/contracts-gen": "^1.0.13", "@0x/contracts-gen": "^1.0.13",
"@0x/contracts-exchange": "^2.1.14",
"@0x/contracts-multisig": "^3.1.14", "@0x/contracts-multisig": "^3.1.14",
"@0x/contracts-test-utils": "^3.1.2", "@0x/contracts-test-utils": "^3.1.2",
"@0x/dev-utils": "^2.2.1", "@0x/dev-utils": "^2.2.1",

View File

@ -84,9 +84,4 @@ export const constants = {
PPM_DENOMINATOR: 1e6, PPM_DENOMINATOR: 1e6,
PPM_100_PERCENT: 1e6, PPM_100_PERCENT: 1e6,
MAX_CODE_SIZE: 24576, MAX_CODE_SIZE: 24576,
ERC20_PROXY_ID: '0xf47261b0',
ERC721_PROXY_ID: '0x02571792',
ERC1155_PROXY_ID: '0xa7cb5fb7',
MULTI_ASSET_PROXY_ID: '0x94cfcdd7',
STATIC_CALL_PROXY_ID: '0xc339d10a',
}; };