@0x:contracts-integration-tests Added an integration-tests package and a deployment manager class
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -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/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
15
contracts/integration-tests/CHANGELOG.json
Normal file
15
contracts/integration-tests/CHANGELOG.json
Normal file
@@ -0,0 +1,15 @@
|
||||
[
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Created package",
|
||||
"pr": "2240"
|
||||
},
|
||||
{
|
||||
"note": "Added the deployment manager class",
|
||||
"pr": "2240"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
65
contracts/integration-tests/README.md
Normal file
65
contracts/integration-tests/README.md
Normal 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
|
||||
```
|
||||
26
contracts/integration-tests/compiler.json
Normal file
26
contracts/integration-tests/compiler.json
Normal 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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
contracts/integration-tests/contracts/Empty.sol
Normal file
7
contracts/integration-tests/contracts/Empty.sol
Normal 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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
99
contracts/integration-tests/package.json
Normal file
99
contracts/integration-tests/package.json
Normal 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"
|
||||
}
|
||||
}
|
||||
9
contracts/integration-tests/src/artifacts.ts
Normal file
9
contracts/integration-tests/src/artifacts.ts
Normal 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 };
|
||||
453
contracts/integration-tests/src/deployment_mananger.ts
Normal file
453
contracts/integration-tests/src/deployment_mananger.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
3
contracts/integration-tests/src/index.ts
Normal file
3
contracts/integration-tests/src/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './artifacts';
|
||||
export * from './wrappers';
|
||||
export * from './deployment_mananger';
|
||||
6
contracts/integration-tests/src/wrappers.ts
Normal file
6
contracts/integration-tests/src/wrappers.ts
Normal 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';
|
||||
176
contracts/integration-tests/test/deployment_manager_test.ts
Normal file
176
contracts/integration-tests/test/deployment_manager_test.ts
Normal 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),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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
|
||||
6
contracts/integration-tests/tsconfig.json
Normal file
6
contracts/integration-tests/tsconfig.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
|
||||
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
||||
"files": ["generated-artifacts/StakingWithTokens.json"]
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user