@0x:contracts-integration-tests Added an integration-tests package and a deployment manager class

This commit is contained in:
Alex Towle
2019-10-03 16:06:29 -07:00
parent ccf40fd65e
commit 24e4567b25
17 changed files with 938 additions and 14 deletions

2
.gitignore vendored
View File

@@ -82,6 +82,7 @@ TODO.md
packages/testnet-faucets/server/
# generated contract artifacts/
contracts/integration-tests/generated-artifacts/
contracts/staking/generated-artifacts/
contracts/coordinator/generated-artifacts/
contracts/exchange/generated-artifacts/
@@ -115,6 +116,7 @@ contracts/dev-utils/build/
# generated contract wrappers
packages/python-contract-wrappers/generated/
contracts/integration-tests/generated-wrappers/
contracts/staking/generated-wrappers/
contracts/coordinator/generated-wrappers/
contracts/exchange/generated-wrappers/

View File

@@ -1,5 +1,7 @@
lib
.nyc_output
/contracts/integration-tests/generated-wrappers
/contracts/integration-tests/generated-artifacts
/contracts/staking/generated-wrappers
/contracts/staking/generated-artifacts
/contracts/coordinator/generated-wrappers

View File

@@ -36,6 +36,9 @@ export interface Authorizable extends Ownable {
authorized: {
callAsync(authority: string, callData?: Partial<CallData>, defaultBlock?: BlockParam): Promise<boolean>;
};
getAuthorizedAddresses: {
callAsync(callData?: Partial<CallData>, defaultBlock?: BlockParam): Promise<string[]>;
};
}
export interface Ownable {

View File

@@ -0,0 +1,15 @@
[
{
"version": "1.0.0",
"changes": [
{
"note": "Created package",
"pr": "2240"
},
{
"note": "Added the deployment manager class",
"pr": "2240"
}
]
}
]

View File

@@ -0,0 +1,65 @@
## Integration Tests
This package implements integration tests against 0x's smart contracts and will provide a location for external contracts to be tested alongside the 0x smart contracts.
## Installation
**Install**
```bash
npm install @0x/contracts-staking --save
```
## Contributing
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
For proposals regarding the 0x protocol's smart contract architecture, message format, or additional functionality, go to the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository and follow the contribution guidelines provided therein.
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
### Install Dependencies
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
```bash
yarn config set workspaces-experimental true
```
Then install dependencies
```bash
yarn install
```
### Build
To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
```bash
PKG=@0x/contracts-integration-tests yarn build
```
Or continuously rebuild on change:
```bash
PKG=@0x/contracts-integration-tests yarn watch
```
### Clean
```bash
yarn clean
```
### Lint
```bash
yarn lint
```
### Run Tests
```bash
yarn test
```

View File

@@ -0,0 +1,26 @@
{
"artifactsDir": "./generated-artifacts",
"contractsDir": "./contracts",
"useDockerisedSolc": false,
"isOfflineMode": false,
"compilerSettings": {
"evmVersion": "constantinople",
"optimizer": {
"enabled": true,
"runs": 1000000,
"details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true }
},
"outputSelection": {
"*": {
"*": [
"abi",
"devdoc",
"evm.bytecode.object",
"evm.bytecode.sourceMap",
"evm.deployedBytecode.object",
"evm.deployedBytecode.sourceMap"
]
}
}
}
}

View File

@@ -0,0 +1,7 @@
pragma solidity ^0.5.0;
// TODO(jalextowle): This contract must be included to ensure that `abi-gen`
// doesn't fail to run. Remove this contract or remove the contracts directory
// depending on whether or not this package should contain packages.
contract Empty { } // solhint-disable-line no-empty-blocks

View File

@@ -0,0 +1,53 @@
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-staking/contracts/src/Staking.sol";
contract StakingWithTokens is
Staking
{
address public wethAddress;
address public zrxVault;
bytes4 internal constant WETH_PROXY_ID = 0xf47261b0;
function setWethAddress(address weth)
public
{
wethAddress = weth;
}
function setZrxVault(address vault)
public
{
zrxVault = vault;
}
function getWethAssetData()
public
view
returns (bytes memory)
{
return abi.encodeWithSelector(
WETH_PROXY_ID,
wethAddress
);
}
function getWethContract()
public
view
returns (IEtherToken)
{
return IEtherToken(wethAddress);
}
function getZrxVault()
public
view
returns (IZrxVault)
{
return IZrxVault(zrxVault);
}
}

View File

@@ -0,0 +1,99 @@
{
"name": "@0x/contracts-integration-tests",
"version": "1.0.0",
"engines": {
"node": ">=6.12"
},
"description": "Integration tests for the 0x protocol",
"main": "lib/src/index.js",
"directories": {
"test": "test"
},
"scripts": {
"build": "yarn pre_build && tsc -b",
"build:ci": "yarn build",
"pre_build": "run-s compile contracts:gen generate_contract_wrappers",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s build test",
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
"test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html",
"test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
"compile": "sol-compiler",
"watch": "sol-compiler -w",
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers",
"lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
"fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
"coverage:report:text": "istanbul report text",
"coverage:report:html": "istanbul report html && open coverage/index.html",
"profiler:report:html": "istanbul report html && open coverage/index.html",
"coverage:report:lcov": "istanbul report lcov",
"test:circleci": "yarn test",
"contracts:gen": "contracts-gen",
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol",
"compile:truffle": "truffle compile"
},
"config": {
"abis": "./generated-artifacts/@(StakingWithTokens).json",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
},
"repository": {
"type": "git",
"url": "https://github.com/0xProject/0x-monorepo.git"
},
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/0xProject/0x-monorepo/issues"
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
"devDependencies": {
"@0x/abi-gen": "^4.3.0-beta.0",
"@0x/contracts-gen": "^1.1.0-beta.0",
"@0x/dev-utils": "^2.4.0-beta.0",
"@0x/sol-compiler": "^3.2.0-beta.0",
"@0x/tslint-config": "^3.0.1",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"solhint": "^1.4.1",
"truffle": "^5.0.32",
"tslint": "5.11.0",
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^5.5.0-beta.0",
"@0x/contracts-asset-proxy": "^2.3.0-beta.0",
"@0x/contracts-coordinator": "^2.1.0-beta.0",
"@0x/contracts-dev-utils": "^0.1.0-beta.0",
"@0x/contracts-erc1155": "^1.2.0-beta.0",
"@0x/contracts-erc20": "^2.3.0-beta.0",
"@0x/contracts-erc721": "^2.2.0-beta.0",
"@0x/contracts-exchange": "^2.2.0-beta.0",
"@0x/contracts-exchange-forwarder": "^3.1.0-beta.0",
"@0x/contracts-exchange-libs": "^3.1.0-beta.0",
"@0x/contracts-extensions": "^4.1.0-beta.0",
"@0x/contracts-multisig": "^3.2.0-beta.0",
"@0x/contracts-staking": "^1.1.0-beta.0",
"@0x/contracts-test-utils": "^3.2.0-beta.0",
"@0x/contracts-utils": "^3.3.0-beta.0",
"@0x/order-utils": "^8.5.0-beta.0",
"@0x/types": "^2.5.0-beta.0",
"@0x/typescript-typings": "^4.4.0-beta.0",
"@0x/utils": "^4.6.0-beta.0",
"@0x/web3-wrapper": "^6.1.0-beta.0",
"ethereum-types": "^2.2.0-beta.0",
"lodash": "^4.17.11"
},
"publishConfig": {
"access": "public"
}
}

View File

@@ -0,0 +1,9 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
import { ContractArtifact } from 'ethereum-types';
import * as StakingWithTokens from '../generated-artifacts/StakingWithTokens.json';
export const artifacts = { StakingWithTokens: StakingWithTokens as ContractArtifact };

View File

@@ -0,0 +1,453 @@
import {
artifacts as assetProxyArtifacts,
ERC1155ProxyContract,
ERC20ProxyContract,
ERC721ProxyContract,
MultiAssetProxyContract,
StaticCallProxyContract,
} from '@0x/contracts-asset-proxy';
import { artifacts as ERC1155Artifacts, ERC1155Contract } from '@0x/contracts-erc1155';
import { artifacts as ERC20Artifacts, ERC20TokenContract, ZRXTokenContract, WETH9Contract } from '@0x/contracts-erc20';
import { artifacts as ERC721Artifacts, ERC721TokenContract } from '@0x/contracts-erc721';
import {
artifacts as exchangeArtifacts,
AssetProxyDispatcher,
Authorizable,
ExchangeContract,
Ownable,
} from '@0x/contracts-exchange';
import { artifacts as multisigArtifacts, AssetProxyOwnerContract } from '@0x/contracts-multisig';
import {
artifacts as stakingArtifacts,
ReadOnlyProxyContract,
StakingContract,
StakingProxyContract,
ZrxVaultContract,
} from '@0x/contracts-staking';
import { BlockchainTestsEnvironment, constants } from '@0x/contracts-test-utils';
import { Web3ProviderEngine } from '@0x/subproviders';
import { BigNumber } from '@0x/utils';
import { TxData } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts, StakingWithTokensContract } from './';
/**
* Adds a batch of authorities to a list of authorizable contracts.
* @param owner The owner of the authorizable contracts.
* @param authorizers The authorizable contracts.
* @param authorities A list of addresses to authorize in each authorizer contract.
*/
async function batchAddAuthorizedAddressAsync(
owner: string,
authorizers: Authorizable[],
authorities: string[],
): Promise<void> {
for (const authorizer of authorizers) {
for (const authority of authorities) {
await authorizer.addAuthorizedAddress.awaitTransactionSuccessAsync(authority, { from: owner });
}
}
}
/**
* Batch registers asset proxies in a list of registry contracts.
* @param owner The owner of the registry accounts.
* @param registries The registries that the asset proxies should be registered in.
* @param proxies A list of proxy contracts to register.
*/
async function batchRegisterAssetProxyAsync(
owner: string,
registries: AssetProxyDispatcher[],
proxies: string[],
): Promise<void> {
for (const registry of registries) {
for (const proxy of proxies) {
await registry.registerAssetProxy.awaitTransactionSuccessAsync(proxy, { from: owner });
}
}
}
/**
* Transfers ownership of several contracts from one address to another.
* @param owner The address that currently owns the contract instances.
* @param newOwner The address that will be given ownership of the contract instances.
* @param ownedContracts The contracts whose ownership will be transferred.
*/
async function batchTransferOwnershipAsync(
owner: string,
newOwner: AssetProxyOwnerContract,
ownedContracts: Ownable[],
): Promise<void> {
for (const ownedContract of ownedContracts) {
await ownedContract.transferOwnership.awaitTransactionSuccessAsync(newOwner.address, { from: owner });
}
}
// Contract wrappers for all of the asset proxies
interface AssetProxyContracts {
erc20Proxy: ERC20ProxyContract;
erc721Proxy: ERC721ProxyContract;
erc1155Proxy: ERC1155ProxyContract;
multiAssetProxy: MultiAssetProxyContract;
staticCallProxy: StaticCallProxyContract;
}
// Contract wrappers for all of the staking contracts
interface StakingContracts {
readOnlyProxy: ReadOnlyProxyContract;
stakingLogic: StakingWithTokensContract;
stakingProxy: StakingProxyContract;
stakingWrapper: StakingWithTokensContract;
zrxVault: ZrxVaultContract;
}
// Contract wrappers for tokens.
interface TokenContracts {
erc1155: ERC1155Contract;
erc20: ERC20TokenContract;
erc721: ERC721TokenContract;
weth: WETH9Contract;
zrx: ZRXTokenContract;
}
export class DeploymentManager {
public static protocolFeeMultiplier = new BigNumber(150000);
public assetProxies: AssetProxyContracts;
public assetProxyOwner: AssetProxyOwnerContract;
public exchange: ExchangeContract;
public staking: StakingContracts;
public tokens: TokenContracts;
/**
* Fully deploy the 0x exchange and staking contracts and configure the system with the
* asset proxy owner multisig.
* @param environment A blockchain test environment to use for contracts deployment.
*/
public static async deployAsync(environment: BlockchainTestsEnvironment): Promise<DeploymentManager> {
const chainId = await environment.getChainIdAsync();
const [owner] = await environment.getAccountAddressesAsync();
const txDefaults = {
...environment.txDefaults,
from: owner,
};
// Deploy the contracts using the same owner and environment.
const assetProxies = await DeploymentManager._deployAssetProxyContractsAsync(environment, owner, txDefaults);
const exchange = await ExchangeContract.deployFrom0xArtifactAsync(
exchangeArtifacts.Exchange,
environment.provider,
environment.txDefaults,
exchangeArtifacts,
new BigNumber(chainId),
);
const assetProxyOwner = await AssetProxyOwnerContract.deployFrom0xArtifactAsync(
multisigArtifacts.AssetProxyOwner,
environment.provider,
txDefaults,
multisigArtifacts,
[],
[],
[],
[owner],
new BigNumber(1),
constants.ZERO_AMOUNT,
);
const tokens = await DeploymentManager._deployTokenContractsAsync(environment, txDefaults);
const staking = await DeploymentManager._deployStakingContractsAsync(
environment,
owner,
txDefaults,
tokens,
assetProxies,
);
// Configure the asset proxies with the exchange and the exchange with the staking contracts.
await DeploymentManager._configureAssetProxiesWithExchangeAsync(assetProxies, exchange, owner);
await DeploymentManager._configureExchangeWithStakingAsync(exchange, staking, owner);
// Authorize the asset-proxy owner in the staking proxy and in the zrx vault.
await staking.stakingProxy.addAuthorizedAddress.awaitTransactionSuccessAsync(assetProxyOwner.address, {
from: owner,
});
await staking.zrxVault.addAuthorizedAddress.awaitTransactionSuccessAsync(assetProxyOwner.address, {
from: owner,
});
// Remove authorization for the original owner address.
await staking.stakingProxy.removeAuthorizedAddress.awaitTransactionSuccessAsync(owner, { from: owner });
await staking.zrxVault.removeAuthorizedAddress.awaitTransactionSuccessAsync(owner, { from: owner });
// Transfer complete ownership of the system to the asset proxy owner.
await batchTransferOwnershipAsync(owner, assetProxyOwner, [
assetProxies.erc20Proxy,
assetProxies.erc721Proxy,
assetProxies.erc1155Proxy,
assetProxies.multiAssetProxy,
exchange,
staking.readOnlyProxy,
staking.stakingProxy,
]);
return new DeploymentManager(assetProxies, assetProxyOwner, exchange, staking, tokens);
}
/**
* Configures a set of asset proxies with an exchange contract.
* @param assetProxies A set of asset proxies to be configured.
* @param exchange An exchange contract to configure with the asset proxies.
* @param owner An owner address to use when configuring the asset proxies.
*/
protected static async _configureAssetProxiesWithExchangeAsync(
assetProxies: AssetProxyContracts,
exchange: ExchangeContract,
owner: string,
): Promise<void> {
// Register the asset proxies in the exchange contract.
await batchRegisterAssetProxyAsync(
owner,
[exchange],
[
assetProxies.erc20Proxy.address,
assetProxies.erc721Proxy.address,
assetProxies.erc1155Proxy.address,
assetProxies.multiAssetProxy.address,
assetProxies.staticCallProxy.address,
],
);
// Register the asset proxies in the multi-asset proxy.
await batchRegisterAssetProxyAsync(
owner,
[assetProxies.multiAssetProxy],
[
assetProxies.erc20Proxy.address,
assetProxies.erc721Proxy.address,
assetProxies.erc1155Proxy.address,
assetProxies.staticCallProxy.address,
],
);
// Add the multi-asset proxy as an authorized address of the token proxies.
await batchAddAuthorizedAddressAsync(
owner,
[assetProxies.erc20Proxy, assetProxies.erc721Proxy, assetProxies.erc1155Proxy],
[assetProxies.multiAssetProxy.address],
);
// Add the exchange as an authorized address in all of the proxies.
await batchAddAuthorizedAddressAsync(
owner,
[
assetProxies.erc20Proxy,
assetProxies.erc721Proxy,
assetProxies.erc1155Proxy,
assetProxies.multiAssetProxy,
],
[exchange.address],
);
}
/**
* Configures an exchange contract with staking contracts
* @param exchange
* @param staking
* @param owner An owner address to use when configuring the asset proxies.
*/
protected static async _configureExchangeWithStakingAsync(
exchange: ExchangeContract,
staking: StakingContracts,
owner: string,
): Promise<void> {
// Configure the exchange for staking.
await exchange.setProtocolFeeCollectorAddress.awaitTransactionSuccessAsync(staking.stakingProxy.address, {
from: owner,
});
await exchange.setProtocolFeeMultiplier.awaitTransactionSuccessAsync(DeploymentManager.protocolFeeMultiplier);
// Register the exchange contract in staking.
await staking.stakingWrapper.addExchangeAddress.awaitTransactionSuccessAsync(exchange.address, { from: owner });
}
/**
* Deploy a set of asset proxy contracts.
* @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.
*/
protected static async _deployAssetProxyContractsAsync(
environment: BlockchainTestsEnvironment,
owner: string,
txDefaults: Partial<TxData>,
): Promise<AssetProxyContracts> {
const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync(
assetProxyArtifacts.ERC20Proxy,
environment.provider,
txDefaults,
assetProxyArtifacts,
);
const erc721Proxy = await ERC721ProxyContract.deployFrom0xArtifactAsync(
assetProxyArtifacts.ERC721Proxy,
environment.provider,
txDefaults,
assetProxyArtifacts,
);
const erc1155Proxy = await ERC1155ProxyContract.deployFrom0xArtifactAsync(
assetProxyArtifacts.ERC1155Proxy,
environment.provider,
txDefaults,
assetProxyArtifacts,
);
const multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
assetProxyArtifacts.MultiAssetProxy,
environment.provider,
txDefaults,
assetProxyArtifacts,
);
const staticCallProxy = await StaticCallProxyContract.deployFrom0xArtifactAsync(
assetProxyArtifacts.StaticCallProxy,
environment.provider,
txDefaults,
assetProxyArtifacts,
);
return {
erc20Proxy,
erc721Proxy,
erc1155Proxy,
multiAssetProxy,
staticCallProxy,
};
}
/**
* Deploy a set of staking contracts.
* @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 tokens A set of token contracts to use during deployment of the staking contracts.
* @param assetProxies A set of asset proxies to use with the staking contracts.
*/
protected static async _deployStakingContractsAsync(
environment: BlockchainTestsEnvironment,
owner: string,
txDefaults: Partial<TxData>,
tokens: TokenContracts,
assetProxies: AssetProxyContracts,
): Promise<StakingContracts> {
const zrxVault = await ZrxVaultContract.deployFrom0xArtifactAsync(
stakingArtifacts.ZrxVault,
environment.provider,
txDefaults,
stakingArtifacts,
assetProxies.erc20Proxy.address,
tokens.zrx.address,
);
const readOnlyProxy = await ReadOnlyProxyContract.deployFrom0xArtifactAsync(
stakingArtifacts.ReadOnlyProxy,
environment.provider,
txDefaults,
stakingArtifacts,
);
const stakingLogic = await StakingWithTokensContract.deployFrom0xArtifactAsync(
artifacts.StakingWithTokens,
environment.provider,
txDefaults,
stakingArtifacts,
);
const stakingProxy = await StakingProxyContract.deployFrom0xArtifactAsync(
stakingArtifacts.StakingProxy,
environment.provider,
txDefaults,
stakingArtifacts,
stakingLogic.address,
readOnlyProxy.address,
);
const stakingWrapper = new StakingWithTokensContract(stakingProxy.address, environment.provider);
// Authorize the owner address in the staking proxy and the zrx vault.
await stakingProxy.addAuthorizedAddress.awaitTransactionSuccessAsync(owner, { from: owner });
await zrxVault.addAuthorizedAddress.awaitTransactionSuccessAsync(owner, { from: owner });
// Configure the zrx vault and the staking contract.
await zrxVault.setStakingProxy.awaitTransactionSuccessAsync(stakingProxy.address, { from: owner });
await zrxVault.setStakingProxy.awaitTransactionSuccessAsync(stakingProxy.address, { from: owner });
await stakingWrapper.setZrxVault.awaitTransactionSuccessAsync(zrxVault.address, { from: owner });
await stakingWrapper.setWethAddress.awaitTransactionSuccessAsync(tokens.weth.address, { from: owner });
return {
readOnlyProxy,
stakingLogic,
stakingProxy,
stakingWrapper,
zrxVault,
};
}
/**
* Deploy a set of token contracts.
* @param environment The blockchain environment to use.
* @param txDefaults Defaults to use when deploying the asset proxies.
*/
protected static async _deployTokenContractsAsync(
environment: BlockchainTestsEnvironment,
txDefaults: Partial<TxData>,
): Promise<TokenContracts> {
const erc20 = await ERC20TokenContract.deployFrom0xArtifactAsync(
ERC20Artifacts.ERC20Token,
environment.provider,
txDefaults,
ERC20Artifacts,
);
const erc721 = await ERC721TokenContract.deployFrom0xArtifactAsync(
ERC721Artifacts.ERC721Token,
environment.provider,
txDefaults,
ERC721Artifacts,
);
const erc1155 = await ERC1155Contract.deployFrom0xArtifactAsync(
ERC1155Artifacts.ERC1155,
environment.provider,
txDefaults,
ERC1155Artifacts,
);
const weth = await WETH9Contract.deployFrom0xArtifactAsync(
ERC20Artifacts.WETH9,
environment.provider,
txDefaults,
ERC20Artifacts,
);
const zrx = await ZRXTokenContract.deployFrom0xArtifactAsync(
ERC20Artifacts.ZRXToken,
environment.provider,
txDefaults,
ERC20Artifacts,
);
return {
erc1155,
erc20,
erc721,
weth,
zrx,
};
}
private constructor(
assetProxies: AssetProxyContracts,
assetProxyOwner: AssetProxyOwnerContract,
exchange: ExchangeContract,
staking: StakingContracts,
tokens: TokenContracts,
) {
this.assetProxies = assetProxies;
this.assetProxyOwner = assetProxyOwner;
this.exchange = exchange;
this.staking = staking;
this.tokens = tokens;
}
}

