Xianny f0d7d10fe7
update abi-gen with new method interfaces (#2325)
* update abi-gen with new method interfaces

* wip: get all packages to build

* wip: get all packages to build

* Fix two contract wrapper calls

* Export necessary types part of the contract wrapper public interfaces

* Revive and fix wrapper_unit_tests

* Remove duplicate type

* Fix lib_exchange_rich_error_decoder tests

* Fix remaining test failures in contracts-* packages

* Prettier fixes

* remove transactionHelper

* lint and update changelogs

* Fix prettier

* Revert changes to reference docs

* Add back changelog already published and add revert changelog entry

* Add missing CHANGELOG entries

* Add missing comma

* Update mesh-rpc-client dep

* Update Mesh RPC logic in @0x/orderbook to v6.0.1-beta

* Align package versions
2019-11-14 11:22:29 -05:00

413 lines
18 KiB
TypeScript

import {
artifacts as assetProxyArtifacts,
ERC1155ProxyContract,
ERC20ProxyContract,
ERC721ProxyContract,
MultiAssetProxyContract,
StaticCallProxyContract,
} from '@0x/contracts-asset-proxy';
import {
artifacts as exchangeArtifacts,
ExchangeAssetProxyRegisteredEventArgs,
ExchangeContract,
ExchangeEvents,
ExchangeProtocolFeeCollectorAddressEventArgs,
ExchangeProtocolFeeMultiplierEventArgs,
} from '@0x/contracts-exchange';
import { artifacts as multisigArtifacts, ZeroExGovernorContract } from '@0x/contracts-multisig';
import {
artifacts as stakingArtifacts,
constants as stakingConstants,
StakingContract,
StakingEvents,
StakingExchangeAddedEventArgs,
StakingProxyContract,
} from '@0x/contracts-staking';
import { blockchainTests, constants, expect, filterLogsToArguments } from '@0x/contracts-test-utils';
import {
AuthorizableAuthorizedAddressAddedEventArgs,
AuthorizableAuthorizedAddressRemovedEventArgs,
AuthorizableEvents,
} from '@0x/contracts-utils';
import { AssetProxyId } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { TxData } from 'ethereum-types';
import { AssetProxyDispatcher, Authorizable, Ownable } from '../wrapper_interfaces';
// tslint:disable:no-unnecessary-type-assertion
blockchainTests('Deployment and Configuration End to End Tests', env => {
// Available Addresses
let owner: string;
// Contract Instances
let governor: ZeroExGovernorContract;
let erc20Proxy: ERC20ProxyContract;
let erc721Proxy: ERC721ProxyContract;
let erc1155Proxy: ERC1155ProxyContract;
let exchange: ExchangeContract;
let multiAssetProxy: MultiAssetProxyContract;
let staking: StakingContract;
let staticCallProxy: StaticCallProxyContract;
let stakingProxy: StakingProxyContract;
let stakingWrapper: StakingContract;
// TxDefaults
let txDefaults: Partial<TxData>;
// ChainId of the Exchange
let chainId: number;
// Protocol Fees
const protocolFeeMultiplier = new BigNumber(150000);
before(async () => {
// Get the chain ID.
chainId = await env.getChainIdAsync();
// Create accounts and tx defaults
[owner] = await env.getAccountAddressesAsync();
txDefaults = {
...env.txDefaults,
from: owner,
};
// Deploy ZeroExGovernor. For the purposes of this test, we will assume that
// the ZeroExGovernor does not know what destinations will be needed during
// construction.
governor = await ZeroExGovernorContract.deployFrom0xArtifactAsync(
multisigArtifacts.ZeroExGovernor,
env.provider,
txDefaults,
multisigArtifacts,
[],
[],
[],
[owner],
new BigNumber(1),
constants.ZERO_AMOUNT,
);
// Deploy Exchange.
exchange = await ExchangeContract.deployFrom0xArtifactAsync(
exchangeArtifacts.Exchange,
env.provider,
txDefaults,
exchangeArtifacts,
new BigNumber(chainId),
);
// Deploy Staking.
staking = await StakingContract.deployFrom0xArtifactAsync(
stakingArtifacts.Staking,
env.provider,
txDefaults,
stakingArtifacts,
);
// Deploy the staking proxy.
stakingProxy = await StakingProxyContract.deployFrom0xArtifactAsync(
stakingArtifacts.StakingProxy,
env.provider,
txDefaults,
stakingArtifacts,
staking.address,
);
// Authorize owner in the staking proxy.
await stakingProxy.addAuthorizedAddress(owner).awaitTransactionSuccessAsync();
// Deploy the asset proxy contracts.
erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync(
assetProxyArtifacts.ERC20Proxy,
env.provider,
txDefaults,
assetProxyArtifacts,
);
erc721Proxy = await ERC721ProxyContract.deployFrom0xArtifactAsync(
assetProxyArtifacts.ERC721Proxy,
env.provider,
txDefaults,
assetProxyArtifacts,
);
erc1155Proxy = await ERC1155ProxyContract.deployFrom0xArtifactAsync(
assetProxyArtifacts.ERC1155Proxy,
env.provider,
txDefaults,
assetProxyArtifacts,
);
multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
assetProxyArtifacts.MultiAssetProxy,
env.provider,
txDefaults,
assetProxyArtifacts,
);
staticCallProxy = await StaticCallProxyContract.deployFrom0xArtifactAsync(
assetProxyArtifacts.StaticCallProxy,
env.provider,
txDefaults,
assetProxyArtifacts,
);
// Set up the staking wrapper so that the entire staking interface can be accessed
// easily through the proxy.
stakingWrapper = new StakingContract(stakingProxy.address, env.provider);
});
describe('deployment and configuration', () => {
describe('exchange specific', () => {
// Registers an asset proxy in the exchange contract and ensure that the correct state changes occurred.
async function registerAssetProxyAndAssertSuccessAsync(
registrationContract: AssetProxyDispatcher,
assetProxyAddress: string,
assetProxyId: string,
): Promise<void> {
// Register the asset proxy.
const receipt = await registrationContract
.registerAssetProxy(assetProxyAddress)
.awaitTransactionSuccessAsync({
from: owner,
});
// Ensure that the correct event was logged.
const logs = filterLogsToArguments<ExchangeAssetProxyRegisteredEventArgs>(
receipt.logs,
ExchangeEvents.AssetProxyRegistered,
);
expect(logs).to.be.deep.eq([{ id: assetProxyId, assetProxy: assetProxyAddress }]);
// Ensure that the asset proxy was actually registered.
const proxyAddress = await registrationContract.getAssetProxy(assetProxyId).callAsync();
expect(proxyAddress).to.be.eq(assetProxyAddress);
}
// Authorizes an address for a given asset proxy using the owner address.
async function authorizeAddressAndAssertSuccessAsync(
authorizable: Authorizable,
newAuthorityAddress: string,
): Promise<void> {
// Authorize the address.
const receipt = await authorizable
.addAuthorizedAddress(newAuthorityAddress)
.awaitTransactionSuccessAsync({ from: owner });
// Ensure that the correct log was emitted.
const logs = filterLogsToArguments<AuthorizableAuthorizedAddressAddedEventArgs>(
receipt.logs,
AuthorizableEvents.AuthorizedAddressAdded,
);
expect(logs).to.be.deep.eq([{ target: newAuthorityAddress, caller: owner }]);
// Ensure that the address was actually authorized.
const wasAuthorized = await authorizable.authorized(newAuthorityAddress).callAsync();
expect(wasAuthorized).to.be.true();
}
it('should successfully register the asset proxies in the exchange', async () => {
// Register the asset proxies in the exchange.
await registerAssetProxyAndAssertSuccessAsync(exchange, erc20Proxy.address, AssetProxyId.ERC20);
await registerAssetProxyAndAssertSuccessAsync(exchange, erc721Proxy.address, AssetProxyId.ERC721);
await registerAssetProxyAndAssertSuccessAsync(exchange, erc1155Proxy.address, AssetProxyId.ERC1155);
await registerAssetProxyAndAssertSuccessAsync(
exchange,
multiAssetProxy.address,
AssetProxyId.MultiAsset,
);
await registerAssetProxyAndAssertSuccessAsync(
exchange,
staticCallProxy.address,
AssetProxyId.StaticCall,
);
});
it('should successfully register the asset proxies in the multi-asset proxy', async () => {
// Register the asset proxies in the multi-asset proxy.
await registerAssetProxyAndAssertSuccessAsync(multiAssetProxy, erc20Proxy.address, AssetProxyId.ERC20);
await registerAssetProxyAndAssertSuccessAsync(
multiAssetProxy,
erc721Proxy.address,
AssetProxyId.ERC721,
);
await registerAssetProxyAndAssertSuccessAsync(
multiAssetProxy,
erc1155Proxy.address,
AssetProxyId.ERC1155,
);
await registerAssetProxyAndAssertSuccessAsync(
multiAssetProxy,
staticCallProxy.address,
AssetProxyId.StaticCall,
);
});
it('should successfully add the exchange as an authority in the appropriate asset proxies', async () => {
// Authorize the exchange in all of the asset proxies, except for the static call proxy.
await authorizeAddressAndAssertSuccessAsync(erc20Proxy, exchange.address);
await authorizeAddressAndAssertSuccessAsync(erc721Proxy, exchange.address);
await authorizeAddressAndAssertSuccessAsync(erc1155Proxy, exchange.address);
await authorizeAddressAndAssertSuccessAsync(multiAssetProxy, exchange.address);
});
it('should successfully add the multi asset proxy as an authority in the appropriate asset proxies', async () => {
// Authorize the multi-asset proxy in the token asset proxies.
await authorizeAddressAndAssertSuccessAsync(erc20Proxy, multiAssetProxy.address);
await authorizeAddressAndAssertSuccessAsync(erc721Proxy, multiAssetProxy.address);
await authorizeAddressAndAssertSuccessAsync(erc1155Proxy, multiAssetProxy.address);
});
});
describe('staking specific', () => {
it('should have properly configured the staking proxy with the logic contract', async () => {
// Ensure that the registered staking contract is correct.
const stakingAddress = await stakingProxy.stakingContract().callAsync();
expect(stakingAddress).to.be.eq(staking.address);
});
it('should have initialized the correct parameters in the staking proxy', async () => {
// Ensure that the correct parameters were set.
const params = await stakingWrapper.getParams().callAsync();
expect(params).to.be.deep.eq([
stakingConstants.DEFAULT_PARAMS.epochDurationInSeconds,
stakingConstants.DEFAULT_PARAMS.rewardDelegatedStakeWeight,
stakingConstants.DEFAULT_PARAMS.minimumPoolStake,
stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaNumerator,
stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaDenominator,
]);
});
});
describe('exchange and staking integration', () => {
it('should successfully register the exchange in the staking contract', async () => {
// Register the exchange.
const receipt = await stakingWrapper.addExchangeAddress(exchange.address).awaitTransactionSuccessAsync({
from: owner,
});
// Ensure that the correct events were logged.
const logs = filterLogsToArguments<StakingExchangeAddedEventArgs>(
receipt.logs,
StakingEvents.ExchangeAdded,
);
expect(logs).to.be.deep.eq([{ exchangeAddress: exchange.address }]);
// Ensure that the exchange was registered.
const wasRegistered = await stakingWrapper.validExchanges(exchange.address).callAsync();
expect(wasRegistered).to.be.true();
});
it('should successfully register the staking contract in the exchange', async () => {
// Register the staking contract.
const receipt = await exchange
.setProtocolFeeCollectorAddress(stakingProxy.address)
.awaitTransactionSuccessAsync({
from: owner,
});
// Ensure that the correct events were logged.
const logs = filterLogsToArguments<ExchangeProtocolFeeCollectorAddressEventArgs>(
receipt.logs,
ExchangeEvents.ProtocolFeeCollectorAddress,
);
expect(logs).to.be.deep.eq([
{
oldProtocolFeeCollector: constants.NULL_ADDRESS,
updatedProtocolFeeCollector: stakingProxy.address,
},
]);
// Ensure that the staking contract was registered.
const feeCollector = await exchange.protocolFeeCollector().callAsync();
expect(feeCollector).to.be.eq(stakingProxy.address);
});
it('should successfully update the protocol fee multiplier in the staking contract', async () => {
// Update the protocol fee multiplier.
const receipt = await exchange
.setProtocolFeeMultiplier(protocolFeeMultiplier)
.awaitTransactionSuccessAsync();
// Ensure that the correct events were logged.
const logs = filterLogsToArguments<ExchangeProtocolFeeMultiplierEventArgs>(
receipt.logs,
ExchangeEvents.ProtocolFeeMultiplier,
);
expect(logs).to.be.deep.eq([
{
oldProtocolFeeMultiplier: constants.ZERO_AMOUNT,
updatedProtocolFeeMultiplier: protocolFeeMultiplier,
},
]);
// Ensure that the protocol fee multiplier was set correctly.
const multiplier = await exchange.protocolFeeMultiplier().callAsync();
expect(multiplier).bignumber.to.be.eq(protocolFeeMultiplier);
});
});
});
describe('transferring ownership', () => {
// Removes authorization of the "externally owned address" owner and transfers the authorization
// to the asset proxy owner.
async function transferAuthorizationAndAssertSuccessAsync(contract: Authorizable): Promise<void> {
// Remove authorization from the old owner.
let receipt = await contract.removeAuthorizedAddress(owner).awaitTransactionSuccessAsync({ from: owner });
// Ensure that the correct log was recorded.
let logs = filterLogsToArguments<AuthorizableAuthorizedAddressRemovedEventArgs>(
receipt.logs,
AuthorizableEvents.AuthorizedAddressRemoved,
);
expect(logs).to.be.deep.eq([{ target: owner, caller: owner }]);
// Ensure that the owner was actually removed.
let isAuthorized = await contract.authorized(owner).callAsync();
expect(isAuthorized).to.be.false();
// Authorize the asset-proxy owner.
receipt = await contract.addAuthorizedAddress(governor.address).awaitTransactionSuccessAsync({
from: owner,
});
// Ensure that the correct log was recorded.
logs = filterLogsToArguments<AuthorizableAuthorizedAddressAddedEventArgs>(
receipt.logs,
AuthorizableEvents.AuthorizedAddressAdded,
);
expect(logs).to.be.deep.eq([{ target: governor.address, caller: owner }]);
// Ensure that the asset-proxy owner was actually authorized.
isAuthorized = await contract.authorized(governor.address).callAsync();
expect(isAuthorized).to.be.true();
}
// Transfers ownership of a contract to the asset-proxy owner, and ensures that the change was actually made.
async function transferOwnershipAndAssertSuccessAsync(contract: Ownable): Promise<void> {
// Transfer ownership to the new owner.
await contract.transferOwnership(governor.address).awaitTransactionSuccessAsync({ from: owner });
// Ensure that the owner address has been updated.
const ownerAddress = await contract.owner().callAsync();
expect(ownerAddress).to.be.eq(governor.address);
}
it('should transfer authorization of the owner to the asset-proxy owner in the staking contracts', async () => {
// Transfer authorization of the staking system. We intentionally neglect
// to add the asset-proxy owner as an authorized address in the asset proxies
// as a security precaution.
await transferAuthorizationAndAssertSuccessAsync(stakingProxy);
});
it('should transfer ownership of all appropriate contracts to the asset-proxy owner', async () => {
// Transfer ownership of most contracts (we exclude contracts that are not ownable).
await transferOwnershipAndAssertSuccessAsync(exchange);
await transferOwnershipAndAssertSuccessAsync(staking);
await transferOwnershipAndAssertSuccessAsync(stakingProxy);
await transferOwnershipAndAssertSuccessAsync(erc20Proxy);
await transferOwnershipAndAssertSuccessAsync(erc721Proxy);
await transferOwnershipAndAssertSuccessAsync(erc1155Proxy);
await transferOwnershipAndAssertSuccessAsync(multiAssetProxy);
});
});
});
// tslint:enable:no-unnecessary-type-assertion