Merge pull request #574 from 0xProject/feature/rm-rf-deployer

Remove @0xproject/deployer.Deployer. Make contracts able to deploy themselves
This commit is contained in:
Leonid Logvinov
2018-05-11 12:12:39 +02:00
committed by GitHub
129 changed files with 891 additions and 1207 deletions

View File

@@ -70,7 +70,7 @@ jobs:
key: coverage-contracts-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/contracts/coverage/lcov.info
test-deployer:
test-sol-compiler:
docker:
- image: circleci/node:6.12
working_directory: ~/repo
@@ -82,11 +82,11 @@ jobs:
name: testrpc
command: npm run testrpc -- --db testrpc_snapshot
background: true
- run: yarn lerna:run --scope @0xproject/deployer test:circleci
- run: yarn lerna:run --scope @0xproject/sol-compiler test:circleci
- save_cache:
key: coverage-deployer-{{ .Environment.CIRCLE_SHA1 }}
key: coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/deployer/coverage/lcov.info
- ~/repo/packages/sol-compiler/coverage/lcov.info
test-rest:
docker:
- image: circleci/node:6.12
@@ -99,7 +99,7 @@ jobs:
name: testrpc
command: npm run testrpc -- --db testrpc_snapshot
background: true
- run: yarn lerna:run --ignore contracts --ignore 0x.js --ignore @0xproject/deployer test:circleci
- run: yarn lerna:run --ignore contracts --ignore 0x.js --ignore @0xproject/sol-compiler test:circleci
- save_cache:
key: coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
paths:
@@ -177,7 +177,7 @@ jobs:
- coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-deployer-{{ .Environment.CIRCLE_SHA1 }}
- coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
@@ -199,7 +199,7 @@ workflows:
- test-contracts:
requires:
- build
- test-deployer:
- test-sol-compiler:
requires:
- build
- test-rest:
@@ -214,6 +214,6 @@ workflows:
- submit-coverage:
requires:
- test-0xjs
- test-deployer
- test-sol-compiler
- test-rest
- test-contracts

5
.gitignore vendored
View File

@@ -83,9 +83,10 @@ packages/migrations/artifacts/1.0.0
packages/0x.js/src/contract_wrappers/generated/
packages/contracts/src/contract_wrappers/generated/
packages/metacoin/src/contract_wrappers
packages/migrations/src/contract_wrappers
# solc-bin in deployer
packages/deployer/solc_bin/
# solc-bin in sol-compiler
packages/sol-compiler/solc_bin/
# Monorepo scripts
packages/*/scripts/

View File

@@ -1,5 +1,6 @@
lib
.nyc_output
/packages/0x.js/test/artifacts
/packages/contracts/src/artifacts
/packages/metacoin/artifacts
/packages/migrations/artifacts/1.0.0

View File

@@ -17,27 +17,27 @@ This repository is a monorepo including the 0x protocol smart contracts and nume
### Published Packages
| Package | Version | Description |
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| [`0x.js`](/packages/0x.js) | [![npm](https://img.shields.io/npm/v/0x.js.svg)](https://www.npmjs.com/package/0x.js) | A Javascript library for interacting with the 0x protocol |
| [`@0xproject/abi-gen`](/packages/abi-gen) | [![npm](https://img.shields.io/npm/v/@0xproject/abi-gen.svg)](https://www.npmjs.com/package/@0xproject/abi-gen) | Tool to generate TS wrappers from smart contract ABIs |
| [`@0xproject/assert`](/packages/assert) | [![npm](https://img.shields.io/npm/v/@0xproject/assert.svg)](https://www.npmjs.com/package/@0xproject/assert) | Type and schema assertions used by our packages |
| [`@0xproject/base-contract`](/packages/base-contract) | [![npm](https://img.shields.io/npm/v/@0xproject/base-contract.svg)](https://www.npmjs.com/package/@0xproject/base-contract) | BaseContract used by auto-generated `abi-gen` wrapper contracts |
| [`@0xproject/connect`](/packages/connect) | [![npm](https://img.shields.io/npm/v/@0xproject/connect.svg)](https://www.npmjs.com/package/@0xproject/connect) | A Javascript library for interacting with the Standard Relayer API |
| [`@0xproject/deployer`](/packages/deployer) | [![npm](https://img.shields.io/npm/v/@0xproject/deployer.svg)](https://www.npmjs.com/package/@0xproject/deployer) | Solidity project compiler and deployer framework |
| [`@0xproject/dev-utils`](/packages/dev-utils) | [![npm](https://img.shields.io/npm/v/@0xproject/dev-utils.svg)](https://www.npmjs.com/package/@0xproject/dev-utils) | Dev utils to be shared across 0x projects and packages |
| [`@0xproject/json-schemas`](/packages/json-schemas) | [![npm](https://img.shields.io/npm/v/@0xproject/json-schemas.svg)](https://www.npmjs.com/package/@0xproject/json-schemas) | 0x-related json schemas |
| [`@0xproject/monorepo-scripts`](/packages/monorepo-scripts) | [![npm](https://img.shields.io/npm/v/@0xproject/monorepo-scripts.svg)](https://www.npmjs.com/package/@0xproject/monorepo-scripts) | Monorepo scripts |
| [`@0xproject/react-docs`](/packages/react-docs) | [![npm](https://img.shields.io/npm/v/@0xproject/react-docs.svg)](https://www.npmjs.com/package/@0xproject/react-docs) | React documentation component for rendering TypeDoc & Doxity generated JSON |
| [`@0xproject/react-shared`](/packages/react-shared) | [![npm](https://img.shields.io/npm/v/@0xproject/react-shared.svg)](https://www.npmjs.com/package/@0xproject/react-shared) | 0x shared react components |
| [`@0xproject/sra-report`](/packages/sra-report) | [![npm](https://img.shields.io/npm/v/@0xproject/sra-report.svg)](https://www.npmjs.com/package/@0xproject/sra-report) | Generate reports for standard relayer API compliance |
| [`@0xproject/sol-cov`](/packages/sol-cov) | [![npm](https://img.shields.io/npm/v/@0xproject/sol-cov.svg)](https://www.npmjs.com/package/@0xproject/sol-cov) | Solidity test coverage tool |
| [`@0xproject/subproviders`](/packages/subproviders) | [![npm](https://img.shields.io/npm/v/@0xproject/subproviders.svg)](https://www.npmjs.com/package/@0xproject/subproviders) | Useful web3 subproviders (e.g LedgerSubprovider) |
| [`@0xproject/tslint-config`](/packages/tslint-config) | [![npm](https://img.shields.io/npm/v/@0xproject/tslint-config.svg)](https://www.npmjs.com/package/@0xproject/tslint-config) | Custom 0x development TSLint rules |
| [`@0xproject/types`](/packages/types) | [![npm](https://img.shields.io/npm/v/@0xproject/types.svg)](https://www.npmjs.com/package/@0xproject/types) | Shared type declarations |
| [`@0xproject/typescript-typings`](/packages/typescript-typings) | [![npm](https://img.shields.io/npm/v/@0xproject/typescript-typings.svg)](https://www.npmjs.com/package/@0xproject/typescript-typings) | Repository of types for external packages |
| [`@0xproject/utils`](/packages/utils) | [![npm](https://img.shields.io/npm/v/@0xproject/utils.svg)](https://www.npmjs.com/package/@0xproject/utils) | Shared utilities |
| [`@0xproject/web3-wrapper`](/packages/web3-wrapper) | [![npm](https://img.shields.io/npm/v/@0xproject/web3-wrapper.svg)](https://www.npmjs.com/package/@0xproject/web3-wrapper) | Web3 wrapper |
| Package | Version | Description |
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| [`0x.js`](/packages/0x.js) | [![npm](https://img.shields.io/npm/v/0x.js.svg)](https://www.npmjs.com/package/0x.js) | A Javascript library for interacting with the 0x protocol |
| [`@0xproject/abi-gen`](/packages/abi-gen) | [![npm](https://img.shields.io/npm/v/@0xproject/abi-gen.svg)](https://www.npmjs.com/package/@0xproject/abi-gen) | Tool to generate TS wrappers from smart contract ABIs |
| [`@0xproject/assert`](/packages/assert) | [![npm](https://img.shields.io/npm/v/@0xproject/assert.svg)](https://www.npmjs.com/package/@0xproject/assert) | Type and schema assertions used by our packages |
| [`@0xproject/base-contract`](/packages/base-contract) | [![npm](https://img.shields.io/npm/v/@0xproject/base-contract.svg)](https://www.npmjs.com/package/@0xproject/base-contract) | BaseContract used by auto-generated `abi-gen` wrapper contracts |
| [`@0xproject/connect`](/packages/connect) | [![npm](https://img.shields.io/npm/v/@0xproject/connect.svg)](https://www.npmjs.com/package/@0xproject/connect) | A Javascript library for interacting with the Standard Relayer API |
| [`@0xproject/sol-compiler`](/packages/sol-compiler) | [![npm](https://img.shields.io/npm/v/@0xproject/sol-compiler.svg)](https://www.npmjs.com/package/@0xproject/sol-compiler) | A thin wrapper around Solc.js that outputs artifacts, resolves imports, only re-compiles when needed, and other niceties. |
| [`@0xproject/dev-utils`](/packages/dev-utils) | [![npm](https://img.shields.io/npm/v/@0xproject/dev-utils.svg)](https://www.npmjs.com/package/@0xproject/dev-utils) | Dev utils to be shared across 0x projects and packages |
| [`@0xproject/json-schemas`](/packages/json-schemas) | [![npm](https://img.shields.io/npm/v/@0xproject/json-schemas.svg)](https://www.npmjs.com/package/@0xproject/json-schemas) | 0x-related json schemas |
| [`@0xproject/monorepo-scripts`](/packages/monorepo-scripts) | [![npm](https://img.shields.io/npm/v/@0xproject/monorepo-scripts.svg)](https://www.npmjs.com/package/@0xproject/monorepo-scripts) | Monorepo scripts |
| [`@0xproject/react-docs`](/packages/react-docs) | [![npm](https://img.shields.io/npm/v/@0xproject/react-docs.svg)](https://www.npmjs.com/package/@0xproject/react-docs) | React documentation component for rendering TypeDoc & Doxity generated JSON |
| [`@0xproject/react-shared`](/packages/react-shared) | [![npm](https://img.shields.io/npm/v/@0xproject/react-shared.svg)](https://www.npmjs.com/package/@0xproject/react-shared) | 0x shared react components |
| [`@0xproject/sra-report`](/packages/sra-report) | [![npm](https://img.shields.io/npm/v/@0xproject/sra-report.svg)](https://www.npmjs.com/package/@0xproject/sra-report) | Generate reports for standard relayer API compliance |
| [`@0xproject/sol-cov`](/packages/sol-cov) | [![npm](https://img.shields.io/npm/v/@0xproject/sol-cov.svg)](https://www.npmjs.com/package/@0xproject/sol-cov) | Solidity test coverage tool |
| [`@0xproject/subproviders`](/packages/subproviders) | [![npm](https://img.shields.io/npm/v/@0xproject/subproviders.svg)](https://www.npmjs.com/package/@0xproject/subproviders) | Useful web3 subproviders (e.g LedgerSubprovider) |
| [`@0xproject/tslint-config`](/packages/tslint-config) | [![npm](https://img.shields.io/npm/v/@0xproject/tslint-config.svg)](https://www.npmjs.com/package/@0xproject/tslint-config) | Custom 0x development TSLint rules |
| [`@0xproject/types`](/packages/types) | [![npm](https://img.shields.io/npm/v/@0xproject/types.svg)](https://www.npmjs.com/package/@0xproject/types) | Shared type declarations |
| [`@0xproject/typescript-typings`](/packages/typescript-typings) | [![npm](https://img.shields.io/npm/v/@0xproject/typescript-typings.svg)](https://www.npmjs.com/package/@0xproject/typescript-typings) | Repository of types for external packages |
| [`@0xproject/utils`](/packages/utils) | [![npm](https://img.shields.io/npm/v/@0xproject/utils.svg)](https://www.npmjs.com/package/@0xproject/utils) | Shared utilities |
| [`@0xproject/web3-wrapper`](/packages/web3-wrapper) | [![npm](https://img.shields.io/npm/v/@0xproject/web3-wrapper.svg)](https://www.npmjs.com/package/@0xproject/web3-wrapper) | Web3 wrapper |
### Private Packages
@@ -56,7 +56,7 @@ Dedicated documentation pages:
* [0x Connect](https://0xproject.com/docs/connect)
* [Smart contracts](https://0xproject.com/docs/contracts)
* [Subproviders](https://0xproject.com/docs/subproviders)
* [Deployer](https://0xproject.com/docs/deployer)
* [Sol Compiler](https://0xproject.com/docs/sol-compiler)
* [Web3-wrapper](https://0xproject.com/docs/web3-wrapper)
* [JSON-schemas](https://0xproject.com/docs/json-schemas)
* [Sol-cov](https://0xproject.com/docs/sol-cov)

View File

@@ -16,15 +16,14 @@
"prebuild": "run-s clean generate_contract_wrappers",
"build": "run-p build:umd:prod build:commonjs; exit 0;",
"generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'",
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
"lint": "tslint --project .",
"test:circleci": "run-s test:coverage",
"test": "run-s clean test:commonjs",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/1.0.0/$i.json test/artifacts; done;",
"clean": "shx rm -rf _bundles lib test_temp scripts",
"build:umd:prod": "NODE_ENV=production webpack",
"build:commonjs": "tsc && yarn update_artifacts && copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"build:commonjs": "tsc && copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"test:commonjs": "run-s build:commonjs run_mocha",
"run_mocha": "mocha lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js",
@@ -34,7 +33,6 @@
},
"config": {
"compact_artifacts": "Exchange DummyToken ZRXToken Token EtherToken TokenTransferProxy TokenRegistry",
"contracts": "Exchange DummyToken ZRXToken Token WETH9 TokenTransferProxy MultiSigWallet MultiSigWalletWithTimeLock MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress MaliciousToken TokenRegistry Arbitrage EtherDelta AccountLevels",
"postpublish": {
"assets": [
"packages/0x.js/_bundles/index.js",
@@ -61,7 +59,7 @@
"node": ">=6.0.0"
},
"devDependencies": {
"@0xproject/deployer": "^0.4.3",
"@0xproject/sol-compiler": "^0.4.3",
"@0xproject/dev-utils": "^0.4.1",
"@0xproject/migrations": "^0.0.5",
"@0xproject/monorepo-scripts": "^0.1.19",

View File

@@ -144,10 +144,10 @@ export class ZeroEx {
]);
const artifactJSONs = _.values(artifacts);
const abiArrays = _.map(artifactJSONs, artifact => artifact.abi);
const defaults = {
const txDefaults = {
gasPrice: config.gasPrice,
};
this._web3Wrapper = new Web3Wrapper(provider, defaults);
this._web3Wrapper = new Web3Wrapper(provider, txDefaults);
_.forEach(abiArrays, abi => {
this._web3Wrapper.abiDecoder.addABI(abi);
});

View File

@@ -1,7 +1,18 @@
import { devConstants } from '@0xproject/dev-utils';
import { runMigrationsAsync } from '@0xproject/migrations';
import * as path from 'path';
import { deployer } from './utils/deployer';
import { constants } from './utils/constants';
import { provider } from './utils/web3_wrapper';
before('migrate contracts', async () => {
await runMigrationsAsync(deployer);
before('migrate contracts', async function() {
// HACK: Since the migrations take longer then our global mocha timeout limit
// we manually increase it for this before hook.
this.timeout(20000);
const txDefaults = {
gas: devConstants.GAS_ESTIMATE,
from: devConstants.TESTRPC_FIRST_ADDRESS,
};
const artifactsDir = `../migrations/artifacts/1.0.0`;
await runMigrationsAsync(provider, artifactsDir, txDefaults);
});

View File

@@ -1,18 +0,0 @@
import { Deployer } from '@0xproject/deployer';
import { devConstants } from '@0xproject/dev-utils';
import * as path from 'path';
import { constants } from './constants';
import { provider } from './web3_wrapper';
const artifactsDir = path.resolve('test', 'artifacts');
const deployerOpts = {
artifactsDir,
provider,
networkId: constants.TESTRPC_NETWORK_ID,
defaults: {
gas: devConstants.GAS_ESTIMATE,
},
};
export const deployer = new Deployer(deployerOpts);

View File

@@ -35,7 +35,6 @@ export class FillScenarios {
const web3Wrapper = (this._zeroEx as any)._web3Wrapper as Web3Wrapper;
for (const token of this._tokens) {
if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') {
const defaults = {};
const dummyToken = new DummyTokenContract(
artifacts.DummyTokenArtifact.abi,
token.address,

View File

@@ -6,7 +6,7 @@
"types": "lib/index.d.ts",
"scripts": {
"build:watch": "tsc -w",
"lint": "tslint --project . 'src/**/*.ts'",
"lint": "tslint --project .",
"clean": "shx rm -rf lib scripts",
"build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js"

