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:
@@ -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
5
.gitignore
vendored
@@ -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/
|
||||
|
@@ -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
|
||||
|
44
README.md
44
README.md
@@ -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) | [](https://www.npmjs.com/package/0x.js) | A Javascript library for interacting with the 0x protocol |
|
||||
| [`@0xproject/abi-gen`](/packages/abi-gen) | [](https://www.npmjs.com/package/@0xproject/abi-gen) | Tool to generate TS wrappers from smart contract ABIs |
|
||||
| [`@0xproject/assert`](/packages/assert) | [](https://www.npmjs.com/package/@0xproject/assert) | Type and schema assertions used by our packages |
|
||||
| [`@0xproject/base-contract`](/packages/base-contract) | [](https://www.npmjs.com/package/@0xproject/base-contract) | BaseContract used by auto-generated `abi-gen` wrapper contracts |
|
||||
| [`@0xproject/connect`](/packages/connect) | [](https://www.npmjs.com/package/@0xproject/connect) | A Javascript library for interacting with the Standard Relayer API |
|
||||
| [`@0xproject/deployer`](/packages/deployer) | [](https://www.npmjs.com/package/@0xproject/deployer) | Solidity project compiler and deployer framework |
|
||||
| [`@0xproject/dev-utils`](/packages/dev-utils) | [](https://www.npmjs.com/package/@0xproject/dev-utils) | Dev utils to be shared across 0x projects and packages |
|
||||
| [`@0xproject/json-schemas`](/packages/json-schemas) | [](https://www.npmjs.com/package/@0xproject/json-schemas) | 0x-related json schemas |
|
||||
| [`@0xproject/monorepo-scripts`](/packages/monorepo-scripts) | [](https://www.npmjs.com/package/@0xproject/monorepo-scripts) | Monorepo scripts |
|
||||
| [`@0xproject/react-docs`](/packages/react-docs) | [](https://www.npmjs.com/package/@0xproject/react-docs) | React documentation component for rendering TypeDoc & Doxity generated JSON |
|
||||
| [`@0xproject/react-shared`](/packages/react-shared) | [](https://www.npmjs.com/package/@0xproject/react-shared) | 0x shared react components |
|
||||
| [`@0xproject/sra-report`](/packages/sra-report) | [](https://www.npmjs.com/package/@0xproject/sra-report) | Generate reports for standard relayer API compliance |
|
||||
| [`@0xproject/sol-cov`](/packages/sol-cov) | [](https://www.npmjs.com/package/@0xproject/sol-cov) | Solidity test coverage tool |
|
||||
| [`@0xproject/subproviders`](/packages/subproviders) | [](https://www.npmjs.com/package/@0xproject/subproviders) | Useful web3 subproviders (e.g LedgerSubprovider) |
|
||||
| [`@0xproject/tslint-config`](/packages/tslint-config) | [](https://www.npmjs.com/package/@0xproject/tslint-config) | Custom 0x development TSLint rules |
|
||||
| [`@0xproject/types`](/packages/types) | [](https://www.npmjs.com/package/@0xproject/types) | Shared type declarations |
|
||||
| [`@0xproject/typescript-typings`](/packages/typescript-typings) | [](https://www.npmjs.com/package/@0xproject/typescript-typings) | Repository of types for external packages |
|
||||
| [`@0xproject/utils`](/packages/utils) | [](https://www.npmjs.com/package/@0xproject/utils) | Shared utilities |
|
||||
| [`@0xproject/web3-wrapper`](/packages/web3-wrapper) | [](https://www.npmjs.com/package/@0xproject/web3-wrapper) | Web3 wrapper |
|
||||
| Package | Version | Description |
|
||||
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [`0x.js`](/packages/0x.js) | [](https://www.npmjs.com/package/0x.js) | A Javascript library for interacting with the 0x protocol |
|
||||
| [`@0xproject/abi-gen`](/packages/abi-gen) | [](https://www.npmjs.com/package/@0xproject/abi-gen) | Tool to generate TS wrappers from smart contract ABIs |
|
||||
| [`@0xproject/assert`](/packages/assert) | [](https://www.npmjs.com/package/@0xproject/assert) | Type and schema assertions used by our packages |
|
||||
| [`@0xproject/base-contract`](/packages/base-contract) | [](https://www.npmjs.com/package/@0xproject/base-contract) | BaseContract used by auto-generated `abi-gen` wrapper contracts |
|
||||
| [`@0xproject/connect`](/packages/connect) | [](https://www.npmjs.com/package/@0xproject/connect) | A Javascript library for interacting with the Standard Relayer API |
|
||||
| [`@0xproject/sol-compiler`](/packages/sol-compiler) | [](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) | [](https://www.npmjs.com/package/@0xproject/dev-utils) | Dev utils to be shared across 0x projects and packages |
|
||||
| [`@0xproject/json-schemas`](/packages/json-schemas) | [](https://www.npmjs.com/package/@0xproject/json-schemas) | 0x-related json schemas |
|
||||
| [`@0xproject/monorepo-scripts`](/packages/monorepo-scripts) | [](https://www.npmjs.com/package/@0xproject/monorepo-scripts) | Monorepo scripts |
|
||||
| [`@0xproject/react-docs`](/packages/react-docs) | [](https://www.npmjs.com/package/@0xproject/react-docs) | React documentation component for rendering TypeDoc & Doxity generated JSON |
|
||||
| [`@0xproject/react-shared`](/packages/react-shared) | [](https://www.npmjs.com/package/@0xproject/react-shared) | 0x shared react components |
|
||||
| [`@0xproject/sra-report`](/packages/sra-report) | [](https://www.npmjs.com/package/@0xproject/sra-report) | Generate reports for standard relayer API compliance |
|
||||
| [`@0xproject/sol-cov`](/packages/sol-cov) | [](https://www.npmjs.com/package/@0xproject/sol-cov) | Solidity test coverage tool |
|
||||
| [`@0xproject/subproviders`](/packages/subproviders) | [](https://www.npmjs.com/package/@0xproject/subproviders) | Useful web3 subproviders (e.g LedgerSubprovider) |
|
||||
| [`@0xproject/tslint-config`](/packages/tslint-config) | [](https://www.npmjs.com/package/@0xproject/tslint-config) | Custom 0x development TSLint rules |
|
||||
| [`@0xproject/types`](/packages/types) | [](https://www.npmjs.com/package/@0xproject/types) | Shared type declarations |
|
||||
| [`@0xproject/typescript-typings`](/packages/typescript-typings) | [](https://www.npmjs.com/package/@0xproject/typescript-typings) | Repository of types for external packages |
|
||||
| [`@0xproject/utils`](/packages/utils) | [](https://www.npmjs.com/package/@0xproject/utils) | Shared utilities |
|
||||
| [`@0xproject/web3-wrapper`](/packages/web3-wrapper) | [](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)
|
||||
|
@@ -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",
|
||||
|
@@ -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);
|
||||
});
|
||||
|
@@ -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);
|
||||
});
|
||||
|
@@ -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);
|
@@ -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,
|
||||
|
@@ -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"
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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",
|
||||
|
@@ -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(
|
||||
|
@@ -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",
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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"
|
||||
}
|
||||
|
@@ -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,
|
||||
|
@@ -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,
|
||||
});
|
||||
|
@@ -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 = {
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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',
|
||||
|
@@ -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 () => {
|
||||
|
@@ -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 () => {
|
||||
|
@@ -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, {
|
||||
|
@@ -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);
|
||||
});
|
||||
});
|
||||
|
@@ -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;
|
||||
});
|
||||
|
@@ -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);
|
@@ -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;
|
||||
|
@@ -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;
|
||||
});
|
||||
|
@@ -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,
|
||||
};
|
||||
|
@@ -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),
|
||||
};
|
||||
|
@@ -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;
|
||||
})();
|
@@ -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);
|
||||
},
|
||||
};
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -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;
|
||||
},
|
||||
};
|
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
@@ -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",
|
||||
|
@@ -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);
|
||||
},
|
||||
};
|
||||
|
@@ -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',
|
||||
}),
|
||||
);
|
||||
|
@@ -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",
|
||||
|
@@ -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
4
packages/metacoin/src/global.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
declare module '*.json' {
|
||||
const value: any;
|
||||
export default value;
|
||||
}
|
@@ -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();
|
||||
|
@@ -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',
|
||||
};
|
||||
|
@@ -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);
|
||||
},
|
||||
};
|
||||
|
@@ -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);
|
20
packages/migrations/compiler.json
Normal file
20
packages/migrations/compiler.json
Normal 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"
|
||||
]
|
||||
}
|
@@ -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": {
|
||||
|
26
packages/migrations/src/artifact_writer.ts
Normal file
26
packages/migrations/src/artifact_writer.ts
Normal 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'));
|
||||
}
|
||||
}
|
31
packages/migrations/src/artifacts.ts
Normal file
31
packages/migrations/src/artifacts.ts
Normal 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,
|
||||
};
|
@@ -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);
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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,
|
||||
},
|
||||
|
@@ -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",
|
||||
|
@@ -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. ***');
|
||||
|
@@ -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
|
||||
|
@@ -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 });
|
||||
|
@@ -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",
|
||||
|
@@ -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",
|
||||
|
@@ -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",
|
||||
|
@@ -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
|
@@ -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",
|
46
packages/sol-compiler/src/cli.ts
Normal file
46
packages/sol-compiler/src/cli.ts
Normal 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);
|
||||
});
|
@@ -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,
|
@@ -1,3 +1,2 @@
|
||||
export { Deployer } from './deployer';
|
||||
export { Compiler } from './compiler';
|
||||
export { ContractArtifact, ContractNetworks } from './utils/types';
|
@@ -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;
|
||||
}
|
6
packages/sol-compiler/src/utils/utils.ts
Normal file
6
packages/sol-compiler/src/utils/utils.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export const utils = {
|
||||
stringifyWithFormatting(obj: any): string {
|
||||
const stringifiedObj = JSON.stringify(obj, null, '\t');
|
||||
return stringifiedObj;
|
||||
},
|
||||
};
|
@@ -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);
|
||||
});
|
@@ -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));
|
@@ -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",
|
||||
|
@@ -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[] = [];
|
||||
|
@@ -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
Reference in New Issue
Block a user