View File

@@ -0,0 +1,3 @@
export * from './artifacts';
export * from './wrappers';
export * from './deployment_mananger';

View File

@@ -0,0 +1,6 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../generated-wrappers/staking_with_tokens';

View File

@@ -0,0 +1,176 @@
import { Authorizable, Ownable } from '@0x/contracts-exchange';
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
import { DeploymentManager } from '../src';
blockchainTests('Deployment Manager', env => {
let owner: string;
let deploymentManager: DeploymentManager;
before(async () => {
[owner] = await env.getAccountAddressesAsync();
deploymentManager = await DeploymentManager.deployAsync(env);
});
async function batchAssertAuthoritiesAsync(
authorities: string[],
authorizedContracts: Authorizable[],
): Promise<void> {
for (const authorized of authorizedContracts) {
expect(await authorized.getAuthorizedAddresses.callAsync()).to.be.deep.eq(authorities);
}
}
async function batchAssertAuthorizedAsync(
authorizedAddress: string,
authorizedContracts: Authorizable[],
): Promise<void> {
for (const authorized of authorizedContracts) {
expect(await authorized.authorized.callAsync(authorizedAddress)).to.be.true();
}
}
async function batchAssertOwnerAsync(ownerAddress: string, owners: Ownable[]): Promise<void> {
for (const ownerContract of owners) {
expect(await ownerContract.owner.callAsync()).to.be.eq(ownerAddress);
}
}
describe('asset proxy owner', () => {
it('should be owned by `owner`', async () => {
// Ensure that the owners of the asset proxy only contain the owner.
const owners = await deploymentManager.assetProxyOwner.getOwners.callAsync();
expect(owners).to.be.deep.eq([owner]);
});
});
describe('asset proxies', () => {
it('should be owned be the asset proxy owner', async () => {
await batchAssertOwnerAsync(deploymentManager.assetProxyOwner.address, [
deploymentManager.assetProxies.erc1155Proxy,
deploymentManager.assetProxies.erc20Proxy,
deploymentManager.assetProxies.erc721Proxy,
deploymentManager.assetProxies.multiAssetProxy,
]);
});
it('should have authorized the multi-asset proxy', async () => {
await batchAssertAuthorizedAsync(deploymentManager.assetProxies.multiAssetProxy.address, [
deploymentManager.assetProxies.erc1155Proxy,
deploymentManager.assetProxies.erc20Proxy,
deploymentManager.assetProxies.erc721Proxy,
]);
});
it('should have authorized the exchange', async () => {
await batchAssertAuthorizedAsync(deploymentManager.exchange.address, [
deploymentManager.assetProxies.erc1155Proxy,
deploymentManager.assetProxies.erc20Proxy,
deploymentManager.assetProxies.erc721Proxy,
deploymentManager.assetProxies.multiAssetProxy,
]);
});
it('should have the correct authorities list', async () => {
// The multi-asset proxy should only have the exchange in the authorities list.
const authorities = await deploymentManager.assetProxies.multiAssetProxy.getAuthorizedAddresses.callAsync();
expect(authorities).to.be.deep.eq([deploymentManager.exchange.address]);
// The other asset proxies should have the exchange and the multi-asset proxy in their
// authorities list.
await batchAssertAuthoritiesAsync(
[deploymentManager.assetProxies.multiAssetProxy.address, deploymentManager.exchange.address],
[
deploymentManager.assetProxies.erc1155Proxy,
deploymentManager.assetProxies.erc20Proxy,
deploymentManager.assetProxies.erc721Proxy,
],
);
});
});
describe('exchange', () => {
it('should be owned by the asset proxy owner', async () => {
const exchangeOwner = await deploymentManager.exchange.owner.callAsync();
expect(exchangeOwner).to.be.eq(deploymentManager.assetProxyOwner.address);
});
/*
TODO(jalextowle): This test should be enabled once the Exchange is
made an Authorizable contract.
it('should have authorized the asset proxy owner', async () => {
const isAuthorized = await deploymentManager.exchange.owner.callAsync(
deploymentManager.assetProxyOwner.address,
);
expect(isAuthorized).to.be.true();
});
*/
it('should have registered the staking proxy', async () => {
const feeCollector = await deploymentManager.exchange.protocolFeeCollector.callAsync();
expect(feeCollector).to.be.eq(deploymentManager.staking.stakingProxy.address);
});
it('should have set the protocol fee multiplier', async () => {
const feeMultiplier = await deploymentManager.exchange.protocolFeeMultiplier.callAsync();
expect(feeMultiplier).bignumber.to.be.eq(DeploymentManager.protocolFeeMultiplier);
});
});
describe('staking', () => {
it('should be owned by the asset proxy owner', async () => {
const stakingOwner = await deploymentManager.staking.stakingProxy.owner.callAsync();
expect(stakingOwner).to.be.eq(deploymentManager.assetProxyOwner.address);
});
it('should have authorized the asset proxy owner in the staking proxy', async () => {
const isAuthorized = await deploymentManager.staking.stakingProxy.authorized.callAsync(
deploymentManager.assetProxyOwner.address,
);
expect(isAuthorized).to.be.true();
});
it('should have registered the exchange in the staking proxy', async () => {
const isValid = await deploymentManager.staking.stakingProxy.validExchanges.callAsync(
deploymentManager.exchange.address,
);
expect(isValid).to.be.true();
});
it('should have registered the read-only proxy in the staking proxy', async () => {
const readOnlyProxy = await deploymentManager.staking.stakingProxy.readOnlyProxy.callAsync();
expect(readOnlyProxy).to.be.eq(deploymentManager.staking.readOnlyProxy.address);
});
it('should have registered the staking contract in the staking proxy', async () => {
const stakingContract = await deploymentManager.staking.stakingProxy.stakingContract.callAsync();
expect(stakingContract).to.be.eq(deploymentManager.staking.stakingLogic.address);
});
it('should have registered the weth contract in the staking contract', async () => {
const weth = await deploymentManager.staking.stakingWrapper.wethAddress.callAsync();
expect(weth).to.be.eq(deploymentManager.tokens.weth.address);
});
it('should have registered the zrx vault in the staking contract', async () => {
const zrxVault = await deploymentManager.staking.stakingWrapper.zrxVault.callAsync();
expect(zrxVault).to.be.eq(deploymentManager.staking.zrxVault.address);
});
it('should have registered the staking proxy in the zrx vault', async () => {
const stakingProxy = await deploymentManager.staking.zrxVault.stakingProxyAddress.callAsync();
expect(stakingProxy).to.be.eq(deploymentManager.staking.stakingProxy.address);
});
it('should have correctly set the params', async () => {
const params = await deploymentManager.staking.stakingWrapper.getParams.callAsync();
expect(params).to.be.deep.eq(
[10 * 60 * 60 * 24, (90 * constants.PPM_DENOMINATOR) / 100, 100 * 1e18, 10, 1, 2].map(
value => new BigNumber(value),
),
);
});
});
});