View File

@@ -114,7 +114,7 @@ for (const abiFileName of abiFileNames) {
if (_.isUndefined(ABI)) {
logUtils.log(`${chalk.red(`ABI not found in ${abiFileName}.`)}`);
logUtils.log(
`Please make sure your ABI file is either an array with ABI entries or a truffle artifact or 0x deployer artifact`,
`Please make sure your ABI file is either an array with ABI entries or a truffle artifact or 0x sol-compiler artifact`,
);
process.exit(1);
}

View File

@@ -8,7 +8,7 @@
"build:watch": "tsc -w",
"build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"clean": "shx rm -rf lib test_temp scripts",
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
"lint": "tslint --project .",
"run_mocha": "mocha lib/test/**/*_test.js --exit",
"prepublishOnly": "run-p build",
"test": "run-s clean build run_mocha",

View File

@@ -1,6 +1,7 @@
import {
AbiDefinition,
AbiType,
ConstructorAbi,
ContractAbi,
DataItem,
MethodAbi,
@@ -24,6 +25,8 @@ export class BaseContract {
protected _web3Wrapper: Web3Wrapper;
public abi: ContractAbi;
public address: string;
public contractName: string;
public constructorArgs: any[] = [];
protected static _formatABIDataItemList(
abis: DataItem[],
values: any[],
@@ -37,11 +40,31 @@ export class BaseContract {
protected static _bigNumberToString(type: string, value: any): any {
return _.isObject(value) && value.isBigNumber ? value.toString() : value;
}
protected static _lookupConstructorAbi(abi: ContractAbi): ConstructorAbi {
const constructorAbiIfExists = _.find(
abi,
(abiDefinition: AbiDefinition) => abiDefinition.type === AbiType.Constructor,
) as ConstructorAbi | undefined;
if (!_.isUndefined(constructorAbiIfExists)) {
return constructorAbiIfExists;
} else {
// If the constructor is not explicitly defined, it won't be included in the ABI. It is
// still callable however, so we construct what the ABI would look like were it to exist.
const defaultConstructorAbi: ConstructorAbi = {
type: AbiType.Constructor,
stateMutability: 'nonpayable',
payable: false,
inputs: [],
};
return defaultConstructorAbi;
}
}
protected static _bnToBigNumber(type: string, value: any): any {
return _.isObject(value) && value._bn ? new BigNumber(value.toString()) : value;
}
protected async _applyDefaultsToTxDataAsync<T extends Partial<TxData | TxDataPayable>>(
protected static async _applyDefaultsToTxDataAsync<T extends Partial<TxData | TxDataPayable>>(
txData: T,
txDefaults: Partial<TxData>,
estimateGasAsync?: (txData: T) => Promise<number>,
): Promise<TxData> {
// Gas amount sourced with the following priorities:
@@ -49,13 +72,12 @@ export class BaseContract {
// 2. Global config passed in at library instantiation
// 3. Gas estimate calculation + safety margin
const removeUndefinedProperties = _.pickBy;
const txDataWithDefaults = ({
to: this.address,
...removeUndefinedProperties(this._web3Wrapper.getContractDefaults()),
const txDataWithDefaults: TxData = {
...removeUndefinedProperties(txDefaults),
...removeUndefinedProperties(txData as any),
// HACK: TS can't prove that T is spreadable.
// Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged
} as any) as TxData;
} as any;
if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) {
const estimatedGas = await estimateGasAsync(txData);
txDataWithDefaults.gas = estimatedGas;
@@ -82,8 +104,15 @@ export class BaseContract {
}) as MethodAbi;
return methodAbi;
}
constructor(abi: ContractAbi, address: string, provider: Provider, defaults?: Partial<TxData>) {
this._web3Wrapper = new Web3Wrapper(provider, defaults);
constructor(
contractName: string,
abi: ContractAbi,
address: string,
provider: Provider,
txDefaults?: Partial<TxData>,
) {
this.contractName = contractName;
this._web3Wrapper = new Web3Wrapper(provider, txDefaults);
this.abi = abi;
this.address = address;
const methodAbis = this.abi.filter(

View File

@@ -16,7 +16,7 @@
"build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"clean": "shx rm -rf lib test_temp scripts",
"copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures",
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
"lint": "tslint --project .",
"run_mocha": "mocha lib/test/**/*_test.js --exit",
"test": "run-s clean build copy_test_fixtures run_mocha",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",

View File

@@ -5,8 +5,9 @@
// tslint:disable:no-consecutive-blank-lines
// tslint:disable-next-line:no-unused-variable
import { BaseContract } from '@0xproject/base-contract';
import { ContractArtifact } from '@0xproject/sol-compiler';
import { BlockParam, BlockParamLiteral, CallData, ContractAbi, DataItem, MethodAbi, Provider, TxData, TxDataPayable } from '@0xproject/types';
import { BigNumber, classUtils, promisify } from '@0xproject/utils';
import { BigNumber, classUtils, logUtils, promisify } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as ethers from 'ethers';
import * as _ from 'lodash';
@@ -39,8 +40,49 @@ export class {{contractName}}Contract extends BaseContract {
{{> tx contractName=../contractName}}
{{/this.constant}}
{{/each}}
constructor(abi: ContractAbi, address: string, provider: Provider, defaults?: Partial<TxData>) {
super(abi, address, provider, defaults);
public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact,
provider: Provider,
txDefaults: Partial<TxData>,
{{> typed_params inputs=ctor.inputs}}
): Promise<{{contractName}}Contract> {
if (_.isUndefined(artifact.compilerOutput)) {
throw new Error('Compiler output not found in the artifact file');
}
const bytecode = artifact.compilerOutput.evm.bytecode.object;
const abi = artifact.compilerOutput.abi;
return {{contractName}}Contract.deployAsync(bytecode, abi, provider, txDefaults, {{> params inputs=ctor.inputs}});
}
public static async deployAsync(
bytecode: string,
abi: ContractAbi,
provider: Provider,
txDefaults: Partial<TxData>,
{{> typed_params inputs=ctor.inputs}}
): Promise<{{contractName}}Contract> {
const constructorAbi = BaseContract._lookupConstructorAbi(abi);
[{{> params inputs=ctor.inputs}}] = BaseContract._formatABIDataItemList(
constructorAbi.inputs,
[{{> params inputs=ctor.inputs}}],
BaseContract._bigNumberToString,
);
const txData = ethers.Contract.getDeployTransaction(bytecode, abi, {{> params inputs=ctor.inputs}});
const web3Wrapper = new Web3Wrapper(provider);
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
txData,
txDefaults,
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
);
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
logUtils.log(`transactionHash: ${txHash}`);
const txReceipt = await web3Wrapper.awaitTransactionMinedAsync(txHash);
logUtils.log(`{{contractName}} successfully deployed at ${txReceipt.contractAddress}`);
const contractInstance = new {{contractName}}Contract(abi, txReceipt.contractAddress as string, provider, txDefaults);
contractInstance.constructorArgs = [{{> params inputs=ctor.inputs}}];
return contractInstance;
}
constructor(abi: ContractAbi, address: string, provider: Provider, txDefaults?: Partial<TxData>) {
super("{{contractName}}", abi, address, provider, txDefaults);
classUtils.bindAll(this, ['_ethersInterfacesByFunctionSignature', 'address', 'abi', '_web3Wrapper']);
}
} // tslint:disable:max-file-line-count

View File

@@ -12,10 +12,12 @@ async callAsync(
{{> params inputs=inputs}}
) as ethers.CallDescription;
const encodedData = ethersFunction.data;
const callDataWithDefaults = await self._applyDefaultsToTxDataAsync(
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
{
to: self.address,
data: encodedData,
}
},
self._web3Wrapper.getContractDefaults(),
)
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
let resultArray = ethersFunction.parse(rawCallResult);

View File

@@ -14,11 +14,13 @@ public {{this.tsName}} = {
const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}(
{{> params inputs=inputs}}
).data;
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
{
to: self.address,
...txData,
data: encodedData,
},
self._web3Wrapper.getContractDefaults(),
self.{{this.tsName}}.estimateGasAsync.bind(
self,
{{> params inputs=inputs}}
@@ -33,15 +35,17 @@ public {{this.tsName}} = {
): Promise<number> {
const self = this as any as {{contractName}}Contract;
const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs;
[{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(this));
[{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString);
const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}(
{{> params inputs=inputs}}
).data;
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
{
to: self.address,
...txData,
data: encodedData,
}
},
self._web3Wrapper.getContractDefaults(),
);
const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
return gas;
@@ -51,7 +55,7 @@ public {{this.tsName}} = {
): string {
const self = this as any as {{contractName}}Contract;
const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs;
[{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self));
[{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString);
const abiEncodedTransactionData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}(
{{> params inputs=inputs}}
).data;

View File

@@ -16,17 +16,17 @@
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
"run_mocha": "mocha 'lib/test/**/*.js' --timeout 100000 --bail --exit",
"compile:comment": "Yarn workspaces do not link binaries correctly so we need to reference them directly https://github.com/yarnpkg/yarn/issues/3846",
"compile": "node ../deployer/lib/src/cli.js compile",
"compile": "node ../sol-compiler/lib/src/cli.js",
"clean": "shx rm -rf ./lib",
"generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis ${npm_package_config_abis} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'",
"lint": "tslint --project . 'migrations/**/*.ts' 'test/**/*.ts' 'util/**/*.ts' 'deploy/**/*.ts'",
"lint": "tslint --project .",
"coverage:report:text": "istanbul report text",
"coverage:report:html": "istanbul report html && open coverage/index.html",
"coverage:report:lcov": "istanbul report lcov",
"test:circleci": "yarn test:coverage"
},
"config": {
"abis": "../migrations/artifacts/1.0.0/@(DummyToken|TokenTransferProxy|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|Arbitrage|EtherDelta|AccountLevels).json"
"abis": "../migrations/artifacts/1.0.0/@(DummyToken|TokenTransferProxy|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|Arbitrage|EtherDelta|AccountLevels|WETH9|MaliciousToken).json"
},
"repository": {
"type": "git",
@@ -60,7 +60,8 @@
},
"dependencies": {
"0x.js": "^0.37.2",
"@0xproject/deployer": "^0.4.3",
"@0xproject/base-contract": "^0.3.1",
"@0xproject/sol-compiler": "^0.4.3",
"@0xproject/types": "^0.6.3",
"@0xproject/typescript-typings": "^0.3.1",
"@0xproject/utils": "^0.6.1",
@@ -68,7 +69,7 @@
"bn.js": "^4.11.8",
"ethereumjs-abi": "^0.6.4",
"ethereumjs-util": "^5.1.1",
"ethers-contracts": "^2.2.1",
"ethers": "^3.0.15",
"lodash": "^4.17.4",
"web3": "^0.20.0"
}

View File

@@ -4,12 +4,14 @@ import { BigNumber, promisify } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
import { WETH9Contract } from '../src/contract_wrappers/generated/weth9';
import { artifacts } from '../util/artifacts';
import { constants } from '../util/constants';
import { ContractName } from '../util/types';
import { chaiSetup } from './utils/chai_setup';
import { deployer } from './utils/deployer';
import { provider, web3Wrapper } from './utils/web3_wrapper';
import { provider, txDefaults, web3Wrapper } from './utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -24,7 +26,7 @@ describe('EtherToken', () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
account = accounts[0];
const etherToken = await deployer.deployAsync(ContractName.EtherToken);
const etherToken = await WETH9Contract.deployFrom0xArtifactAsync(artifacts.EtherToken, provider, txDefaults);
etherTokenAddress = etherToken.address;
zeroEx = new ZeroEx(provider, {
gasPrice,

View File

@@ -13,7 +13,9 @@ import {
LogErrorContractEventArgs,
LogFillContractEventArgs,
} from '../../src/contract_wrappers/generated/exchange';
import { MaliciousTokenContract } from '../../src/contract_wrappers/generated/malicious_token';
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
import { artifacts } from '../../util/artifacts';
import { Balances } from '../../util/balances';
import { constants } from '../../util/constants';
import { crypto } from '../../util/crypto';
@@ -21,8 +23,8 @@ import { ExchangeWrapper } from '../../util/exchange_wrapper';
import { OrderFactory } from '../../util/order_factory';
import { BalancesByOwner, ContractName, ExchangeContractErrs } from '../../util/types';
import { chaiSetup } from '../utils/chai_setup';
import { deployer } from '../utils/deployer';
import { provider, web3Wrapper } from '../utils/web3_wrapper';
import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -54,25 +56,47 @@ describe('Exchange', () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
maker = accounts[0];
[tokenOwner, taker, feeRecipient] = accounts;
const [repInstance, dgdInstance, zrxInstance] = await Promise.all([
deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS),
deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS),
deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS),
[rep, dgd, zrx] = await Promise.all([
DummyTokenContract.deployFrom0xArtifactAsync(
artifacts.DummyToken,
provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
),
DummyTokenContract.deployFrom0xArtifactAsync(
artifacts.DummyToken,
provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
),
DummyTokenContract.deployFrom0xArtifactAsync(
artifacts.DummyToken,
provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
),
]);
rep = new DummyTokenContract(repInstance.abi, repInstance.address, provider);
dgd = new DummyTokenContract(dgdInstance.abi, dgdInstance.address, provider);
zrx = new DummyTokenContract(zrxInstance.abi, zrxInstance.address, provider);
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
tokenTransferProxy = new TokenTransferProxyContract(
tokenTransferProxyInstance.abi,
tokenTransferProxyInstance.address,
tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync(
artifacts.TokenTransferProxy,
provider,
txDefaults,
);
const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [
exchange = await ExchangeContract.deployFrom0xArtifactAsync(
artifacts.Exchange,
provider,
txDefaults,
zrx.address,
tokenTransferProxy.address,
]);
exchange = new ExchangeContract(exchangeInstance.abi, exchangeInstance.address, provider);
);
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] });
zeroEx = new ZeroEx(provider, {
exchangeContractAddress: exchange.address,
@@ -689,7 +713,11 @@ describe('Exchange', () => {
it('should throw if getBalance or getAllowance attempts to change state and \
shouldThrowOnInsufficientBalanceOrAllowance = false', async () => {
const maliciousToken = await deployer.deployAsync(ContractName.MaliciousToken);
const maliciousToken = await MaliciousTokenContract.deployFrom0xArtifactAsync(
artifacts.MaliciousToken,
provider,
txDefaults,
);
await maliciousToken.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
from: taker,
});

View File

@@ -11,13 +11,18 @@ import {
LogErrorContractEventArgs,
LogFillContractEventArgs,
} from '../../src/contract_wrappers/generated/exchange';
import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
import { TokenRegistryContract } from '../../src/contract_wrappers/generated/token_registry';
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
import { artifacts } from '../../util/artifacts';
import { constants } from '../../util/constants';
import { ExchangeWrapper } from '../../util/exchange_wrapper';
import { OrderFactory } from '../../util/order_factory';
import { ContractName } from '../../util/types';
import { chaiSetup } from '../utils/chai_setup';
import { deployer } from '../utils/deployer';
import { provider, web3Wrapper } from '../utils/web3_wrapper';
import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -35,19 +40,53 @@ describe('Exchange', () => {
before(async () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
[maker, feeRecipient] = accounts;
const tokenRegistry = await deployer.deployAsync(ContractName.TokenRegistry);
const tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy);
const tokenRegistry = await TokenRegistryContract.deployFrom0xArtifactAsync(
artifacts.TokenRegistry,
provider,
txDefaults,
);
const tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync(
artifacts.TokenTransferProxy,
provider,
txDefaults,
);
const [rep, dgd, zrx] = await Promise.all([
deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS),
deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS),
deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS),
DummyTokenContract.deployFrom0xArtifactAsync(
artifacts.DummyToken,
provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
),
DummyTokenContract.deployFrom0xArtifactAsync(
artifacts.DummyToken,
provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
),
DummyTokenContract.deployFrom0xArtifactAsync(
artifacts.DummyToken,
provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
),
]);
const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [
const exchange = await ExchangeContract.deployFrom0xArtifactAsync(
artifacts.Exchange,
provider,
txDefaults,
zrx.address,
tokenTransferProxy.address,
]);
const exchange = new ExchangeContract(exchangeInstance.abi, exchangeInstance.address, provider);
await tokenTransferProxy.addAuthorizedAddress(exchange.address, { from: accounts[0] });
);
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] });
const zeroEx = new ZeroEx(provider, { networkId: constants.TESTRPC_NETWORK_ID });
exchangeWrapper = new ExchangeWrapper(exchange, zeroEx);
const defaultOrderParams = {

View File

@@ -15,14 +15,15 @@ import {
} from '../../src/contract_wrappers/generated/exchange';
import { TokenRegistryContract } from '../../src/contract_wrappers/generated/token_registry';
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
import { artifacts } from '../../util/artifacts';
import { Balances } from '../../util/balances';
import { constants } from '../../util/constants';
import { ExchangeWrapper } from '../../util/exchange_wrapper';
import { OrderFactory } from '../../util/order_factory';
import { BalancesByOwner, ContractName } from '../../util/types';
import { chaiSetup } from '../utils/chai_setup';
import { deployer } from '../utils/deployer';
import { provider, web3Wrapper } from '../utils/web3_wrapper';
import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -54,27 +55,52 @@ describe('Exchange', () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
tokenOwner = accounts[0];
[maker, taker, feeRecipient] = accounts;
const [repInstance, dgdInstance, zrxInstance] = await Promise.all([
deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS),
deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS),
deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS),
[rep, dgd, zrx] = await Promise.all([
DummyTokenContract.deployFrom0xArtifactAsync(
artifacts.DummyToken,
provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
),
DummyTokenContract.deployFrom0xArtifactAsync(
artifacts.DummyToken,
provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
),
DummyTokenContract.deployFrom0xArtifactAsync(
artifacts.DummyToken,
provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
),
]);
rep = new DummyTokenContract(repInstance.abi, repInstance.address, provider);
dgd = new DummyTokenContract(dgdInstance.abi, dgdInstance.address, provider);
zrx = new DummyTokenContract(zrxInstance.abi, zrxInstance.address, provider);
const tokenRegistryInstance = await deployer.deployAsync(ContractName.TokenRegistry);
tokenRegistry = new TokenRegistryContract(tokenRegistryInstance.abi, tokenRegistryInstance.address, provider);
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
tokenTransferProxy = new TokenTransferProxyContract(
tokenTransferProxyInstance.abi,
tokenTransferProxyInstance.address,
tokenRegistry = await TokenRegistryContract.deployFrom0xArtifactAsync(
artifacts.TokenRegistry,
provider,
txDefaults,
);
const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [
tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync(
artifacts.TokenTransferProxy,
provider,
txDefaults,
);
exchange = await ExchangeContract.deployFrom0xArtifactAsync(
artifacts.Exchange,
provider,
txDefaults,
zrx.address,
tokenTransferProxy.address,
]);
exchange = new ExchangeContract(exchangeInstance.abi, exchangeInstance.address, provider);
);
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] });
const zeroEx = new ZeroEx(provider, { networkId: constants.TESTRPC_NETWORK_ID });
exWrapper = new ExchangeWrapper(exchange, zeroEx);

View File

@@ -14,10 +14,10 @@ import { MultiSigWrapper } from '../util/multi_sig_wrapper';
import { ContractName, SubmissionContractEventArgs } from '../util/types';
import { chaiSetup } from './utils/chai_setup';
import { deployer } from './utils/deployer';
import { provider, web3Wrapper } from './utils/web3_wrapper';
const MULTI_SIG_ABI = artifacts.MultiSigWalletWithTimeLockArtifact.compilerOutput.abi;
import { provider, txDefaults, web3Wrapper } from './utils/web3_wrapper';
const MULTI_SIG_ABI = artifacts.MultiSigWalletWithTimeLock.compilerOutput.abi;
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
@@ -47,15 +47,13 @@ describe('MultiSigWalletWithTimeLock', () => {
describe('changeTimeLock', () => {
describe('initially non-time-locked', async () => {
before('deploy a wallet', async () => {
const multiSigInstance = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [
multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync(
artifacts.MultiSigWalletWithTimeLock,
provider,
txDefaults,
owners,
SIGNATURES_REQUIRED,
0,
]);
multiSig = new MultiSigWalletWithTimeLockContract(
multiSigInstance.abi,
multiSigInstance.address,
provider,
new BigNumber(0),
);
multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract);
@@ -144,15 +142,13 @@ describe('MultiSigWalletWithTimeLock', () => {
});
describe('initially time-locked', async () => {
before('deploy a wallet', async () => {
const multiSigInstance = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [
multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync(
artifacts.MultiSigWalletWithTimeLock,
provider,
txDefaults,
owners,
SIGNATURES_REQUIRED,
SECONDS_TIME_LOCKED,
]);
multiSig = new MultiSigWalletWithTimeLockContract(
multiSigInstance.abi,
multiSigInstance.address,
provider,
);
multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract);

View File

@@ -1,6 +1,6 @@
import { LogWithDecodedArgs, ZeroEx } from '0x.js';
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
import { AbiDecoder } from '@0xproject/utils';
import { AbiDecoder, BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
import * as Web3 from 'web3';
@@ -15,11 +15,11 @@ import { MultiSigWrapper } from '../util/multi_sig_wrapper';
import { ContractName, SubmissionContractEventArgs, TransactionDataParams } from '../util/types';
import { chaiSetup } from './utils/chai_setup';
import { deployer } from './utils/deployer';
import { provider, web3Wrapper } from './utils/web3_wrapper';
const PROXY_ABI = artifacts.TokenTransferProxyArtifact.compilerOutput.abi;
import { provider, txDefaults, web3Wrapper } from './utils/web3_wrapper';
const PROXY_ABI = artifacts.TokenTransferProxy.compilerOutput.abi;
const MUTISIG_WALLET_WITH_TIME_LOCK_EXCEPT_REMOVE_AUTHORIZED_ADDRESS_ABI =
artifacts.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressArtifact.compilerOutput.abi;
artifacts.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.compilerOutput.abi;
chaiSetup.configure();
const expect = chai.expect;
@@ -29,8 +29,8 @@ const abiDecoder = new AbiDecoder([MUTISIG_WALLET_WITH_TIME_LOCK_EXCEPT_REMOVE_A
describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
const zeroEx = new ZeroEx(provider, { networkId: constants.TESTRPC_NETWORK_ID });
let owners: string[];
const requiredApprovals = 2;
const SECONDS_TIME_LOCKED = 1000000;
const requiredApprovals = new BigNumber(2);
const SECONDS_TIME_LOCKED = new BigNumber(1000000);
// initialize fake addresses
let authorizedAddress: string;
@@ -46,23 +46,22 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
owners = [accounts[0], accounts[1]];
[authorizedAddress, unauthorizedAddress] = accounts;
const initialOwner = accounts[0];
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
tokenTransferProxy = new TokenTransferProxyContract(
tokenTransferProxyInstance.abi,
tokenTransferProxyInstance.address,
tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync(
artifacts.TokenTransferProxy,
provider,
txDefaults,
);
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(authorizedAddress, {
from: initialOwner,
});
const multiSigInstance = await deployer.deployAsync(
ContractName.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,
[owners, requiredApprovals, SECONDS_TIME_LOCKED, tokenTransferProxy.address],
);
multiSig = new MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract(
multiSigInstance.abi,
multiSigInstance.address,
multiSig = await MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract.deployFrom0xArtifactAsync(
artifacts.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,
provider,
txDefaults,
owners,
requiredApprovals,
SECONDS_TIME_LOCKED,
tokenTransferProxy.address,
);
await tokenTransferProxy.transferOwnership.sendTransactionAsync(multiSig.address, {
from: initialOwner,
@@ -110,7 +109,11 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
});
it('should throw if tx destination is not the tokenTransferProxy', async () => {
const invalidTokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy);
const invalidTokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync(
artifacts.TokenTransferProxy,
provider,
txDefaults,
);
const invalidDestination = invalidTokenTransferProxy.address;
const dataParams: TransactionDataParams = {
name: 'removeAuthorizedAddress',

View File

@@ -8,13 +8,13 @@ import * as _ from 'lodash';
import * as Web3 from 'web3';
import { TokenRegistryContract } from '../src/contract_wrappers/generated/token_registry';
import { artifacts } from '../util/artifacts';
import { constants } from '../util/constants';
import { TokenRegWrapper } from '../util/token_registry_wrapper';
import { ContractName } from '../util/types';
import { chaiSetup } from './utils/chai_setup';
import { deployer } from './utils/deployer';
import { provider, web3Wrapper } from './utils/web3_wrapper';
import { provider, txDefaults, web3Wrapper } from './utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -29,8 +29,7 @@ describe('TokenRegistry', () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
owner = accounts[0];
notOwner = accounts[1];
const tokenRegInstance = await deployer.deployAsync(ContractName.TokenRegistry);
tokenReg = new TokenRegistryContract(tokenRegInstance.abi, tokenRegInstance.address, provider);
tokenReg = await TokenRegistryContract.deployFrom0xArtifactAsync(artifacts.TokenRegistry, provider, txDefaults);
tokenRegWrapper = new TokenRegWrapper(tokenReg);
});
beforeEach(async () => {

View File

@@ -4,11 +4,12 @@ import * as chai from 'chai';
import * as Web3 from 'web3';
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
import { artifacts } from '../../util/artifacts';
import { constants } from '../../util/constants';
import { ContractName } from '../../util/types';
import { chaiSetup } from '../utils/chai_setup';
import { deployer } from '../utils/deployer';
import { provider, web3Wrapper } from '../utils/web3_wrapper';
import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -23,11 +24,10 @@ describe('TokenTransferProxy', () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
owner = address = accounts[0];
notOwner = accounts[1];
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
tokenTransferProxy = new TokenTransferProxyContract(
tokenTransferProxyInstance.abi,
tokenTransferProxyInstance.address,
tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync(
artifacts.TokenTransferProxy,
provider,
txDefaults,
);
});
beforeEach(async () => {

View File

@@ -6,12 +6,13 @@ import * as Web3 from 'web3';
import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
import { artifacts } from '../../util/artifacts';
import { Balances } from '../../util/balances';
import { constants } from '../../util/constants';
import { ContractName } from '../../util/types';
import { chaiSetup } from '../utils/chai_setup';
import { deployer } from '../utils/deployer';
import { provider, web3Wrapper } from '../utils/web3_wrapper';
import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -31,15 +32,20 @@ describe('TokenTransferProxy', () => {
before(async () => {
accounts = await web3Wrapper.getAvailableAddressesAsync();
owner = notAuthorized = accounts[0];
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
tokenTransferProxy = new TokenTransferProxyContract(
tokenTransferProxyInstance.abi,
tokenTransferProxyInstance.address,
tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync(
artifacts.TokenTransferProxy,
provider,
txDefaults,
);
rep = await DummyTokenContract.deployFrom0xArtifactAsync(
artifacts.DummyToken,
provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
);
const repInstance = await deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS);
rep = new DummyTokenContract(repInstance.abi, repInstance.address, provider);
dmyBalances = new Balances([rep], [accounts[0], accounts[1]]);
await Promise.all([
rep.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, {

View File

@@ -6,9 +6,13 @@ import * as chai from 'chai';
import ethUtil = require('ethereumjs-util');
import * as Web3 from 'web3';
import { AccountLevelsContract } from '../../src/contract_wrappers/generated/account_levels';
import { ArbitrageContract } from '../../src/contract_wrappers/generated/arbitrage';
import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
import { EtherDeltaContract } from '../../src/contract_wrappers/generated/ether_delta';
import { ExchangeContract } from '../../src/contract_wrappers/generated/exchange';
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
import { artifacts } from '../../util/artifacts';
import { Balances } from '../../util/balances';
import { constants } from '../../util/constants';
import { crypto } from '../../util/crypto';
@@ -16,8 +20,8 @@ import { ExchangeWrapper } from '../../util/exchange_wrapper';
import { OrderFactory } from '../../util/order_factory';
import { BalancesByOwner, ContractName, ExchangeContractErrs } from '../../util/types';
import { chaiSetup } from '../utils/chai_setup';
import { deployer } from '../utils/deployer';
import { provider, web3Wrapper } from '../utils/web3_wrapper';
import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -36,8 +40,8 @@ describe('Arbitrage', () => {
const INITIAL_BALANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
const INITIAL_ALLOWANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
let weth: Web3.ContractInstance;
let zrx: Web3.ContractInstance;
let weth: DummyTokenContract;
let zrx: DummyTokenContract;
let arbitrage: ArbitrageContract;
let etherDelta: EtherDeltaContract;
@@ -54,33 +58,61 @@ describe('Arbitrage', () => {
before(async () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
[coinbase, maker, edMaker, edFrontRunner] = accounts;
weth = await deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS);
zrx = await deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS);
const accountLevels = await deployer.deployAsync(ContractName.AccountLevels);
weth = await DummyTokenContract.deployFrom0xArtifactAsync(
artifacts.DummyToken,
provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
);
zrx = await DummyTokenContract.deployFrom0xArtifactAsync(
artifacts.DummyToken,
provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
);
const accountLevels = await AccountLevelsContract.deployFrom0xArtifactAsync(
artifacts.AccountLevels,
provider,
txDefaults,
);
const edAdminAddress = accounts[0];
const edMakerFee = 0;
const edTakerFee = 0;
const edFeeRebate = 0;
const etherDeltaInstance = await deployer.deployAsync(ContractName.EtherDelta, [
const edMakerFee = new BigNumber(0);
const edTakerFee = new BigNumber(0);
const edFeeRebate = new BigNumber(0);
etherDelta = await EtherDeltaContract.deployFrom0xArtifactAsync(
artifacts.EtherDelta,
provider,
txDefaults,
edAdminAddress,
feeRecipient,
accountLevels.address,
edMakerFee,
edTakerFee,
edFeeRebate,
]);
etherDelta = new EtherDeltaContract(etherDeltaInstance.abi, etherDeltaInstance.address, provider);
const tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy);
const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [
);
const tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync(
artifacts.TokenTransferProxy,
provider,
txDefaults,
);
const exchange = await ExchangeContract.deployFrom0xArtifactAsync(
artifacts.Exchange,
provider,
txDefaults,
zrx.address,
tokenTransferProxy.address,
]);
await tokenTransferProxy.addAuthorizedAddress(exchangeInstance.address, { from: accounts[0] });
);
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] });
zeroEx = new ZeroEx(provider, {
exchangeContractAddress: exchangeInstance.address,
exchangeContractAddress: exchange.address,
networkId: constants.TESTRPC_NETWORK_ID,
});
const exchange = new ExchangeContract(exchangeInstance.abi, exchangeInstance.address, provider);
exWrapper = new ExchangeWrapper(exchange, zeroEx);
makerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), 18);
@@ -97,37 +129,39 @@ describe('Arbitrage', () => {
takerFee: new BigNumber(0),
};
orderFactory = new OrderFactory(zeroEx, defaultOrderParams);
const arbitrageInstance = await deployer.deployAsync(ContractName.Arbitrage, [
arbitrage = await ArbitrageContract.deployFrom0xArtifactAsync(
artifacts.Arbitrage,
provider,
txDefaults,
exchange.address,
etherDelta.address,
tokenTransferProxy.address,
]);
arbitrage = new ArbitrageContract(arbitrageInstance.abi, arbitrageInstance.address, provider);
);
// Enable arbitrage and withdrawals of tokens
await arbitrage.setAllowances.sendTransactionAsync(weth.address, { from: coinbase });
await arbitrage.setAllowances.sendTransactionAsync(zrx.address, { from: coinbase });
// Give some tokens to arbitrage contract
await weth.setBalance(arbitrage.address, takerTokenAmount, { from: coinbase });
await weth.setBalance.sendTransactionAsync(arbitrage.address, takerTokenAmount, { from: coinbase });
// Fund the maker on exchange side
await zrx.setBalance(maker, makerTokenAmount, { from: coinbase });
await zrx.setBalance.sendTransactionAsync(maker, makerTokenAmount, { from: coinbase });
// Set the allowance for the maker on Exchange side
await zrx.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { from: maker });
await zrx.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, { from: maker });
amountGive = ZeroEx.toBaseUnitAmount(new BigNumber(2), 18);
// Fund the maker on EtherDelta side
await weth.setBalance(edMaker, amountGive, { from: coinbase });
await weth.setBalance.sendTransactionAsync(edMaker, amountGive, { from: coinbase });
// Set the allowance for the maker on EtherDelta side
await weth.approve(etherDelta.address, INITIAL_ALLOWANCE, { from: edMaker });
await weth.approve.sendTransactionAsync(etherDelta.address, INITIAL_ALLOWANCE, { from: edMaker });
// Deposit maker funds into EtherDelta
await etherDelta.depositToken.sendTransactionAsync(weth.address, amountGive, { from: edMaker });
amountGet = makerTokenAmount;
// Fund the front runner on EtherDelta side
await zrx.setBalance(edFrontRunner, amountGet, { from: coinbase });
await zrx.setBalance.sendTransactionAsync(edFrontRunner, amountGet, { from: coinbase });
// Set the allowance for the front-runner on EtherDelta side
await zrx.approve(etherDelta.address, INITIAL_ALLOWANCE, { from: edFrontRunner });
await zrx.approve.sendTransactionAsync(etherDelta.address, INITIAL_ALLOWANCE, { from: edFrontRunner });
// Deposit front runner funds into EtherDelta
await etherDelta.depositToken.sendTransactionAsync(zrx.address, amountGet, { from: edFrontRunner });
});
@@ -194,11 +228,11 @@ describe('Arbitrage', () => {
from: coinbase,
});
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
const postBalance = await weth.balanceOf(arbitrage.address);
const postBalance = await weth.balanceOf.callAsync(arbitrage.address);
expect(postBalance).to.be.bignumber.equal(amountGive);
});
it('should fail and revert if front-runned', async () => {
const preBalance = await weth.balanceOf(arbitrage.address);
const preBalance = await weth.balanceOf.callAsync(arbitrage.address);
// Front-running transaction
await etherDelta.trade.sendTransactionAsync(
tokenGet,
@@ -218,7 +252,7 @@ describe('Arbitrage', () => {
await expect(
arbitrage.makeAtomicTrade.sendTransactionAsync(addresses, values, v, r, s, { from: coinbase }),
).to.be.rejectedWith(constants.REVERT);
const postBalance = await weth.balanceOf(arbitrage.address);
const postBalance = await weth.balanceOf.callAsync(arbitrage.address);
expect(preBalance).to.be.bignumber.equal(postBalance);
});
});

View File

@@ -6,12 +6,12 @@ import * as chai from 'chai';
import * as Web3 from 'web3';
import { DummyTokenContract } from '../src/contract_wrappers/generated/dummy_token';
import { artifacts } from '../util/artifacts';
import { constants } from '../util/constants';
import { ContractName } from '../util/types';
import { chaiSetup } from './utils/chai_setup';
import { deployer } from './utils/deployer';
import { provider, web3Wrapper } from './utils/web3_wrapper';
import { provider, txDefaults, web3Wrapper } from './utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -33,8 +33,15 @@ describe('UnlimitedAllowanceToken', () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
owner = accounts[0];
spender = accounts[1];
const tokenInstance = await deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS);
token = new DummyTokenContract(tokenInstance.abi, tokenInstance.address, provider);
token = await DummyTokenContract.deployFrom0xArtifactAsync(
artifacts.DummyToken,
provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
);
await token.mint.sendTransactionAsync(MAX_MINT_VALUE, { from: owner });
tokenAddress = token.address;
});

View File

@@ -1,18 +0,0 @@
import { Deployer } from '@0xproject/deployer';
import { devConstants } from '@0xproject/dev-utils';
import * as path from 'path';
import { constants } from '../../util/constants';
import { web3 } from './web3_wrapper';
const deployerOpts = {
provider: web3.currentProvider,
artifactsDir: path.resolve('lib', 'src', 'artifacts'),
networkId: constants.TESTRPC_NETWORK_ID,
defaults: {
gas: devConstants.GAS_ESTIMATE,
},
};
export const deployer = new Deployer(deployerOpts);

View File

@@ -1,7 +1,11 @@
import { web3Factory } from '@0xproject/dev-utils';
import { devConstants, web3Factory } from '@0xproject/dev-utils';
import { Provider } from '@0xproject/types';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
export const txDefaults = {
from: devConstants.TESTRPC_FIRST_ADDRESS,
gas: devConstants.GAS_ESTIMATE,
};
const providerConfigs = { shouldUseInProcessGanache: true };
export const web3 = web3Factory.create(providerConfigs);
export const provider = web3.currentProvider;

View File

@@ -6,12 +6,12 @@ import * as chai from 'chai';
import * as Web3 from 'web3';
import { ZRXTokenContract } from '../src/contract_wrappers/generated/zrx_token';
import { artifacts } from '../util/artifacts';
import { constants } from '../util/constants';
import { ContractName } from '../util/types';
import { chaiSetup } from './utils/chai_setup';
import { deployer } from './utils/deployer';
import { provider, web3Wrapper } from './utils/web3_wrapper';
import { provider, txDefaults, web3Wrapper } from './utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -34,8 +34,7 @@ describe('ZRXToken', () => {
zeroEx = new ZeroEx(provider, {
networkId: constants.TESTRPC_NETWORK_ID,
});
const zrxInstance = await deployer.deployAsync(ContractName.ZRXToken);
zrx = new ZRXTokenContract(zrxInstance.abi, zrxInstance.address, provider);
zrx = await ZRXTokenContract.deployFrom0xArtifactAsync(artifacts.ZRX, provider, txDefaults);
zrxAddress = zrx.address;
MAX_UINT = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
});

View File

@@ -1,25 +1,31 @@
import { ContractArtifact } from '@0xproject/deployer';
import { ContractArtifact } from '@0xproject/sol-compiler';
import * as DummyTokenArtifact from '../src/artifacts/DummyToken.json';
import * as ExchangeArtifact from '../src/artifacts/Exchange.json';
import * as MaliciousTokenArtifact from '../src/artifacts/MaliciousToken.json';
import * as MultiSigWalletWithTimeLockArtifact from '../src/artifacts/MultiSigWalletWithTimeLock.json';
import * as MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressArtifact from '../src/artifacts/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json';
import * as TokenArtifact from '../src/artifacts/Token.json';
import * as TokenRegistryArtifact from '../src/artifacts/TokenRegistry.json';
import * as TokenTransferProxyArtifact from '../src/artifacts/TokenTransferProxy.json';
import * as EtherTokenArtifact from '../src/artifacts/WETH9.json';
import * as ZRXArtifact from '../src/artifacts/ZRXToken.json';
import * as AccountLevels from '../src/artifacts/AccountLevels.json';
import * as Arbitrage from '../src/artifacts/Arbitrage.json';
import * as DummyToken from '../src/artifacts/DummyToken.json';
import * as EtherDelta from '../src/artifacts/EtherDelta.json';
import * as Exchange from '../src/artifacts/Exchange.json';
import * as MaliciousToken from '../src/artifacts/MaliciousToken.json';
import * as MultiSigWalletWithTimeLock from '../src/artifacts/MultiSigWalletWithTimeLock.json';
import * as MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress from '../src/artifacts/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json';
import * as Token from '../src/artifacts/Token.json';
import * as TokenRegistry from '../src/artifacts/TokenRegistry.json';
import * as TokenTransferProxy from '../src/artifacts/TokenTransferProxy.json';
import * as EtherToken from '../src/artifacts/WETH9.json';
import * as ZRX from '../src/artifacts/ZRXToken.json';
export const artifacts = {
ZRXArtifact: (ZRXArtifact as any) as ContractArtifact,
DummyTokenArtifact: (DummyTokenArtifact as any) as ContractArtifact,
TokenArtifact: (TokenArtifact as any) as ContractArtifact,
ExchangeArtifact: (ExchangeArtifact as any) as ContractArtifact,
EtherTokenArtifact: (EtherTokenArtifact as any) as ContractArtifact,
TokenRegistryArtifact: (TokenRegistryArtifact as any) as ContractArtifact,
MaliciousTokenArtifact: (MaliciousTokenArtifact as any) as ContractArtifact,
TokenTransferProxyArtifact: (TokenTransferProxyArtifact as any) as ContractArtifact,
MultiSigWalletWithTimeLockArtifact: (MultiSigWalletWithTimeLockArtifact as any) as ContractArtifact,
MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressArtifact: (MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressArtifact as any) as ContractArtifact,
AccountLevels: (AccountLevels as any) as ContractArtifact,
Arbitrage: (Arbitrage as any) as ContractArtifact,
EtherDelta: (EtherDelta as any) as ContractArtifact,
ZRX: (ZRX as any) as ContractArtifact,
DummyToken: (DummyToken as any) as ContractArtifact,
Token: (Token as any) as ContractArtifact,
Exchange: (Exchange as any) as ContractArtifact,
EtherToken: (EtherToken as any) as ContractArtifact,
TokenRegistry: (TokenRegistry as any) as ContractArtifact,
MaliciousToken: (MaliciousToken as any) as ContractArtifact,
TokenTransferProxy: (TokenTransferProxy as any) as ContractArtifact,
MultiSigWalletWithTimeLock: (MultiSigWalletWithTimeLock as any) as ContractArtifact,
MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress: (MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress as any) as ContractArtifact,
};

View File

@@ -1,7 +1,4 @@
const DUMMY_TOKEN_NAME = '';
const DUMMY_TOKEN_SYMBOL = '';
const DUMMY_TOKEN_DECIMALS = 18;
const DUMMY_TOKEN_TOTAL_SUPPLY = 0;
import { BigNumber } from '@0xproject/utils';
export const constants = {
INVALID_OPCODE: 'invalid opcode',
@@ -10,5 +7,8 @@ export const constants = {
MAX_ETHERTOKEN_WITHDRAW_GAS: 43000,
MAX_TOKEN_TRANSFERFROM_GAS: 80000,
MAX_TOKEN_APPROVE_GAS: 60000,
DUMMY_TOKEN_ARGS: [DUMMY_TOKEN_NAME, DUMMY_TOKEN_SYMBOL, DUMMY_TOKEN_DECIMALS, DUMMY_TOKEN_TOTAL_SUPPLY],
DUMMY_TOKEN_NAME: '',
DUMMY_TOKEN_SYMBOL: '',
DUMMY_TOKEN_DECIMALS: new BigNumber(18),
DUMMY_TOKEN_TOTAL_SUPPLY: new BigNumber(0),
};

View File

@@ -1,137 +0,0 @@
#!/usr/bin/env node
// We need the above pragma since this script will be run as a command-line tool.
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
import * as path from 'path';
import * as Web3 from 'web3';
import * as yargs from 'yargs';
import { commands } from './commands';
import { constants } from './utils/constants';
import { consoleReporter } from './utils/error_reporter';
import { CliOptions, CompilerOptions, DeployerOptions } from './utils/types';
const DEFAULT_CONTRACTS_DIR = path.resolve('src/contracts');
const DEFAULT_ARTIFACTS_DIR = path.resolve('src/artifacts');
const DEFAULT_NETWORK_ID = 50;
const DEFAULT_JSONRPC_URL = 'http://localhost:8545';
const DEFAULT_GAS_PRICE = (10 ** 9 * 2).toString();
const DEFAULT_CONTRACTS_LIST = '*';
const SEPARATOR = ',';
/**
* Compiles all contracts with options passed in through CLI.
* @param argv Instance of process.argv provided by yargs.
*/
async function onCompileCommandAsync(argv: CliOptions): Promise<void> {
const opts: CompilerOptions = {
contractsDir: argv.contractsDir,
artifactsDir: argv.artifactsDir,
contracts: argv.contracts === DEFAULT_CONTRACTS_LIST ? DEFAULT_CONTRACTS_LIST : argv.contracts.split(SEPARATOR),
};
await commands.compileAsync(opts);
}
/**
* Deploys a single contract with provided name and args.
* @param argv Instance of process.argv provided by yargs.
*/
async function onDeployCommandAsync(argv: CliOptions): Promise<void> {
const url = argv.jsonrpcUrl;
const provider = new Web3.providers.HttpProvider(url);
const web3Wrapper = new Web3Wrapper(provider);
const networkId = await web3Wrapper.getNetworkIdAsync();
const compilerOpts: CompilerOptions = {
contractsDir: argv.contractsDir,
artifactsDir: argv.artifactsDir,
contracts: argv.contracts === DEFAULT_CONTRACTS_LIST ? DEFAULT_CONTRACTS_LIST : argv.contracts.split(SEPARATOR),
};
await commands.compileAsync(compilerOpts);
const defaults = {
gasPrice: new BigNumber(argv.gasPrice),
from: argv.account,
};
const deployerOpts: DeployerOptions = {
artifactsDir: argv.artifactsDir || DEFAULT_ARTIFACTS_DIR,
jsonrpcUrl: argv.jsonrpcUrl,
networkId,
defaults,
};
const deployerArgsString = argv.constructorArgs as string;
const deployerArgs = deployerArgsString.split(SEPARATOR);
await commands.deployAsync(argv.contract as string, deployerArgs, deployerOpts);
}
/**
* Adds additional required options for when the user is calling the deploy command.
* @param yargsInstance yargs instance provided in builder function callback.
*/
function deployCommandBuilder(yargsInstance: any) {
return yargsInstance
.option('network-id', {
type: 'number',
default: DEFAULT_NETWORK_ID,
description: 'mainnet=1, kovan=42, testrpc=50',
})
.option('contract', {
type: 'string',
description: 'name of contract to deploy, excluding .sol extension',
})
.option('constructor-args', {
type: 'string',
description: 'comma separated list of constructor args to deploy contract with',
})
.option('jsonrpc-url', {
type: 'string',
default: DEFAULT_JSONRPC_URL,
description: 'url of JSON RPC',
})
.option('account', {
type: 'string',
description: 'account to use for deploying contracts',
})
.option('gas-price', {
type: 'string',
default: DEFAULT_GAS_PRICE,
description: 'gasPrice to be used for transactions',
})
.demandOption(['contract', 'args', 'account'])
.help().argv;
}
/**
* Adds additional required options for when the user is calling the compile command.
* @param yargsInstance yargs instance provided in builder function callback.
*/
function compileCommandBuilder(yargsInstance: any) {
return yargsInstance
.option('contracts', {
type: 'string',
default: DEFAULT_CONTRACTS_LIST,
description: 'comma separated list of contracts to compile',
})
.help().argv;
}
(() => {
const identityCommandBuilder = _.identity;
return yargs
.option('contracts-dir', {
type: 'string',
description: 'path of contracts directory to compile',
})
.option('artifacts-dir', {
type: 'string',
description: 'path to write contracts artifacts to',
})
.demandCommand(1)
.command('compile', 'compile contracts', compileCommandBuilder, consoleReporter(onCompileCommandAsync))
.command(
'deploy',
'deploy a single contract with provided arguments',
deployCommandBuilder,
consoleReporter(onDeployCommandAsync),
)
.help().argv;
})();

View File

@@ -1,14 +0,0 @@
import { Compiler } from './compiler';
import { Deployer } from './deployer';
import { CompilerOptions, DeployerOptions } from './utils/types';
export const commands = {
async compileAsync(opts: CompilerOptions): Promise<void> {
const compiler = new Compiler(opts);
await compiler.compileAsync();
},
async deployAsync(contractName: string, args: any[], opts: DeployerOptions): Promise<void> {
const deployer = new Deployer(opts);
await deployer.deployAndSaveAsync(contractName, args);
},
};

View File

@@ -1,223 +0,0 @@
import { AbiType, ConstructorAbi, ContractAbi, Provider, TxData } from '@0xproject/types';
import { logUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
import * as solc from 'solc';
import * as Web3 from 'web3';
import { Contract } from './utils/contract';
import { encoder } from './utils/encoder';
import { fsWrapper } from './utils/fs_wrapper';
import {
ContractArtifact,
ContractNetworkData,
DeployerOptions,
ProviderDeployerOptions,
UrlDeployerOptions,
} from './utils/types';
import { utils } from './utils/utils';
// Gas added to gas estimate to make sure there is sufficient gas for deployment.
const EXTRA_GAS = 200000;
/**
* The Deployer facilitates deploying Solidity smart contracts to the blockchain.
* It can be used to build custom migration scripts.
*/
export class Deployer {
public web3Wrapper: Web3Wrapper;
private _artifactsDir: string;
private _networkId: number;
private _defaults: Partial<TxData>;
/**
* Gets data for current version stored in artifact.
* @param contractArtifact The contract artifact.
* @return Version specific contract data.
*/
private static _getContractCompilerOutputFromArtifactIfExists(
contractArtifact: ContractArtifact,
): solc.StandardContractOutput {
const compilerOutputIfExists = contractArtifact.compilerOutput;
if (_.isUndefined(compilerOutputIfExists)) {
throw new Error(`Compiler output not found in artifact for contract: ${contractArtifact.contractName}`);
}
return compilerOutputIfExists;
}
/**
* Instantiate a new instance of the Deployer class.
* @param opts Deployer options, including either an RPC url or Provider instance.
* @returns A Deployer instance
*/
constructor(opts: DeployerOptions) {
this._artifactsDir = opts.artifactsDir;
this._networkId = opts.networkId;
this._defaults = opts.defaults;
let provider: Provider;
if (_.isUndefined((opts as ProviderDeployerOptions).provider)) {
const jsonrpcUrl = (opts as UrlDeployerOptions).jsonrpcUrl;
if (_.isUndefined(jsonrpcUrl)) {
throw new Error(`Deployer options don't contain provider nor jsonrpcUrl. Please pass one of them`);
}
provider = new Web3.providers.HttpProvider(jsonrpcUrl);
} else {
provider = (opts as ProviderDeployerOptions).provider;
}
this.web3Wrapper = new Web3Wrapper(provider, this._defaults);
}
/**
* Loads a contract's corresponding artifacts and deploys it with the supplied constructor arguments.
* @param contractName Name of the contract to deploy. Must match name of an artifact in supplied artifacts directory.
* @param args Array of contract constructor arguments.
* @return Deployed contract instance.
*/
public async deployAsync(contractName: string, args: any[] = []): Promise<Web3.ContractInstance> {
const contractArtifactIfExists: ContractArtifact = this._loadContractArtifactIfExists(contractName);
const compilerOutput = Deployer._getContractCompilerOutputFromArtifactIfExists(contractArtifactIfExists);
const data = compilerOutput.evm.bytecode.object;
const from = await this._getFromAddressAsync();
const gas = await this._getAllowableGasEstimateAsync(data);
const txData = {
gasPrice: this._defaults.gasPrice,
from,
data,
gas,
};
if (_.isUndefined(compilerOutput.abi)) {
throw new Error(`ABI not found in ${contractName} artifacts`);
}
const abi = compilerOutput.abi;
const constructorAbi = _.find(abi, { type: AbiType.Constructor }) as ConstructorAbi;
const constructorArgs = _.isUndefined(constructorAbi) ? [] : constructorAbi.inputs;
if (constructorArgs.length !== args.length) {
const constructorSignature = `constructor(${_.map(constructorArgs, arg => `${arg.type} ${arg.name}`).join(
', ',
)})`;
throw new Error(
`${contractName} expects ${constructorArgs.length} constructor params: ${constructorSignature}. Got ${
args.length
}`,
);
}
const web3ContractInstance = await this._deployFromAbiAsync(abi, args, txData);
logUtils.log(`${contractName}.sol successfully deployed at ${web3ContractInstance.address}`);
const contractInstance = new Contract(web3ContractInstance, this._defaults);
return contractInstance;
}
/**
* Loads a contract's artifact, deploys it with supplied constructor arguments, and saves the updated data
* back to the artifact file.
* @param contractName Name of the contract to deploy. Must match name of an artifact in artifacts directory.
* @param args Array of contract constructor arguments.
* @return Deployed contract instance.
*/
public async deployAndSaveAsync(contractName: string, args: any[] = []): Promise<Web3.ContractInstance> {
const contractInstance = await this.deployAsync(contractName, args);
await this._saveContractDataToArtifactAsync(contractName, contractInstance.address, args);
return contractInstance;
}
/**
* Deploys a contract given its ABI, arguments, and transaction data.
* @param abi ABI of contract to deploy.
* @param args Constructor arguments to use in deployment.
* @param txData Tx options used for deployment.
* @return Promise that resolves to a web3 contract instance.
*/
private async _deployFromAbiAsync(abi: ContractAbi, args: any[], txData: TxData): Promise<any> {
const contract: Web3.Contract<Web3.ContractInstance> = this.web3Wrapper.getContractFromAbi(abi);
const deployPromise = new Promise((resolve, reject) => {
/**
* Contract is inferred as 'any' because TypeScript
* is not able to read 'new' from the Contract interface
*/
(contract as any).new(...args, txData, (err: Error, res: any): any => {
if (err) {
reject(err);
} else if (_.isUndefined(res.address) && !_.isUndefined(res.transactionHash)) {
logUtils.log(`transactionHash: ${res.transactionHash}`);
} else {
resolve(res);
}
});
});
return deployPromise;
}
/**
* Updates a contract artifact's address and encoded constructor arguments.
* @param contractName Name of contract. Must match an existing artifact.
* @param contractAddress Contract address to save to artifact.
* @param args Contract constructor arguments that will be encoded and saved to artifact.
*/
private async _saveContractDataToArtifactAsync(
contractName: string,
contractAddress: string,
args: any[],
): Promise<void> {
const contractArtifactIfExists: ContractArtifact = this._loadContractArtifactIfExists(contractName);
const compilerOutput = Deployer._getContractCompilerOutputFromArtifactIfExists(contractArtifactIfExists);
if (_.isUndefined(compilerOutput.abi)) {
throw new Error(`ABI not found in ${contractName} artifacts`);
}
const abi = compilerOutput.abi;
const encodedConstructorArgs = encoder.encodeConstructorArgsFromAbi(args, abi);
const newContractData: ContractNetworkData = {
address: contractAddress,
links: {},
constructorArgs: encodedConstructorArgs,
};
const newArtifact = {
...contractArtifactIfExists,
networks: {
...contractArtifactIfExists.networks,
[this._networkId]: newContractData,
},
};
const artifactString = utils.stringifyWithFormatting(newArtifact);
const artifactPath = `${this._artifactsDir}/${contractName}.json`;
await fsWrapper.writeFileAsync(artifactPath, artifactString);
}
/**
* Loads a contract artifact, if it exists.
* @param contractName Name of the contract, without the extension.
* @return The contract artifact.
*/
private _loadContractArtifactIfExists(contractName: string): ContractArtifact {
const artifactPath = `${this._artifactsDir}/${contractName}.json`;
try {
const contractArtifact: ContractArtifact = require(artifactPath);
return contractArtifact;
} catch (err) {
throw new Error(`Artifact not found for contract: ${contractName} at ${artifactPath}`);
}
}
/**
* Gets the address to use for sending a transaction.
* @return The default from address. If not specified, returns the first address accessible by web3.
*/
private async _getFromAddressAsync(): Promise<string> {
let from: string;
if (_.isUndefined(this._defaults.from)) {
const accounts = await this.web3Wrapper.getAvailableAddressesAsync();
from = accounts[0];
} else {
from = this._defaults.from;
}
return from;
}
/**
* Estimates the gas required for a transaction.
* If gas would be over the block gas limit, the max allowable gas is returned instead.
* @param data Bytecode to estimate gas for.
* @return Gas estimate for transaction data.
*/
private async _getAllowableGasEstimateAsync(data: string): Promise<number> {
const block = await this.web3Wrapper.getBlockAsync('latest');
let gas: number;
try {
const gasEstimate: number = await this.web3Wrapper.estimateGasAsync({ data });
gas = Math.min(gasEstimate + EXTRA_GAS, block.gasLimit);
} catch (err) {
gas = block.gasLimit;
}
return gas;
}
}

View File

@@ -1,80 +0,0 @@
import { schemas, SchemaValidator } from '@0xproject/json-schemas';
import { AbiType, ContractAbi, EventAbi, FunctionAbi, MethodAbi, TxData } from '@0xproject/types';
import { promisify } from '@0xproject/utils';
import * as _ from 'lodash';
import * as Web3 from 'web3';
export class Contract implements Web3.ContractInstance {
public address: string;
public abi: ContractAbi;
private _contract: Web3.ContractInstance;
private _defaults: Partial<TxData>;
private _validator: SchemaValidator;
// This class instance is going to be populated with functions and events depending on the ABI
// and we don't know their types in advance
[name: string]: any;
constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<TxData>) {
this._contract = web3ContractInstance;
this.address = web3ContractInstance.address;
this.abi = web3ContractInstance.abi;
this._defaults = defaults;
this._populateEvents();
this._populateFunctions();
this._validator = new SchemaValidator();
}
private _populateFunctions(): void {
const functionsAbi = _.filter(this.abi, abiPart => abiPart.type === AbiType.Function) as FunctionAbi[];
_.forEach(functionsAbi, (functionAbi: MethodAbi) => {
if (functionAbi.constant) {
const cbStyleCallFunction = this._contract[functionAbi.name].call;
this[functionAbi.name] = promisify(cbStyleCallFunction, this._contract);
this[functionAbi.name].call = promisify(cbStyleCallFunction, this._contract);
} else {
const cbStyleFunction = this._contract[functionAbi.name];
const cbStyleCallFunction = this._contract[functionAbi.name].call;
const cbStyleEstimateGasFunction = this._contract[functionAbi.name].estimateGas;
this[functionAbi.name] = this._promisifyWithDefaultParams(cbStyleFunction);
this[functionAbi.name].estimateGasAsync = promisify(cbStyleEstimateGasFunction);
this[functionAbi.name].sendTransactionAsync = this._promisifyWithDefaultParams(cbStyleFunction);
this[functionAbi.name].call = promisify(cbStyleCallFunction, this._contract);
}
});
}
private _populateEvents(): void {
const eventsAbi = _.filter(this.abi, abiPart => abiPart.type === AbiType.Event) as EventAbi[];
_.forEach(eventsAbi, (eventAbi: EventAbi) => {
this[eventAbi.name] = this._contract[eventAbi.name];
});
}
private _promisifyWithDefaultParams(fn: (...args: any[]) => void): (...args: any[]) => Promise<any> {
const promisifiedWithDefaultParams = async (...args: any[]) => {
const promise = new Promise((resolve, reject) => {
const lastArg = args[args.length - 1];
let txData: Partial<TxData> = {};
if (this._isTxData(lastArg)) {
txData = args.pop();
}
txData = {
...this._defaults,
...txData,
};
const callback = (err: Error, data: any) => {
if (_.isNull(err)) {
resolve(data);
} else {
reject(err);
}
};
args.push(txData);
args.push(callback);
fn.apply(this._contract, args);
});
return promise;
};
return promisifiedWithDefaultParams;
}
private _isTxData(lastArg: any): boolean {
const isValid = this._validator.isValid(lastArg, schemas.txDataSchema);
return isValid;
}
}

View File

@@ -1,18 +0,0 @@
import { logUtils } from '@0xproject/utils';
/**
* Makes an async function no-throw printing errors to the console
* @param asyncFn async function to wrap
* @return Wrapped version of the passed function
*/
export function consoleReporter<T>(asyncFn: (arg: T) => Promise<void>): (arg: T) => Promise<void> {
const noThrowFnAsync = async (arg: T) => {
try {
const result = await asyncFn(arg);
return result;
} catch (err) {
logUtils.log(`${err}`);
}
};
return noThrowFnAsync;
}

View File

@@ -1,8 +0,0 @@
export const utils = {
stringifyWithFormatting(obj: any): string {
const jsonReplacer: null = null;
const numberOfJsonSpaces = 4;
const stringifiedObj = JSON.stringify(obj, jsonReplacer, numberOfJsonSpaces);
return stringifiedObj;
},
};

View File

@@ -1,74 +0,0 @@
import * as chai from 'chai';
import 'mocha';
import { Compiler } from '../src/compiler';
import { Deployer } from '../src/deployer';
import { fsWrapper } from '../src/utils/fs_wrapper';
import { CompilerOptions, ContractArtifact, ContractNetworkData, DoneCallback } from '../src/utils/types';
import { constructor_args, exchange_binary } from './fixtures/exchange_bin';
import { constants } from './util/constants';
import { provider } from './util/provider';
const expect = chai.expect;
describe('#Deployer', () => {
const artifactsDir = `${__dirname}/fixtures/artifacts`;
const contractsDir = `${__dirname}/fixtures/contracts`;
const exchangeArtifactPath = `${artifactsDir}/Exchange.json`;
const compilerOpts: CompilerOptions = {
artifactsDir,
contractsDir,
contracts: constants.contracts,
};
const compiler = new Compiler(compilerOpts);
const deployerOpts = {
artifactsDir,
networkId: constants.networkId,
provider,
defaults: {
gasPrice: constants.gasPrice,
},
};
const deployer = new Deployer(deployerOpts);
beforeEach(function(done: DoneCallback) {
this.timeout(constants.timeoutMs);
(async () => {
if (fsWrapper.doesPathExistSync(exchangeArtifactPath)) {
await fsWrapper.removeFileAsync(exchangeArtifactPath);
}
await compiler.compileAsync();
done();
})().catch(done);
});
describe('#deployAsync', () => {
it('should deploy the Exchange contract without updating the Exchange artifact', async () => {
const exchangeConstructorArgs = [constants.zrxTokenAddress, constants.tokenTransferProxyAddress];
const exchangeContractInstance = await deployer.deployAsync('Exchange', exchangeConstructorArgs);
const opts = {
encoding: 'utf8',
};
const exchangeArtifactString = await fsWrapper.readFileAsync(exchangeArtifactPath, opts);
const exchangeArtifact: ContractArtifact = JSON.parse(exchangeArtifactString);
const exchangeContractData: ContractNetworkData = exchangeArtifact.networks[constants.networkId];
const exchangeAddress = exchangeContractInstance.address;
expect(exchangeAddress).to.not.equal(undefined);
expect(exchangeContractData).to.equal(undefined);
});
});
describe('#deployAndSaveAsync', () => {
it('should save the correct contract address and constructor arguments to the Exchange artifact', async () => {
const exchangeConstructorArgs = [constants.zrxTokenAddress, constants.tokenTransferProxyAddress];
const exchangeContractInstance = await deployer.deployAndSaveAsync('Exchange', exchangeConstructorArgs);
const opts = {
encoding: 'utf8',
};
const exchangeArtifactString = await fsWrapper.readFileAsync(exchangeArtifactPath, opts);
const exchangeArtifact: ContractArtifact = JSON.parse(exchangeArtifactString);
const exchangeContractData: ContractNetworkData = exchangeArtifact.networks[constants.networkId];
const exchangeAddress = exchangeContractInstance.address;
expect(exchangeAddress).to.be.equal(exchangeContractData.address);
expect(constructor_args).to.be.equal(exchangeContractData.constructorArgs);
});
});
});

View File

@@ -13,7 +13,7 @@
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"clean": "shx rm -rf lib scripts",
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
"lint": "tslint --project .",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js"
},
"license": "Apache-2.0",

View File

@@ -15,8 +15,7 @@ export const coverage = {
_getCoverageSubprovider(): CoverageSubprovider {
const artifactsPath = '../migrations/artifacts/1.0.0';
const contractsPath = 'src/contracts';
const networkId = 50;
const defaultFromAddress = constants.TESTRPC_FIRST_ADDRESS;
return new CoverageSubprovider(artifactsPath, contractsPath, networkId, defaultFromAddress);
return new CoverageSubprovider(artifactsPath, contractsPath, defaultFromAddress);
},
};

View File

@@ -60,9 +60,9 @@ export const web3Factory = {
provider.addProvider(
new GanacheSubprovider({
logger,
verbose: env.parseBoolean(EnvVars.SolidityCoverage),
verbose: env.parseBoolean(EnvVars.VerboseGanache),
port: 8545,
networkId: 50,
network_id: 50,
mnemonic: 'concert load couple harbor equip island argue ramp clarify fence smart topic',
}),
);

View File

@@ -6,7 +6,7 @@
"types": "lib/src/index.d.ts",
"scripts": {
"build:watch": "tsc -w",
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
"lint": "tslint --project .",
"test": "run-s clean build run_mocha",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",

View File

@@ -18,14 +18,14 @@
"coverage:report:html": "istanbul report html && open coverage/index.html",
"coverage:report:lcov": "istanbul report lcov",
"test:circleci": "yarn test:coverage",
"compile": "node ../deployer/lib/src/cli.js compile"
"compile": "node ../sol-compiler/lib/src/cli.js compile"
},
"author": "",
"license": "Apache-2.0",
"dependencies": {
"@0xproject/abi-gen": "^0.2.13",
"@0xproject/base-contract": "^0.3.1",
"@0xproject/deployer": "^0.4.3",
"@0xproject/sol-compiler": "^0.4.3",
"@0xproject/sol-cov": "^0.0.10",
"@0xproject/subproviders": "^0.10.1",
"@0xproject/tslint-config": "^0.4.17",

4
packages/metacoin/src/global.d.ts vendored Normal file
View File

@@ -0,0 +1,4 @@
declare module '*.json' {
const value: any;
export default value;
}

View File

@@ -1,15 +1,19 @@
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
import { ContractArtifact } from '@0xproject/sol-compiler';
import { LogWithDecodedArgs } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
import * as MetacoinArtifact from '../artifacts/Metacoin.json';
import { MetacoinContract, TransferContractEventArgs } from '../src/contract_wrappers/metacoin';
import { chaiSetup } from './utils/chai_setup';
import { deployer } from './utils/deployer';
import { config } from './utils/config';
import { provider, web3Wrapper } from './utils/web3_wrapper';
const artifact: ContractArtifact = MetacoinArtifact as any;
chaiSetup.configure();
const { expect } = chai;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
@@ -19,9 +23,8 @@ describe('Metacoin', () => {
const ownerAddress = devConstants.TESTRPC_FIRST_ADDRESS;
const INITIAL_BALANCE = new BigNumber(10000);
before(async () => {
const metacoinInstance = await deployer.deployAsync('Metacoin');
web3Wrapper.abiDecoder.addABI(metacoinInstance.abi);
metacoin = new MetacoinContract(metacoinInstance.abi, metacoinInstance.address, provider);
metacoin = await MetacoinContract.deployFrom0xArtifactAsync(artifact, provider, config.txDefaults);
web3Wrapper.abiDecoder.addABI(metacoin.abi);
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();

View File

@@ -1,3 +1,4 @@
import { devConstants } from '@0xproject/dev-utils';
import * as path from 'path';
export const config = {
@@ -5,5 +6,8 @@ export const config = {
artifactsDir: path.resolve(__dirname, '../../artifacts'),
contractsDir: path.resolve(__dirname, '../../contracts'),
ganacheLogFile: 'ganache.log',
txDefaults: {
from: devConstants.TESTRPC_FIRST_ADDRESS,
},
mnemonic: 'concert load couple harbor equip island argue ramp clarify fence smart topic',
};

View File

@@ -15,6 +15,6 @@ export const coverage = {
},
_getCoverageSubprovider(): CoverageSubprovider {
const defaultFromAddress = devConstants.TESTRPC_FIRST_ADDRESS;
return new CoverageSubprovider(config.artifactsDir, config.contractsDir, config.networkId, defaultFromAddress);
return new CoverageSubprovider(config.artifactsDir, config.contractsDir, defaultFromAddress);
},
};

View File

@@ -1,17 +0,0 @@
import { Deployer } from '@0xproject/deployer';
import { devConstants } from '@0xproject/dev-utils';
import * as path from 'path';
import { config } from './config';
import { web3Wrapper } from './web3_wrapper';
const deployerOpts = {
provider: web3Wrapper.getProvider(),
artifactsDir: config.artifactsDir,
networkId: config.networkId,
defaults: {
from: devConstants.TESTRPC_FIRST_ADDRESS,
},
};
export const deployer = new Deployer(deployerOpts);

View File

@@ -0,0 +1,20 @@
{
"artifactsDir": "artifacts/1.0.0",
"contractsDir": "../contracts/src/contracts",
"contracts": [
"Exchange",
"DummyToken",
"ZRXToken",
"Token",
"WETH9",
"TokenTransferProxy",
"MultiSigWallet",
"MultiSigWalletWithTimeLock",
"MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress",
"MaliciousToken",
"TokenRegistry",
"Arbitrage",
"EtherDelta",
"AccountLevels"
]
}

View File

@@ -6,20 +6,24 @@
"types": "lib/index.d.ts",
"scripts": {
"build:watch": "tsc -w",
"prebuild": "run-s clean compile copy_artifacts generate_contract_wrappers",
"copy_artifacts": "copyfiles -u 4 'artifacts/1.0.0/**/*' ./lib/src/artifacts",
"build": "tsc",
"clean": "shx rm -rf lib",
"lint": "tslint --project . 'src/**/*.ts'",
"lint": "tslint --project .",
"migrate": "run-s build compile script:migrate",
"script:migrate": "node ./lib/migrate.js",
"copy_artifacts": "copyfiles 'src/artifacts/**/*' ./lib",
"compile": "node ../deployer/lib/src/cli.js compile --contracts ${npm_package_config_contracts} --contracts-dir ../contracts/src/contracts --artifacts-dir src/artifacts"
"copy_artifacts": "copyfiles 'artifacts/1.0.0/**/*' ./lib",
"generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis ${npm_package_config_abis} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers --backend ethers && prettier --write 'src/contract_wrappers/**.ts'",
"compile": "node ../sol-compiler/lib/src/cli.js compile"
},
"config": {
"contracts": "Exchange,DummyToken,ZRXToken,Token,WETH9,TokenTransferProxy,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,MaliciousToken,TokenRegistry,Arbitrage,EtherDelta,AccountLevels"
"abis": "artifacts/1.0.0/@(DummyToken|TokenTransferProxy|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|Arbitrage|EtherDelta|AccountLevels|WETH9|MaliciousToken).json"
},
"license": "Apache-2.0",
"devDependencies": {
"@0xproject/dev-utils": "^0.4.1",
"@0xproject/types": "^0.6.3",
"@0xproject/tslint-config": "^0.4.17",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
@@ -27,9 +31,12 @@
"typescript": "2.7.1"
},
"dependencies": {
"@0xproject/deployer": "^0.4.3",
"@0xproject/sol-compiler": "^0.4.3",
"@0xproject/base-contract": "^0.3.1",
"@0xproject/typescript-typings": "^0.3.1",
"@0xproject/utils": "^0.6.1",
"@0xproject/web3-wrapper": "^0.6.3",
"ethers": "^3.0.15",
"lodash": "^4.17.4"
},
"publishConfig": {

View File

@@ -0,0 +1,26 @@
import { BaseContract } from '@0xproject/base-contract';
import { ContractArtifact } from '@0xproject/sol-compiler';
import * as fs from 'fs';
import * as path from 'path';
export class ArtifactWriter {
private _artifactsDir: string;
private _networkId: number;
constructor(artifactsDir: string, networkId: number) {
this._artifactsDir = artifactsDir;
this._networkId = networkId;
}
// This updates the artifact file but does not update the `artifacts` module above. It will not
// contain the saved artifact changes.
public saveArtifact(contract: BaseContract): void {
const contractName = contract.contractName;
const artifactFile = path.join(this._artifactsDir, `${contractName}.json`);
const artifact: ContractArtifact = JSON.parse(fs.readFileSync(artifactFile).toString());
artifact.networks[this._networkId] = {
address: contract.address,
links: {},
constructorArgs: JSON.stringify(contract.constructorArgs),
};
fs.writeFileSync(artifactFile, JSON.stringify(artifact, null, '\t'));
}
}

View File

@@ -0,0 +1,31 @@
import { ContractArtifact } from '@0xproject/sol-compiler';
import * as AccountLevels from '../artifacts/1.0.0/AccountLevels.json';
import * as Arbitrage from '../artifacts/1.0.0/Arbitrage.json';
import * as DummyToken from '../artifacts/1.0.0/DummyToken.json';
import * as EtherDelta from '../artifacts/1.0.0/EtherDelta.json';
import * as Exchange from '../artifacts/1.0.0/Exchange.json';
import * as MaliciousToken from '../artifacts/1.0.0/MaliciousToken.json';
import * as MultiSigWalletWithTimeLock from '../artifacts/1.0.0/MultiSigWalletWithTimeLock.json';
import * as MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress from '../artifacts/1.0.0/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json';
import * as Token from '../artifacts/1.0.0/Token.json';
import * as TokenRegistry from '../artifacts/1.0.0/TokenRegistry.json';
import * as TokenTransferProxy from '../artifacts/1.0.0/TokenTransferProxy.json';
import * as EtherToken from '../artifacts/1.0.0/WETH9.json';
import * as ZRX from '../artifacts/1.0.0/ZRXToken.json';
export const artifacts = {
AccountLevels: (AccountLevels as any) as ContractArtifact,
Arbitrage: (Arbitrage as any) as ContractArtifact,
EtherDelta: (EtherDelta as any) as ContractArtifact,
ZRX: (ZRX as any) as ContractArtifact,
DummyToken: (DummyToken as any) as ContractArtifact,
Token: (Token as any) as ContractArtifact,
Exchange: (Exchange as any) as ContractArtifact,
EtherToken: (EtherToken as any) as ContractArtifact,
TokenRegistry: (TokenRegistry as any) as ContractArtifact,
MaliciousToken: (MaliciousToken as any) as ContractArtifact,
TokenTransferProxy: (TokenTransferProxy as any) as ContractArtifact,
MultiSigWalletWithTimeLock: (MultiSigWalletWithTimeLock as any) as ContractArtifact,
MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress: (MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress as any) as ContractArtifact,
};

View File

@@ -1,24 +1,21 @@
#!/usr/bin/env node
import { Deployer } from '@0xproject/deployer';
import { devConstants } from '@0xproject/dev-utils';
import { devConstants, web3Factory } from '@0xproject/dev-utils';
import { Provider } from '@0xproject/types';
import { logUtils } from '@0xproject/utils';
import * as path from 'path';
import { runMigrationsAsync } from './migration';
(async () => {
const deployerOpts = {
jsonrpcUrl: 'http://localhost:8545',
artifactsDir: path.resolve('src', 'artifacts'),
networkId: 50,
defaults: {
gas: devConstants.GAS_ESTIMATE,
},
const txDefaults = {
from: devConstants.TESTRPC_FIRST_ADDRESS,
};
const deployer = new Deployer(deployerOpts);
await runMigrationsAsync(deployer);
const providerConfigs = { shouldUseInProcessGanache: false };
const web3 = web3Factory.create(providerConfigs);
const provider = web3.currentProvider;
const artifactsDir = 'artifacts/1.0.0';
await runMigrationsAsync(provider, artifactsDir, txDefaults);
process.exit(0);
})().catch(err => {
logUtils.log(err);
process.exit(1);

View File

@@ -1,8 +1,17 @@
import { Deployer } from '@0xproject/deployer';
import { Provider, TxData } from '@0xproject/types';
import { BigNumber, NULL_BYTES } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
import { ArtifactWriter } from './artifact_writer';
import { artifacts } from './artifacts';
import { DummyTokenContract } from './contract_wrappers/dummy_token';
import { ExchangeContract } from './contract_wrappers/exchange';
import { MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract } from './contract_wrappers/multi_sig_wallet_with_time_lock_except_remove_authorized_address';
import { TokenRegistryContract } from './contract_wrappers/token_registry';
import { TokenTransferProxyContract } from './contract_wrappers/token_transfer_proxy';
import { WETH9Contract } from './contract_wrappers/weth9';
import { ZRXTokenContract } from './contract_wrappers/zrx_token';
import { ContractName } from './types';
import { tokenInfo } from './utils/token_info';
@@ -10,27 +19,54 @@ import { tokenInfo } from './utils/token_info';
* Custom migrations should be defined in this function. This will be called with the CLI 'migrate' command.
* Migrations could be written to run in parallel, but if you want contract addresses to be created deterministically,
* the migration should be written to run synchronously.
* @param deployer Deployer instance.
* @param provider Web3 provider instance.
* @param artifactsDir The directory with compiler artifact files.
* @param txDefaults Default transaction values to use when deploying contracts.
*/
export const runMigrationsAsync = async (deployer: Deployer) => {
const web3Wrapper: Web3Wrapper = deployer.web3Wrapper;
export const runMigrationsAsync = async (provider: Provider, artifactsDir: string, txDefaults: Partial<TxData>) => {
const web3Wrapper = new Web3Wrapper(provider);
const networkId = await web3Wrapper.getNetworkIdAsync();
const artifactsWriter = new ArtifactWriter(artifactsDir, networkId);
const tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync(
artifacts.TokenTransferProxy,
provider,
txDefaults,
);
artifactsWriter.saveArtifact(tokenTransferProxy);
const zrxToken = await ZRXTokenContract.deployFrom0xArtifactAsync(artifacts.ZRX, provider, txDefaults);
artifactsWriter.saveArtifact(zrxToken);
const etherToken = await WETH9Contract.deployFrom0xArtifactAsync(artifacts.EtherToken, provider, txDefaults);
artifactsWriter.saveArtifact(etherToken);
const tokenReg = await TokenRegistryContract.deployFrom0xArtifactAsync(
artifacts.TokenRegistry,
provider,
txDefaults,
);
artifactsWriter.saveArtifact(tokenReg);
const accounts: string[] = await web3Wrapper.getAvailableAddressesAsync();
const tokenTransferProxy = await deployer.deployAndSaveAsync(ContractName.TokenTransferProxy);
const zrxToken = await deployer.deployAndSaveAsync(ContractName.ZRXToken);
const etherToken = await deployer.deployAndSaveAsync(ContractName.WETH9);
const tokenReg = await deployer.deployAndSaveAsync(ContractName.TokenRegistry);
const exchangeArgs = [zrxToken.address, tokenTransferProxy.address];
const owners = [accounts[0], accounts[1]];
const confirmationsRequired = new BigNumber(2);
const secondsRequired = new BigNumber(0);
const multiSigArgs = [owners, confirmationsRequired, secondsRequired, tokenTransferProxy.address];
const exchange = await deployer.deployAndSaveAsync(ContractName.Exchange, exchangeArgs);
const multiSig = await deployer.deployAndSaveAsync(
ContractName.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,
multiSigArgs,
const exchange = await ExchangeContract.deployFrom0xArtifactAsync(
artifacts.Exchange,
provider,
txDefaults,
zrxToken.address,
tokenTransferProxy.address,
);
artifactsWriter.saveArtifact(exchange);
const multiSig = await MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract.deployFrom0xArtifactAsync(
artifacts.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,
provider,
txDefaults,
owners,
confirmationsRequired,
secondsRequired,
tokenTransferProxy.address,
);
artifactsWriter.saveArtifact(multiSig);
const owner = accounts[0];
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: owner });
@@ -70,8 +106,15 @@ export const runMigrationsAsync = async (deployer: Deployer) => {
);
for (const token of tokenInfo) {
const totalSupply = new BigNumber(100000000000000000000);
const args = [token.name, token.symbol, token.decimals, totalSupply];
const dummyToken = await deployer.deployAsync(ContractName.DummyToken, args);
const dummyToken = await DummyTokenContract.deployFrom0xArtifactAsync(
artifacts.DummyToken,
provider,
txDefaults,
token.name,
token.symbol,
token.decimals,
totalSupply,
);
await tokenReg.addToken.sendTransactionAsync(
dummyToken.address,
token.name,

View File

@@ -1,3 +1,5 @@
import { BigNumber } from '@0xproject/utils';
export interface MultiSigConfig {
owners: string[];
confirmationsRequired: number;
@@ -12,7 +14,7 @@ export interface Token {
address?: string;
name: string;
symbol: string;
decimals: number;
decimals: BigNumber;
ipfsHash: string;
swarmHash: string;
}

View File

@@ -1,4 +1,4 @@
import { NULL_BYTES } from '@0xproject/utils';
import { BigNumber, NULL_BYTES } from '@0xproject/utils';
import { Token } from '../types';
@@ -6,35 +6,35 @@ export const tokenInfo: Token[] = [
{
name: 'Augur Reputation Token',
symbol: 'REP',
decimals: 18,
decimals: new BigNumber(18),
ipfsHash: NULL_BYTES,
swarmHash: NULL_BYTES,
},
{
name: 'Digix DAO Token',
symbol: 'DGD',
decimals: 18,
decimals: new BigNumber(18),
ipfsHash: NULL_BYTES,
swarmHash: NULL_BYTES,
},
{
name: 'Golem Network Token',
symbol: 'GNT',
decimals: 18,
decimals: new BigNumber(18),
ipfsHash: NULL_BYTES,
swarmHash: NULL_BYTES,
},
{
name: 'MakerDAO',
symbol: 'MKR',
decimals: 18,
decimals: new BigNumber(18),
ipfsHash: NULL_BYTES,
swarmHash: NULL_BYTES,
},
{
name: 'Melon Token',
symbol: 'MLN',
decimals: 18,
decimals: new BigNumber(18),
ipfsHash: NULL_BYTES,
swarmHash: NULL_BYTES,
},

View File

@@ -6,7 +6,7 @@
"types": "lib/index.d.ts",
"scripts": {
"build:watch": "tsc -w",
"lint": "tslint --project . 'src/**/*.ts'",
"lint": "tslint --project .",
"clean": "shx rm -rf lib",
"build": "tsc",
"test:publish": "run-s build script:publish",

View File

@@ -10,7 +10,7 @@ import { constants } from './constants';
import { utils } from './utils';
// For some reason, `depcheck` hangs on some packages. Add them here.
const IGNORE_PACKAGES = ['@0xproject/deployer'];
const IGNORE_PACKAGES = ['@0xproject/sol-compiler'];
(async () => {
utils.log('*** NOTE: Not all deps listed here are actually not required. ***');

View File

@@ -32,7 +32,7 @@ const packageNameToWebsitePath: { [name: string]: string } = {
contracts: 'contracts',
connect: 'connect',
'json-schemas': 'json-schemas',
deployer: 'deployer',
'sol-compiler': 'sol-compiler',
'sol-cov': 'sol-cov',
subproviders: 'subproviders',
'order-utils': 'order-utils',
@@ -214,7 +214,7 @@ async function updateChangeLogsAsync(updatedPublicLernaPackages: LernaPackage[])
}
// Save updated CHANGELOG.json
fs.writeFileSync(changelogJSONPath, JSON.stringify(changelogs, null, 4));
fs.writeFileSync(changelogJSONPath, JSON.stringify(changelogs, null, '\t'));
await utils.prettifyAsync(changelogJSONPath, constants.monorepoRootPath);
utils.log(`${packageName}: Updated CHANGELOG.json`);
// Generate updated CHANGELOG.md

View File

@@ -46,7 +46,7 @@ import { utils } from './utils';
include: ['index.ts'],
};
const tsconfigFilePath = path.join(testDirectory, 'tsconfig.json');
fs.writeFileSync(tsconfigFilePath, JSON.stringify(tsConfig, null, 4));
fs.writeFileSync(tsconfigFilePath, JSON.stringify(tsConfig, null, '\t'));
utils.log(`Compiling ${packageName}`);
const tscBinaryPath = path.join(monorepoRootPath, './node_modules/typescript/bin/tsc');
await execAsync(tscBinaryPath, { cwd: testDirectory });

View File

@@ -4,7 +4,7 @@
"version": "0.0.11",
"description": "An example app using react-docs",
"scripts": {
"lint": "tslint --project . 'ts/**/*.ts' 'ts/**/*.tsx'",
"lint": "tslint --project .",
"build": "tsc",
"build:example": "NODE_ENV=production webpack",
"build:watch": "tsc -w",

View File

@@ -5,7 +5,7 @@
"main": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": {
"lint": "tslint --project . 'src/**/*.ts' 'src/**/*.tsx'",
"lint": "tslint --project .",
"build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts",
"build:watch": "tsc -w",
"clean": "shx rm -rf lib scripts",

View File

@@ -5,7 +5,7 @@
"main": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": {
"lint": "tslint --project . 'src/**/*.ts' 'src/**/*.tsx'",
"lint": "tslint --project .",
"build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts",
"build:watch": "tsc -w",
"clean": "shx rm -rf lib scripts",

View File

@@ -1,21 +1,21 @@
## @0xproject/deployer
## @0xproject/sol-compiler
This repository contains a CLI tool that facilitates compiling and deployment of smart contracts.
This repository contains a CLI tool that facilitates compiling smart contracts.
### Read the [Documentation](https://0xproject.com/docs/deployer).
### Read the [Documentation](https://0xproject.com/docs/sol-compiler).
## Installation
#### CLI Installation
```bash
yarn global add @0xproject/deployer
yarn global add @0xproject/sol-compiler
```
#### API Installation
```bash
yarn add @0xproject/deployer
yarn add @0xproject/sol-compiler
```
If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`:
@@ -29,14 +29,13 @@ If your project is in [TypeScript](https://www.typescriptlang.org/), add the fol
**Import**
```typescript
import { Deployer, Compiler } from '@0xproject/deployer';
import { Compiler } from '@0xproject/sol-compiler';
```
or
```javascript
var Deployer = require('@0xproject/deployer').Deployer;
var Compiler = require('@0xproject/deployer').Compiler;
var Compiler = require('@0xproject/sol-compiler').Compiler;
```
## Contributing

View File

@@ -1,7 +1,7 @@
{
"name": "@0xproject/deployer",
"name": "@0xproject/sol-compiler",
"version": "0.4.3",
"description": "Smart contract deployer of 0x protocol",
"description": "Solidity compiler wrapper and artifactor",
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
@@ -14,7 +14,7 @@
"compile": "npm run build; node lib/src/cli.js compile",
"clean": "shx rm -rf lib scripts",
"migrate": "npm run build; node lib/src/cli.js migrate",
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
"lint": "tslint --project .",
"test:circleci": "yarn test:coverage",
"docs:stage": "yarn build && node ./scripts/stage_docs.js",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js",
@@ -28,13 +28,13 @@
"extraFileIncludes": [
"../types/src/index.ts"
],
"s3BucketPath": "s3://doc-jsons/deployer/",
"s3StagingBucketPath": "s3://staging-doc-jsons/deployer/"
"s3BucketPath": "s3://doc-jsons/sol-compiler/",
"s3StagingBucketPath": "s3://staging-doc-jsons/sol-compiler/"
}
}
},
"bin": {
"0x-deployer": "lib/src/cli.js"
"sol-compiler": "lib/src/cli.js"
},
"repository": {
"type": "git",
@@ -45,7 +45,7 @@
"bugs": {
"url": "https://github.com/0xProject/0x-monorepo/issues"
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/deployer/README.md",
"homepage": "https://github.com/0xProject/0x-monorepo/packages/sol-compiler/README.md",
"devDependencies": {
"@0xproject/dev-utils": "^0.4.1",
"@0xproject/monorepo-scripts": "^0.1.19",

View File

@@ -0,0 +1,46 @@
#!/usr/bin/env node
// We need the above pragma since this script will be run as a command-line tool.
import { BigNumber, logUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
import * as path from 'path';
import * as Web3 from 'web3';
import * as yargs from 'yargs';
import { Compiler } from './compiler';
import { constants } from './utils/constants';
import { CompilerOptions } from './utils/types';
const DEFAULT_CONTRACTS_LIST = '*';
const SEPARATOR = ',';
(async () => {
const argv = yargs
.option('contracts-dir', {
type: 'string',
description: 'path of contracts directory to compile',
})
.option('artifacts-dir', {
type: 'string',
description: 'path to write contracts artifacts to',
})
.option('contracts', {
type: 'string',
description: 'comma separated list of contracts to compile',
})
.help().argv;
const contracts = _.isUndefined(argv.contracts)
? undefined
: argv.contracts === DEFAULT_CONTRACTS_LIST ? DEFAULT_CONTRACTS_LIST : argv.contracts.split(SEPARATOR);
const opts: CompilerOptions = {
contractsDir: argv.contractsDir,
artifactsDir: argv.artifactsDir,
contracts,
};
const compiler = new Compiler(opts);
await compiler.compileAsync();
})().catch(err => {
logUtils.log(err);
process.exit(1);
});

View File

@@ -134,7 +134,7 @@ export class Compiler {
const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION;
const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings);
const didSourceChange = currentArtifact.sourceTreeHashHex !== sourceTreeHashHex;
shouldCompile = isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange;
shouldCompile = !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange;
}
if (!shouldCompile) {
return;
@@ -203,6 +203,20 @@ export class Compiler {
}. Please make sure your contract has the same name as it's file name`,
);
}
if (!_.isUndefined(compiledData.evm)) {
if (!_.isUndefined(compiledData.evm.bytecode) && !_.isUndefined(compiledData.evm.bytecode.object)) {
compiledData.evm.bytecode.object = ethUtil.addHexPrefix(compiledData.evm.bytecode.object);
}
if (
!_.isUndefined(compiledData.evm.deployedBytecode) &&
!_.isUndefined(compiledData.evm.deployedBytecode.object)
) {
compiledData.evm.deployedBytecode.object = ethUtil.addHexPrefix(
compiledData.evm.deployedBytecode.object,
);
}
}
const sourceCodes = _.mapValues(
compiled.sources,
(_1, sourceFilePath) => this._resolver.resolve(sourceFilePath).source,

View File

@@ -1,3 +1,2 @@
export { Deployer } from './deployer';
export { Compiler } from './compiler';
export { ContractArtifact, ContractNetworks } from './utils/types';

View File

@@ -50,17 +50,6 @@ export interface SolcErrors {
[key: string]: boolean;
}
export interface CliOptions extends yargs.Arguments {
artifactsDir: string;
contractsDir: string;
jsonrpcUrl: string;
networkId: number;
gasPrice: string;
account?: string;
contract?: string;
args?: string;
}
export interface CompilerOptions {
contractsDir?: string;
artifactsDir?: string;
@@ -68,22 +57,6 @@ export interface CompilerOptions {
contracts?: string[] | '*';
}
export interface BaseDeployerOptions {
artifactsDir: string;
networkId: number;
defaults: Partial<TxData>;
}
export interface ProviderDeployerOptions extends BaseDeployerOptions {
provider: Provider;
}
export interface UrlDeployerOptions extends BaseDeployerOptions {
jsonrpcUrl: string;
}
export type DeployerOptions = UrlDeployerOptions | ProviderDeployerOptions;
export interface ContractSourceData {
[contractName: string]: ContractSpecificSourceData;
}

View File

@@ -0,0 +1,6 @@
export const utils = {
stringifyWithFormatting(obj: any): string {
const stringifiedObj = JSON.stringify(obj, null, '\t');
return stringifiedObj;
},
};

View File

@@ -37,7 +37,7 @@ describe('#Compiler', function() {
const exchangeArtifactString = await fsWrapper.readFileAsync(exchangeArtifactPath, opts);
const exchangeArtifact: ContractArtifact = JSON.parse(exchangeArtifactString);
// The last 43 bytes of the binaries are metadata which may not be equivalent
const unlinkedBinaryWithoutMetadata = exchangeArtifact.compilerOutput.evm.bytecode.object.slice(0, -86);
const unlinkedBinaryWithoutMetadata = exchangeArtifact.compilerOutput.evm.bytecode.object.slice(2, -86);
const exchangeBinaryWithoutMetadata = exchange_binary.slice(0, -86);
expect(unlinkedBinaryWithoutMetadata).to.equal(exchangeBinaryWithoutMetadata);
});

View File

@@ -55,8 +55,8 @@ describe('Compiler utils', () => {
const dependencies = parseDependencies({ source, path });
const expectedDependencies = [
'zeppelin-solidity/contracts/token/ERC20/ERC20.sol',
'packages/deployer/lib/test/fixtures/contracts/TokenTransferProxy.sol',
'packages/deployer/lib/test/fixtures/contracts/base/SafeMath.sol',
'packages/sol-compiler/lib/test/fixtures/contracts/TokenTransferProxy.sol',
'packages/sol-compiler/lib/test/fixtures/contracts/base/SafeMath.sol',
];
_.each(expectedDependencies, expectedDepdency => {
const foundDependency = _.find(dependencies, dependency => _.endsWith(dependency, expectedDepdency));

View File

@@ -6,7 +6,7 @@
"types": "lib/src/index.d.ts",
"scripts": {
"build:watch": "tsc -w",
"lint": "tslint --project . 'src/**/*.ts'",
"lint": "tslint --project .",
"test": "run-s clean build compile_test run_mocha",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
@@ -14,7 +14,7 @@
"run_mocha": "mocha lib/test/**/*_test.js --exit",
"clean": "shx rm -rf lib scripts",
"build": "copyfiles 'test/fixtures/**/*' ./lib && tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"compile_test": "node ../deployer/lib/src/cli.js compile",
"compile_test": "node ../sol-compiler/lib/src/cli.js compile",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js",
"docs:stage": "yarn build && node ./scripts/stage_docs.js",
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES",
@@ -54,10 +54,9 @@
"solidity-parser-antlr": "^0.2.8"
},
"devDependencies": {
"@0xproject/deployer": "^0.3.5",
"@0xproject/monorepo-scripts": "^0.1.19",
"@0xproject/tslint-config": "^0.4.17",
"@types/istanbul": "^0.4.29",
"@types/istanbul": "^0.4.30",
"@types/mocha": "^2.2.42",
"@types/node": "^8.0.53",
"chai": "^4.0.1",

View File

@@ -5,7 +5,7 @@ import * as path from 'path';
import { ContractData } from './types';
export const collectContractsData = (artifactsPath: string, sourcesPath: string, networkId: number) => {
export const collectContractsData = (artifactsPath: string, sourcesPath: string) => {
const artifactsGlob = `${artifactsPath}/**/*.json`;
const artifactFileNames = glob.sync(artifactsGlob, { absolute: true });
const contractsData: ContractData[] = [];

View File

@@ -1,3 +1,4 @@
import { addHexPrefix } from 'ethereumjs-util';
import * as fs from 'fs';
import { Collector } from 'istanbul';
import * as _ from 'lodash';
@@ -36,21 +37,18 @@ export class CoverageManager {
constructor(
artifactsPath: string,
sourcesPath: string,
networkId: number,
getContractCodeAsync: (address: string) => Promise<string>,
) {
this._getContractCodeAsync = getContractCodeAsync;
this._sourcesPath = sourcesPath;
this._contractsData = collectContractsData(artifactsPath, this._sourcesPath, networkId);
this._contractsData = collectContractsData(artifactsPath, this._sourcesPath);
}
public appendTraceInfo(traceInfo: TraceInfo): void {
this._traceInfos.push(traceInfo);
}
public async writeCoverageAsync(): Promise<void> {
const finalCoverage = await this._computeCoverageAsync();
const jsonReplacer: null = null;
const numberOfJsonSpaces = 4;
const stringifiedCoverage = JSON.stringify(finalCoverage, jsonReplacer, numberOfJsonSpaces);
const stringifiedCoverage = JSON.stringify(finalCoverage, null, '\t');
fs.writeFileSync('coverage/coverage.json', stringifiedCoverage);
}
private _getSingleFileCoverageForTrace(
@@ -134,7 +132,7 @@ export class CoverageManager {
if (traceInfo.address !== constants.NEW_CONTRACT) {
// Runtime transaction
let runtimeBytecode = (traceInfo as TraceInfoExistingContract).runtimeBytecode;
runtimeBytecode = utils.removeHexPrefix(runtimeBytecode);
runtimeBytecode = addHexPrefix(runtimeBytecode);
const contractData = _.find(this._contractsData, { runtimeBytecode }) as ContractData;
if (_.isUndefined(contractData)) {
throw new Error(`Transaction to an unknown address: ${traceInfo.address}`);
@@ -159,7 +157,7 @@ export class CoverageManager {
} else {
// Contract creation transaction
let bytecode = (traceInfo as TraceInfoNewContract).bytecode;
bytecode = utils.removeHexPrefix(bytecode);
bytecode = addHexPrefix(bytecode);
const contractData = _.find(this._contractsData, contractDataCandidate =>
bytecode.startsWith(contractDataCandidate.bytecode),
) as ContractData;
@@ -185,7 +183,6 @@ export class CoverageManager {
}
}
}
// TODO: Remove any cast as soon as https://github.com/DefinitelyTyped/DefinitelyTyped/pull/24233 gets merged
return (collector as any).getFinalCoverage();
return collector.getFinalCoverage();
}
}

Some files were not shown because too many files have changed in this diff Show More