* 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
		
			
				
	
	
		
			413 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			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
 |