View File

@@ -6,6 +6,17 @@ import {
MultiAssetProxyContract,
StaticCallProxyContract,
} from '@0x/contracts-asset-proxy';
import {
artifacts as exchangeArtifacts,
AssetProxyDispatcher,
Authorizable,
ExchangeAssetProxyRegisteredEventArgs,
ExchangeContract,
ExchangeEvents,
ExchangeProtocolFeeCollectorAddressEventArgs,
ExchangeProtocolFeeMultiplierEventArgs,
Ownable,
} from '@0x/contracts-exchange';
import { artifacts as multisigArtifacts, AssetProxyOwnerContract } from '@0x/contracts-multisig';
import {
artifacts as stakingArtifacts,
@@ -25,18 +36,6 @@ import { AssetProxyId } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { TxData } from 'ethereum-types';
import {
artifacts as exchangeArtifacts,
AssetProxyDispatcher,
Authorizable,
ExchangeAssetProxyRegisteredEventArgs,
ExchangeContract,
ExchangeEvents,
ExchangeProtocolFeeCollectorAddressEventArgs,
ExchangeProtocolFeeMultiplierEventArgs,
Ownable,
} from '../../src';
// tslint:disable:no-unnecessary-type-assertion
blockchainTests('Deployment and Configuration End to End Tests', env => {
// Available Addresses

View File

@@ -0,0 +1,6 @@
{
"extends": "../../tsconfig",
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
"files": ["generated-artifacts/StakingWithTokens.json"]
}

View File

@@ -46,7 +46,7 @@ contract AssetProxyOwner is
mapping (bytes4 => mapping (address => TimeLock)) public functionCallTimeLocks;
/// @dev Contract constructor sets initial owners, required number of confirmations, and default time lock
/// It will also register unique timelocks for each passed in function selector / destination combo.
/// It will also register unique timelocks for each passed in function selector / destination combo.
/// @param _functionSelectors Array of function selectors for registered functions.
/// @param _destinations Array of destinations for registered function calls.
/// @param _functionCallTimeLockSeconds Array of seconds that each registered function call will be timelocked.
@@ -170,7 +170,7 @@ contract AssetProxyOwner is
bool hasCustomTimeLock,
bytes4 functionSelector,
address destination,
uint128 newSecondsTimeLocked
uint128 newSecondsTimeLocked
)
internal
{