diff options
author | Brandon Millman <brandon.millman@gmail.com> | 2018-05-24 05:16:32 +0800 |
---|---|---|
committer | Brandon Millman <brandon.millman@gmail.com> | 2018-05-24 05:16:32 +0800 |
commit | 3fe94891d3569a4615f4aa32d47f0065b5957fe9 (patch) | |
tree | 83d4e4ccf7748d2100aa935c457de0a893eaec9c /packages | |
parent | d0abc60176dba3116cb3986d298ab5164c1fe49c (diff) | |
parent | f6b81f588d98e09e7a5806902d94e2892d029481 (diff) | |
download | dexon-0x-contracts-3fe94891d3569a4615f4aa32d47f0065b5957fe9.tar.gz dexon-0x-contracts-3fe94891d3569a4615f4aa32d47f0065b5957fe9.tar.zst dexon-0x-contracts-3fe94891d3569a4615f4aa32d47f0065b5957fe9.zip |
Merge branch 'v2-prototype' into feature/website/wallet-flex-box
* v2-prototype: (95 commits)
Add missing dep to website
Upgrade solidity parser
Fix trace test
Fix linter issues
Move contract utils
Fix prettier
Fix NameResolver
Fix prettier
Remove 0x.js as a dependency from website
Enable 0x.js tests
Fix small bug in order-utils
Address feedback
Fix Tslint error caused by "PromiseLike" value
Fix Tslint error caused by "PromiseLike" value
Update dogfood url
fix contract-wrappers version
Parse compiler.json in SolCompilerArtifactsAdapter
Fix TokenTransferProxy artifact name since it's now suffixed with _v1
Update yarn.lock
Fix signature verification test
...
Diffstat (limited to 'packages')
231 files changed, 2483 insertions, 1241 deletions
diff --git a/packages/0x.js/CHANGELOG.json b/packages/0x.js/CHANGELOG.json index 5e4a726b1..2a219180d 100644 --- a/packages/0x.js/CHANGELOG.json +++ b/packages/0x.js/CHANGELOG.json @@ -11,7 +11,8 @@ "Renamed ZeroExError to ContractWrappersErrors since they now lives in the @0xproject/contract-wrappers subpackage", "pr": 579 } - ] + ], + "timestamp": 1527008270 }, { "timestamp": 1525477860, diff --git a/packages/0x.js/CHANGELOG.md b/packages/0x.js/CHANGELOG.md index 353e0de29..f7ceaa552 100644 --- a/packages/0x.js/CHANGELOG.md +++ b/packages/0x.js/CHANGELOG.md @@ -5,7 +5,12 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.37.2 - _May 5, 2018_ +## v0.38.0 - _May 22, 2018_ + + * Renamed createOrderStateWatcher to createOrderWatcherAsync since it is now async (#579) + * Renamed ZeroExError to ContractWrappersErrors since they now lives in the @0xproject/contract-wrappers subpackage (#579) + +## v0.37.2 - _May 4, 2018_ * Dependencies updated diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json index 2fff1c058..a498124b6 100644 --- a/packages/0x.js/package.json +++ b/packages/0x.js/package.json @@ -1,6 +1,6 @@ { "name": "0x.js", - "version": "0.37.2", + "version": "0.38.0", "engines": { "node": ">=6.12" }, @@ -28,9 +28,7 @@ "build:umd:prod": "NODE_ENV=production webpack", "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", - "_comment": {"run_mocha": "mocha lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit", - "note": "The `run_mocha` test has been commented out by @hysz (greg@0xproject.com) until the migration package and 0x.js have been updated for V2."}, - "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", "docs:stage": "node scripts/stage_docs.js", "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES", @@ -68,12 +66,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@0xproject/abi-gen": "^0.2.13", - "@0xproject/dev-utils": "^0.4.1", - "@0xproject/migrations": "^0.0.5", - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/sol-compiler": "^0.4.3", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/abi-gen": "^0.3.0", + "@0xproject/dev-utils": "^0.4.2", + "@0xproject/migrations": "^0.0.6", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/sol-compiler": "^0.5.0", + "@0xproject/tslint-config": "^0.4.18", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", "@types/node": "^8.0.53", @@ -100,16 +98,16 @@ "webpack": "^3.1.0" }, "dependencies": { - "@0xproject/assert": "^0.2.9", - "@0xproject/base-contract": "^0.3.1", - "@0xproject/contract-wrappers": "^0.0.1", - "@0xproject/order-utils": "^0.0.4", - "@0xproject/order-watcher": "^0.0.1", - "@0xproject/sol-compiler": "^0.4.3", - "@0xproject/types": "^0.6.3", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", - "@0xproject/web3-wrapper": "^0.6.3", + "@0xproject/assert": "^0.2.10", + "@0xproject/base-contract": "^0.3.2", + "@0xproject/contract-wrappers": "^0.0.2", + "@0xproject/order-utils": "^0.0.5", + "@0xproject/order-watcher": "^0.0.2", + "@0xproject/sol-compiler": "^0.5.0", + "@0xproject/types": "^0.7.0", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", + "@0xproject/web3-wrapper": "^0.6.4", "ethers": "^3.0.15", "lodash": "^4.17.4" }, diff --git a/packages/0x.js/src/schemas/zero_ex_public_network_config_schema.ts b/packages/0x.js/src/schemas/zero_ex_public_network_config_schema.ts index 9da31481a..f7f6727f0 100644 --- a/packages/0x.js/src/schemas/zero_ex_public_network_config_schema.ts +++ b/packages/0x.js/src/schemas/zero_ex_public_network_config_schema.ts @@ -1,9 +1,23 @@ +const networkNameToId: { [networkName: string]: number } = { + mainnet: 1, + ropsten: 3, + rinkeby: 4, + kovan: 42, + ganache: 50, +}; + export const zeroExPublicNetworkConfigSchema = { id: '/ZeroExPublicNetworkConfig', properties: { networkId: { type: 'number', - enum: [1, 3, 4, 42, 50], + enum: [ + networkNameToId.mainnet, + networkNameToId.ropsten, + networkNameToId.rinkeby, + networkNameToId.kovan, + networkNameToId.ganache, + ], }, gasPrice: { $ref: '/Number' }, zrxContractAddress: { $ref: '/Address' }, diff --git a/packages/0x.js/test/artifacts_test.ts b/packages/0x.js/test/artifacts_test.ts index ca554a4f5..982fb8e63 100644 --- a/packages/0x.js/test/artifacts_test.ts +++ b/packages/0x.js/test/artifacts_test.ts @@ -15,7 +15,7 @@ const TIMEOUT = 10000; describe('Artifacts', () => { describe('contracts are deployed on kovan', () => { const kovanRpcUrl = constants.KOVAN_RPC_URL; - const provider = web3Factory.create({ rpcUrl: kovanRpcUrl }).currentProvider; + const provider = web3Factory.getRpcProvider({ rpcUrl: kovanRpcUrl }); const config = { networkId: constants.KOVAN_NETWORK_ID, }; @@ -32,7 +32,7 @@ describe('Artifacts', () => { }); describe('contracts are deployed on ropsten', () => { const ropstenRpcUrl = constants.ROPSTEN_RPC_URL; - const provider = web3Factory.create({ rpcUrl: ropstenRpcUrl }).currentProvider; + const provider = web3Factory.getRpcProvider({ rpcUrl: ropstenRpcUrl }); const config = { networkId: constants.ROPSTEN_NETWORK_ID, }; diff --git a/packages/0x.js/test/global_hooks.ts b/packages/0x.js/test/global_hooks.ts index 53b3ef545..fa1dfae38 100644 --- a/packages/0x.js/test/global_hooks.ts +++ b/packages/0x.js/test/global_hooks.ts @@ -8,7 +8,8 @@ import { provider } from './utils/web3_wrapper'; before('migrate contracts', async function(): Promise<void> { // HACK: Since the migrations take longer then our global mocha timeout limit // we manually increase it for this before hook. - this.timeout(20000); + const mochaTestTimeoutMs = 20000; + this.timeout(mochaTestTimeoutMs); const txDefaults = { gas: devConstants.GAS_ESTIMATE, from: devConstants.TESTRPC_FIRST_ADDRESS, diff --git a/packages/0x.js/test/utils/web3_wrapper.ts b/packages/0x.js/test/utils/web3_wrapper.ts index b0ccfa546..71a0dc1c2 100644 --- a/packages/0x.js/test/utils/web3_wrapper.ts +++ b/packages/0x.js/test/utils/web3_wrapper.ts @@ -2,8 +2,7 @@ import { devConstants, web3Factory } from '@0xproject/dev-utils'; import { Provider } from '@0xproject/types'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; -const web3 = web3Factory.create({ shouldUseInProcessGanache: true }); -const provider: Provider = web3.currentProvider; -const web3Wrapper = new Web3Wrapper(web3.currentProvider); +const provider: Provider = web3Factory.getRpcProvider({ shouldUseInProcessGanache: true }); +const web3Wrapper = new Web3Wrapper(provider); export { provider, web3Wrapper }; diff --git a/packages/abi-gen/CHANGELOG.json b/packages/abi-gen/CHANGELOG.json index 4b23b8118..71cbaac1e 100644 --- a/packages/abi-gen/CHANGELOG.json +++ b/packages/abi-gen/CHANGELOG.json @@ -6,7 +6,8 @@ "note": "Properly export the executable binary", "pr": 588 } - ] + ], + "timestamp": 1527008270 }, { "timestamp": 1525477860, diff --git a/packages/abi-gen/CHANGELOG.md b/packages/abi-gen/CHANGELOG.md index 803414e14..bcd807a3c 100644 --- a/packages/abi-gen/CHANGELOG.md +++ b/packages/abi-gen/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.2.13 - _May 5, 2018_ +## v0.3.0 - _May 22, 2018_ + + * Properly export the executable binary (#588) + +## v0.2.13 - _May 4, 2018_ * Dependencies updated diff --git a/packages/abi-gen/package.json b/packages/abi-gen/package.json index ca666dc9b..d3af33fdf 100644 --- a/packages/abi-gen/package.json +++ b/packages/abi-gen/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/abi-gen", - "version": "0.2.13", + "version": "0.3.0", "engines": { "node": ">=6.12" }, @@ -27,9 +27,9 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md", "dependencies": { - "@0xproject/types": "^0.6.3", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", + "@0xproject/types": "^0.7.0", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", "chalk": "^2.3.0", "glob": "^7.1.2", "handlebars": "^4.0.11", @@ -39,8 +39,8 @@ "yargs": "^10.0.3" }, "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", "@types/glob": "^5.0.33", "@types/handlebars": "^4.0.36", "@types/mkdirp": "^0.5.1", diff --git a/packages/assert/CHANGELOG.json b/packages/assert/CHANGELOG.json index f826c7675..048763732 100644 --- a/packages/assert/CHANGELOG.json +++ b/packages/assert/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1527008270, + "version": "0.2.10", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1525477860, "version": "0.2.9", "changes": [ diff --git a/packages/assert/CHANGELOG.md b/packages/assert/CHANGELOG.md index ab058b9fc..974ac5c42 100644 --- a/packages/assert/CHANGELOG.md +++ b/packages/assert/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.2.9 - _May 5, 2018_ +## v0.2.10 - _May 22, 2018_ + + * Dependencies updated + +## v0.2.9 - _May 4, 2018_ * Dependencies updated diff --git a/packages/assert/package.json b/packages/assert/package.json index e3ac0d3ed..88f4dac99 100644 --- a/packages/assert/package.json +++ b/packages/assert/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/assert", - "version": "0.2.9", + "version": "0.2.10", "engines": { "node": ">=6.12" }, @@ -30,8 +30,8 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/assert/README.md", "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", "@types/valid-url": "^1.0.2", @@ -47,9 +47,9 @@ "typescript": "2.7.1" }, "dependencies": { - "@0xproject/json-schemas": "^0.7.23", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", + "@0xproject/json-schemas": "^0.7.24", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", "lodash": "^4.17.4", "valid-url": "^1.0.9" }, diff --git a/packages/assert/test/assert_test.ts b/packages/assert/test/assert_test.ts index 58d3e53b5..e61ec93e0 100644 --- a/packages/assert/test/assert_test.ts +++ b/packages/assert/test/assert_test.ts @@ -11,6 +11,7 @@ chai.config.includeStack = true; chai.use(dirtyChai); const expect = chai.expect; +// tslint:disable:custom-no-magic-numbers describe('Assertions', () => { const variableName = 'variable'; describe('#isBigNumber', () => { @@ -252,3 +253,4 @@ describe('Assertions', () => { }); }); }); +// tslint:enable:custom-no-magic-numbers diff --git a/packages/base-contract/CHANGELOG.json b/packages/base-contract/CHANGELOG.json index 106c26989..04029576c 100644 --- a/packages/base-contract/CHANGELOG.json +++ b/packages/base-contract/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1527008270, + "version": "0.3.2", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1525477860, "version": "0.3.1", "changes": [ diff --git a/packages/base-contract/CHANGELOG.md b/packages/base-contract/CHANGELOG.md index b57bd5fc0..90ad066b5 100644 --- a/packages/base-contract/CHANGELOG.md +++ b/packages/base-contract/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.3.1 - _May 5, 2018_ +## v0.3.2 - _May 22, 2018_ + + * Dependencies updated + +## v0.3.1 - _May 4, 2018_ * Dependencies updated diff --git a/packages/base-contract/package.json b/packages/base-contract/package.json index ca59dc4c8..f79d3ebf6 100644 --- a/packages/base-contract/package.json +++ b/packages/base-contract/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/base-contract", - "version": "0.3.1", + "version": "0.3.2", "engines": { "node": ">=6.12" }, @@ -29,8 +29,8 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/base-contract/README.md", "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", "@types/lodash": "4.14.104", "chai": "^4.0.1", "copyfiles": "^1.2.0", @@ -42,10 +42,10 @@ "typescript": "2.7.1" }, "dependencies": { - "@0xproject/types": "^0.6.3", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", - "@0xproject/web3-wrapper": "^0.6.3", + "@0xproject/types": "^0.7.0", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", + "@0xproject/web3-wrapper": "^0.6.4", "ethers": "^3.0.15", "lodash": "^4.17.4" }, diff --git a/packages/connect/CHANGELOG.json b/packages/connect/CHANGELOG.json index dd172e975..58fcc635b 100644 --- a/packages/connect/CHANGELOG.json +++ b/packages/connect/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1527008270, + "version": "0.6.13", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1525477860, "version": "0.6.12", "changes": [ diff --git a/packages/connect/CHANGELOG.md b/packages/connect/CHANGELOG.md index 4e118de38..acc6f33bd 100644 --- a/packages/connect/CHANGELOG.md +++ b/packages/connect/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.6.12 - _May 5, 2018_ +## v0.6.13 - _May 22, 2018_ + + * Dependencies updated + +## v0.6.12 - _May 4, 2018_ * Dependencies updated diff --git a/packages/connect/package.json b/packages/connect/package.json index 65aa50a42..ed54b47ac 100644 --- a/packages/connect/package.json +++ b/packages/connect/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/connect", - "version": "0.6.12", + "version": "0.6.13", "engines": { "node": ">=6.12" }, @@ -50,19 +50,19 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md", "dependencies": { - "@0xproject/assert": "^0.2.9", - "@0xproject/json-schemas": "^0.7.23", - "@0xproject/types": "^0.6.3", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", + "@0xproject/assert": "^0.2.10", + "@0xproject/json-schemas": "^0.7.24", + "@0xproject/types": "^0.7.0", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", "isomorphic-fetch": "^2.2.1", "lodash": "^4.17.4", "query-string": "^5.0.1", "websocket": "^1.0.25" }, "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", "@types/fetch-mock": "^5.12.1", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json index 18ca4143e..84e773933 100644 --- a/packages/contract-wrappers/CHANGELOG.json +++ b/packages/contract-wrappers/CHANGELOG.json @@ -1,5 +1,15 @@ [ { + "version": "0.0.2", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1527008544 + }, + { + "timestamp": 1527008270, "version": "0.0.1", "changes": [ { diff --git a/packages/contract-wrappers/CHANGELOG.md b/packages/contract-wrappers/CHANGELOG.md index 5565d6210..c8a0145d5 100644 --- a/packages/contract-wrappers/CHANGELOG.md +++ b/packages/contract-wrappers/CHANGELOG.md @@ -4,3 +4,11 @@ Edit the package's CHANGELOG.json file only. --> CHANGELOG + +## v0.0.2 - _May 22, 2018_ + + * Dependencies updated + +## v0.0.1 - _May 22, 2018_ + + * Moved contractWrappers out of 0x.js (#579) diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json index 6cb16c2c0..10719c831 100644 --- a/packages/contract-wrappers/package.json +++ b/packages/contract-wrappers/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/contract-wrappers", - "version": "0.0.1", + "version": "0.0.2", "description": "Smart TS wrappers for 0x smart contracts", "keywords": [ "0xproject", @@ -27,7 +27,7 @@ }, "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", + "contracts": "Exchange DummyToken ZRXToken Token WETH9 TokenTransferProxy_v1 MultiSigWallet MultiSigWalletWithTimeLock MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress MaliciousToken TokenRegistry Arbitrage EtherDelta AccountLevels", "postpublish": { "assets": [ "packages/contract-wrappers/_bundles/index.js", @@ -44,13 +44,13 @@ "node": ">=6.0.0" }, "devDependencies": { - "@0xproject/abi-gen": "^0.2.13", - "@0xproject/dev-utils": "^0.4.1", - "@0xproject/migrations": "^0.0.5", - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/sol-compiler": "^0.4.3", - "@0xproject/subproviders": "^0.10.1", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/abi-gen": "^0.3.0", + "@0xproject/dev-utils": "^0.4.2", + "@0xproject/migrations": "^0.0.6", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/sol-compiler": "^0.5.0", + "@0xproject/subproviders": "^0.10.2", + "@0xproject/tslint-config": "^0.4.18", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", "@types/node": "^8.0.53", @@ -76,15 +76,15 @@ "web3-provider-engine": "^14.0.4" }, "dependencies": { - "@0xproject/assert": "^0.2.9", - "@0xproject/base-contract": "^0.3.1", - "@0xproject/fill-scenarios": "^0.0.1", - "@0xproject/json-schemas": "^0.7.23", - "@0xproject/order-utils": "^0.0.4", - "@0xproject/types": "^0.6.3", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", - "@0xproject/web3-wrapper": "^0.6.3", + "@0xproject/assert": "^0.2.10", + "@0xproject/base-contract": "^0.3.2", + "@0xproject/fill-scenarios": "^0.0.2", + "@0xproject/json-schemas": "^0.7.24", + "@0xproject/order-utils": "^0.0.5", + "@0xproject/types": "^0.7.0", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", + "@0xproject/web3-wrapper": "^0.6.4", "ethereumjs-blockstream": "^2.0.6", "ethereumjs-util": "^5.1.1", "ethers": "^3.0.15", diff --git a/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts b/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts index bf1000afa..304cd100b 100644 --- a/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts +++ b/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts @@ -1,9 +1,23 @@ +const networkNameToId: { [networkName: string]: number } = { + mainnet: 1, + ropsten: 3, + rinkeby: 4, + kovan: 42, + ganache: 50, +}; + export const contractWrappersPublicNetworkConfigSchema = { id: '/ZeroExContractPublicNetworkConfig', properties: { networkId: { type: 'number', - enum: [1, 3, 4, 42, 50], + enum: [ + networkNameToId.mainnet, + networkNameToId.kovan, + networkNameToId.ropsten, + networkNameToId.rinkeby, + networkNameToId.ganache, + ], }, gasPrice: { $ref: '/Number' }, zrxContractAddress: { $ref: '/Address' }, diff --git a/packages/contract-wrappers/src/utils/constants.ts b/packages/contract-wrappers/src/utils/constants.ts index 07da6745d..76d805cac 100644 --- a/packages/contract-wrappers/src/utils/constants.ts +++ b/packages/contract-wrappers/src/utils/constants.ts @@ -6,6 +6,7 @@ export const constants = { INVALID_JUMP_PATTERN: 'invalid JUMP at', OUT_OF_GAS_PATTERN: 'out of gas', INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string', + // tslint:disable-next-line:custom-no-magic-numbers UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1), DEFAULT_BLOCK_POLLING_INTERVAL: 1000, }; diff --git a/packages/contract-wrappers/src/utils/filter_utils.ts b/packages/contract-wrappers/src/utils/filter_utils.ts index c5df7321e..4ec9e256b 100644 --- a/packages/contract-wrappers/src/utils/filter_utils.ts +++ b/packages/contract-wrappers/src/utils/filter_utils.ts @@ -73,14 +73,14 @@ export const filterUtils = { return false; } if (!_.isUndefined(filter.topics)) { - return filterUtils.matchesTopics(log.topics, filter.topics); + return filterUtils.doesMatchTopics(log.topics, filter.topics); } return true; }, - matchesTopics(logTopics: string[], filterTopics: Array<string[] | string | null>): boolean { + doesMatchTopics(logTopics: string[], filterTopics: Array<string[] | string | null>): boolean { const matchesTopic = _.zipWith(logTopics, filterTopics, filterUtils.matchesTopic.bind(filterUtils)); - const matchesTopics = _.every(matchesTopic); - return matchesTopics; + const doesMatchTopics = _.every(matchesTopic); + return doesMatchTopics; }, matchesTopic(logTopic: string, filterTopic: string[] | string | null): boolean { if (_.isArray(filterTopic)) { diff --git a/packages/contract-wrappers/src/utils/utils.ts b/packages/contract-wrappers/src/utils/utils.ts index af1125632..7cf9450a0 100644 --- a/packages/contract-wrappers/src/utils/utils.ts +++ b/packages/contract-wrappers/src/utils/utils.ts @@ -5,7 +5,8 @@ export const utils = { return new Error(`Unexpected switch value: ${value} encountered for ${name}`); }, getCurrentUnixTimestampSec(): BigNumber { - return new BigNumber(Date.now() / 1000).round(); + const milisecondsInSecond = 1000; + return new BigNumber(Date.now() / milisecondsInSecond).round(); }, getCurrentUnixTimestampMs(): BigNumber { return new BigNumber(Date.now()); diff --git a/packages/contract-wrappers/test/artifacts_test.ts b/packages/contract-wrappers/test/artifacts_test.ts index 446b8f9d1..eaaa89c48 100644 --- a/packages/contract-wrappers/test/artifacts_test.ts +++ b/packages/contract-wrappers/test/artifacts_test.ts @@ -15,7 +15,7 @@ const TIMEOUT = 10000; describe('Artifacts', () => { describe('contracts are deployed on kovan', () => { const kovanRpcUrl = constants.KOVAN_RPC_URL; - const provider = web3Factory.create({ rpcUrl: kovanRpcUrl }).currentProvider; + const provider = web3Factory.getRpcProvider({ rpcUrl: kovanRpcUrl }); const config = { networkId: constants.KOVAN_NETWORK_ID, }; @@ -32,7 +32,7 @@ describe('Artifacts', () => { }); describe('contracts are deployed on ropsten', () => { const ropstenRpcUrl = constants.ROPSTEN_RPC_URL; - const provider = web3Factory.create({ rpcUrl: ropstenRpcUrl }).currentProvider; + const provider = web3Factory.getRpcProvider({ rpcUrl: ropstenRpcUrl }); const config = { networkId: constants.ROPSTEN_NETWORK_ID, }; diff --git a/packages/contract-wrappers/test/ether_token_wrapper_test.ts b/packages/contract-wrappers/test/ether_token_wrapper_test.ts index 974db34b1..e06fe96e5 100644 --- a/packages/contract-wrappers/test/ether_token_wrapper_test.ts +++ b/packages/contract-wrappers/test/ether_token_wrapper_test.ts @@ -42,7 +42,7 @@ describe('EtherTokenWrapper', () => { let addressWithETH: string; let wethContractAddress: string; let depositWeiAmount: BigNumber; - let decimalPlaces: number; + const decimalPlaces = 7; let addressWithoutFunds: string; const gasPrice = new BigNumber(1); const zeroExConfig = { @@ -60,7 +60,6 @@ describe('EtherTokenWrapper', () => { addressWithETH = userAddresses[0]; wethContractAddress = contractWrappers.etherToken.getContractAddressIfExists() as string; depositWeiAmount = Web3Wrapper.toWei(new BigNumber(5)); - decimalPlaces = 7; addressWithoutFunds = userAddresses[1]; }); beforeEach(async () => { @@ -155,6 +154,7 @@ describe('EtherTokenWrapper', () => { const preWETHBalance = await contractWrappers.token.getBalanceAsync(wethContractAddress, addressWithETH); expect(preWETHBalance).to.be.bignumber.equal(0); + // tslint:disable-next-line:custom-no-magic-numbers const overWETHBalance = preWETHBalance.add(999999999); return expect( diff --git a/packages/contract-wrappers/test/global_hooks.ts b/packages/contract-wrappers/test/global_hooks.ts index 53b3ef545..fa1dfae38 100644 --- a/packages/contract-wrappers/test/global_hooks.ts +++ b/packages/contract-wrappers/test/global_hooks.ts @@ -8,7 +8,8 @@ import { provider } from './utils/web3_wrapper'; before('migrate contracts', async function(): Promise<void> { // HACK: Since the migrations take longer then our global mocha timeout limit // we manually increase it for this before hook. - this.timeout(20000); + const mochaTestTimeoutMs = 20000; + this.timeout(mochaTestTimeoutMs); const txDefaults = { gas: devConstants.GAS_ESTIMATE, from: devConstants.TESTRPC_FIRST_ADDRESS, diff --git a/packages/contract-wrappers/test/order_validation_test.ts b/packages/contract-wrappers/test/order_validation_test.ts index 2acdece3e..a14dc24b6 100644 --- a/packages/contract-wrappers/test/order_validation_test.ts +++ b/packages/contract-wrappers/test/order_validation_test.ts @@ -106,6 +106,7 @@ describe('OrderValidation', () => { }); it('should succeed if the order is asymmetric and fillable', async () => { const makerFillableAmount = fillableAmount; + // tslint:disable-next-line:custom-no-magic-numbers const takerFillableAmount = fillableAmount.minus(4); const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync( makerTokenAddress, @@ -172,6 +173,7 @@ describe('OrderValidation', () => { fillableAmount, ); // 27 <--> 28 + // tslint:disable-next-line:custom-no-magic-numbers signedOrder.ecSignature.v = 28 - signedOrder.ecSignature.v + 27; return expect( contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync( @@ -206,6 +208,7 @@ describe('OrderValidation', () => { takerAddress, fillableAmount, ); + // tslint:disable-next-line:custom-no-magic-numbers const nonTakerAddress = userAddresses[6]; return expect( contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync( @@ -353,6 +356,7 @@ describe('OrderValidation', () => { takerAddress, zrxTokenAddress, ); + // tslint:disable-next-line:custom-no-magic-numbers expect(transferFromAsync.callCount).to.be.equal(4); expect( transferFromAsync @@ -423,6 +427,7 @@ describe('OrderValidation', () => { takerAddress, zrxTokenAddress, ); + // tslint:disable-next-line:custom-no-magic-numbers expect(transferFromAsync.callCount).to.be.equal(4); expect( transferFromAsync @@ -491,6 +496,7 @@ describe('OrderValidation', () => { takerAddress, zrxTokenAddress, ); + // tslint:disable-next-line:custom-no-magic-numbers expect(transferFromAsync.callCount).to.be.equal(4); const makerFillAmount = transferFromAsync.getCall(0).args[3]; expect(makerFillAmount).to.be.bignumber.equal(makerTokenAmount); @@ -518,6 +524,7 @@ describe('OrderValidation', () => { ); const makerPartialFee = makerFee.div(2); const takerPartialFee = takerFee.div(2); + // tslint:disable-next-line:custom-no-magic-numbers expect(transferFromAsync.callCount).to.be.equal(4); const partialMakerFee = transferFromAsync.getCall(2).args[3]; expect(partialMakerFee).to.be.bignumber.equal(makerPartialFee); diff --git a/packages/contract-wrappers/test/utils/web3_wrapper.ts b/packages/contract-wrappers/test/utils/web3_wrapper.ts index b0ccfa546..71a0dc1c2 100644 --- a/packages/contract-wrappers/test/utils/web3_wrapper.ts +++ b/packages/contract-wrappers/test/utils/web3_wrapper.ts @@ -2,8 +2,7 @@ import { devConstants, web3Factory } from '@0xproject/dev-utils'; import { Provider } from '@0xproject/types'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; -const web3 = web3Factory.create({ shouldUseInProcessGanache: true }); -const provider: Provider = web3.currentProvider; -const web3Wrapper = new Web3Wrapper(web3.currentProvider); +const provider: Provider = web3Factory.getRpcProvider({ shouldUseInProcessGanache: true }); +const web3Wrapper = new Web3Wrapper(provider); export { provider, web3Wrapper }; diff --git a/packages/contract_templates/contract.handlebars b/packages/contract_templates/contract.handlebars index ed11ac8d2..41f46695b 100644 --- a/packages/contract_templates/contract.handlebars +++ b/packages/contract_templates/contract.handlebars @@ -31,6 +31,7 @@ export enum {{contractName}}Events { {{/if}} // tslint:disable:no-parameter-reassignment +// tslint:disable-next-line:class-name export class {{contractName}}Contract extends BaseContract { {{#each methods}} {{#this.constant}} diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 9c7142cdb..1c66a3b86 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "contracts", - "version": "2.1.28", + "version": "2.1.29", "engines": { "node": ">=6.12" }, @@ -28,8 +28,7 @@ "test:circleci": "yarn test:coverage" }, "config": { - "abis": - "../migrations/artifacts/2.0.0/@(DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TestAssetProxyDispatcher|TestLibBytes|TestLibs|TestSignatureValidator|TokenRegistry|WETH9|ZRXToken).json" + "abis": "../migrations/artifacts/2.0.0/@(DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TestAssetProxyDispatcher|TestLibBytes|TestLibs|TestSignatureValidator|TokenRegistry|WETH9|ZRXToken).json" }, "repository": { "type": "git", @@ -42,9 +41,11 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts/README.md", "devDependencies": { - "@0xproject/abi-gen": "^0.2.13", - "@0xproject/dev-utils": "^0.4.1", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/abi-gen": "^0.3.0", + "@0xproject/dev-utils": "^0.4.2", + "@0xproject/tslint-config": "^0.4.18", + "@0xproject/subproviders": "^0.10.1", + "@0xproject/sol-cov": "^0.0.11", "@types/lodash": "4.14.104", "@types/node": "^8.0.53", "@types/yargs": "^10.0.0", @@ -64,13 +65,14 @@ "yargs": "^10.0.3" }, "dependencies": { - "0x.js": "^0.37.2", - "@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", - "@0xproject/web3-wrapper": "^0.6.3", + "@0xproject/base-contract": "^0.3.2", + "@0xproject/contract-wrappers": "^0.0.2", + "@0xproject/order-utils": "^0.0.5", + "@0xproject/sol-compiler": "^0.5.0", + "@0xproject/types": "^0.7.0", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", + "@0xproject/web3-wrapper": "^0.6.4", "bn.js": "^4.11.8", "ethereumjs-abi": "^0.6.4", "ethereumjs-util": "^5.1.1", diff --git a/packages/contracts/src/utils/address_utils.ts b/packages/contracts/src/utils/address_utils.ts index 01a7a6fd4..dc63459f9 100644 --- a/packages/contracts/src/utils/address_utils.ts +++ b/packages/contracts/src/utils/address_utils.ts @@ -1,10 +1,10 @@ -import { ZeroEx } from '0x.js'; +import { generatePseudoRandomSalt } from '@0xproject/order-utils'; import { crypto } from './crypto'; export const addressUtils = { generatePseudoRandomAddress(): string { - const randomBigNum = ZeroEx.generatePseudoRandomSalt(); + const randomBigNum = generatePseudoRandomSalt(); const randomBuff = crypto.solSHA3([randomBigNum]); const randomAddress = `0x${randomBuff.slice(0, 20).toString('hex')}`; return randomAddress; diff --git a/packages/contracts/src/utils/constants.ts b/packages/contracts/src/utils/constants.ts index 3fd2a0a3b..483340186 100644 --- a/packages/contracts/src/utils/constants.ts +++ b/packages/contracts/src/utils/constants.ts @@ -1,5 +1,5 @@ -import { ZeroEx } from '0x.js'; import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; @@ -20,6 +20,7 @@ export const constants = { INVALID_OPCODE: 'invalid opcode', REVERT: 'revert', TESTRPC_NETWORK_ID: 50, + AWAIT_TRANSACTION_MINED_MS: 100, MAX_ETHERTOKEN_WITHDRAW_GAS: 43000, MAX_TOKEN_TRANSFERFROM_GAS: 80000, MAX_TOKEN_APPROVE_GAS: 60000, @@ -30,13 +31,14 @@ export const constants = { NUM_DUMMY_ERC20_TO_DEPLOY: 3, NUM_DUMMY_ERC721_TO_DEPLOY: 1, NUM_ERC721_TOKENS_TO_MINT: 2, + NULL_ADDRESS: '0x0000000000000000000000000000000000000000', TESTRPC_PRIVATE_KEYS: _.map(TESTRPC_PRIVATE_KEYS_STRINGS, privateKeyString => ethUtil.toBuffer(privateKeyString)), - INITIAL_ERC20_BALANCE: ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18), - INITIAL_ERC20_ALLOWANCE: ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18), + INITIAL_ERC20_BALANCE: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18), + INITIAL_ERC20_ALLOWANCE: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18), STATIC_ORDER_PARAMS: { - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18), - makerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18), - takerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), + makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), + takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), }, }; diff --git a/packages/contracts/src/utils/coverage.ts b/packages/contracts/src/utils/coverage.ts new file mode 100644 index 000000000..a37939464 --- /dev/null +++ b/packages/contracts/src/utils/coverage.ts @@ -0,0 +1,21 @@ +import { devConstants } from '@0xproject/dev-utils'; +import { CoverageSubprovider, SolCompilerArtifactAdapter } from '@0xproject/sol-cov'; +import * as fs from 'fs'; +import * as _ from 'lodash'; + +let coverageSubprovider: CoverageSubprovider; + +export const coverage = { + getCoverageSubproviderSingleton(): CoverageSubprovider { + if (_.isUndefined(coverageSubprovider)) { + coverageSubprovider = coverage._getCoverageSubprovider(); + } + return coverageSubprovider; + }, + _getCoverageSubprovider(): CoverageSubprovider { + const defaultFromAddress = devConstants.TESTRPC_FIRST_ADDRESS; + const solCompilerArtifactAdapter = new SolCompilerArtifactAdapter(); + const subprovider = new CoverageSubprovider(solCompilerArtifactAdapter, defaultFromAddress); + return subprovider; + }, +}; diff --git a/packages/contracts/src/utils/erc20_wrapper.ts b/packages/contracts/src/utils/erc20_wrapper.ts index f12571b48..0303649a5 100644 --- a/packages/contracts/src/utils/erc20_wrapper.ts +++ b/packages/contracts/src/utils/erc20_wrapper.ts @@ -23,7 +23,7 @@ export class ERC20Wrapper { } public async deployDummyTokensAsync(): Promise<DummyERC20TokenContract[]> { this._dummyTokenContracts = await Promise.all( - _.times(constants.NUM_DUMMY_ERC20_TO_DEPLOY, () => + _.times(constants.NUM_DUMMY_ERC20_TO_DEPLOY, async () => DummyERC20TokenContract.deployFrom0xArtifactAsync( artifacts.DummyERC20Token, this._provider, @@ -45,7 +45,7 @@ export class ERC20Wrapper { ); return this._proxyContract; } - public async setBalancesAndAllowancesAsync() { + public async setBalancesAndAllowancesAsync(): Promise<void> { this._validateDummyTokenContractsExistOrThrow(); this._validateProxyContractExistsOrThrow(); const setBalancePromises: Array<Promise<string>> = []; @@ -103,12 +103,12 @@ export class ERC20Wrapper { const tokenAddresses = _.map(this._dummyTokenContracts, dummyTokenContract => dummyTokenContract.address); return tokenAddresses; } - private _validateDummyTokenContractsExistOrThrow() { + private _validateDummyTokenContractsExistOrThrow(): void { if (_.isUndefined(this._dummyTokenContracts)) { throw new Error('Dummy ERC20 tokens not yet deployed, please call "deployDummyTokensAsync"'); } } - private _validateProxyContractExistsOrThrow() { + private _validateProxyContractExistsOrThrow(): void { if (_.isUndefined(this._proxyContract)) { throw new Error('ERC20 proxy contract not yet deployed, please call "deployProxyAsync"'); } diff --git a/packages/contracts/src/utils/erc721_wrapper.ts b/packages/contracts/src/utils/erc721_wrapper.ts index 5b5de262f..aee796e4b 100644 --- a/packages/contracts/src/utils/erc721_wrapper.ts +++ b/packages/contracts/src/utils/erc721_wrapper.ts @@ -1,4 +1,4 @@ -import { ZeroEx } from '0x.js'; +import { generatePseudoRandomSalt } from '@0xproject/order-utils'; import { Provider } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; @@ -25,7 +25,7 @@ export class ERC721Wrapper { } public async deployDummyTokensAsync(): Promise<DummyERC721TokenContract[]> { this._dummyTokenContracts = await Promise.all( - _.times(constants.NUM_DUMMY_ERC721_TO_DEPLOY, () => + _.times(constants.NUM_DUMMY_ERC721_TO_DEPLOY, async () => DummyERC721TokenContract.deployFrom0xArtifactAsync( artifacts.DummyERC721Token, this._provider, @@ -45,7 +45,7 @@ export class ERC721Wrapper { ); return this._proxyContract; } - public async setBalancesAndAllowancesAsync() { + public async setBalancesAndAllowancesAsync(): Promise<void> { this._validateDummyTokenContractsExistOrThrow(); this._validateProxyContractExistsOrThrow(); const setBalancePromises: Array<Promise<string>> = []; @@ -54,7 +54,7 @@ export class ERC721Wrapper { _.forEach(this._dummyTokenContracts, dummyTokenContract => { _.forEach(this._tokenOwnerAddresses, tokenOwnerAddress => { _.forEach(_.range(constants.NUM_ERC721_TOKENS_TO_MINT), () => { - const tokenId = ZeroEx.generatePseudoRandomSalt(); + const tokenId = generatePseudoRandomSalt(); setBalancePromises.push( dummyTokenContract.mint.sendTransactionAsync(tokenOwnerAddress, tokenId, { from: this._contractOwnerAddress, @@ -125,17 +125,17 @@ export class ERC721Wrapper { const tokenAddresses = _.map(this._dummyTokenContracts, dummyTokenContract => dummyTokenContract.address); return tokenAddresses; } - private _validateDummyTokenContractsExistOrThrow() { + private _validateDummyTokenContractsExistOrThrow(): void { if (_.isUndefined(this._dummyTokenContracts)) { throw new Error('Dummy ERC721 tokens not yet deployed, please call "deployDummyTokensAsync"'); } } - private _validateProxyContractExistsOrThrow() { + private _validateProxyContractExistsOrThrow(): void { if (_.isUndefined(this._proxyContract)) { throw new Error('ERC721 proxy contract not yet deployed, please call "deployProxyAsync"'); } } - private _validateBalancesAndAllowancesSetOrThrow() { + private _validateBalancesAndAllowancesSetOrThrow(): void { if (_.keys(this._initialTokenIdsByOwner).length === 0) { throw new Error( 'Dummy ERC721 balances and allowances not yet set, please call "setBalancesAndAllowancesAsync"', diff --git a/packages/contracts/src/utils/exchange_wrapper.ts b/packages/contracts/src/utils/exchange_wrapper.ts index 46531fa3f..0d0977ab8 100644 --- a/packages/contracts/src/utils/exchange_wrapper.ts +++ b/packages/contracts/src/utils/exchange_wrapper.ts @@ -1,5 +1,6 @@ -import { TransactionReceiptWithDecodedLogs, ZeroEx } from '0x.js'; +import { Provider, TransactionReceiptWithDecodedLogs } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import * as Web3 from 'web3'; @@ -13,11 +14,11 @@ import { AssetProxyId, OrderInfo, SignedOrder, SignedTransaction } from './types export class ExchangeWrapper { private _exchange: ExchangeContract; + private _web3Wrapper: Web3Wrapper; private _logDecoder: LogDecoder = new LogDecoder(constants.TESTRPC_NETWORK_ID); - private _zeroEx: ZeroEx; - constructor(exchangeContract: ExchangeContract, zeroEx: ZeroEx) { + constructor(exchangeContract: ExchangeContract, provider: Provider) { this._exchange = exchangeContract; - this._zeroEx = zeroEx; + this._web3Wrapper = new Web3Wrapper(provider); } public async fillOrderAsync( signedOrder: SignedOrder, @@ -196,7 +197,7 @@ export class ExchangeWrapper { opts: { oldAssetProxyAddressIfExists?: string } = {}, ): Promise<TransactionReceiptWithDecodedLogs> { const oldAssetProxyAddress = _.isUndefined(opts.oldAssetProxyAddressIfExists) - ? ZeroEx.NULL_ADDRESS + ? constants.NULL_ADDRESS : opts.oldAssetProxyAddressIfExists; const txHash = await this._exchange.registerAssetProxy.sendTransactionAsync( assetProxyId, @@ -245,8 +246,8 @@ export class ExchangeWrapper { const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash); return tx; } - private async _getTxWithDecodedExchangeLogsAsync(txHash: string) { - const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash); + private async _getTxWithDecodedExchangeLogsAsync(txHash: string): Promise<TransactionReceiptWithDecodedLogs> { + const tx = await this._web3Wrapper.awaitTransactionMinedAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); tx.logs = _.filter(tx.logs, log => log.address === this._exchange.address); tx.logs = _.map(tx.logs, log => this._logDecoder.decodeLogOrThrow(log)); return tx; diff --git a/packages/contracts/src/utils/formatters.ts b/packages/contracts/src/utils/formatters.ts index e706c15b5..bfa48d6f1 100644 --- a/packages/contracts/src/utils/formatters.ts +++ b/packages/contracts/src/utils/formatters.ts @@ -5,7 +5,7 @@ import { orderUtils } from './order_utils'; import { BatchCancelOrders, BatchFillOrders, MarketBuyOrders, MarketSellOrders, SignedOrder } from './types'; export const formatters = { - createBatchFill(signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[] = []) { + createBatchFill(signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[] = []): BatchFillOrders { const batchFill: BatchFillOrders = { orders: [], signatures: [], @@ -21,7 +21,7 @@ export const formatters = { }); return batchFill; }, - createMarketSellOrders(signedOrders: SignedOrder[], takerAssetFillAmount: BigNumber) { + createMarketSellOrders(signedOrders: SignedOrder[], takerAssetFillAmount: BigNumber): MarketSellOrders { const marketSellOrders: MarketSellOrders = { orders: [], signatures: [], @@ -34,7 +34,7 @@ export const formatters = { }); return marketSellOrders; }, - createMarketBuyOrders(signedOrders: SignedOrder[], makerAssetFillAmount: BigNumber) { + createMarketBuyOrders(signedOrders: SignedOrder[], makerAssetFillAmount: BigNumber): MarketBuyOrders { const marketBuyOrders: MarketBuyOrders = { orders: [], signatures: [], @@ -47,7 +47,7 @@ export const formatters = { }); return marketBuyOrders; }, - createBatchCancel(signedOrders: SignedOrder[]) { + createBatchCancel(signedOrders: SignedOrder[]): BatchCancelOrders { const batchCancel: BatchCancelOrders = { orders: [], }; diff --git a/packages/contracts/test/utils/match_order_tester.ts b/packages/contracts/src/utils/match_order_tester.ts index 14930de08..30039937f 100644 --- a/packages/contracts/test/utils/match_order_tester.ts +++ b/packages/contracts/src/utils/match_order_tester.ts @@ -1,28 +1,28 @@ -import { LogWithDecodedArgs, ZeroEx } from '0x.js'; import { BlockchainLifecycle } from '@0xproject/dev-utils'; +import { LogWithDecodedArgs } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; import ethUtil = require('ethereumjs-util'); import * as _ from 'lodash'; -import { DummyERC20TokenContract } from '../../src/contract_wrappers/generated/dummy_e_r_c20_token'; -import { DummyERC721TokenContract } from '../../src/contract_wrappers/generated/dummy_e_r_c721_token'; -import { ERC20ProxyContract } from '../../src/contract_wrappers/generated/e_r_c20_proxy'; -import { ERC721ProxyContract } from '../../src/contract_wrappers/generated/e_r_c721_proxy'; +import { DummyERC20TokenContract } from '../contract_wrappers/generated/dummy_e_r_c20_token'; +import { DummyERC721TokenContract } from '../contract_wrappers/generated/dummy_e_r_c721_token'; +import { ERC20ProxyContract } from '../contract_wrappers/generated/e_r_c20_proxy'; +import { ERC721ProxyContract } from '../contract_wrappers/generated/e_r_c721_proxy'; import { CancelContractEventArgs, ExchangeContract, FillContractEventArgs, -} from '../../src/contract_wrappers/generated/exchange'; -import { assetProxyUtils } from '../../src/utils/asset_proxy_utils'; -import { chaiSetup } from '../../src/utils/chai_setup'; -import { constants } from '../../src/utils/constants'; -import { crypto } from '../../src/utils/crypto'; -import { ERC20Wrapper } from '../../src/utils/erc20_wrapper'; -import { ERC721Wrapper } from '../../src/utils/erc721_wrapper'; -import { ExchangeWrapper } from '../../src/utils/exchange_wrapper'; -import { OrderFactory } from '../../src/utils/order_factory'; -import { orderUtils } from '../../src/utils/order_utils'; +} from '../contract_wrappers/generated/exchange'; +import { assetProxyUtils } from '../utils/asset_proxy_utils'; +import { chaiSetup } from '../utils/chai_setup'; +import { constants } from '../utils/constants'; +import { crypto } from '../utils/crypto'; +import { ERC20Wrapper } from '../utils/erc20_wrapper'; +import { ERC721Wrapper } from '../utils/erc721_wrapper'; +import { ExchangeWrapper } from '../utils/exchange_wrapper'; +import { OrderFactory } from '../utils/order_factory'; +import { orderUtils } from '../utils/order_utils'; import { AssetProxyId, ContractName, @@ -31,8 +31,8 @@ import { ExchangeStatus, SignedOrder, TransferAmountsByMatchOrders as TransferAmounts, -} from '../../src/utils/types'; -import { provider, web3Wrapper } from '../../src/utils/web3_wrapper'; +} from '../utils/types'; +import { provider, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -55,10 +55,10 @@ export class MatchOrderTester { realERC20BalancesByOwner: ERC20BalancesByOwner, expectedNewERC721TokenIdsByOwner: ERC721TokenIdsByOwner, realERC721TokenIdsByOwner: ERC721TokenIdsByOwner, - ) { + ): boolean { // ERC20 Balances - const erc20BalancesMatch = _.isEqual(expectedNewERC20BalancesByOwner, realERC20BalancesByOwner); - if (!erc20BalancesMatch) { + const doesErc20BalancesMatch = _.isEqual(expectedNewERC20BalancesByOwner, realERC20BalancesByOwner); + if (!doesErc20BalancesMatch) { return false; } // ERC721 Token Ids @@ -75,8 +75,11 @@ export class MatchOrderTester { _.sortBy(tokenIds); }); }); - const erc721TokenIdsMatch = _.isEqual(sortedExpectedNewERC721TokenIdsByOwner, sortedNewERC721TokenIdsByOwner); - return erc721TokenIdsMatch; + const doesErc721TokenIdsMatch = _.isEqual( + sortedExpectedNewERC721TokenIdsByOwner, + sortedNewERC721TokenIdsByOwner, + ); + return doesErc721TokenIdsMatch; } /// @dev Constructs new MatchOrderTester. /// @param exchangeWrapper Used to call to the Exchange. @@ -156,13 +159,13 @@ export class MatchOrderTester { expectedTransferAmounts, ); // Assert our expected balances are equal to the actual balances - const expectedBalancesMatchRealBalances = MatchOrderTester._compareExpectedAndRealBalances( + const didExpectedBalancesMatchRealBalances = MatchOrderTester._compareExpectedAndRealBalances( expectedERC20BalancesByOwner, newERC20BalancesByOwner, expectedERC721TokenIdsByOwner, newERC721TokenIdsByOwner, ); - expect(expectedBalancesMatchRealBalances).to.be.true(); + expect(didExpectedBalancesMatchRealBalances).to.be.true(); return [newERC20BalancesByOwner, newERC721TokenIdsByOwner]; } /// @dev Calculates expected transfer amounts between order makers, fee recipients, and diff --git a/packages/contracts/src/utils/order_factory.ts b/packages/contracts/src/utils/order_factory.ts index 044e9b865..86b3d5ac7 100644 --- a/packages/contracts/src/utils/order_factory.ts +++ b/packages/contracts/src/utils/order_factory.ts @@ -1,7 +1,8 @@ -import { ZeroEx } from '0x.js'; +import { generatePseudoRandomSalt } from '@0xproject/order-utils'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; +import { constants } from './constants'; import { orderUtils } from './order_utils'; import { signingUtils } from './signing_utils'; import { SignatureType, SignedOrder, UnsignedOrder } from './types'; @@ -19,10 +20,10 @@ export class OrderFactory { ): SignedOrder { const randomExpiration = new BigNumber(Math.floor((Date.now() + Math.random() * 100000000000) / 1000)); const order = ({ - senderAddress: ZeroEx.NULL_ADDRESS, + senderAddress: constants.NULL_ADDRESS, expirationTimeSeconds: randomExpiration, - salt: ZeroEx.generatePseudoRandomSalt(), - takerAddress: ZeroEx.NULL_ADDRESS, + salt: generatePseudoRandomSalt(), + takerAddress: constants.NULL_ADDRESS, ...this._defaultOrderParams, ...customOrderParams, } as any) as UnsignedOrder; diff --git a/packages/contracts/src/utils/order_utils.ts b/packages/contracts/src/utils/order_utils.ts index 7a482ad9e..8adc6b735 100644 --- a/packages/contracts/src/utils/order_utils.ts +++ b/packages/contracts/src/utils/order_utils.ts @@ -4,7 +4,7 @@ import ethUtil = require('ethereumjs-util'); import * as _ from 'lodash'; import { crypto } from './crypto'; -import { OrderStruct, SignatureType, SignedOrder, UnsignedOrder } from './types'; +import { CancelOrder, MatchOrder, OrderStruct, SignatureType, SignedOrder, UnsignedOrder } from './types'; export const orderUtils = { createFill: (signedOrder: SignedOrder, takerAssetFillAmount?: BigNumber) => { @@ -15,7 +15,7 @@ export const orderUtils = { }; return fill; }, - createCancel(signedOrder: SignedOrder, takerAssetCancelAmount?: BigNumber) { + createCancel(signedOrder: SignedOrder, takerAssetCancelAmount?: BigNumber): CancelOrder { const cancel = { order: orderUtils.getOrderStruct(signedOrder), takerAssetCancelAmount: takerAssetCancelAmount || signedOrder.takerAssetAmount, @@ -80,7 +80,7 @@ export const orderUtils = { const orderHashHex = `0x${orderHashBuff.toString('hex')}`; return orderHashHex; }, - createMatchOrders(signedOrderLeft: SignedOrder, signedOrderRight: SignedOrder) { + createMatchOrders(signedOrderLeft: SignedOrder, signedOrderRight: SignedOrder): MatchOrder { const fill = { left: orderUtils.getOrderStruct(signedOrderLeft), right: orderUtils.getOrderStruct(signedOrderRight), diff --git a/packages/contracts/src/utils/transaction_factory.ts b/packages/contracts/src/utils/transaction_factory.ts index 3a4f48330..941bff96d 100644 --- a/packages/contracts/src/utils/transaction_factory.ts +++ b/packages/contracts/src/utils/transaction_factory.ts @@ -1,4 +1,4 @@ -import { ZeroEx } from '0x.js'; +import { generatePseudoRandomSalt } from '@0xproject/order-utils'; import { BigNumber } from '@0xproject/utils'; import * as ethUtil from 'ethereumjs-util'; @@ -20,7 +20,7 @@ export class TransactionFactory { data: string, signatureType: SignatureType = SignatureType.Ecrecover, ): SignedTransaction { - const salt = ZeroEx.generatePseudoRandomSalt(); + const salt = generatePseudoRandomSalt(); const txHash = crypto.solSHA3([this._exchangeAddress, salt, ethUtil.toBuffer(data)]); const signature = signingUtils.signMessage(txHash, this._privateKey, signatureType); const signedTx = { diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts index 8d81adece..ef86b4f38 100644 --- a/packages/contracts/src/utils/types.ts +++ b/packages/contracts/src/utils/types.ts @@ -197,3 +197,15 @@ export interface ProxyData { tokenAddress?: string; data?: any; } + +export interface CancelOrder { + order: OrderStruct; + takerAssetCancelAmount: BigNumber; +} + +export interface MatchOrder { + left: OrderStruct; + right: OrderStruct; + leftSignature: string; + rightSignature: string; +} diff --git a/packages/contracts/src/utils/web3_wrapper.ts b/packages/contracts/src/utils/web3_wrapper.ts index ed1c488a2..02595506b 100644 --- a/packages/contracts/src/utils/web3_wrapper.ts +++ b/packages/contracts/src/utils/web3_wrapper.ts @@ -1,12 +1,19 @@ -import { devConstants, web3Factory } from '@0xproject/dev-utils'; +import { devConstants, env, EnvVars, web3Factory } from '@0xproject/dev-utils'; +import { prependSubprovider } from '@0xproject/subproviders'; import { Provider } from '@0xproject/types'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import { coverage } from './coverage'; + 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; +export const provider = web3Factory.getRpcProvider(providerConfigs); +const isCoverageEnabled = env.parseBoolean(EnvVars.SolidityCoverage); +if (isCoverageEnabled) { + const coverageSubprovider = coverage.getCoverageSubproviderSingleton(); + prependSubprovider(provider, coverageSubprovider); +} export const web3Wrapper = new Web3Wrapper(provider); diff --git a/packages/contracts/test/asset_proxy/authorizable.ts b/packages/contracts/test/asset_proxy/authorizable.ts index 636b9096b..52e9ea87f 100644 --- a/packages/contracts/test/asset_proxy/authorizable.ts +++ b/packages/contracts/test/asset_proxy/authorizable.ts @@ -20,6 +20,12 @@ describe('Authorizable', () => { let address: string; let authorizable: MixinAuthorizableContract; before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); + before(async () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); owner = address = accounts[0]; notOwner = accounts[1]; @@ -42,12 +48,18 @@ describe('Authorizable', () => { ).to.be.rejectedWith(constants.REVERT); }); it('should allow owner to add an authorized address', async () => { - await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }); + await web3Wrapper.awaitTransactionMinedAsync( + await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); const isAuthorized = await authorizable.authorized.callAsync(address); expect(isAuthorized).to.be.true(); }); it('should throw if owner attempts to authorize a duplicate address', async () => { - await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }); + await web3Wrapper.awaitTransactionMinedAsync( + await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); return expect( authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }), ).to.be.rejectedWith(constants.REVERT); @@ -56,7 +68,10 @@ describe('Authorizable', () => { describe('removeAuthorizedAddress', () => { it('should throw if not called by owner', async () => { - await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }); + await web3Wrapper.awaitTransactionMinedAsync( + await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); return expect( authorizable.removeAuthorizedAddress.sendTransactionAsync(address, { from: notOwner, @@ -65,10 +80,16 @@ describe('Authorizable', () => { }); it('should allow owner to remove an authorized address', async () => { - await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }); - await authorizable.removeAuthorizedAddress.sendTransactionAsync(address, { - from: owner, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + await web3Wrapper.awaitTransactionMinedAsync( + await authorizable.removeAuthorizedAddress.sendTransactionAsync(address, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); const isAuthorized = await authorizable.authorized.callAsync(address); expect(isAuthorized).to.be.false(); }); @@ -86,16 +107,22 @@ describe('Authorizable', () => { it('should return all authorized addresses', async () => { const initial = await authorizable.getAuthorizedAddresses.callAsync(); expect(initial).to.have.length(0); - await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { - from: owner, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); const afterAdd = await authorizable.getAuthorizedAddresses.callAsync(); expect(afterAdd).to.have.length(1); expect(afterAdd).to.include(address); - await authorizable.removeAuthorizedAddress.sendTransactionAsync(address, { - from: owner, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await authorizable.removeAuthorizedAddress.sendTransactionAsync(address, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); const afterRemove = await authorizable.getAuthorizedAddresses.callAsync(); expect(afterRemove).to.have.length(0); }); diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts index e7ef9a0d3..4ee38db80 100644 --- a/packages/contracts/test/asset_proxy/proxies.ts +++ b/packages/contracts/test/asset_proxy/proxies.ts @@ -1,4 +1,3 @@ -import { ZeroEx } from '0x.js'; import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; @@ -37,8 +36,12 @@ describe('Asset Transfer Proxies', () => { let erc721Wrapper: ERC721Wrapper; let erc721MakerTokenId: BigNumber; - let zeroEx: ZeroEx; - + before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); before(async () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); const usedAddresses = ([owner, notAuthorized, exchangeAddress, makerAddress, takerAddress] = accounts); @@ -49,22 +52,24 @@ describe('Asset Transfer Proxies', () => { [zrxToken] = await erc20Wrapper.deployDummyTokensAsync(); erc20Proxy = await erc20Wrapper.deployProxyAsync(); await erc20Wrapper.setBalancesAndAllowancesAsync(); - await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeAddress, { - from: owner, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeAddress, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); [erc721Token] = await erc721Wrapper.deployDummyTokensAsync(); erc721Proxy = await erc721Wrapper.deployProxyAsync(); await erc721Wrapper.setBalancesAndAllowancesAsync(); const erc721Balances = await erc721Wrapper.getBalancesAsync(); erc721MakerTokenId = erc721Balances[makerAddress][erc721Token.address][0]; - await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeAddress, { - from: owner, - }); - - zeroEx = new ZeroEx(provider, { - networkId: constants.TESTRPC_NETWORK_ID, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeAddress, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); @@ -80,12 +85,15 @@ describe('Asset Transfer Proxies', () => { // Perform a transfer from makerAddress to takerAddress const erc20Balances = await erc20Wrapper.getBalancesAsync(); const amount = new BigNumber(10); - await erc20Proxy.transferFrom.sendTransactionAsync( - encodedProxyMetadata, - makerAddress, - takerAddress, - amount, - { from: exchangeAddress }, + await web3Wrapper.awaitTransactionMinedAsync( + await erc20Proxy.transferFrom.sendTransactionAsync( + encodedProxyMetadata, + makerAddress, + takerAddress, + amount, + { from: exchangeAddress }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, ); // Verify transfer was successful const newBalances = await erc20Wrapper.getBalancesAsync(); @@ -103,12 +111,15 @@ describe('Asset Transfer Proxies', () => { // Perform a transfer from makerAddress to takerAddress const erc20Balances = await erc20Wrapper.getBalancesAsync(); const amount = new BigNumber(0); - await erc20Proxy.transferFrom.sendTransactionAsync( - encodedProxyMetadata, - makerAddress, - takerAddress, - amount, - { from: exchangeAddress }, + await web3Wrapper.awaitTransactionMinedAsync( + await erc20Proxy.transferFrom.sendTransactionAsync( + encodedProxyMetadata, + makerAddress, + takerAddress, + amount, + { from: exchangeAddress }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, ); // Verify transfer was successful const newBalances = await erc20Wrapper.getBalancesAsync(); @@ -126,9 +137,12 @@ describe('Asset Transfer Proxies', () => { // Create allowance less than transfer amount. Set allowance on proxy. const allowance = new BigNumber(0); const transferAmount = new BigNumber(10); - await zrxToken.approve.sendTransactionAsync(erc20Proxy.address, allowance, { - from: makerAddress, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await zrxToken.approve.sendTransactionAsync(erc20Proxy.address, allowance, { + from: makerAddress, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); // Perform a transfer; expect this to fail. return expect( erc20Proxy.transferFrom.sendTransactionAsync( @@ -179,7 +193,7 @@ describe('Asset Transfer Proxies', () => { amounts, { from: exchangeAddress }, ); - const res = await zeroEx.awaitTransactionMinedAsync(txHash); + const res = await web3Wrapper.awaitTransactionMinedAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); const newBalances = await erc20Wrapper.getBalancesAsync(); expect(res.logs.length).to.equal(numTransfers); @@ -200,7 +214,7 @@ describe('Asset Transfer Proxies', () => { const toAddresses = _.times(numTransfers, () => takerAddress); const amounts = _.times(numTransfers, () => amount); - expect( + return expect( erc20Proxy.batchTransferFrom.sendTransactionAsync( assetMetadata, fromAddresses, @@ -232,12 +246,15 @@ describe('Asset Transfer Proxies', () => { // Perform a transfer from makerAddress to takerAddress const erc20Balances = await erc20Wrapper.getBalancesAsync(); const amount = new BigNumber(1); - await erc721Proxy.transferFrom.sendTransactionAsync( - encodedProxyMetadata, - makerAddress, - takerAddress, - amount, - { from: exchangeAddress }, + await web3Wrapper.awaitTransactionMinedAsync( + await erc721Proxy.transferFrom.sendTransactionAsync( + encodedProxyMetadata, + makerAddress, + takerAddress, + amount, + { from: exchangeAddress }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, ); // Verify transfer was successful const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); @@ -297,9 +314,12 @@ describe('Asset Transfer Proxies', () => { erc721MakerTokenId, ); // Remove transfer approval for makerAddress. - await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, false, { - from: makerAddress, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, false, { + from: makerAddress, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); // Perform a transfer; expect this to fail. const amount = new BigNumber(1); return expect( @@ -356,7 +376,7 @@ describe('Asset Transfer Proxies', () => { amounts, { from: exchangeAddress }, ); - const res = await zeroEx.awaitTransactionMinedAsync(txHash); + const res = await web3Wrapper.awaitTransactionMinedAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); expect(res.logs.length).to.equal(numTransfers); const newOwnerMakerAssetA = await erc721Token.ownerOf.callAsync(makerTokenIdA); @@ -378,7 +398,7 @@ describe('Asset Transfer Proxies', () => { const toAddresses = _.times(numTransfers, () => takerAddress); const amounts = _.times(numTransfers, () => new BigNumber(1)); - expect( + return expect( erc721Proxy.batchTransferFrom.sendTransactionAsync( assetMetadata, fromAddresses, diff --git a/packages/contracts/test/ether_token.ts b/packages/contracts/test/ether_token.ts index 418fbc45e..9b04dd187 100644 --- a/packages/contracts/test/ether_token.ts +++ b/packages/contracts/test/ether_token.ts @@ -1,4 +1,4 @@ -import { ContractWrappersError, ZeroEx } from '0x.js'; +import { ContractWrappers, ContractWrappersError } from '@0xproject/contract-wrappers'; import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BigNumber, promisify } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; @@ -17,16 +17,23 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('EtherToken', () => { let account: string; - const gasPrice = ZeroEx.toBaseUnitAmount(new BigNumber(20), 9); - let zeroEx: ZeroEx; + const gasPrice = Web3Wrapper.toBaseUnitAmount(new BigNumber(20), 9); + let contractWrappers: ContractWrappers; let etherTokenAddress: string; + + before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); before(async () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); account = accounts[0]; const etherToken = await WETH9Contract.deployFrom0xArtifactAsync(artifacts.EtherToken, provider, txDefaults); etherTokenAddress = etherToken.address; - zeroEx = new ZeroEx(provider, { + contractWrappers = new ContractWrappers(provider, { gasPrice, networkId: constants.TESTRPC_NETWORK_ID, }); @@ -42,23 +49,23 @@ describe('EtherToken', () => { const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account); const ethToDeposit = initEthBalance.plus(1); - return expect(zeroEx.etherToken.depositAsync(etherTokenAddress, ethToDeposit, account)).to.be.rejectedWith( - ContractWrappersError.InsufficientEthBalanceForDeposit, - ); + return expect( + contractWrappers.etherToken.depositAsync(etherTokenAddress, ethToDeposit, account), + ).to.be.rejectedWith(ContractWrappersError.InsufficientEthBalanceForDeposit); }); it('should convert deposited Ether to wrapped Ether tokens', async () => { const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account); - const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); + const initEthTokenBalance = await contractWrappers.token.getBalanceAsync(etherTokenAddress, account); const ethToDeposit = new BigNumber(Web3Wrapper.toWei(new BigNumber(1))); - const txHash = await zeroEx.etherToken.depositAsync(etherTokenAddress, ethToDeposit, account); - const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); + const txHash = await contractWrappers.etherToken.depositAsync(etherTokenAddress, ethToDeposit, account); + const receipt = await web3Wrapper.awaitTransactionMinedAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); const ethSpentOnGas = gasPrice.times(receipt.gasUsed); const finalEthBalance = await web3Wrapper.getBalanceInWeiAsync(account); - const finalEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); + const finalEthTokenBalance = await contractWrappers.token.getBalanceAsync(etherTokenAddress, account); expect(finalEthBalance).to.be.bignumber.equal(initEthBalance.minus(ethToDeposit.plus(ethSpentOnGas))); expect(finalEthTokenBalance).to.be.bignumber.equal(initEthTokenBalance.plus(ethToDeposit)); @@ -67,29 +74,34 @@ describe('EtherToken', () => { describe('withdraw', () => { it('should throw if caller attempts to withdraw greater than caller balance', async () => { - const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); + const initEthTokenBalance = await contractWrappers.token.getBalanceAsync(etherTokenAddress, account); const ethTokensToWithdraw = initEthTokenBalance.plus(1); return expect( - zeroEx.etherToken.withdrawAsync(etherTokenAddress, ethTokensToWithdraw, account), + contractWrappers.etherToken.withdrawAsync(etherTokenAddress, ethTokensToWithdraw, account), ).to.be.rejectedWith(ContractWrappersError.InsufficientWEthBalanceForWithdrawal); }); it('should convert ether tokens to ether with sufficient balance', async () => { const ethToDeposit = new BigNumber(Web3Wrapper.toWei(new BigNumber(1))); - await zeroEx.etherToken.depositAsync(etherTokenAddress, ethToDeposit, account); - const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); + await contractWrappers.etherToken.depositAsync(etherTokenAddress, ethToDeposit, account); + const initEthTokenBalance = await contractWrappers.token.getBalanceAsync(etherTokenAddress, account); const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account); const ethTokensToWithdraw = initEthTokenBalance; expect(ethTokensToWithdraw).to.not.be.bignumber.equal(0); - const txHash = await zeroEx.etherToken.withdrawAsync(etherTokenAddress, ethTokensToWithdraw, account, { - gasLimit: constants.MAX_ETHERTOKEN_WITHDRAW_GAS, - }); - const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); + const txHash = await contractWrappers.etherToken.withdrawAsync( + etherTokenAddress, + ethTokensToWithdraw, + account, + { + gasLimit: constants.MAX_ETHERTOKEN_WITHDRAW_GAS, + }, + ); + const receipt = await web3Wrapper.awaitTransactionMinedAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); const ethSpentOnGas = gasPrice.times(receipt.gasUsed); const finalEthBalance = await web3Wrapper.getBalanceInWeiAsync(account); - const finalEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); + const finalEthTokenBalance = await contractWrappers.token.getBalanceAsync(etherTokenAddress, account); expect(finalEthBalance).to.be.bignumber.equal( initEthBalance.plus(ethTokensToWithdraw.minus(ethSpentOnGas)), @@ -101,9 +113,9 @@ describe('EtherToken', () => { describe('fallback', () => { it('should convert sent ether to ether tokens', async () => { const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account); - const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); + const initEthTokenBalance = await contractWrappers.token.getBalanceAsync(etherTokenAddress, account); - const ethToDeposit = ZeroEx.toBaseUnitAmount(new BigNumber(1), 18); + const ethToDeposit = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18); const txHash = await web3Wrapper.sendTransactionAsync({ from: account, @@ -112,11 +124,11 @@ describe('EtherToken', () => { gasPrice, }); - const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); + const receipt = await web3Wrapper.awaitTransactionMinedAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); const ethSpentOnGas = gasPrice.times(receipt.gasUsed); const finalEthBalance = await web3Wrapper.getBalanceInWeiAsync(account); - const finalEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); + const finalEthTokenBalance = await contractWrappers.token.getBalanceAsync(etherTokenAddress, account); expect(finalEthBalance).to.be.bignumber.equal(initEthBalance.minus(ethToDeposit.plus(ethSpentOnGas))); expect(finalEthTokenBalance).to.be.bignumber.equal(initEthTokenBalance.plus(ethToDeposit)); diff --git a/packages/contracts/test/exchange/core.ts b/packages/contracts/test/exchange/core.ts index be3252800..f1d9a4156 100644 --- a/packages/contracts/test/exchange/core.ts +++ b/packages/contracts/test/exchange/core.ts @@ -1,6 +1,7 @@ -import { LogWithDecodedArgs, ZeroEx } from '0x.js'; import { BlockchainLifecycle } from '@0xproject/dev-utils'; +import { LogWithDecodedArgs } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; import ethUtil = require('ethereumjs-util'); import 'make-promises-safe'; @@ -59,8 +60,12 @@ describe('Exchange core', () => { let defaultMakerAssetAddress: string; let defaultTakerAssetAddress: string; - let zeroEx: ZeroEx; - + before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); before(async () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = accounts); @@ -85,20 +90,22 @@ describe('Exchange core', () => { txDefaults, assetProxyUtils.encodeERC20ProxyData(zrxToken.address), ); - zeroEx = new ZeroEx(provider, { - exchangeContractAddress: exchange.address, - networkId: constants.TESTRPC_NETWORK_ID, - }); - exchangeWrapper = new ExchangeWrapper(exchange, zeroEx); + exchangeWrapper = new ExchangeWrapper(exchange, provider); await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, owner); await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC721, erc721Proxy.address, owner); - await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { - from: owner, - }); - await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { - from: owner, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + await web3Wrapper.awaitTransactionMinedAsync( + await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); defaultMakerAssetAddress = erc20TokenA.address; defaultTakerAssetAddress = erc20TokenB.address; @@ -166,8 +173,8 @@ describe('Exchange core', () => { it('should transfer the correct amounts when makerAssetAmount === takerAssetAmount', async () => { signedOrder = orderFactory.newSignedOrder({ - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), }); const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync( @@ -219,8 +226,8 @@ describe('Exchange core', () => { it('should transfer the correct amounts when makerAssetAmount > takerAssetAmount', async () => { signedOrder = orderFactory.newSignedOrder({ - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), }); const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync( @@ -272,8 +279,8 @@ describe('Exchange core', () => { it('should transfer the correct amounts when makerAssetAmount < takerAssetAmount', async () => { signedOrder = orderFactory.newSignedOrder({ - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), }); const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync( @@ -326,8 +333,8 @@ describe('Exchange core', () => { it('should transfer the correct amounts when taker is specified and order is claimed by taker', async () => { signedOrder = orderFactory.newSignedOrder({ takerAddress, - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), }); const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync( @@ -445,8 +452,8 @@ describe('Exchange core', () => { it('should throw when taker is specified and order is claimed by other', async () => { signedOrder = orderFactory.newSignedOrder({ takerAddress: feeRecipientAddress, - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), }); return expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith( constants.REVERT, @@ -455,7 +462,7 @@ describe('Exchange core', () => { it('should throw if signature is invalid', async () => { signedOrder = orderFactory.newSignedOrder({ - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), }); const invalidR = ethUtil.sha3('invalidR'); @@ -501,7 +508,7 @@ describe('Exchange core', () => { it('should throw if maker erc20Balances are too low to fill order', async () => { signedOrder = orderFactory.newSignedOrder({ - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18), }); return expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith( @@ -511,7 +518,7 @@ describe('Exchange core', () => { it('should throw if taker erc20Balances are too low to fill order', async () => { signedOrder = orderFactory.newSignedOrder({ - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18), }); return expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith( @@ -520,23 +527,45 @@ describe('Exchange core', () => { }); it('should throw if maker allowances are too low to fill order', async () => { - await erc20TokenA.approve.sendTransactionAsync(erc20Proxy.address, new BigNumber(0), { - from: makerAddress, - }); - expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(constants.REVERT); - await erc20TokenA.approve.sendTransactionAsync(erc20Proxy.address, constants.INITIAL_ERC20_ALLOWANCE, { - from: makerAddress, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await erc20TokenA.approve.sendTransactionAsync(erc20Proxy.address, new BigNumber(0), { + from: makerAddress, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + // HACK: `rejectWith` returns a "promise-like" type, but not an actual "Promise", so TSLint + // complains, even though we do need to `await` it. So we disable the TSLint error below. + // tslint:disable-next-line:await-promise + await expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith( + constants.REVERT, + ); + await web3Wrapper.awaitTransactionMinedAsync( + await erc20TokenA.approve.sendTransactionAsync(erc20Proxy.address, constants.INITIAL_ERC20_ALLOWANCE, { + from: makerAddress, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); }); it('should throw if taker allowances are too low to fill order', async () => { - await erc20TokenB.approve.sendTransactionAsync(erc20Proxy.address, new BigNumber(0), { - from: takerAddress, - }); - expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(constants.REVERT); - await erc20TokenB.approve.sendTransactionAsync(erc20Proxy.address, constants.INITIAL_ERC20_ALLOWANCE, { - from: takerAddress, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await erc20TokenB.approve.sendTransactionAsync(erc20Proxy.address, new BigNumber(0), { + from: takerAddress, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + // HACK: `rejectWith` returns a "promise-like" type, but not an actual "Promise", so TSLint + // complains, even though we do need to `await` it. So we disable the TSLint error below. + // tslint:disable-next-line:await-promise + await expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith( + constants.REVERT, + ); + await web3Wrapper.awaitTransactionMinedAsync( + await erc20TokenB.approve.sendTransactionAsync(erc20Proxy.address, constants.INITIAL_ERC20_ALLOWANCE, { + from: takerAddress, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); }); it('should not change erc20Balances if an order is expired', async () => { @@ -681,23 +710,23 @@ describe('Exchange core', () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); const signedOrders = await Promise.all([ orderFactory.newSignedOrder({ - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(9), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(9), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(9), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(9), 18), salt: new BigNumber(0), }), orderFactory.newSignedOrder({ - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(79), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(79), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(79), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(79), 18), salt: new BigNumber(1), }), orderFactory.newSignedOrder({ - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(979), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(979), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(979), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(979), 18), salt: new BigNumber(2), }), orderFactory.newSignedOrder({ - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(7979), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(7979), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(7979), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(7979), 18), salt: new BigNumber(3), }), ]); @@ -873,7 +902,7 @@ describe('Exchange core', () => { const makerAssetId = erc721MakerAssetIds[0]; signedOrder = orderFactory.newSignedOrder({ makerAssetAmount: new BigNumber(1), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultTakerAssetAddress), }); @@ -913,7 +942,7 @@ describe('Exchange core', () => { const takerAssetId = erc721TakerAssetIds[0]; signedOrder = orderFactory.newSignedOrder({ takerAssetAmount: new BigNumber(1), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId), makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultMakerAssetAddress), }); diff --git a/packages/contracts/test/exchange/dispatcher.ts b/packages/contracts/test/exchange/dispatcher.ts index db2f18ddc..a2238bd10 100644 --- a/packages/contracts/test/exchange/dispatcher.ts +++ b/packages/contracts/test/exchange/dispatcher.ts @@ -1,4 +1,3 @@ -import { ZeroEx } from '0x.js'; import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; @@ -37,6 +36,12 @@ describe('AssetProxyDispatcher', () => { let erc721Wrapper: ERC721Wrapper; before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); + before(async () => { // Setup accounts & addresses const accounts = await web3Wrapper.getAvailableAddressesAsync(); const usedAddresses = ([owner, notOwner, makerAddress, takerAddress] = accounts); @@ -56,12 +61,18 @@ describe('AssetProxyDispatcher', () => { provider, txDefaults, ); - await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(assetProxyDispatcher.address, { - from: owner, - }); - await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(assetProxyDispatcher.address, { - from: owner, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(assetProxyDispatcher.address, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + await web3Wrapper.awaitTransactionMinedAsync( + await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(assetProxyDispatcher.address, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); @@ -71,12 +82,15 @@ describe('AssetProxyDispatcher', () => { }); describe('registerAssetProxy', () => { it('should record proxy upon registration', async () => { - const prevProxyAddress = ZeroEx.NULL_ADDRESS; - await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( - AssetProxyId.ERC20, - erc20Proxy.address, - prevProxyAddress, - { from: owner }, + const prevProxyAddress = constants.NULL_ADDRESS; + await web3Wrapper.awaitTransactionMinedAsync( + await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( + AssetProxyId.ERC20, + erc20Proxy.address, + prevProxyAddress, + { from: owner }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, ); const proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20); expect(proxyAddress).to.be.equal(erc20Proxy.address); @@ -84,22 +98,28 @@ describe('AssetProxyDispatcher', () => { it('should be able to record multiple proxies', async () => { // Record first proxy - const prevERC20ProxyAddress = ZeroEx.NULL_ADDRESS; - await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( - AssetProxyId.ERC20, - erc20Proxy.address, - prevERC20ProxyAddress, - { from: owner }, + const prevERC20ProxyAddress = constants.NULL_ADDRESS; + await web3Wrapper.awaitTransactionMinedAsync( + await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( + AssetProxyId.ERC20, + erc20Proxy.address, + prevERC20ProxyAddress, + { from: owner }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, ); let proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20); expect(proxyAddress).to.be.equal(erc20Proxy.address); // Record another proxy - const prevERC721ProxyAddress = ZeroEx.NULL_ADDRESS; - await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( - AssetProxyId.ERC721, - erc721Proxy.address, - prevERC721ProxyAddress, - { from: owner }, + const prevERC721ProxyAddress = constants.NULL_ADDRESS; + await web3Wrapper.awaitTransactionMinedAsync( + await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( + AssetProxyId.ERC721, + erc721Proxy.address, + prevERC721ProxyAddress, + { from: owner }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, ); proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC721); expect(proxyAddress).to.be.equal(erc721Proxy.address); @@ -107,12 +127,15 @@ describe('AssetProxyDispatcher', () => { it('should replace proxy address upon re-registration', async () => { // Initial registration - const prevProxyAddress = ZeroEx.NULL_ADDRESS; - await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( - AssetProxyId.ERC20, - erc20Proxy.address, - prevProxyAddress, - { from: owner }, + const prevProxyAddress = constants.NULL_ADDRESS; + await web3Wrapper.awaitTransactionMinedAsync( + await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( + AssetProxyId.ERC20, + erc20Proxy.address, + prevProxyAddress, + { from: owner }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, ); let proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20); expect(proxyAddress).to.be.equal(erc20Proxy.address); @@ -125,11 +148,14 @@ describe('AssetProxyDispatcher', () => { // Register new ERC20 Transfer Proxy contract const newAddress = newErc20TransferProxy.address; const currentAddress = erc20Proxy.address; - await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( - AssetProxyId.ERC20, - newAddress, - currentAddress, - { from: owner }, + await web3Wrapper.awaitTransactionMinedAsync( + await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( + AssetProxyId.ERC20, + newAddress, + currentAddress, + { from: owner }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, ); // Verify new asset proxy has replaced initial version proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20); @@ -138,21 +164,24 @@ describe('AssetProxyDispatcher', () => { it('should throw if registering with incorrect "currentAssetProxyAddress" field', async () => { // Initial registration - const prevProxyAddress = ZeroEx.NULL_ADDRESS; - await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( - AssetProxyId.ERC20, - erc20Proxy.address, - prevProxyAddress, - { from: owner }, + const prevProxyAddress = constants.NULL_ADDRESS; + await web3Wrapper.awaitTransactionMinedAsync( + await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( + AssetProxyId.ERC20, + erc20Proxy.address, + prevProxyAddress, + { from: owner }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, ); const proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20); expect(proxyAddress).to.be.equal(erc20Proxy.address); - // The following transaction will throw because the currentAddress is no longer ZeroEx.NULL_ADDRESS + // The following transaction will throw because the currentAddress is no longer constants.NULL_ADDRESS return expect( assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( AssetProxyId.ERC20, erc20Proxy.address, - ZeroEx.NULL_ADDRESS, + constants.NULL_ADDRESS, { from: owner }, ), ).to.be.rejectedWith(constants.REVERT); @@ -160,29 +189,35 @@ describe('AssetProxyDispatcher', () => { it('should be able to reset proxy address to NULL', async () => { // Initial registration - const prevProxyAddress = ZeroEx.NULL_ADDRESS; - await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( - AssetProxyId.ERC20, - erc20Proxy.address, - prevProxyAddress, - { from: owner }, + const prevProxyAddress = constants.NULL_ADDRESS; + await web3Wrapper.awaitTransactionMinedAsync( + await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( + AssetProxyId.ERC20, + erc20Proxy.address, + prevProxyAddress, + { from: owner }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, ); const proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20); expect(proxyAddress).to.be.equal(erc20Proxy.address); // The following transaction will reset the proxy address - const newProxyAddress = ZeroEx.NULL_ADDRESS; - await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( - AssetProxyId.ERC20, - newProxyAddress, - erc20Proxy.address, - { from: owner }, + const newProxyAddress = constants.NULL_ADDRESS; + await web3Wrapper.awaitTransactionMinedAsync( + await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( + AssetProxyId.ERC20, + newProxyAddress, + erc20Proxy.address, + { from: owner }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, ); const finalProxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20); expect(finalProxyAddress).to.be.equal(newProxyAddress); }); it('should throw if requesting address is not owner', async () => { - const prevProxyAddress = ZeroEx.NULL_ADDRESS; + const prevProxyAddress = constants.NULL_ADDRESS; return expect( assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( AssetProxyId.ERC20, @@ -194,7 +229,7 @@ describe('AssetProxyDispatcher', () => { }); it('should throw if attempting to register a proxy to the incorrect id', async () => { - const prevProxyAddress = ZeroEx.NULL_ADDRESS; + const prevProxyAddress = constants.NULL_ADDRESS; return expect( assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( AssetProxyId.ERC721, @@ -208,12 +243,15 @@ describe('AssetProxyDispatcher', () => { describe('getAssetProxy', () => { it('should return correct address of registered proxy', async () => { - const prevProxyAddress = ZeroEx.NULL_ADDRESS; - await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( - AssetProxyId.ERC20, - erc20Proxy.address, - prevProxyAddress, - { from: owner }, + const prevProxyAddress = constants.NULL_ADDRESS; + await web3Wrapper.awaitTransactionMinedAsync( + await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( + AssetProxyId.ERC20, + erc20Proxy.address, + prevProxyAddress, + { from: owner }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, ); const proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20); expect(proxyAddress).to.be.equal(erc20Proxy.address); @@ -221,31 +259,37 @@ describe('AssetProxyDispatcher', () => { it('should return NULL address if requesting non-existent proxy', async () => { const proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20); - expect(proxyAddress).to.be.equal(ZeroEx.NULL_ADDRESS); + expect(proxyAddress).to.be.equal(constants.NULL_ADDRESS); }); }); describe('dispatchTransferFrom', () => { it('should dispatch transfer to registered proxy', async () => { // Register ERC20 proxy - const prevProxyAddress = ZeroEx.NULL_ADDRESS; - await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( - AssetProxyId.ERC20, - erc20Proxy.address, - prevProxyAddress, - { from: owner }, + const prevProxyAddress = constants.NULL_ADDRESS; + await web3Wrapper.awaitTransactionMinedAsync( + await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( + AssetProxyId.ERC20, + erc20Proxy.address, + prevProxyAddress, + { from: owner }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, ); // Construct metadata for ERC20 proxy const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address); // Perform a transfer from makerAddress to takerAddress const erc20Balances = await erc20Wrapper.getBalancesAsync(); const amount = new BigNumber(10); - await assetProxyDispatcher.publicDispatchTransferFrom.sendTransactionAsync( - encodedProxyMetadata, - makerAddress, - takerAddress, - amount, - { from: owner }, + await web3Wrapper.awaitTransactionMinedAsync( + await assetProxyDispatcher.publicDispatchTransferFrom.sendTransactionAsync( + encodedProxyMetadata, + makerAddress, + takerAddress, + amount, + { from: owner }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, ); // Verify transfer was successful const newBalances = await erc20Wrapper.getBalancesAsync(); diff --git a/packages/contracts/test/exchange/libs.ts b/packages/contracts/test/exchange/libs.ts index 1036cb815..5c530a9b1 100644 --- a/packages/contracts/test/exchange/libs.ts +++ b/packages/contracts/test/exchange/libs.ts @@ -1,4 +1,3 @@ -import { ZeroEx } from '0x.js'; import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; @@ -26,10 +25,15 @@ describe('Exchange libs', () => { let libs: TestLibsContract; before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); + before(async () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); const makerAddress = accounts[0]; libs = await TestLibsContract.deployFrom0xArtifactAsync(artifacts.TestLibs, provider, txDefaults); - const zeroEx = new ZeroEx(provider, { networkId: constants.TESTRPC_NETWORK_ID }); const defaultOrderParams = { ...constants.STATIC_ORDER_PARAMS, diff --git a/packages/contracts/test/exchange/match_orders.ts b/packages/contracts/test/exchange/match_orders.ts index 94cdf4598..8a3c91520 100644 --- a/packages/contracts/test/exchange/match_orders.ts +++ b/packages/contracts/test/exchange/match_orders.ts @@ -1,6 +1,7 @@ -import { LogWithDecodedArgs, ZeroEx } from '0x.js'; import { BlockchainLifecycle } from '@0xproject/dev-utils'; +import { LogWithDecodedArgs } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; import ethUtil = require('ethereumjs-util'); import * as _ from 'lodash'; @@ -36,7 +37,7 @@ import { } from '../../src/utils/types'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; -import { MatchOrderTester } from '../utils/match_order_tester'; +import { MatchOrderTester } from '../../src/utils/match_order_tester'; chaiSetup.configure(); const expect = chai.expect; @@ -76,8 +77,12 @@ describe('matchOrders', () => { let matchOrderTester: MatchOrderTester; - let zeroEx: ZeroEx; - + before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); before(async () => { // Create accounts const accounts = await web3Wrapper.getAvailableAddressesAsync(); @@ -111,20 +116,22 @@ describe('matchOrders', () => { txDefaults, assetProxyUtils.encodeERC20ProxyData(zrxToken.address), ); - zeroEx = new ZeroEx(provider, { - exchangeContractAddress: exchange.address, - networkId: constants.TESTRPC_NETWORK_ID, - }); - exchangeWrapper = new ExchangeWrapper(exchange, zeroEx); + exchangeWrapper = new ExchangeWrapper(exchange, provider); await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, owner); await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC721, erc721Proxy.address, owner); // Authorize ERC20 and ERC721 trades by exchange - await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { - from: owner, - }); - await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { - from: owner, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + await web3Wrapper.awaitTransactionMinedAsync( + await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); // Set default addresses defaultERC20MakerAssetAddress = erc20TokenA.address; defaultERC20TakerAssetAddress = erc20TokenB.address; @@ -161,16 +168,16 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(5), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(2), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Match signedOrderLeft with signedOrderRight @@ -195,16 +202,16 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(5), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(5), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Store original taker balance @@ -240,16 +247,16 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(5), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(20), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(4), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(20), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(4), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Match orders @@ -274,16 +281,16 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(50), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(2), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Match orders @@ -308,16 +315,16 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(50), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(2), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Match orders @@ -347,8 +354,8 @@ describe('matchOrders', () => { makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(50), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Match signedOrderLeft with signedOrderRight2 @@ -377,8 +384,8 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(2), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressLeft, }); @@ -386,8 +393,8 @@ describe('matchOrders', () => { makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(50), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Match orders @@ -417,8 +424,8 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(50), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), feeRecipientAddress: feeRecipientAddressLeft, }); // Match signedOrderLeft2 with signedOrderRight @@ -450,16 +457,16 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(5), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(2), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress, }); // Match orders @@ -478,16 +485,16 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(5), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(2), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Match orders @@ -507,16 +514,16 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(5), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(2), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Match orders @@ -536,16 +543,16 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(5), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(2), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Match orders @@ -565,16 +572,16 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(5), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(2), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Match orders @@ -594,16 +601,16 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(5), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: makerAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(2), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: makerAddressRight, }); // Match orders @@ -622,16 +629,16 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(5), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(2), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Cancel left order @@ -648,16 +655,16 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(5), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(2), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Cancel right order @@ -674,16 +681,16 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(5), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Match orders @@ -704,16 +711,16 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(5), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(2), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Match orders @@ -734,16 +741,16 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(5), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(2), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Match orders @@ -766,14 +773,14 @@ describe('matchOrders', () => { makerAssetData: assetProxyUtils.encodeERC721ProxyData(defaultERC721AssetAddress, erc721TokenToTransfer), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), makerAssetAmount: new BigNumber(1), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC721ProxyData(defaultERC721AssetAddress, erc721TokenToTransfer), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: new BigNumber(1), feeRecipientAddress: feeRecipientAddressRight, }); @@ -800,7 +807,7 @@ describe('matchOrders', () => { makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC721ProxyData(defaultERC721AssetAddress, erc721TokenToTransfer), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: new BigNumber(1), feeRecipientAddress: feeRecipientAddressLeft, }); @@ -809,7 +816,7 @@ describe('matchOrders', () => { makerAssetData: assetProxyUtils.encodeERC721ProxyData(defaultERC721AssetAddress, erc721TokenToTransfer), takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), makerAssetAmount: new BigNumber(1), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressRight, }); // Match orders diff --git a/packages/contracts/test/exchange/signature_validator.ts b/packages/contracts/test/exchange/signature_validator.ts index 489ed32c5..91614c666 100644 --- a/packages/contracts/test/exchange/signature_validator.ts +++ b/packages/contracts/test/exchange/signature_validator.ts @@ -1,4 +1,3 @@ -import { ZeroEx } from '0x.js'; import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; @@ -26,6 +25,12 @@ describe('MixinSignatureValidator', () => { let signatureValidator: TestSignatureValidatorContract; before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); + before(async () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); const makerAddress = accounts[0]; signatureValidator = await TestSignatureValidatorContract.deployFrom0xArtifactAsync( @@ -33,7 +38,6 @@ describe('MixinSignatureValidator', () => { provider, txDefaults, ); - const zeroEx = new ZeroEx(provider, { networkId: constants.TESTRPC_NETWORK_ID }); const defaultOrderParams = { ...constants.STATIC_ORDER_PARAMS, @@ -62,12 +66,12 @@ describe('MixinSignatureValidator', () => { it('should return true with a valid signature', async () => { const orderHashHex = orderUtils.getOrderHashHex(signedOrder); - const success = await signatureValidator.publicIsValidSignature.callAsync( + const isValidSignature = await signatureValidator.publicIsValidSignature.callAsync( orderHashHex, signedOrder.makerAddress, signedOrder.signature, ); - expect(success).to.be.true(); + expect(isValidSignature).to.be.true(); }); it('should return false with an invalid signature', async () => { @@ -81,12 +85,12 @@ describe('MixinSignatureValidator', () => { const invalidSigHex = `0x${invalidSigBuff.toString('hex')}`; signedOrder.signature = invalidSigHex; const orderHashHex = orderUtils.getOrderHashHex(signedOrder); - const success = await signatureValidator.publicIsValidSignature.callAsync( + const isValidSignature = await signatureValidator.publicIsValidSignature.callAsync( orderHashHex, signedOrder.makerAddress, signedOrder.signature, ); - expect(success).to.be.false(); + expect(isValidSignature).to.be.false(); }); }); }); diff --git a/packages/contracts/test/exchange/transactions.ts b/packages/contracts/test/exchange/transactions.ts index 482475554..203c05e53 100644 --- a/packages/contracts/test/exchange/transactions.ts +++ b/packages/contracts/test/exchange/transactions.ts @@ -1,5 +1,3 @@ -import { ZeroEx } from '0x.js'; - import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; @@ -59,8 +57,12 @@ describe('Exchange transactions', () => { let defaultMakerTokenAddress: string; let defaultTakerTokenAddress: string; - let zeroEx: ZeroEx; - + before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); before(async () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); const usedAddresses = ([owner, senderAddress, makerAddress, takerAddress, feeRecipientAddress] = accounts); @@ -77,14 +79,13 @@ describe('Exchange transactions', () => { txDefaults, assetProxyUtils.encodeERC20ProxyData(zrxToken.address), ); - zeroEx = new ZeroEx(provider, { - exchangeContractAddress: exchange.address, - networkId: constants.TESTRPC_NETWORK_ID, - }); - exchangeWrapper = new ExchangeWrapper(exchange, zeroEx); + exchangeWrapper = new ExchangeWrapper(exchange, provider); await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, owner); - await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: owner }); + await web3Wrapper.awaitTransactionMinedAsync( + await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: owner }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); defaultMakerTokenAddress = erc20TokenA.address; defaultTakerTokenAddress = erc20TokenB.address; @@ -179,7 +180,7 @@ describe('Exchange transactions', () => { it('should reset the currentContextAddress', async () => { await exchangeWrapper.executeTransactionAsync(signedTx, senderAddress); const currentContextAddress = await exchange.currentContextAddress.callAsync(); - expect(currentContextAddress).to.equal(ZeroEx.NULL_ADDRESS); + expect(currentContextAddress).to.equal(constants.NULL_ADDRESS); }); }); diff --git a/packages/contracts/test/exchange/wrapper.ts b/packages/contracts/test/exchange/wrapper.ts index 0b79308dd..39f861968 100644 --- a/packages/contracts/test/exchange/wrapper.ts +++ b/packages/contracts/test/exchange/wrapper.ts @@ -1,4 +1,3 @@ -import { ZeroEx } from '0x.js'; import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; @@ -54,8 +53,12 @@ describe('Exchange wrappers', () => { let defaultMakerAssetAddress: string; let defaultTakerAssetAddress: string; - let zeroEx: ZeroEx; - + before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); before(async () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = accounts); @@ -80,20 +83,22 @@ describe('Exchange wrappers', () => { txDefaults, assetProxyUtils.encodeERC20ProxyData(zrxToken.address), ); - zeroEx = new ZeroEx(provider, { - exchangeContractAddress: exchange.address, - networkId: constants.TESTRPC_NETWORK_ID, - }); - exchangeWrapper = new ExchangeWrapper(exchange, zeroEx); + exchangeWrapper = new ExchangeWrapper(exchange, provider); await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, owner); await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC721, erc721Proxy.address, owner); - await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { - from: owner, - }); - await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { - from: owner, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + await web3Wrapper.awaitTransactionMinedAsync( + await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); defaultMakerAssetAddress = erc20TokenA.address; defaultTakerAssetAddress = erc20TokenB.address; @@ -119,8 +124,8 @@ describe('Exchange wrappers', () => { describe('fillOrKillOrder', () => { it('should transfer the correct amounts', async () => { const signedOrder = orderFactory.newSignedOrder({ - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), }); const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2); await exchangeWrapper.fillOrKillOrderAsync(signedOrder, takerAddress, { @@ -187,8 +192,8 @@ describe('Exchange wrappers', () => { describe('fillOrderNoThrow', () => { it('should transfer the correct amounts', async () => { const signedOrder = orderFactory.newSignedOrder({ - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), }); const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2); await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress, { @@ -231,7 +236,7 @@ describe('Exchange wrappers', () => { it('should not change erc20Balances if maker erc20Balances are too low to fill order', async () => { const signedOrder = orderFactory.newSignedOrder({ - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18), }); await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress); @@ -241,7 +246,7 @@ describe('Exchange wrappers', () => { it('should not change erc20Balances if taker erc20Balances are too low to fill order', async () => { const signedOrder = orderFactory.newSignedOrder({ - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18), }); await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress); @@ -251,13 +256,19 @@ describe('Exchange wrappers', () => { it('should not change erc20Balances if maker allowances are too low to fill order', async () => { const signedOrder = orderFactory.newSignedOrder(); - await erc20TokenA.approve.sendTransactionAsync(erc20Proxy.address, new BigNumber(0), { - from: makerAddress, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await erc20TokenA.approve.sendTransactionAsync(erc20Proxy.address, new BigNumber(0), { + from: makerAddress, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress); - await erc20TokenA.approve.sendTransactionAsync(erc20Proxy.address, constants.INITIAL_ERC20_ALLOWANCE, { - from: makerAddress, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await erc20TokenA.approve.sendTransactionAsync(erc20Proxy.address, constants.INITIAL_ERC20_ALLOWANCE, { + from: makerAddress, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); const newBalances = await erc20Wrapper.getBalancesAsync(); expect(newBalances).to.be.deep.equal(erc20Balances); @@ -265,13 +276,19 @@ describe('Exchange wrappers', () => { it('should not change erc20Balances if taker allowances are too low to fill order', async () => { const signedOrder = orderFactory.newSignedOrder(); - await erc20TokenB.approve.sendTransactionAsync(erc20Proxy.address, new BigNumber(0), { - from: takerAddress, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await erc20TokenB.approve.sendTransactionAsync(erc20Proxy.address, new BigNumber(0), { + from: takerAddress, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress); - await erc20TokenB.approve.sendTransactionAsync(erc20Proxy.address, constants.INITIAL_ERC20_ALLOWANCE, { - from: takerAddress, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await erc20TokenB.approve.sendTransactionAsync(erc20Proxy.address, constants.INITIAL_ERC20_ALLOWANCE, { + from: takerAddress, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); const newBalances = await erc20Wrapper.getBalancesAsync(); expect(newBalances).to.be.deep.equal(erc20Balances); @@ -620,7 +637,7 @@ describe('Exchange wrappers', () => { }); it('should fill all signedOrders if cannot fill entire takerAssetFillAmount', async () => { - const takerAssetFillAmount = ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18); + const takerAssetFillAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18); _.forEach(signedOrders, signedOrder => { erc20Balances[makerAddress][defaultMakerAssetAddress] = erc20Balances[makerAddress][ defaultMakerAssetAddress @@ -663,7 +680,7 @@ describe('Exchange wrappers', () => { return expect( exchangeWrapper.marketSellOrdersAsync(signedOrders, takerAddress, { - takerAssetFillAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1000), 18), + takerAssetFillAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), 18), }), ).to.be.rejectedWith(constants.REVERT); }); @@ -709,7 +726,7 @@ describe('Exchange wrappers', () => { }); it('should fill all signedOrders if cannot fill entire takerAssetFillAmount', async () => { - const takerAssetFillAmount = ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18); + const takerAssetFillAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18); _.forEach(signedOrders, signedOrder => { erc20Balances[makerAddress][defaultMakerAssetAddress] = erc20Balances[makerAddress][ defaultMakerAssetAddress @@ -752,7 +769,7 @@ describe('Exchange wrappers', () => { return expect( exchangeWrapper.marketSellOrdersNoThrowAsync(signedOrders, takerAddress, { - takerAssetFillAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1000), 18), + takerAssetFillAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), 18), }), ).to.be.rejectedWith(constants.REVERT); }); @@ -798,7 +815,7 @@ describe('Exchange wrappers', () => { }); it('should fill all signedOrders if cannot fill entire makerAssetFillAmount', async () => { - const makerAssetFillAmount = ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18); + const makerAssetFillAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18); _.forEach(signedOrders, signedOrder => { erc20Balances[makerAddress][defaultMakerAssetAddress] = erc20Balances[makerAddress][ defaultMakerAssetAddress @@ -841,7 +858,7 @@ describe('Exchange wrappers', () => { return expect( exchangeWrapper.marketBuyOrdersAsync(signedOrders, takerAddress, { - makerAssetFillAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1000), 18), + makerAssetFillAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), 18), }), ).to.be.rejectedWith(constants.REVERT); }); @@ -887,7 +904,7 @@ describe('Exchange wrappers', () => { }); it('should fill all signedOrders if cannot fill entire takerAssetFillAmount', async () => { - const takerAssetFillAmount = ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18); + const takerAssetFillAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18); _.forEach(signedOrders, signedOrder => { erc20Balances[makerAddress][defaultMakerAssetAddress] = erc20Balances[makerAddress][ defaultMakerAssetAddress @@ -930,7 +947,7 @@ describe('Exchange wrappers', () => { return expect( exchangeWrapper.marketBuyOrdersNoThrowAsync(signedOrders, takerAddress, { - makerAssetFillAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1000), 18), + makerAssetFillAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), 18), }), ).to.be.rejectedWith(constants.REVERT); }); diff --git a/packages/contracts/test/global_hooks.ts b/packages/contracts/test/global_hooks.ts index 089521d94..8b48b030d 100644 --- a/packages/contracts/test/global_hooks.ts +++ b/packages/contracts/test/global_hooks.ts @@ -1,4 +1,6 @@ -import { coverage, env, EnvVars } from '@0xproject/dev-utils'; +import { env, EnvVars } from '@0xproject/dev-utils'; + +import { coverage } from '../src/utils/coverage'; after('generate coverage report', async () => { if (env.parseBoolean(EnvVars.SolidityCoverage)) { diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts index 5ed5c356f..ce3adbdae 100644 --- a/packages/contracts/test/libraries/lib_bytes.ts +++ b/packages/contracts/test/libraries/lib_bytes.ts @@ -1,5 +1,5 @@ -import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs, ZeroEx } from '0x.js'; import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; +import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import BN = require('bn.js'); @@ -33,6 +33,12 @@ describe('LibBytes', () => { const testUint256 = new BigNumber(testBytes32, 16); before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); + before(async () => { // Setup accounts & addresses const accounts = await web3Wrapper.getAvailableAddressesAsync(); owner = accounts[0]; diff --git a/packages/contracts/test/multi_sig_with_time_lock.ts b/packages/contracts/test/multi_sig_with_time_lock.ts index 8e58006ac..6f18de3e7 100644 --- a/packages/contracts/test/multi_sig_with_time_lock.ts +++ b/packages/contracts/test/multi_sig_with_time_lock.ts @@ -1,5 +1,5 @@ -import { LogWithDecodedArgs, ZeroEx } from '0x.js'; import { BlockchainLifecycle, web3Factory } from '@0xproject/dev-utils'; +import { LogWithDecodedArgs } from '@0xproject/types'; import { AbiDecoder, BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; @@ -20,7 +20,6 @@ const MULTI_SIG_ABI = artifacts.MultiSigWalletWithTimeLock.compilerOutput.abi; chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); -const zeroEx = new ZeroEx(provider, { networkId: constants.TESTRPC_NETWORK_ID }); const abiDecoder = new AbiDecoder([MULTI_SIG_ABI]); describe('MultiSigWalletWithTimeLock', () => { @@ -45,6 +44,12 @@ describe('MultiSigWalletWithTimeLock', () => { describe('changeTimeLock', () => { describe('initially non-time-locked', async () => { + before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); before('deploy a wallet', async () => { multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync( artifacts.MultiSigWalletWithTimeLock, @@ -74,8 +79,11 @@ describe('MultiSigWalletWithTimeLock', () => { args: [SECONDS_TIME_LOCKED.toNumber()], }; const txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); - const subRes = await zeroEx.awaitTransactionMinedAsync(txHash); - const log = abiDecoder.tryToDecodeLogOrNoop(subRes.logs[0]) as LogWithDecodedArgs< + const txReceipt = await web3Wrapper.awaitTransactionMinedAsync( + txHash, + constants.AWAIT_TRANSACTION_MINED_MS, + ); + const log = abiDecoder.tryToDecodeLogOrNoop(txReceipt.logs[0]) as LogWithDecodedArgs< SubmissionContractEventArgs >; @@ -94,14 +102,17 @@ describe('MultiSigWalletWithTimeLock', () => { args: [SECONDS_TIME_LOCKED.toNumber()], }; let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); - const subRes = await zeroEx.awaitTransactionMinedAsync(txHash); - const log = abiDecoder.tryToDecodeLogOrNoop(subRes.logs[0]) as LogWithDecodedArgs< + const txReceipt = await web3Wrapper.awaitTransactionMinedAsync( + txHash, + constants.AWAIT_TRANSACTION_MINED_MS, + ); + const log = abiDecoder.tryToDecodeLogOrNoop(txReceipt.logs[0]) as LogWithDecodedArgs< SubmissionContractEventArgs >; txId = log.args.transactionId; txHash = await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] }); - const res = await zeroEx.awaitTransactionMinedAsync(txHash); + const res = await web3Wrapper.awaitTransactionMinedAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); expect(res.logs).to.have.length(2); const blockNum = await web3Wrapper.getBlockNumberAsync(); @@ -121,18 +132,22 @@ describe('MultiSigWalletWithTimeLock', () => { args: [SECONDS_TIME_LOCKED.toNumber()], }; let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); - const subRes = await zeroEx.awaitTransactionMinedAsync(txHash); - const log = abiDecoder.tryToDecodeLogOrNoop(subRes.logs[0]) as LogWithDecodedArgs< + const txReceipt = await web3Wrapper.awaitTransactionMinedAsync( + txHash, + constants.AWAIT_TRANSACTION_MINED_MS, + ); + const log = abiDecoder.tryToDecodeLogOrNoop(txReceipt.logs[0]) as LogWithDecodedArgs< SubmissionContractEventArgs >; txId = log.args.transactionId; txHash = await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] }); + await web3Wrapper.awaitTransactionMinedAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); expect(initialSecondsTimeLocked).to.be.equal(0); txHash = await multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }); - const res = await zeroEx.awaitTransactionMinedAsync(txHash); + const res = await web3Wrapper.awaitTransactionMinedAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); expect(res.logs).to.have.length(2); const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.callAsync()); @@ -140,6 +155,12 @@ describe('MultiSigWalletWithTimeLock', () => { }); }); describe('initially time-locked', async () => { + before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); before('deploy a wallet', async () => { multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync( artifacts.MultiSigWalletWithTimeLock, @@ -161,16 +182,19 @@ describe('MultiSigWalletWithTimeLock', () => { args: [newSecondsTimeLocked], }; let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); - const subRes = await zeroEx.awaitTransactionMinedAsync(txHash); - const log = abiDecoder.tryToDecodeLogOrNoop(subRes.logs[0]) as LogWithDecodedArgs< + let txReceipt = await web3Wrapper.awaitTransactionMinedAsync( + txHash, + constants.AWAIT_TRANSACTION_MINED_MS, + ); + const log = abiDecoder.tryToDecodeLogOrNoop(txReceipt.logs[0]) as LogWithDecodedArgs< SubmissionContractEventArgs >; txId = log.args.transactionId; txHash = await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1], }); - const confRes = await zeroEx.awaitTransactionMinedAsync(txHash); - expect(confRes.logs).to.have.length(2); + txReceipt = await web3Wrapper.awaitTransactionMinedAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); + expect(txReceipt.logs).to.have.length(2); }); const newSecondsTimeLocked = 0; it('should throw if it has enough confirmations but is not past the time lock', async () => { @@ -181,7 +205,10 @@ describe('MultiSigWalletWithTimeLock', () => { it('should execute if it has enough confirmations and is past the time lock', async () => { await web3Wrapper.increaseTimeAsync(SECONDS_TIME_LOCKED.toNumber()); - await multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }); + await web3Wrapper.awaitTransactionMinedAsync( + await multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.callAsync()); expect(secondsTimeLocked).to.be.bignumber.equal(newSecondsTimeLocked); diff --git a/packages/contracts/test/token_registry.ts b/packages/contracts/test/token_registry.ts index 9e4f7ca3b..49d4f3901 100644 --- a/packages/contracts/test/token_registry.ts +++ b/packages/contracts/test/token_registry.ts @@ -1,4 +1,3 @@ -import { ZeroEx } from '0x.js'; import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BigNumber, NULL_BYTES } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; @@ -25,6 +24,12 @@ describe('TokenRegistry', () => { let tokenReg: TokenRegistryContract; let tokenRegWrapper: TokenRegWrapper; before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); + before(async () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); owner = accounts[0]; notOwner = accounts[1]; @@ -60,7 +65,7 @@ describe('TokenRegistry', () => { }; const nullToken = { - address: ZeroEx.NULL_ADDRESS, + address: constants.NULL_ADDRESS, name: '', symbol: '', decimals: 0, @@ -137,9 +142,12 @@ describe('TokenRegistry', () => { }); it('should change the token name when called by owner', async () => { - await tokenReg.setTokenName.sendTransactionAsync(token1.address, token2.name, { - from: owner, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await tokenReg.setTokenName.sendTransactionAsync(token1.address, token2.name, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); const [newData, oldData] = await Promise.all([ tokenRegWrapper.getTokenByNameAsync(token2.name), tokenRegWrapper.getTokenByNameAsync(token1.name), @@ -176,7 +184,10 @@ describe('TokenRegistry', () => { }); it('should change the token symbol when called by owner', async () => { - await tokenReg.setTokenSymbol.sendTransactionAsync(token1.address, token2.symbol, { from: owner }); + await web3Wrapper.awaitTransactionMinedAsync( + await tokenReg.setTokenSymbol.sendTransactionAsync(token1.address, token2.symbol, { from: owner }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); const [newData, oldData] = await Promise.all([ tokenRegWrapper.getTokenBySymbolAsync(token2.symbol), tokenRegWrapper.getTokenBySymbolAsync(token1.symbol), @@ -217,9 +228,12 @@ describe('TokenRegistry', () => { it('should remove token metadata when called by owner', async () => { const index = new BigNumber(0); - await tokenReg.removeToken.sendTransactionAsync(token1.address, index, { - from: owner, - }); + await web3Wrapper.awaitTransactionMinedAsync( + await tokenReg.removeToken.sendTransactionAsync(token1.address, index, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); const tokenData = await tokenRegWrapper.getTokenMetaDataAsync(token1.address); expect(tokenData).to.be.deep.equal(nullToken); }); diff --git a/packages/contracts/test/tutorials/arbitrage.ts b/packages/contracts/test/tutorials/arbitrage.ts index 723ddb066..e5787d5b8 100644 --- a/packages/contracts/test/tutorials/arbitrage.ts +++ b/packages/contracts/test/tutorials/arbitrage.ts @@ -38,7 +38,7 @@ // let amountGive: BigNumber; // let makerTokenAmount: BigNumber; // let takerTokenAmount: BigNumber; -// const feeRecipient = ZeroEx.NULL_ADDRESS; +// const feeRecipient = constants.NULL_ADDRESS; // const INITIAL_BALANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18); // const INITIAL_ALLOWANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18); @@ -115,7 +115,7 @@ // exchangeContractAddress: exchange.address, // networkId: constants.TESTRPC_NETWORK_ID, // }); -// exWrapper = new ExchangeWrapper(exchange, zeroEx); +// exWrapper = new ExchangeWrapper(exchange, provider); // makerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), 18); // takerTokenAmount = makerTokenAmount; diff --git a/packages/contracts/test/unlimited_allowance_token.ts b/packages/contracts/test/unlimited_allowance_token.ts index 8851a04ef..e831301e1 100644 --- a/packages/contracts/test/unlimited_allowance_token.ts +++ b/packages/contracts/test/unlimited_allowance_token.ts @@ -1,4 +1,4 @@ -import { ZeroEx } from '0x.js'; +import { ContractWrappers } from '@0xproject/contract-wrappers'; import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; @@ -19,7 +19,7 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('UnlimitedAllowanceToken', () => { let owner: string; let spender: string; - const zeroEx = new ZeroEx(provider, { + const contractWrappers = new ContractWrappers(provider, { networkId: constants.TESTRPC_NETWORK_ID, }); @@ -28,6 +28,12 @@ describe('UnlimitedAllowanceToken', () => { let token: DummyERC20TokenContract; before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); + before(async () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); owner = accounts[0]; spender = accounts[1]; @@ -40,7 +46,10 @@ describe('UnlimitedAllowanceToken', () => { constants.DUMMY_TOKEN_DECIMALS, constants.DUMMY_TOKEN_TOTAL_SUPPLY, ); - await token.mint.sendTransactionAsync(MAX_MINT_VALUE, { from: owner }); + await web3Wrapper.awaitTransactionMinedAsync( + await token.mint.sendTransactionAsync(MAX_MINT_VALUE, { from: owner }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); tokenAddress = token.address; }); beforeEach(async () => { @@ -51,7 +60,7 @@ describe('UnlimitedAllowanceToken', () => { }); describe('transfer', () => { it('should throw if owner has insufficient balance', async () => { - const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const ownerBalance = await contractWrappers.token.getBalanceAsync(tokenAddress, owner); const amountToTransfer = ownerBalance.plus(1); return expect(token.transfer.callAsync(spender, amountToTransfer, { from: owner })).to.be.rejectedWith( constants.REVERT, @@ -60,11 +69,11 @@ describe('UnlimitedAllowanceToken', () => { it('should transfer balance from sender to receiver', async () => { const receiver = spender; - const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const initOwnerBalance = await contractWrappers.token.getBalanceAsync(tokenAddress, owner); const amountToTransfer = new BigNumber(1); - await zeroEx.token.transferAsync(tokenAddress, owner, receiver, amountToTransfer); - const finalOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const finalReceiverBalance = await zeroEx.token.getBalanceAsync(tokenAddress, receiver); + await contractWrappers.token.transferAsync(tokenAddress, owner, receiver, amountToTransfer); + const finalOwnerBalance = await contractWrappers.token.getBalanceAsync(tokenAddress, owner); + const finalReceiverBalance = await contractWrappers.token.getBalanceAsync(tokenAddress, receiver); const expectedFinalOwnerBalance = initOwnerBalance.minus(amountToTransfer); const expectedFinalReceiverBalance = amountToTransfer; @@ -82,9 +91,9 @@ describe('UnlimitedAllowanceToken', () => { describe('transferFrom', () => { it('should throw if owner has insufficient balance', async () => { - const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const ownerBalance = await contractWrappers.token.getBalanceAsync(tokenAddress, owner); const amountToTransfer = ownerBalance.plus(1); - await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, amountToTransfer); + await contractWrappers.token.setAllowanceAsync(tokenAddress, owner, spender, amountToTransfer); return expect( token.transferFrom.callAsync(owner, spender, amountToTransfer, { from: spender, @@ -93,12 +102,12 @@ describe('UnlimitedAllowanceToken', () => { }); it('should throw if spender has insufficient allowance', async () => { - const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const ownerBalance = await contractWrappers.token.getBalanceAsync(tokenAddress, owner); const amountToTransfer = ownerBalance; - const spenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); - const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; - expect(spenderAllowanceIsInsufficient).to.be.true(); + const spenderAllowance = await contractWrappers.token.getAllowanceAsync(tokenAddress, owner, spender); + const isSpenderAllowanceInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; + expect(isSpenderAllowanceInsufficient).to.be.true(); return expect( token.transferFrom.callAsync(owner, spender, amountToTransfer, { @@ -116,44 +125,44 @@ describe('UnlimitedAllowanceToken', () => { }); it('should not modify spender allowance if spender allowance is 2^256 - 1', async () => { - const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const initOwnerBalance = await contractWrappers.token.getBalanceAsync(tokenAddress, owner); const amountToTransfer = initOwnerBalance; - const initSpenderAllowance = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; - await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, { + const initSpenderAllowance = contractWrappers.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; + await contractWrappers.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); + await contractWrappers.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, { gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS, }); - const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); + const newSpenderAllowance = await contractWrappers.token.getAllowanceAsync(tokenAddress, owner, spender); expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance); }); it('should transfer the correct balances if spender has sufficient allowance', async () => { - const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const initOwnerBalance = await contractWrappers.token.getBalanceAsync(tokenAddress, owner); const amountToTransfer = initOwnerBalance; const initSpenderAllowance = initOwnerBalance; - await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, { + await contractWrappers.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); + await contractWrappers.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, { gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS, }); - const newOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const newSpenderBalance = await zeroEx.token.getBalanceAsync(tokenAddress, spender); + const newOwnerBalance = await contractWrappers.token.getBalanceAsync(tokenAddress, owner); + const newSpenderBalance = await contractWrappers.token.getBalanceAsync(tokenAddress, spender); expect(newOwnerBalance).to.be.bignumber.equal(0); expect(newSpenderBalance).to.be.bignumber.equal(initOwnerBalance); }); it('should modify allowance if spender has sufficient allowance less than 2^256 - 1', async () => { - const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const initOwnerBalance = await contractWrappers.token.getBalanceAsync(tokenAddress, owner); const amountToTransfer = initOwnerBalance; const initSpenderAllowance = initOwnerBalance; - await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, { + await contractWrappers.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); + await contractWrappers.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, { gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS, }); - const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); + const newSpenderAllowance = await contractWrappers.token.getAllowanceAsync(tokenAddress, owner, spender); expect(newSpenderAllowance).to.be.bignumber.equal(0); }); }); diff --git a/packages/contracts/test/zrx_token.ts b/packages/contracts/test/zrx_token.ts index 7a72f85dc..e632364ef 100644 --- a/packages/contracts/test/zrx_token.ts +++ b/packages/contracts/test/zrx_token.ts @@ -1,4 +1,4 @@ -import { ZeroEx } from '0x.js'; +import { ContractWrappers } from '@0xproject/contract-wrappers'; import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; @@ -19,7 +19,7 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('ZRXToken', () => { let owner: string; let spender: string; - let zeroEx: ZeroEx; + let contractWrappers: ContractWrappers; let MAX_UINT: BigNumber; @@ -27,15 +27,21 @@ describe('ZRXToken', () => { let zrxAddress: string; before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); + before(async () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); owner = accounts[0]; spender = accounts[1]; - zeroEx = new ZeroEx(provider, { + contractWrappers = new ContractWrappers(provider, { networkId: constants.TESTRPC_NETWORK_ID, }); zrxToken = await ZRXTokenContract.deployFrom0xArtifactAsync(artifacts.ZRX, provider, txDefaults); zrxAddress = zrxToken.address; - MAX_UINT = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; + MAX_UINT = contractWrappers.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; }); beforeEach(async () => { await blockchainLifecycle.startAsync(); @@ -53,7 +59,7 @@ describe('ZRXToken', () => { it('should have a total supply of 1 billion tokens', async () => { const totalSupply = new BigNumber(await zrxToken.totalSupply.callAsync()); const expectedTotalSupply = 1000000000; - expect(ZeroEx.toUnitAmount(totalSupply, 18)).to.be.bignumber.equal(expectedTotalSupply); + expect(Web3Wrapper.toUnitAmount(totalSupply, 18)).to.be.bignumber.equal(expectedTotalSupply); }); it('should be named 0x Protocol Token', async () => { @@ -71,7 +77,7 @@ describe('ZRXToken', () => { describe('constructor', () => { it('should initialize owner balance to totalSupply', async () => { - const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); + const ownerBalance = await contractWrappers.token.getBalanceAsync(zrxAddress, owner); const totalSupply = new BigNumber(await zrxToken.totalSupply.callAsync()); expect(totalSupply).to.be.bignumber.equal(ownerBalance); }); @@ -80,11 +86,11 @@ describe('ZRXToken', () => { describe('transfer', () => { it('should transfer balance from sender to receiver', async () => { const receiver = spender; - const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); + const initOwnerBalance = await contractWrappers.token.getBalanceAsync(zrxAddress, owner); const amountToTransfer = new BigNumber(1); - await zeroEx.token.transferAsync(zrxAddress, owner, receiver, amountToTransfer); - const finalOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); - const finalReceiverBalance = await zeroEx.token.getBalanceAsync(zrxAddress, receiver); + await contractWrappers.token.transferAsync(zrxAddress, owner, receiver, amountToTransfer); + const finalOwnerBalance = await contractWrappers.token.getBalanceAsync(zrxAddress, owner); + const finalReceiverBalance = await contractWrappers.token.getBalanceAsync(zrxAddress, receiver); const expectedFinalOwnerBalance = initOwnerBalance.minus(amountToTransfer); const expectedFinalReceiverBalance = amountToTransfer; @@ -102,9 +108,9 @@ describe('ZRXToken', () => { describe('transferFrom', () => { it('should return false if owner has insufficient balance', async () => { - const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); + const ownerBalance = await contractWrappers.token.getBalanceAsync(zrxAddress, owner); const amountToTransfer = ownerBalance.plus(1); - await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, amountToTransfer, { + await contractWrappers.token.setAllowanceAsync(zrxAddress, owner, spender, amountToTransfer, { gasLimit: constants.MAX_TOKEN_APPROVE_GAS, }); const didReturnTrue = await zrxToken.transferFrom.callAsync(owner, spender, amountToTransfer, { @@ -114,12 +120,12 @@ describe('ZRXToken', () => { }); it('should return false if spender has insufficient allowance', async () => { - const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); + const ownerBalance = await contractWrappers.token.getBalanceAsync(zrxAddress, owner); const amountToTransfer = ownerBalance; - const spenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender); - const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; - expect(spenderAllowanceIsInsufficient).to.be.true(); + const spenderAllowance = await contractWrappers.token.getAllowanceAsync(zrxAddress, owner, spender); + const isSpenderAllowanceInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; + expect(isSpenderAllowanceInsufficient).to.be.true(); const didReturnTrue = await zrxToken.transferFrom.callAsync(owner, spender, amountToTransfer, { from: spender, @@ -136,46 +142,46 @@ describe('ZRXToken', () => { }); it('should not modify spender allowance if spender allowance is 2^256 - 1', async () => { - const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); + const initOwnerBalance = await contractWrappers.token.getBalanceAsync(zrxAddress, owner); const amountToTransfer = initOwnerBalance; const initSpenderAllowance = MAX_UINT; - await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance, { + await contractWrappers.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance, { gasLimit: constants.MAX_TOKEN_APPROVE_GAS, }); - await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer, { + await contractWrappers.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer, { gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS, }); - const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender); + const newSpenderAllowance = await contractWrappers.token.getAllowanceAsync(zrxAddress, owner, spender); expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance); }); it('should transfer the correct balances if spender has sufficient allowance', async () => { - const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); - const initSpenderBalance = await zeroEx.token.getBalanceAsync(zrxAddress, spender); + const initOwnerBalance = await contractWrappers.token.getBalanceAsync(zrxAddress, owner); + const initSpenderBalance = await contractWrappers.token.getBalanceAsync(zrxAddress, spender); const amountToTransfer = initOwnerBalance; const initSpenderAllowance = initOwnerBalance; - await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer, { + await contractWrappers.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance); + await contractWrappers.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer, { gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS, }); - const newOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); - const newSpenderBalance = await zeroEx.token.getBalanceAsync(zrxAddress, spender); + const newOwnerBalance = await contractWrappers.token.getBalanceAsync(zrxAddress, owner); + const newSpenderBalance = await contractWrappers.token.getBalanceAsync(zrxAddress, spender); expect(newOwnerBalance).to.be.bignumber.equal(0); expect(newSpenderBalance).to.be.bignumber.equal(initSpenderBalance.plus(initOwnerBalance)); }); it('should modify allowance if spender has sufficient allowance less than 2^256 - 1', async () => { - const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); + const initOwnerBalance = await contractWrappers.token.getBalanceAsync(zrxAddress, owner); const amountToTransfer = initOwnerBalance; - await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, amountToTransfer); - await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer, { + await contractWrappers.token.setAllowanceAsync(zrxAddress, owner, spender, amountToTransfer); + await contractWrappers.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer, { gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS, }); - const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender); + const newSpenderAllowance = await contractWrappers.token.getAllowanceAsync(zrxAddress, owner, spender); expect(newSpenderAllowance).to.be.bignumber.equal(0); }); }); diff --git a/packages/contracts/tslint.json b/packages/contracts/tslint.json index ffaefe83a..1ab924e47 100644 --- a/packages/contracts/tslint.json +++ b/packages/contracts/tslint.json @@ -1,3 +1,6 @@ { - "extends": ["@0xproject/tslint-config"] + "extends": ["@0xproject/tslint-config"], + "rules": { + "custom-no-magic-numbers": false + } } diff --git a/packages/dev-utils/CHANGELOG.json b/packages/dev-utils/CHANGELOG.json index 3f70a93cc..ecb43a42e 100644 --- a/packages/dev-utils/CHANGELOG.json +++ b/packages/dev-utils/CHANGELOG.json @@ -3,10 +3,15 @@ "version": "0.4.2", "changes": [ { + "note": "Pass SolCompilerArtifactAdapter to CoverageSubprovider", + "pr": 589 + }, + { "note": "Move callbackErrorReporter over from 0x.js", "pr": 579 } - ] + ], + "timestamp": 1527008544 }, { "timestamp": 1525477860, diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index ab824c898..8e2f007d2 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.4.1 - _May 5, 2018_ +## v0.4.2 - _May 22, 2018_ + + * Move callbackErrorReporter over from 0x.js (#579) + +## v0.4.1 - _May 4, 2018_ * Dependencies updated diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 49964c82a..0b11029f6 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/dev-utils", - "version": "0.4.1", + "version": "0.4.2", "engines": { "node": ">=6.12" }, @@ -29,8 +29,8 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/dev-utils/README.md", "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", "chai": "^4.0.1", @@ -44,11 +44,10 @@ "typescript": "2.7.1" }, "dependencies": { - "@0xproject/sol-cov": "^0.0.10", - "@0xproject/subproviders": "^0.10.1", - "@0xproject/types": "^0.6.3", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/web3-wrapper": "^0.6.3", + "@0xproject/subproviders": "^0.10.2", + "@0xproject/types": "^0.7.0", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/web3-wrapper": "^0.6.4", "lodash": "^4.17.4", "web3": "^0.20.0", "web3-provider-engine": "^14.0.4" diff --git a/packages/dev-utils/src/coverage.ts b/packages/dev-utils/src/coverage.ts deleted file mode 100644 index 6f7640835..000000000 --- a/packages/dev-utils/src/coverage.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { CoverageSubprovider } from '@0xproject/sol-cov'; -import * as _ from 'lodash'; - -import { constants } from './constants'; - -let coverageSubprovider: CoverageSubprovider; - -export const coverage = { - getCoverageSubproviderSingleton(): CoverageSubprovider { - if (_.isUndefined(coverageSubprovider)) { - coverageSubprovider = coverage._getCoverageSubprovider(); - } - return coverageSubprovider; - }, - _getCoverageSubprovider(): CoverageSubprovider { - const artifactsPath = '../migrations/artifacts/1.0.0'; - const contractsPath = 'src/contracts'; - const defaultFromAddress = constants.TESTRPC_FIRST_ADDRESS; - return new CoverageSubprovider(artifactsPath, contractsPath, defaultFromAddress); - }, -}; diff --git a/packages/dev-utils/src/index.ts b/packages/dev-utils/src/index.ts index 9124f3e28..d4c19f1bf 100644 --- a/packages/dev-utils/src/index.ts +++ b/packages/dev-utils/src/index.ts @@ -1,6 +1,5 @@ export { BlockchainLifecycle } from './blockchain_lifecycle'; export { web3Factory } from './web3_factory'; export { constants as devConstants } from './constants'; -export { coverage } from './coverage'; export { env, EnvVars } from './env'; export { callbackErrorReporter } from './callback_error_reporter'; diff --git a/packages/dev-utils/src/web3_factory.ts b/packages/dev-utils/src/web3_factory.ts index 4cd343c44..5b32d3930 100644 --- a/packages/dev-utils/src/web3_factory.ts +++ b/packages/dev-utils/src/web3_factory.ts @@ -13,16 +13,8 @@ import * as _ from 'lodash'; import * as process from 'process'; import { constants } from './constants'; -import { coverage } from './coverage'; import { env, EnvVars } from './env'; -// HACK: web3 leaks XMLHttpRequest into the global scope and causes requests to hang -// because they are using the wrong XHR package. -// importing web3 after subproviders fixes this issue -// Filed issue: https://github.com/ethereum/web3.js/issues/844 -// tslint:disable-next-line:ordered-imports -import * as Web3 from 'web3'; - export interface Web3Config { hasAddresses?: boolean; // default: true shouldUseInProcessGanache?: boolean; // default: false @@ -30,18 +22,8 @@ export interface Web3Config { } export const web3Factory = { - create(config: Web3Config = {}): Web3 { - const provider = this.getRpcProvider(config); - const web3 = new Web3(); - web3.setProvider(provider); - return web3; - }, - getRpcProvider(config: Web3Config = {}): Provider { + getRpcProvider(config: Web3Config = {}): ProviderEngine { const provider = new ProviderEngine(); - const isCoverageEnabled = env.parseBoolean(EnvVars.SolidityCoverage); - if (isCoverageEnabled) { - provider.addProvider(coverage.getCoverageSubproviderSingleton()); - } const hasAddresses = _.isUndefined(config.hasAddresses) || config.hasAddresses; if (!hasAddresses) { provider.addProvider(new EmptyWalletSubprovider()); diff --git a/packages/fill-scenarios/CHANGELOG.json b/packages/fill-scenarios/CHANGELOG.json index 3cbba3ecb..c97cc7dd8 100644 --- a/packages/fill-scenarios/CHANGELOG.json +++ b/packages/fill-scenarios/CHANGELOG.json @@ -1,5 +1,15 @@ [ { + "timestamp": 1527008544, + "version": "0.0.2", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { + "timestamp": 1527008544, "version": "0.0.1", "changes": [ { diff --git a/packages/fill-scenarios/CHANGELOG.md b/packages/fill-scenarios/CHANGELOG.md new file mode 100644 index 000000000..b32b8a289 --- /dev/null +++ b/packages/fill-scenarios/CHANGELOG.md @@ -0,0 +1,14 @@ +<!-- +This file is auto-generated using the monorepo-scripts package. Don't edit directly. +Edit the package's CHANGELOG.json file only. +--> + +CHANGELOG + +## v0.0.2 - _May 22, 2018_ + + * Dependencies updated + +## v0.0.1 - _May 22, 2018_ + + * Move FillScenarios out of 0x.js (#579) diff --git a/packages/fill-scenarios/package.json b/packages/fill-scenarios/package.json index ee426c7a1..0d8ea6d13 100644 --- a/packages/fill-scenarios/package.json +++ b/packages/fill-scenarios/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/fill-scenarios", - "version": "0.0.1", + "version": "0.0.2", "description": "0x order fill scenario generator", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -23,10 +23,10 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/fill-scenarios/README.md", "devDependencies": { - "@0xproject/abi-gen": "^0.2.13", - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/sol-compiler": "^0.4.3", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/abi-gen": "^0.3.0", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/sol-compiler": "^0.5.0", + "@0xproject/tslint-config": "^0.4.18", "@types/lodash": "4.14.104", "copyfiles": "^1.2.0", "make-promises-safe": "^1.1.0", @@ -36,12 +36,12 @@ "typescript": "2.7.1" }, "dependencies": { - "@0xproject/base-contract": "^0.3.1", - "@0xproject/order-utils": "^0.0.4", - "@0xproject/types": "^0.6.3", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", - "@0xproject/web3-wrapper": "^0.6.3", + "@0xproject/base-contract": "^0.3.2", + "@0xproject/order-utils": "^0.0.5", + "@0xproject/types": "^0.7.0", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", + "@0xproject/web3-wrapper": "^0.6.4", "ethers": "^3.0.15", "lodash": "^4.17.4" }, diff --git a/packages/json-schemas/CHANGELOG.json b/packages/json-schemas/CHANGELOG.json index 4114cdcf4..ea0df7eb7 100644 --- a/packages/json-schemas/CHANGELOG.json +++ b/packages/json-schemas/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1527008794, + "version": "0.7.24", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1525477860, "version": "0.7.23", "changes": [ diff --git a/packages/json-schemas/CHANGELOG.md b/packages/json-schemas/CHANGELOG.md index 257d14fdf..0b35f2408 100644 --- a/packages/json-schemas/CHANGELOG.md +++ b/packages/json-schemas/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.7.23 - _May 5, 2018_ +## v0.7.24 - _May 22, 2018_ + + * Dependencies updated + +## v0.7.23 - _May 4, 2018_ * Dependencies updated diff --git a/packages/json-schemas/package.json b/packages/json-schemas/package.json index aece885ec..1612bbc0a 100644 --- a/packages/json-schemas/package.json +++ b/packages/json-schemas/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/json-schemas", - "version": "0.7.23", + "version": "0.7.24", "engines": { "node": ">=6.12" }, @@ -45,15 +45,15 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/json-schemas/README.md", "dependencies": { - "@0xproject/typescript-typings": "^0.3.1", + "@0xproject/typescript-typings": "^0.3.2", "@types/node": "^8.0.53", "jsonschema": "^1.2.0", "lodash.values": "^4.3.0" }, "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/tslint-config": "^0.4.17", - "@0xproject/utils": "^0.6.1", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", + "@0xproject/utils": "^0.6.2", "@types/lodash.foreach": "^4.5.3", "@types/lodash.values": "^4.3.3", "@types/mocha": "^2.2.42", diff --git a/packages/json-schemas/test/schema_test.ts b/packages/json-schemas/test/schema_test.ts index ac6a68b59..b9574a0c9 100644 --- a/packages/json-schemas/test/schema_test.ts +++ b/packages/json-schemas/test/schema_test.ts @@ -149,7 +149,8 @@ describe('Schema', () => { }); describe('#blockParamSchema', () => { it('should validate valid block param', () => { - const testCases = [42, 'latest', 'pending', 'earliest']; + const blockNumber = 42; + const testCases = [blockNumber, 'latest', 'pending', 'earliest']; validateAgainstSchema(testCases, blockParamSchema); }); it('should fail for invalid block param', () => { @@ -182,6 +183,7 @@ describe('Schema', () => { validateAgainstSchema(testCases, tokenSchema); }); it('should fail for invalid token', () => { + const num = 4; const testCases = [ { ...token, @@ -192,7 +194,7 @@ describe('Schema', () => { decimals: undefined, }, [], - 4, + num, ]; const shouldFail = true; validateAgainstSchema(testCases, tokenSchema, shouldFail); @@ -871,10 +873,12 @@ describe('Schema', () => { }); describe('#jsNumberSchema', () => { it('should validate valid js number', () => { + // tslint:disable-next-line:custom-no-magic-numbers const testCases = [1, 42]; validateAgainstSchema(testCases, jsNumber); }); it('should fail for invalid js number', () => { + // tslint:disable-next-line:custom-no-magic-numbers const testCases = [NaN, -1, new BigNumber(1)]; const shouldFail = true; validateAgainstSchema(testCases, jsNumber, shouldFail); @@ -882,13 +886,14 @@ describe('Schema', () => { }); describe('#txDataSchema', () => { it('should validate valid txData', () => { + const bigNumGasAmount = new BigNumber(42); const testCases = [ { from: NULL_ADDRESS, }, { from: NULL_ADDRESS, - gas: new BigNumber(42), + gas: bigNumGasAmount, }, { from: NULL_ADDRESS, diff --git a/packages/metacoin/contracts/Metacoin.sol b/packages/metacoin/contracts/Metacoin.sol index ac212b32e..dc67e6242 100644 --- a/packages/metacoin/contracts/Metacoin.sol +++ b/packages/metacoin/contracts/Metacoin.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.21; +pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; contract Metacoin { @@ -16,7 +16,7 @@ contract Metacoin { uint32 callback; } - function Metacoin() public { + constructor () public { balances[msg.sender] = 10000; } @@ -24,7 +24,7 @@ contract Metacoin { if (balances[msg.sender] < transferData.amount) return false; balances[msg.sender] -= transferData.amount; balances[transferData.to] += transferData.amount; - Transfer(msg.sender, transferData.to, transferData.amount); + emit Transfer(msg.sender, transferData.to, transferData.amount); return true; } diff --git a/packages/metacoin/package.json b/packages/metacoin/package.json index 83d083b3f..312aa0819 100644 --- a/packages/metacoin/package.json +++ b/packages/metacoin/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/metacoin", - "version": "0.0.6", + "version": "0.0.7", "engines": { "node": ">=6.12" }, @@ -26,21 +26,21 @@ "author": "", "license": "Apache-2.0", "dependencies": { - "@0xproject/abi-gen": "^0.2.13", - "@0xproject/base-contract": "^0.3.1", - "@0xproject/sol-compiler": "^0.4.3", - "@0xproject/sol-cov": "^0.0.10", - "@0xproject/subproviders": "^0.10.1", - "@0xproject/tslint-config": "^0.4.17", - "@0xproject/types": "^0.6.3", - "@0xproject/utils": "^0.6.1", - "@0xproject/web3-wrapper": "^0.6.3", + "@0xproject/abi-gen": "^0.3.0", + "@0xproject/base-contract": "^0.3.2", + "@0xproject/sol-compiler": "^0.5.0", + "@0xproject/sol-cov": "^0.0.11", + "@0xproject/subproviders": "^0.10.2", + "@0xproject/tslint-config": "^0.4.18", + "@0xproject/types": "^0.7.0", + "@0xproject/utils": "^0.6.2", + "@0xproject/web3-wrapper": "^0.6.4", "ethers": "^3.0.15", "lodash": "^4.17.4", "web3-provider-engine": "^14.0.4" }, "devDependencies": { - "@0xproject/dev-utils": "^0.4.1", + "@0xproject/dev-utils": "^0.4.2", "chai": "^4.0.1", "chai-as-promised": "^7.1.0", "chai-bignumber": "^2.0.1", diff --git a/packages/metacoin/test/utils/config.ts b/packages/metacoin/test/utils/config.ts index 389edb388..ef4932845 100644 --- a/packages/metacoin/test/utils/config.ts +++ b/packages/metacoin/test/utils/config.ts @@ -3,8 +3,8 @@ import * as path from 'path'; export const config = { networkId: 50, - artifactsDir: path.resolve(__dirname, '../../artifacts'), - contractsDir: path.resolve(__dirname, '../../contracts'), + artifactsDir: 'artifacts', + contractsDir: 'contracts', ganacheLogFile: 'ganache.log', txDefaults: { from: devConstants.TESTRPC_FIRST_ADDRESS, diff --git a/packages/metacoin/test/utils/coverage.ts b/packages/metacoin/test/utils/coverage.ts index debd544ed..945afb0a7 100644 --- a/packages/metacoin/test/utils/coverage.ts +++ b/packages/metacoin/test/utils/coverage.ts @@ -1,5 +1,5 @@ import { devConstants } from '@0xproject/dev-utils'; -import { CoverageSubprovider } from '@0xproject/sol-cov'; +import { CoverageSubprovider, SolCompilerArtifactAdapter } from '@0xproject/sol-cov'; import * as _ from 'lodash'; import { config } from './config'; @@ -15,6 +15,7 @@ export const coverage = { }, _getCoverageSubprovider(): CoverageSubprovider { const defaultFromAddress = devConstants.TESTRPC_FIRST_ADDRESS; - return new CoverageSubprovider(config.artifactsDir, config.contractsDir, defaultFromAddress); + const zeroExArtifactsAdapter = new SolCompilerArtifactAdapter(config.artifactsDir, config.contractsDir); + return new CoverageSubprovider(zeroExArtifactsAdapter, defaultFromAddress); }, }; diff --git a/packages/metacoin/test/utils/web3_wrapper.ts b/packages/metacoin/test/utils/web3_wrapper.ts index b4bb61f09..724ed4e1f 100644 --- a/packages/metacoin/test/utils/web3_wrapper.ts +++ b/packages/metacoin/test/utils/web3_wrapper.ts @@ -1,5 +1,5 @@ import { env, EnvVars } from '@0xproject/dev-utils'; -import { GanacheSubprovider } from '@0xproject/subproviders'; +import { GanacheSubprovider, prependSubprovider } from '@0xproject/subproviders'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as fs from 'fs'; import * as _ from 'lodash'; @@ -9,10 +9,6 @@ import { config } from './config'; import { coverage } from './coverage'; export const provider = new ProviderEngine(); -const isCoverageEnabled = env.parseBoolean(EnvVars.SolidityCoverage); -if (isCoverageEnabled) { - provider.addProvider(coverage.getCoverageSubproviderSingleton()); -} provider.addProvider( new GanacheSubprovider({ logger: { @@ -27,4 +23,10 @@ provider.addProvider( ); provider.start(); +const isCoverageEnabled = env.parseBoolean(EnvVars.SolidityCoverage); +if (isCoverageEnabled) { + const coverageSubprovider = coverage.getCoverageSubproviderSingleton(); + prependSubprovider(provider, coverageSubprovider); +} + export const web3Wrapper = new Web3Wrapper(provider); diff --git a/packages/migrations/CHANGELOG.json b/packages/migrations/CHANGELOG.json index 142468dad..f22d4a77f 100644 --- a/packages/migrations/CHANGELOG.json +++ b/packages/migrations/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1527008794, + "version": "0.0.6", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1525477860, "version": "0.0.5", "changes": [ diff --git a/packages/migrations/CHANGELOG.md b/packages/migrations/CHANGELOG.md index 99da91a35..78d915b6c 100644 --- a/packages/migrations/CHANGELOG.md +++ b/packages/migrations/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.0.5 - _May 5, 2018_ +## v0.0.6 - _May 22, 2018_ + + * Dependencies updated + +## v0.0.5 - _May 4, 2018_ * Dependencies updated diff --git a/packages/migrations/artifacts/1.0.0/DummyERC20Token.json b/packages/migrations/artifacts/1.0.0/DummyERC20Token.json index 808652210..3ac218e24 100644 --- a/packages/migrations/artifacts/1.0.0/DummyERC20Token.json +++ b/packages/migrations/artifacts/1.0.0/DummyERC20Token.json @@ -305,14 +305,14 @@ "evm": { "bytecode": { "linkReferences": {}, - "object": "0x60806040523480156200001157600080fd5b506040516200193b3803806200193b833981018060405262000037919081019062000228565b33600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600490805190602001906200009092919062000105565b508260059080519060200190620000a992919062000105565b508160068190555080600281905550806000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050505062000361565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200014857805160ff191683800117855562000179565b8280016001018555821562000179579182015b82811115620001785782518255916020019190600101906200015b565b5b5090506200018891906200018c565b5090565b620001b191905b80821115620001ad57600081600090555060010162000193565b5090565b90565b600082601f8301121515620001c857600080fd5b8151620001df620001d982620002f4565b620002c6565b91508082526020830160208301858383011115620001fc57600080fd5b620002098382846200032b565b50505092915050565b600062000220825162000321565b905092915050565b600080600080608085870312156200023f57600080fd5b600085015167ffffffffffffffff8111156200025a57600080fd5b6200026887828801620001b4565b945050602085015167ffffffffffffffff8111156200028657600080fd5b6200029487828801620001b4565b9350506040620002a78782880162000212565b9250506060620002ba8782880162000212565b91505092959194509250565b6000604051905081810181811067ffffffffffffffff82111715620002ea57600080fd5b8060405250919050565b600067ffffffffffffffff8211156200030c57600080fd5b601f19601f8301169050602081019050919050565b6000819050919050565b60005b838110156200034b5780820151818401526020810190506200032e565b838111156200035b576000848401525b50505050565b6115ca80620003716000396000f3006080604052600436106100c5576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100ca578063095ea7b3146100f557806318160ddd1461013257806323b872dd1461015d578063313ce5671461019a57806370a08231146101c55780638da5cb5b1461020257806395d89b411461022d578063a0712d6814610258578063a9059cbb14610281578063dd62ed3e146102be578063e30443bc146102fb578063f2fde38b14610324575b600080fd5b3480156100d657600080fd5b506100df61034d565b6040516100ec9190611464565b60405180910390f35b34801561010157600080fd5b5061011c600480360361011791908101906112ac565b6103eb565b6040516101299190611449565b60405180910390f35b34801561013e57600080fd5b506101476104dd565b60405161015491906114c6565b60405180910390f35b34801561016957600080fd5b50610184600480360361017f919081019061125d565b6104e3565b6040516101919190611449565b60405180910390f35b3480156101a657600080fd5b506101af6109cc565b6040516101bc91906114c6565b60405180910390f35b3480156101d157600080fd5b506101ec60048036036101e791908101906111f8565b6109d2565b6040516101f991906114c6565b60405180910390f35b34801561020e57600080fd5b50610217610a1a565b604051610224919061142e565b60405180910390f35b34801561023957600080fd5b50610242610a40565b60405161024f9190611464565b60405180910390f35b34801561026457600080fd5b5061027f600480360361027a91908101906112e8565b610ade565b005b34801561028d57600080fd5b506102a860048036036102a391908101906112ac565b610bcb565b6040516102b59190611449565b60405180910390f35b3480156102ca57600080fd5b506102e560048036036102e09190810190611221565b610eda565b6040516102f291906114c6565b60405180910390f35b34801561030757600080fd5b50610322600480360361031d91908101906112ac565b610f61565b005b34801561033057600080fd5b5061034b600480360361034691908101906111f8565b61108c565b005b60048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103e35780601f106103b8576101008083540402835291602001916103e3565b820191906000526020600020905b8154815290600101906020018083116103c657829003601f168201915b505050505081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516104cb91906114c6565b60405180910390a36001905092915050565b60025481565b600080600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050826000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015606060405190810160405280602a81526020017f496e73756666696369656e742062616c616e636520746f20636f6d706c65746581526020017f207472616e736665722e00000000000000000000000000000000000000000000815250901515610647576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161063e9190611464565b60405180910390fd5b5082811015606060405190810160405280602c81526020017f496e73756666696369656e7420616c6c6f77616e636520746f20636f6d706c6581526020017f7465207472616e736665722e00000000000000000000000000000000000000008152509015156106ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e39190611464565b60405180910390fd5b506000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054836000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011015606060405190810160405280602581526020017f5472616e7366657220776f756c6420726573756c7420696e20616e206f76657281526020017f666c6f772e00000000000000000000000000000000000000000000000000000081525090151561080f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108069190611464565b60405180910390fd5b50826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550826000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81101561095b5782600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040516109b891906114c6565b60405180910390a360019150509392505050565b60065481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610ad65780601f10610aab57610100808354040283529160200191610ad6565b820191906000526020600020905b815481529060010190602001808311610ab957829003601f168201915b505050505081565b68056bc75e2d631000008111151515610b2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b23906114a6565b60405180910390fd5b610b74816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611199565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610bc260025482611199565b60028190555050565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015606060405190810160405280602a81526020017f496e73756666696369656e742062616c616e636520746f20636f6d706c65746581526020017f207472616e736665722e00000000000000000000000000000000000000000000815250901515610caf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ca69190611464565b60405180910390fd5b506000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011015606060405190810160405280602581526020017f5472616e7366657220776f756c6420726573756c7420696e20616e206f76657281526020017f666c6f772e000000000000000000000000000000000000000000000000000000815250901515610dd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc99190611464565b60405180910390fd5b50816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610ec891906114c6565b60405180910390a36001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610ff5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fec90611486565b60405180910390fd5b610ffe836109d2565b9050808210156110285761101d60025461101883856111b7565b6111b7565b600281905550611044565b61103d60025461103884846111b7565b611199565b6002819055505b816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561111e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161111590611486565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415156111965780600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b60008082840190508381101515156111ad57fe5b8091505092915050565b60008282111515156111c557fe5b818303905092915050565b60006111dc8235611522565b905092915050565b60006111f08235611542565b905092915050565b60006020828403121561120a57600080fd5b6000611218848285016111d0565b91505092915050565b6000806040838503121561123457600080fd5b6000611242858286016111d0565b9250506020611253858286016111d0565b9150509250929050565b60008060006060848603121561127257600080fd5b6000611280868287016111d0565b9350506020611291868287016111d0565b92505060406112a2868287016111e4565b9150509250925092565b600080604083850312156112bf57600080fd5b60006112cd858286016111d0565b92505060206112de858286016111e4565b9150509250929050565b6000602082840312156112fa57600080fd5b6000611308848285016111e4565b91505092915050565b61131a816114ec565b82525050565b6113298161150c565b82525050565b600061133a826114e1565b80845261134e81602086016020860161154c565b6113578161157f565b602085010191505092915050565b6000603382527f4f6e6c7920636f6e7472616374206f776e657220697320616c6c6f776564207460208301527f6f2063616c6c2074686973206d6574686f642e000000000000000000000000006040830152606082019050919050565b6000603782527f4d696e74696e67206d6f7265207468616e20313030303030303030303030303060208301527f30303030303030206973206e6f7420616c6c6f7765642e0000000000000000006040830152606082019050919050565b61142881611518565b82525050565b60006020820190506114436000830184611311565b92915050565b600060208201905061145e6000830184611320565b92915050565b6000602082019050818103600083015261147e818461132f565b905092915050565b6000602082019050818103600083015261149f81611365565b9050919050565b600060208201905081810360008301526114bf816113c2565b9050919050565b60006020820190506114db600083018461141f565b92915050565b600081519050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b8381101561156a57808201518184015260208101905061154f565b83811115611579576000848401525b50505050565b6000601f19601f83011690509190505600a265627a7a72305820dbb48ab34f59e30595d90684cb2e3bf356f8749f5dd5e617ce527adda15d5c346c6578706572696d656e74616cf50037", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x193B CODESIZE SUB DUP1 PUSH3 0x193B DUP4 CODECOPY DUP2 ADD DUP1 PUSH1 0x40 MSTORE PUSH3 0x37 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH3 0x228 JUMP JUMPDEST CALLER PUSH1 0x3 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP DUP4 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0x90 SWAP3 SWAP2 SWAP1 PUSH3 0x105 JUMP JUMPDEST POP DUP3 PUSH1 0x5 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xA9 SWAP3 SWAP2 SWAP1 PUSH3 0x105 JUMP JUMPDEST POP DUP2 PUSH1 0x6 DUP2 SWAP1 SSTORE POP DUP1 PUSH1 0x2 DUP2 SWAP1 SSTORE POP DUP1 PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP POP POP POP POP PUSH3 0x361 JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x148 JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x179 JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x179 JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x178 JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x15B JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x188 SWAP2 SWAP1 PUSH3 0x18C JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x1B1 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x1AD JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x193 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH1 0x1F DUP4 ADD SLT ISZERO ISZERO PUSH3 0x1C8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 MLOAD PUSH3 0x1DF PUSH3 0x1D9 DUP3 PUSH3 0x2F4 JUMP JUMPDEST PUSH3 0x2C6 JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE PUSH1 0x20 DUP4 ADD PUSH1 0x20 DUP4 ADD DUP6 DUP4 DUP4 ADD GT ISZERO PUSH3 0x1FC JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH3 0x209 DUP4 DUP3 DUP5 PUSH3 0x32B JUMP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH3 0x220 DUP3 MLOAD PUSH3 0x321 JUMP JUMPDEST SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP1 PUSH1 0x80 DUP6 DUP8 SUB SLT ISZERO PUSH3 0x23F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP6 ADD MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH3 0x25A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH3 0x268 DUP8 DUP3 DUP9 ADD PUSH3 0x1B4 JUMP JUMPDEST SWAP5 POP POP PUSH1 0x20 DUP6 ADD MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH3 0x286 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH3 0x294 DUP8 DUP3 DUP9 ADD PUSH3 0x1B4 JUMP JUMPDEST SWAP4 POP POP PUSH1 0x40 PUSH3 0x2A7 DUP8 DUP3 DUP9 ADD PUSH3 0x212 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x60 PUSH3 0x2BA DUP8 DUP3 DUP9 ADD PUSH3 0x212 JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP6 SWAP2 SWAP5 POP SWAP3 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x40 MLOAD SWAP1 POP DUP2 DUP2 ADD DUP2 DUP2 LT PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT OR ISZERO PUSH3 0x2EA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP1 PUSH1 0x40 MSTORE POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT ISZERO PUSH3 0x30C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1F NOT PUSH1 0x1F DUP4 ADD AND SWAP1 POP PUSH1 0x20 DUP2 ADD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH3 0x34B JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH3 0x32E JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH3 0x35B JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH2 0x15CA DUP1 PUSH3 0x371 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0xC5 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xCA JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0xF5 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x132 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x15D JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x19A JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x1C5 JUMPI DUP1 PUSH4 0x8DA5CB5B EQ PUSH2 0x202 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x22D JUMPI DUP1 PUSH4 0xA0712D68 EQ PUSH2 0x258 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x281 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x2BE JUMPI DUP1 PUSH4 0xE30443BC EQ PUSH2 0x2FB JUMPI DUP1 PUSH4 0xF2FDE38B EQ PUSH2 0x324 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0xD6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xDF PUSH2 0x34D JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xEC SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x101 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x11C PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x117 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12AC JUMP JUMPDEST PUSH2 0x3EB JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x129 SWAP2 SWAP1 PUSH2 0x1449 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x13E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x147 PUSH2 0x4DD JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x154 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x169 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x184 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x17F SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x125D JUMP JUMPDEST PUSH2 0x4E3 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x191 SWAP2 SWAP1 PUSH2 0x1449 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1A6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x1AF PUSH2 0x9CC JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x1BC SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1D1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x1EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x1E7 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x11F8 JUMP JUMPDEST PUSH2 0x9D2 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x1F9 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x20E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x217 PUSH2 0xA1A JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x224 SWAP2 SWAP1 PUSH2 0x142E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x239 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x242 PUSH2 0xA40 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x24F SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x264 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x27F PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x27A SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12E8 JUMP JUMPDEST PUSH2 0xADE JUMP JUMPDEST STOP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x28D JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x2A8 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x2A3 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12AC JUMP JUMPDEST PUSH2 0xBCB JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x2B5 SWAP2 SWAP1 PUSH2 0x1449 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x2CA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x2E5 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x2E0 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1221 JUMP JUMPDEST PUSH2 0xEDA JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x2F2 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x307 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x322 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x31D SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12AC JUMP JUMPDEST PUSH2 0xF61 JUMP JUMPDEST STOP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x330 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x34B PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x346 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x11F8 JUMP JUMPDEST PUSH2 0x108C JUMP JUMPDEST STOP JUMPDEST PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x3E3 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x3B8 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x3E3 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x3C6 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP DUP2 JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x1 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP5 PUSH1 0x40 MLOAD PUSH2 0x4CB SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x2 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x1 PUSH1 0x0 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP DUP3 PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2A DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x496E73756666696369656E742062616C616E636520746F20636F6D706C657465 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x207472616E736665722E00000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x647 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x63E SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP3 DUP2 LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2C DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x496E73756666696369656E7420616C6C6F77616E636520746F20636F6D706C65 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x7465207472616E736665722E0000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x6EC JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x6E3 SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD DUP4 PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD ADD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x5472616E7366657220776F756C6420726573756C7420696E20616E206F766572 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x666C6F772E000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x80F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x806 SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP3 PUSH1 0x0 DUP1 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP DUP3 PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD SUB SWAP3 POP POP DUP2 SWAP1 SSTORE POP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 LT ISZERO PUSH2 0x95B JUMPI DUP3 PUSH1 0x1 PUSH1 0x0 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD SUB SWAP3 POP POP DUP2 SWAP1 SSTORE POP JUMPDEST DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP6 PUSH1 0x40 MLOAD PUSH2 0x9B8 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 PUSH1 0x1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x6 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x3 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 JUMP JUMPDEST PUSH1 0x5 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0xAD6 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xAAB JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xAD6 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xAB9 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP DUP2 JUMP JUMPDEST PUSH9 0x56BC75E2D63100000 DUP2 GT ISZERO ISZERO ISZERO PUSH2 0xB2C JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xB23 SWAP1 PUSH2 0x14A6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xB74 DUP2 PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0x1199 JUMP JUMPDEST PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xBC2 PUSH1 0x2 SLOAD DUP3 PUSH2 0x1199 JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2A DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x496E73756666696369656E742062616C616E636520746F20636F6D706C657465 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x207472616E736665722E00000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0xCAF JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xCA6 SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD DUP3 PUSH1 0x0 DUP1 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD ADD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x5472616E7366657220776F756C6420726573756C7420696E20616E206F766572 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x666C6F772E000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0xDD2 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xDC9 SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP2 PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD SUB SWAP3 POP POP DUP2 SWAP1 SSTORE POP DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP5 PUSH1 0x40 MLOAD PUSH2 0xEC8 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x3 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO ISZERO PUSH2 0xFF5 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xFEC SWAP1 PUSH2 0x1486 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xFFE DUP4 PUSH2 0x9D2 JUMP JUMPDEST SWAP1 POP DUP1 DUP3 LT ISZERO PUSH2 0x1028 JUMPI PUSH2 0x101D PUSH1 0x2 SLOAD PUSH2 0x1018 DUP4 DUP6 PUSH2 0x11B7 JUMP JUMPDEST PUSH2 0x11B7 JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH2 0x1044 JUMP JUMPDEST PUSH2 0x103D PUSH1 0x2 SLOAD PUSH2 0x1038 DUP5 DUP5 PUSH2 0x11B7 JUMP JUMPDEST PUSH2 0x1199 JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP JUMPDEST DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP POP POP POP JUMP JUMPDEST PUSH1 0x3 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO ISZERO PUSH2 0x111E JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x1115 SWAP1 PUSH2 0x1486 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO ISZERO PUSH2 0x1196 JUMPI DUP1 PUSH1 0x3 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO ISZERO ISZERO PUSH2 0x11AD JUMPI INVALID JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 DUP3 GT ISZERO ISZERO ISZERO PUSH2 0x11C5 JUMPI INVALID JUMPDEST DUP2 DUP4 SUB SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x11DC DUP3 CALLDATALOAD PUSH2 0x1522 JUMP JUMPDEST SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x11F0 DUP3 CALLDATALOAD PUSH2 0x1542 JUMP JUMPDEST SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x120A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1218 DUP5 DUP3 DUP6 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x1234 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1242 DUP6 DUP3 DUP7 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x1253 DUP6 DUP3 DUP7 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0x60 DUP5 DUP7 SUB SLT ISZERO PUSH2 0x1272 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1280 DUP7 DUP3 DUP8 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP4 POP POP PUSH1 0x20 PUSH2 0x1291 DUP7 DUP3 DUP8 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x40 PUSH2 0x12A2 DUP7 DUP3 DUP8 ADD PUSH2 0x11E4 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 POP SWAP3 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x12BF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x12CD DUP6 DUP3 DUP7 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x12DE DUP6 DUP3 DUP7 ADD PUSH2 0x11E4 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x12FA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1308 DUP5 DUP3 DUP6 ADD PUSH2 0x11E4 JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH2 0x131A DUP2 PUSH2 0x14EC JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH2 0x1329 DUP2 PUSH2 0x150C JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x133A DUP3 PUSH2 0x14E1 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH2 0x134E DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x154C JUMP JUMPDEST PUSH2 0x1357 DUP2 PUSH2 0x157F JUMP JUMPDEST PUSH1 0x20 DUP6 ADD ADD SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x33 DUP3 MSTORE PUSH32 0x4F6E6C7920636F6E7472616374206F776E657220697320616C6C6F7765642074 PUSH1 0x20 DUP4 ADD MSTORE PUSH32 0x6F2063616C6C2074686973206D6574686F642E00000000000000000000000000 PUSH1 0x40 DUP4 ADD MSTORE PUSH1 0x60 DUP3 ADD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x37 DUP3 MSTORE PUSH32 0x4D696E74696E67206D6F7265207468616E203130303030303030303030303030 PUSH1 0x20 DUP4 ADD MSTORE PUSH32 0x30303030303030206973206E6F7420616C6C6F7765642E000000000000000000 PUSH1 0x40 DUP4 ADD MSTORE PUSH1 0x60 DUP3 ADD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH2 0x1428 DUP2 PUSH2 0x1518 JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH2 0x1443 PUSH1 0x0 DUP4 ADD DUP5 PUSH2 0x1311 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH2 0x145E PUSH1 0x0 DUP4 ADD DUP5 PUSH2 0x1320 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP DUP2 DUP2 SUB PUSH1 0x0 DUP4 ADD MSTORE PUSH2 0x147E DUP2 DUP5 PUSH2 0x132F JUMP JUMPDEST SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP DUP2 DUP2 SUB PUSH1 0x0 DUP4 ADD MSTORE PUSH2 0x149F DUP2 PUSH2 0x1365 JUMP JUMPDEST SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP DUP2 DUP2 SUB PUSH1 0x0 DUP4 ADD MSTORE PUSH2 0x14BF DUP2 PUSH2 0x13C2 JUMP JUMPDEST SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH2 0x14DB PUSH1 0x0 DUP4 ADD DUP5 PUSH2 0x141F JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 ISZERO ISZERO SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x156A JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x154F JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x1579 JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F NOT PUSH1 0x1F DUP4 ADD AND SWAP1 POP SWAP2 SWAP1 POP JUMP STOP LOG2 PUSH6 0x627A7A723058 KECCAK256 0xdb 0xb4 DUP11 0xb3 0x4f MSIZE 0xe3 SDIV SWAP6 0xd9 MOD DUP5 0xcb 0x2e EXTCODESIZE RETURN JUMP 0xf8 PUSH21 0x9F5DD5E617CE527ADDA15D5C346C6578706572696D PUSH6 0x6E74616CF500 CALLDATACOPY ", + "object": "0x60806040523480156200001157600080fd5b506040516200193b3803806200193b833981018060405262000037919081019062000228565b33600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600490805190602001906200009092919062000105565b508260059080519060200190620000a992919062000105565b508160068190555080600281905550806000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050505062000361565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200014857805160ff191683800117855562000179565b8280016001018555821562000179579182015b82811115620001785782518255916020019190600101906200015b565b5b5090506200018891906200018c565b5090565b620001b191905b80821115620001ad57600081600090555060010162000193565b5090565b90565b600082601f8301121515620001c857600080fd5b8151620001df620001d982620002f4565b620002c6565b91508082526020830160208301858383011115620001fc57600080fd5b620002098382846200032b565b50505092915050565b600062000220825162000321565b905092915050565b600080600080608085870312156200023f57600080fd5b600085015167ffffffffffffffff8111156200025a57600080fd5b6200026887828801620001b4565b945050602085015167ffffffffffffffff8111156200028657600080fd5b6200029487828801620001b4565b9350506040620002a78782880162000212565b9250506060620002ba8782880162000212565b91505092959194509250565b6000604051905081810181811067ffffffffffffffff82111715620002ea57600080fd5b8060405250919050565b600067ffffffffffffffff8211156200030c57600080fd5b601f19601f8301169050602081019050919050565b6000819050919050565b60005b838110156200034b5780820151818401526020810190506200032e565b838111156200035b576000848401525b50505050565b6115ca80620003716000396000f3006080604052600436106100c5576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100ca578063095ea7b3146100f557806318160ddd1461013257806323b872dd1461015d578063313ce5671461019a57806370a08231146101c55780638da5cb5b1461020257806395d89b411461022d578063a0712d6814610258578063a9059cbb14610281578063dd62ed3e146102be578063e30443bc146102fb578063f2fde38b14610324575b600080fd5b3480156100d657600080fd5b506100df61034d565b6040516100ec9190611464565b60405180910390f35b34801561010157600080fd5b5061011c600480360361011791908101906112ac565b6103eb565b6040516101299190611449565b60405180910390f35b34801561013e57600080fd5b506101476104dd565b60405161015491906114c6565b60405180910390f35b34801561016957600080fd5b50610184600480360361017f919081019061125d565b6104e3565b6040516101919190611449565b60405180910390f35b3480156101a657600080fd5b506101af6109cc565b6040516101bc91906114c6565b60405180910390f35b3480156101d157600080fd5b506101ec60048036036101e791908101906111f8565b6109d2565b6040516101f991906114c6565b60405180910390f35b34801561020e57600080fd5b50610217610a1a565b604051610224919061142e565b60405180910390f35b34801561023957600080fd5b50610242610a40565b60405161024f9190611464565b60405180910390f35b34801561026457600080fd5b5061027f600480360361027a91908101906112e8565b610ade565b005b34801561028d57600080fd5b506102a860048036036102a391908101906112ac565b610bcb565b6040516102b59190611449565b60405180910390f35b3480156102ca57600080fd5b506102e560048036036102e09190810190611221565b610eda565b6040516102f291906114c6565b60405180910390f35b34801561030757600080fd5b50610322600480360361031d91908101906112ac565b610f61565b005b34801561033057600080fd5b5061034b600480360361034691908101906111f8565b61108c565b005b60048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103e35780601f106103b8576101008083540402835291602001916103e3565b820191906000526020600020905b8154815290600101906020018083116103c657829003601f168201915b505050505081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516104cb91906114c6565b60405180910390a36001905092915050565b60025481565b600080600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050826000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015606060405190810160405280602a81526020017f496e73756666696369656e742062616c616e636520746f20636f6d706c65746581526020017f207472616e736665722e00000000000000000000000000000000000000000000815250901515610647576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161063e9190611464565b60405180910390fd5b5082811015606060405190810160405280602c81526020017f496e73756666696369656e7420616c6c6f77616e636520746f20636f6d706c6581526020017f7465207472616e736665722e00000000000000000000000000000000000000008152509015156106ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e39190611464565b60405180910390fd5b506000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054836000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011015606060405190810160405280602581526020017f5472616e7366657220776f756c6420726573756c7420696e20616e206f76657281526020017f666c6f772e00000000000000000000000000000000000000000000000000000081525090151561080f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108069190611464565b60405180910390fd5b50826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550826000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81101561095b5782600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040516109b891906114c6565b60405180910390a360019150509392505050565b60065481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610ad65780601f10610aab57610100808354040283529160200191610ad6565b820191906000526020600020905b815481529060010190602001808311610ab957829003601f168201915b505050505081565b68056bc75e2d631000008111151515610b2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b23906114a6565b60405180910390fd5b610b74816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611199565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610bc260025482611199565b60028190555050565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015606060405190810160405280602a81526020017f496e73756666696369656e742062616c616e636520746f20636f6d706c65746581526020017f207472616e736665722e00000000000000000000000000000000000000000000815250901515610caf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ca69190611464565b60405180910390fd5b506000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011015606060405190810160405280602581526020017f5472616e7366657220776f756c6420726573756c7420696e20616e206f76657281526020017f666c6f772e000000000000000000000000000000000000000000000000000000815250901515610dd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc99190611464565b60405180910390fd5b50816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610ec891906114c6565b60405180910390a36001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610ff5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fec90611486565b60405180910390fd5b610ffe836109d2565b9050808210156110285761101d60025461101883856111b7565b6111b7565b600281905550611044565b61103d60025461103884846111b7565b611199565b6002819055505b816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561111e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161111590611486565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415156111965780600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b60008082840190508381101515156111ad57fe5b8091505092915050565b60008282111515156111c557fe5b818303905092915050565b60006111dc8235611522565b905092915050565b60006111f08235611542565b905092915050565b60006020828403121561120a57600080fd5b6000611218848285016111d0565b91505092915050565b6000806040838503121561123457600080fd5b6000611242858286016111d0565b9250506020611253858286016111d0565b9150509250929050565b60008060006060848603121561127257600080fd5b6000611280868287016111d0565b9350506020611291868287016111d0565b92505060406112a2868287016111e4565b9150509250925092565b600080604083850312156112bf57600080fd5b60006112cd858286016111d0565b92505060206112de858286016111e4565b9150509250929050565b6000602082840312156112fa57600080fd5b6000611308848285016111e4565b91505092915050565b61131a816114ec565b82525050565b6113298161150c565b82525050565b600061133a826114e1565b80845261134e81602086016020860161154c565b6113578161157f565b602085010191505092915050565b6000603382527f4f6e6c7920636f6e7472616374206f776e657220697320616c6c6f776564207460208301527f6f2063616c6c2074686973206d6574686f642e000000000000000000000000006040830152606082019050919050565b6000603782527f4d696e74696e67206d6f7265207468616e20313030303030303030303030303060208301527f30303030303030206973206e6f7420616c6c6f7765642e0000000000000000006040830152606082019050919050565b61142881611518565b82525050565b60006020820190506114436000830184611311565b92915050565b600060208201905061145e6000830184611320565b92915050565b6000602082019050818103600083015261147e818461132f565b905092915050565b6000602082019050818103600083015261149f81611365565b9050919050565b600060208201905081810360008301526114bf816113c2565b9050919050565b60006020820190506114db600083018461141f565b92915050565b600081519050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b8381101561156a57808201518184015260208101905061154f565b83811115611579576000848401525b50505050565b6000601f19601f83011690509190505600a265627a7a723058208f9c89c6f85f64aec1e07cbf745526bbd793fd4abc535035dd77ee4efbc898c36c6578706572696d656e74616cf50037", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x193B CODESIZE SUB DUP1 PUSH3 0x193B DUP4 CODECOPY DUP2 ADD DUP1 PUSH1 0x40 MSTORE PUSH3 0x37 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH3 0x228 JUMP JUMPDEST CALLER PUSH1 0x3 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP DUP4 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0x90 SWAP3 SWAP2 SWAP1 PUSH3 0x105 JUMP JUMPDEST POP DUP3 PUSH1 0x5 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xA9 SWAP3 SWAP2 SWAP1 PUSH3 0x105 JUMP JUMPDEST POP DUP2 PUSH1 0x6 DUP2 SWAP1 SSTORE POP DUP1 PUSH1 0x2 DUP2 SWAP1 SSTORE POP DUP1 PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP POP POP POP POP PUSH3 0x361 JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x148 JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x179 JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x179 JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x178 JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x15B JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x188 SWAP2 SWAP1 PUSH3 0x18C JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x1B1 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x1AD JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x193 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH1 0x1F DUP4 ADD SLT ISZERO ISZERO PUSH3 0x1C8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 MLOAD PUSH3 0x1DF PUSH3 0x1D9 DUP3 PUSH3 0x2F4 JUMP JUMPDEST PUSH3 0x2C6 JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE PUSH1 0x20 DUP4 ADD PUSH1 0x20 DUP4 ADD DUP6 DUP4 DUP4 ADD GT ISZERO PUSH3 0x1FC JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH3 0x209 DUP4 DUP3 DUP5 PUSH3 0x32B JUMP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH3 0x220 DUP3 MLOAD PUSH3 0x321 JUMP JUMPDEST SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP1 PUSH1 0x80 DUP6 DUP8 SUB SLT ISZERO PUSH3 0x23F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP6 ADD MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH3 0x25A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH3 0x268 DUP8 DUP3 DUP9 ADD PUSH3 0x1B4 JUMP JUMPDEST SWAP5 POP POP PUSH1 0x20 DUP6 ADD MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH3 0x286 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH3 0x294 DUP8 DUP3 DUP9 ADD PUSH3 0x1B4 JUMP JUMPDEST SWAP4 POP POP PUSH1 0x40 PUSH3 0x2A7 DUP8 DUP3 DUP9 ADD PUSH3 0x212 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x60 PUSH3 0x2BA DUP8 DUP3 DUP9 ADD PUSH3 0x212 JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP6 SWAP2 SWAP5 POP SWAP3 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x40 MLOAD SWAP1 POP DUP2 DUP2 ADD DUP2 DUP2 LT PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT OR ISZERO PUSH3 0x2EA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP1 PUSH1 0x40 MSTORE POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT ISZERO PUSH3 0x30C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1F NOT PUSH1 0x1F DUP4 ADD AND SWAP1 POP PUSH1 0x20 DUP2 ADD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH3 0x34B JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH3 0x32E JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH3 0x35B JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH2 0x15CA DUP1 PUSH3 0x371 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0xC5 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xCA JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0xF5 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x132 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x15D JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x19A JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x1C5 JUMPI DUP1 PUSH4 0x8DA5CB5B EQ PUSH2 0x202 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x22D JUMPI DUP1 PUSH4 0xA0712D68 EQ PUSH2 0x258 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x281 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x2BE JUMPI DUP1 PUSH4 0xE30443BC EQ PUSH2 0x2FB JUMPI DUP1 PUSH4 0xF2FDE38B EQ PUSH2 0x324 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0xD6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xDF PUSH2 0x34D JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xEC SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x101 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x11C PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x117 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12AC JUMP JUMPDEST PUSH2 0x3EB JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x129 SWAP2 SWAP1 PUSH2 0x1449 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x13E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x147 PUSH2 0x4DD JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x154 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x169 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x184 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x17F SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x125D JUMP JUMPDEST PUSH2 0x4E3 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x191 SWAP2 SWAP1 PUSH2 0x1449 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1A6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x1AF PUSH2 0x9CC JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x1BC SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1D1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x1EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x1E7 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x11F8 JUMP JUMPDEST PUSH2 0x9D2 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x1F9 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x20E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x217 PUSH2 0xA1A JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x224 SWAP2 SWAP1 PUSH2 0x142E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x239 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x242 PUSH2 0xA40 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x24F SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x264 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x27F PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x27A SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12E8 JUMP JUMPDEST PUSH2 0xADE JUMP JUMPDEST STOP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x28D JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x2A8 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x2A3 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12AC JUMP JUMPDEST PUSH2 0xBCB JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x2B5 SWAP2 SWAP1 PUSH2 0x1449 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x2CA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x2E5 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x2E0 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1221 JUMP JUMPDEST PUSH2 0xEDA JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x2F2 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x307 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x322 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x31D SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12AC JUMP JUMPDEST PUSH2 0xF61 JUMP JUMPDEST STOP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x330 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x34B PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x346 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x11F8 JUMP JUMPDEST PUSH2 0x108C JUMP JUMPDEST STOP JUMPDEST PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x3E3 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x3B8 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x3E3 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x3C6 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP DUP2 JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x1 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP5 PUSH1 0x40 MLOAD PUSH2 0x4CB SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x2 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x1 PUSH1 0x0 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP DUP3 PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2A DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x496E73756666696369656E742062616C616E636520746F20636F6D706C657465 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x207472616E736665722E00000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x647 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x63E SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP3 DUP2 LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2C DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x496E73756666696369656E7420616C6C6F77616E636520746F20636F6D706C65 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x7465207472616E736665722E0000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x6EC JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x6E3 SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD DUP4 PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD ADD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x5472616E7366657220776F756C6420726573756C7420696E20616E206F766572 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x666C6F772E000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x80F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x806 SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP3 PUSH1 0x0 DUP1 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP DUP3 PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD SUB SWAP3 POP POP DUP2 SWAP1 SSTORE POP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 LT ISZERO PUSH2 0x95B JUMPI DUP3 PUSH1 0x1 PUSH1 0x0 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD SUB SWAP3 POP POP DUP2 SWAP1 SSTORE POP JUMPDEST DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP6 PUSH1 0x40 MLOAD PUSH2 0x9B8 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 PUSH1 0x1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x6 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x3 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 JUMP JUMPDEST PUSH1 0x5 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0xAD6 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xAAB JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xAD6 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xAB9 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP DUP2 JUMP JUMPDEST PUSH9 0x56BC75E2D63100000 DUP2 GT ISZERO ISZERO ISZERO PUSH2 0xB2C JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xB23 SWAP1 PUSH2 0x14A6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xB74 DUP2 PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0x1199 JUMP JUMPDEST PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xBC2 PUSH1 0x2 SLOAD DUP3 PUSH2 0x1199 JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2A DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x496E73756666696369656E742062616C616E636520746F20636F6D706C657465 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x207472616E736665722E00000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0xCAF JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xCA6 SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD DUP3 PUSH1 0x0 DUP1 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD ADD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x5472616E7366657220776F756C6420726573756C7420696E20616E206F766572 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x666C6F772E000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0xDD2 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xDC9 SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP2 PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD SUB SWAP3 POP POP DUP2 SWAP1 SSTORE POP DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP5 PUSH1 0x40 MLOAD PUSH2 0xEC8 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x3 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO ISZERO PUSH2 0xFF5 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xFEC SWAP1 PUSH2 0x1486 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xFFE DUP4 PUSH2 0x9D2 JUMP JUMPDEST SWAP1 POP DUP1 DUP3 LT ISZERO PUSH2 0x1028 JUMPI PUSH2 0x101D PUSH1 0x2 SLOAD PUSH2 0x1018 DUP4 DUP6 PUSH2 0x11B7 JUMP JUMPDEST PUSH2 0x11B7 JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH2 0x1044 JUMP JUMPDEST PUSH2 0x103D PUSH1 0x2 SLOAD PUSH2 0x1038 DUP5 DUP5 PUSH2 0x11B7 JUMP JUMPDEST PUSH2 0x1199 JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP JUMPDEST DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP POP POP POP JUMP JUMPDEST PUSH1 0x3 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO ISZERO PUSH2 0x111E JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x1115 SWAP1 PUSH2 0x1486 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO ISZERO PUSH2 0x1196 JUMPI DUP1 PUSH1 0x3 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO ISZERO ISZERO PUSH2 0x11AD JUMPI INVALID JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 DUP3 GT ISZERO ISZERO ISZERO PUSH2 0x11C5 JUMPI INVALID JUMPDEST DUP2 DUP4 SUB SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x11DC DUP3 CALLDATALOAD PUSH2 0x1522 JUMP JUMPDEST SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x11F0 DUP3 CALLDATALOAD PUSH2 0x1542 JUMP JUMPDEST SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x120A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1218 DUP5 DUP3 DUP6 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x1234 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1242 DUP6 DUP3 DUP7 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x1253 DUP6 DUP3 DUP7 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0x60 DUP5 DUP7 SUB SLT ISZERO PUSH2 0x1272 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1280 DUP7 DUP3 DUP8 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP4 POP POP PUSH1 0x20 PUSH2 0x1291 DUP7 DUP3 DUP8 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x40 PUSH2 0x12A2 DUP7 DUP3 DUP8 ADD PUSH2 0x11E4 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 POP SWAP3 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x12BF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x12CD DUP6 DUP3 DUP7 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x12DE DUP6 DUP3 DUP7 ADD PUSH2 0x11E4 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x12FA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1308 DUP5 DUP3 DUP6 ADD PUSH2 0x11E4 JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH2 0x131A DUP2 PUSH2 0x14EC JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH2 0x1329 DUP2 PUSH2 0x150C JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x133A DUP3 PUSH2 0x14E1 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH2 0x134E DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x154C JUMP JUMPDEST PUSH2 0x1357 DUP2 PUSH2 0x157F JUMP JUMPDEST PUSH1 0x20 DUP6 ADD ADD SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x33 DUP3 MSTORE PUSH32 0x4F6E6C7920636F6E7472616374206F776E657220697320616C6C6F7765642074 PUSH1 0x20 DUP4 ADD MSTORE PUSH32 0x6F2063616C6C2074686973206D6574686F642E00000000000000000000000000 PUSH1 0x40 DUP4 ADD MSTORE PUSH1 0x60 DUP3 ADD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x37 DUP3 MSTORE PUSH32 0x4D696E74696E67206D6F7265207468616E203130303030303030303030303030 PUSH1 0x20 DUP4 ADD MSTORE PUSH32 0x30303030303030206973206E6F7420616C6C6F7765642E000000000000000000 PUSH1 0x40 DUP4 ADD MSTORE PUSH1 0x60 DUP3 ADD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH2 0x1428 DUP2 PUSH2 0x1518 JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH2 0x1443 PUSH1 0x0 DUP4 ADD DUP5 PUSH2 0x1311 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH2 0x145E PUSH1 0x0 DUP4 ADD DUP5 PUSH2 0x1320 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP DUP2 DUP2 SUB PUSH1 0x0 DUP4 ADD MSTORE PUSH2 0x147E DUP2 DUP5 PUSH2 0x132F JUMP JUMPDEST SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP DUP2 DUP2 SUB PUSH1 0x0 DUP4 ADD MSTORE PUSH2 0x149F DUP2 PUSH2 0x1365 JUMP JUMPDEST SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP DUP2 DUP2 SUB PUSH1 0x0 DUP4 ADD MSTORE PUSH2 0x14BF DUP2 PUSH2 0x13C2 JUMP JUMPDEST SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH2 0x14DB PUSH1 0x0 DUP4 ADD DUP5 PUSH2 0x141F JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 ISZERO ISZERO SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x156A JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x154F JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x1579 JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F NOT PUSH1 0x1F DUP4 ADD AND SWAP1 POP SWAP2 SWAP1 POP JUMP STOP LOG2 PUSH6 0x627A7A723058 KECCAK256 DUP16 SWAP13 DUP10 0xc6 0xf8 0x5f PUSH5 0xAEC1E07CBF PUSH21 0x5526BBD793FD4ABC535035DD77EE4EFBC898C36C65 PUSH25 0x706572696D656E74616CF50037000000000000000000000000 ", "sourceMap": "718:844:0:-;;;850:302;8:9:-1;5:2;;;30:1;27;20:12;5:2;850:302:0;;;;;;;;;;;;;;;;;;;;;;;;371:10:6;363:5;;:18;;;;;;;;;;;;;;;;;;1003:5:0;996:4;:12;;;;;;;;;;;;:::i;:::-;;1027:7;1018:6;:16;;;;;;;;;;;;:::i;:::-;;1055:9;1044:8;:20;;;;1088:12;1074:11;:26;;;;1133:12;1110:8;:20;1119:10;1110:20;;;;;;;;;;;;;;;:35;;;;850:302;;;;718:844;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;6:444:-1:-;;119:3;112:4;104:6;100:17;96:27;89:35;86:2;;;137:1;134;127:12;86:2;167:6;161:13;189:65;204:49;246:6;204:49;;;189:65;;;180:74;;274:6;267:5;260:21;310:4;302:6;298:17;343:4;336:5;332:16;378:3;369:6;364:3;360:16;357:25;354:2;;;395:1;392;385:12;354:2;405:39;437:6;432:3;427;405:39;;;79:371;;;;;;;;458:122;;536:39;567:6;561:13;536:39;;;527:48;;521:59;;;;;587:870;;;;;773:3;761:9;752:7;748:23;744:33;741:2;;;790:1;787;780:12;741:2;846:1;835:9;831:17;825:24;869:18;861:6;858:30;855:2;;;901:1;898;891:12;855:2;921:74;987:7;978:6;967:9;963:22;921:74;;;911:84;;804:197;1053:2;1042:9;1038:18;1032:25;1077:18;1069:6;1066:30;1063:2;;;1109:1;1106;1099:12;1063:2;1129:74;1195:7;1186:6;1175:9;1171:22;1129:74;;;1119:84;;1011:198;1240:2;1258:64;1314:7;1305:6;1294:9;1290:22;1258:64;;;1248:74;;1219:109;1359:2;1377:64;1433:7;1424:6;1413:9;1409:22;1377:64;;;1367:74;;1338:109;735:722;;;;;;;;1464:256;;1526:2;1520:9;1510:19;;1564:4;1556:6;1552:17;1663:6;1651:10;1648:22;1627:18;1615:10;1612:34;1609:62;1606:2;;;1684:1;1681;1674:12;1606:2;1704:10;1700:2;1693:22;1504:216;;;;;1727:259;;1871:18;1863:6;1860:30;1857:2;;;1903:1;1900;1893:12;1857:2;1947:4;1943:9;1936:4;1928:6;1924:17;1920:33;1912:41;;1976:4;1970;1966:15;1958:23;;1794:192;;;;1993:79;;2062:5;2051:16;;2045:27;;;;2080:268;2145:1;2152:101;2166:6;2163:1;2160:13;2152:101;;;2242:1;2237:3;2233:11;2227:18;2223:1;2218:3;2214:11;2207:39;2188:2;2185:1;2181:10;2176:15;;2152:101;;;2268:6;2265:1;2262:13;2259:2;;;2333:1;2324:6;2319:3;2315:16;2308:27;2259:2;2129:219;;;;;718:844:0;;;;;;;" }, "deployedBytecode": { "linkReferences": {}, - "object": "0x6080604052600436106100c5576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100ca578063095ea7b3146100f557806318160ddd1461013257806323b872dd1461015d578063313ce5671461019a57806370a08231146101c55780638da5cb5b1461020257806395d89b411461022d578063a0712d6814610258578063a9059cbb14610281578063dd62ed3e146102be578063e30443bc146102fb578063f2fde38b14610324575b600080fd5b3480156100d657600080fd5b506100df61034d565b6040516100ec9190611464565b60405180910390f35b34801561010157600080fd5b5061011c600480360361011791908101906112ac565b6103eb565b6040516101299190611449565b60405180910390f35b34801561013e57600080fd5b506101476104dd565b60405161015491906114c6565b60405180910390f35b34801561016957600080fd5b50610184600480360361017f919081019061125d565b6104e3565b6040516101919190611449565b60405180910390f35b3480156101a657600080fd5b506101af6109cc565b6040516101bc91906114c6565b60405180910390f35b3480156101d157600080fd5b506101ec60048036036101e791908101906111f8565b6109d2565b6040516101f991906114c6565b60405180910390f35b34801561020e57600080fd5b50610217610a1a565b604051610224919061142e565b60405180910390f35b34801561023957600080fd5b50610242610a40565b60405161024f9190611464565b60405180910390f35b34801561026457600080fd5b5061027f600480360361027a91908101906112e8565b610ade565b005b34801561028d57600080fd5b506102a860048036036102a391908101906112ac565b610bcb565b6040516102b59190611449565b60405180910390f35b3480156102ca57600080fd5b506102e560048036036102e09190810190611221565b610eda565b6040516102f291906114c6565b60405180910390f35b34801561030757600080fd5b50610322600480360361031d91908101906112ac565b610f61565b005b34801561033057600080fd5b5061034b600480360361034691908101906111f8565b61108c565b005b60048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103e35780601f106103b8576101008083540402835291602001916103e3565b820191906000526020600020905b8154815290600101906020018083116103c657829003601f168201915b505050505081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516104cb91906114c6565b60405180910390a36001905092915050565b60025481565b600080600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050826000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015606060405190810160405280602a81526020017f496e73756666696369656e742062616c616e636520746f20636f6d706c65746581526020017f207472616e736665722e00000000000000000000000000000000000000000000815250901515610647576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161063e9190611464565b60405180910390fd5b5082811015606060405190810160405280602c81526020017f496e73756666696369656e7420616c6c6f77616e636520746f20636f6d706c6581526020017f7465207472616e736665722e00000000000000000000000000000000000000008152509015156106ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e39190611464565b60405180910390fd5b506000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054836000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011015606060405190810160405280602581526020017f5472616e7366657220776f756c6420726573756c7420696e20616e206f76657281526020017f666c6f772e00000000000000000000000000000000000000000000000000000081525090151561080f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108069190611464565b60405180910390fd5b50826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550826000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81101561095b5782600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040516109b891906114c6565b60405180910390a360019150509392505050565b60065481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610ad65780601f10610aab57610100808354040283529160200191610ad6565b820191906000526020600020905b815481529060010190602001808311610ab957829003601f168201915b505050505081565b68056bc75e2d631000008111151515610b2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b23906114a6565b60405180910390fd5b610b74816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611199565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610bc260025482611199565b60028190555050565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015606060405190810160405280602a81526020017f496e73756666696369656e742062616c616e636520746f20636f6d706c65746581526020017f207472616e736665722e00000000000000000000000000000000000000000000815250901515610caf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ca69190611464565b60405180910390fd5b506000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011015606060405190810160405280602581526020017f5472616e7366657220776f756c6420726573756c7420696e20616e206f76657281526020017f666c6f772e000000000000000000000000000000000000000000000000000000815250901515610dd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc99190611464565b60405180910390fd5b50816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610ec891906114c6565b60405180910390a36001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610ff5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fec90611486565b60405180910390fd5b610ffe836109d2565b9050808210156110285761101d60025461101883856111b7565b6111b7565b600281905550611044565b61103d60025461103884846111b7565b611199565b6002819055505b816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561111e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161111590611486565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415156111965780600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b60008082840190508381101515156111ad57fe5b8091505092915050565b60008282111515156111c557fe5b818303905092915050565b60006111dc8235611522565b905092915050565b60006111f08235611542565b905092915050565b60006020828403121561120a57600080fd5b6000611218848285016111d0565b91505092915050565b6000806040838503121561123457600080fd5b6000611242858286016111d0565b9250506020611253858286016111d0565b9150509250929050565b60008060006060848603121561127257600080fd5b6000611280868287016111d0565b9350506020611291868287016111d0565b92505060406112a2868287016111e4565b9150509250925092565b600080604083850312156112bf57600080fd5b60006112cd858286016111d0565b92505060206112de858286016111e4565b9150509250929050565b6000602082840312156112fa57600080fd5b6000611308848285016111e4565b91505092915050565b61131a816114ec565b82525050565b6113298161150c565b82525050565b600061133a826114e1565b80845261134e81602086016020860161154c565b6113578161157f565b602085010191505092915050565b6000603382527f4f6e6c7920636f6e7472616374206f776e657220697320616c6c6f776564207460208301527f6f2063616c6c2074686973206d6574686f642e000000000000000000000000006040830152606082019050919050565b6000603782527f4d696e74696e67206d6f7265207468616e20313030303030303030303030303060208301527f30303030303030206973206e6f7420616c6c6f7765642e0000000000000000006040830152606082019050919050565b61142881611518565b82525050565b60006020820190506114436000830184611311565b92915050565b600060208201905061145e6000830184611320565b92915050565b6000602082019050818103600083015261147e818461132f565b905092915050565b6000602082019050818103600083015261149f81611365565b9050919050565b600060208201905081810360008301526114bf816113c2565b9050919050565b60006020820190506114db600083018461141f565b92915050565b600081519050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b8381101561156a57808201518184015260208101905061154f565b83811115611579576000848401525b50505050565b6000601f19601f83011690509190505600a265627a7a72305820dbb48ab34f59e30595d90684cb2e3bf356f8749f5dd5e617ce527adda15d5c346c6578706572696d656e74616cf50037", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0xC5 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xCA JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0xF5 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x132 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x15D JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x19A JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x1C5 JUMPI DUP1 PUSH4 0x8DA5CB5B EQ PUSH2 0x202 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x22D JUMPI DUP1 PUSH4 0xA0712D68 EQ PUSH2 0x258 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x281 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x2BE JUMPI DUP1 PUSH4 0xE30443BC EQ PUSH2 0x2FB JUMPI DUP1 PUSH4 0xF2FDE38B EQ PUSH2 0x324 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0xD6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xDF PUSH2 0x34D JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xEC SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x101 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x11C PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x117 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12AC JUMP JUMPDEST PUSH2 0x3EB JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x129 SWAP2 SWAP1 PUSH2 0x1449 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x13E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x147 PUSH2 0x4DD JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x154 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x169 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x184 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x17F SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x125D JUMP JUMPDEST PUSH2 0x4E3 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x191 SWAP2 SWAP1 PUSH2 0x1449 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1A6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x1AF PUSH2 0x9CC JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x1BC SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1D1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x1EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x1E7 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x11F8 JUMP JUMPDEST PUSH2 0x9D2 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x1F9 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x20E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x217 PUSH2 0xA1A JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x224 SWAP2 SWAP1 PUSH2 0x142E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x239 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x242 PUSH2 0xA40 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x24F SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x264 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x27F PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x27A SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12E8 JUMP JUMPDEST PUSH2 0xADE JUMP JUMPDEST STOP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x28D JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x2A8 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x2A3 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12AC JUMP JUMPDEST PUSH2 0xBCB JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x2B5 SWAP2 SWAP1 PUSH2 0x1449 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x2CA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x2E5 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x2E0 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1221 JUMP JUMPDEST PUSH2 0xEDA JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x2F2 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x307 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x322 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x31D SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12AC JUMP JUMPDEST PUSH2 0xF61 JUMP JUMPDEST STOP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x330 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x34B PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x346 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x11F8 JUMP JUMPDEST PUSH2 0x108C JUMP JUMPDEST STOP JUMPDEST PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x3E3 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x3B8 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x3E3 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x3C6 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP DUP2 JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x1 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP5 PUSH1 0x40 MLOAD PUSH2 0x4CB SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x2 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x1 PUSH1 0x0 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP DUP3 PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2A DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x496E73756666696369656E742062616C616E636520746F20636F6D706C657465 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x207472616E736665722E00000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x647 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x63E SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP3 DUP2 LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2C DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x496E73756666696369656E7420616C6C6F77616E636520746F20636F6D706C65 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x7465207472616E736665722E0000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x6EC JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x6E3 SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD DUP4 PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD ADD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x5472616E7366657220776F756C6420726573756C7420696E20616E206F766572 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x666C6F772E000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x80F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x806 SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP3 PUSH1 0x0 DUP1 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP DUP3 PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD SUB SWAP3 POP POP DUP2 SWAP1 SSTORE POP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 LT ISZERO PUSH2 0x95B JUMPI DUP3 PUSH1 0x1 PUSH1 0x0 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD SUB SWAP3 POP POP DUP2 SWAP1 SSTORE POP JUMPDEST DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP6 PUSH1 0x40 MLOAD PUSH2 0x9B8 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 PUSH1 0x1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x6 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x3 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 JUMP JUMPDEST PUSH1 0x5 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0xAD6 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xAAB JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xAD6 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xAB9 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP DUP2 JUMP JUMPDEST PUSH9 0x56BC75E2D63100000 DUP2 GT ISZERO ISZERO ISZERO PUSH2 0xB2C JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xB23 SWAP1 PUSH2 0x14A6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xB74 DUP2 PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0x1199 JUMP JUMPDEST PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xBC2 PUSH1 0x2 SLOAD DUP3 PUSH2 0x1199 JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2A DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x496E73756666696369656E742062616C616E636520746F20636F6D706C657465 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x207472616E736665722E00000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0xCAF JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xCA6 SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD DUP3 PUSH1 0x0 DUP1 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD ADD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x5472616E7366657220776F756C6420726573756C7420696E20616E206F766572 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x666C6F772E000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0xDD2 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xDC9 SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP2 PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD SUB SWAP3 POP POP DUP2 SWAP1 SSTORE POP DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP5 PUSH1 0x40 MLOAD PUSH2 0xEC8 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x3 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO ISZERO PUSH2 0xFF5 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xFEC SWAP1 PUSH2 0x1486 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xFFE DUP4 PUSH2 0x9D2 JUMP JUMPDEST SWAP1 POP DUP1 DUP3 LT ISZERO PUSH2 0x1028 JUMPI PUSH2 0x101D PUSH1 0x2 SLOAD PUSH2 0x1018 DUP4 DUP6 PUSH2 0x11B7 JUMP JUMPDEST PUSH2 0x11B7 JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH2 0x1044 JUMP JUMPDEST PUSH2 0x103D PUSH1 0x2 SLOAD PUSH2 0x1038 DUP5 DUP5 PUSH2 0x11B7 JUMP JUMPDEST PUSH2 0x1199 JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP JUMPDEST DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP POP POP POP JUMP JUMPDEST PUSH1 0x3 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO ISZERO PUSH2 0x111E JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x1115 SWAP1 PUSH2 0x1486 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO ISZERO PUSH2 0x1196 JUMPI DUP1 PUSH1 0x3 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO ISZERO ISZERO PUSH2 0x11AD JUMPI INVALID JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 DUP3 GT ISZERO ISZERO ISZERO PUSH2 0x11C5 JUMPI INVALID JUMPDEST DUP2 DUP4 SUB SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x11DC DUP3 CALLDATALOAD PUSH2 0x1522 JUMP JUMPDEST SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x11F0 DUP3 CALLDATALOAD PUSH2 0x1542 JUMP JUMPDEST SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x120A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1218 DUP5 DUP3 DUP6 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x1234 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1242 DUP6 DUP3 DUP7 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x1253 DUP6 DUP3 DUP7 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0x60 DUP5 DUP7 SUB SLT ISZERO PUSH2 0x1272 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1280 DUP7 DUP3 DUP8 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP4 POP POP PUSH1 0x20 PUSH2 0x1291 DUP7 DUP3 DUP8 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x40 PUSH2 0x12A2 DUP7 DUP3 DUP8 ADD PUSH2 0x11E4 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 POP SWAP3 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x12BF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x12CD DUP6 DUP3 DUP7 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x12DE DUP6 DUP3 DUP7 ADD PUSH2 0x11E4 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x12FA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1308 DUP5 DUP3 DUP6 ADD PUSH2 0x11E4 JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH2 0x131A DUP2 PUSH2 0x14EC JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH2 0x1329 DUP2 PUSH2 0x150C JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x133A DUP3 PUSH2 0x14E1 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH2 0x134E DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x154C JUMP JUMPDEST PUSH2 0x1357 DUP2 PUSH2 0x157F JUMP JUMPDEST PUSH1 0x20 DUP6 ADD ADD SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x33 DUP3 MSTORE PUSH32 0x4F6E6C7920636F6E7472616374206F776E657220697320616C6C6F7765642074 PUSH1 0x20 DUP4 ADD MSTORE PUSH32 0x6F2063616C6C2074686973206D6574686F642E00000000000000000000000000 PUSH1 0x40 DUP4 ADD MSTORE PUSH1 0x60 DUP3 ADD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x37 DUP3 MSTORE PUSH32 0x4D696E74696E67206D6F7265207468616E203130303030303030303030303030 PUSH1 0x20 DUP4 ADD MSTORE PUSH32 0x30303030303030206973206E6F7420616C6C6F7765642E000000000000000000 PUSH1 0x40 DUP4 ADD MSTORE PUSH1 0x60 DUP3 ADD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH2 0x1428 DUP2 PUSH2 0x1518 JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH2 0x1443 PUSH1 0x0 DUP4 ADD DUP5 PUSH2 0x1311 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH2 0x145E PUSH1 0x0 DUP4 ADD DUP5 PUSH2 0x1320 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP DUP2 DUP2 SUB PUSH1 0x0 DUP4 ADD MSTORE PUSH2 0x147E DUP2 DUP5 PUSH2 0x132F JUMP JUMPDEST SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP DUP2 DUP2 SUB PUSH1 0x0 DUP4 ADD MSTORE PUSH2 0x149F DUP2 PUSH2 0x1365 JUMP JUMPDEST SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP DUP2 DUP2 SUB PUSH1 0x0 DUP4 ADD MSTORE PUSH2 0x14BF DUP2 PUSH2 0x13C2 JUMP JUMPDEST SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH2 0x14DB PUSH1 0x0 DUP4 ADD DUP5 PUSH2 0x141F JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 ISZERO ISZERO SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x156A JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x154F JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x1579 JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F NOT PUSH1 0x1F DUP4 ADD AND SWAP1 POP SWAP2 SWAP1 POP JUMP STOP LOG2 PUSH6 0x627A7A723058 KECCAK256 0xdb 0xb4 DUP11 0xb3 0x4f MSIZE 0xe3 SDIV SWAP6 0xd9 MOD DUP5 0xcb 0x2e EXTCODESIZE RETURN JUMP 0xf8 PUSH21 0x9F5DD5E617CE527ADDA15D5C346C6578706572696D PUSH6 0x6E74616CF500 CALLDATACOPY ", + "object": "0x6080604052600436106100c5576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100ca578063095ea7b3146100f557806318160ddd1461013257806323b872dd1461015d578063313ce5671461019a57806370a08231146101c55780638da5cb5b1461020257806395d89b411461022d578063a0712d6814610258578063a9059cbb14610281578063dd62ed3e146102be578063e30443bc146102fb578063f2fde38b14610324575b600080fd5b3480156100d657600080fd5b506100df61034d565b6040516100ec9190611464565b60405180910390f35b34801561010157600080fd5b5061011c600480360361011791908101906112ac565b6103eb565b6040516101299190611449565b60405180910390f35b34801561013e57600080fd5b506101476104dd565b60405161015491906114c6565b60405180910390f35b34801561016957600080fd5b50610184600480360361017f919081019061125d565b6104e3565b6040516101919190611449565b60405180910390f35b3480156101a657600080fd5b506101af6109cc565b6040516101bc91906114c6565b60405180910390f35b3480156101d157600080fd5b506101ec60048036036101e791908101906111f8565b6109d2565b6040516101f991906114c6565b60405180910390f35b34801561020e57600080fd5b50610217610a1a565b604051610224919061142e565b60405180910390f35b34801561023957600080fd5b50610242610a40565b60405161024f9190611464565b60405180910390f35b34801561026457600080fd5b5061027f600480360361027a91908101906112e8565b610ade565b005b34801561028d57600080fd5b506102a860048036036102a391908101906112ac565b610bcb565b6040516102b59190611449565b60405180910390f35b3480156102ca57600080fd5b506102e560048036036102e09190810190611221565b610eda565b6040516102f291906114c6565b60405180910390f35b34801561030757600080fd5b50610322600480360361031d91908101906112ac565b610f61565b005b34801561033057600080fd5b5061034b600480360361034691908101906111f8565b61108c565b005b60048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103e35780601f106103b8576101008083540402835291602001916103e3565b820191906000526020600020905b8154815290600101906020018083116103c657829003601f168201915b505050505081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516104cb91906114c6565b60405180910390a36001905092915050565b60025481565b600080600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050826000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015606060405190810160405280602a81526020017f496e73756666696369656e742062616c616e636520746f20636f6d706c65746581526020017f207472616e736665722e00000000000000000000000000000000000000000000815250901515610647576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161063e9190611464565b60405180910390fd5b5082811015606060405190810160405280602c81526020017f496e73756666696369656e7420616c6c6f77616e636520746f20636f6d706c6581526020017f7465207472616e736665722e00000000000000000000000000000000000000008152509015156106ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e39190611464565b60405180910390fd5b506000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054836000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011015606060405190810160405280602581526020017f5472616e7366657220776f756c6420726573756c7420696e20616e206f76657281526020017f666c6f772e00000000000000000000000000000000000000000000000000000081525090151561080f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108069190611464565b60405180910390fd5b50826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550826000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81101561095b5782600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040516109b891906114c6565b60405180910390a360019150509392505050565b60065481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610ad65780601f10610aab57610100808354040283529160200191610ad6565b820191906000526020600020905b815481529060010190602001808311610ab957829003601f168201915b505050505081565b68056bc75e2d631000008111151515610b2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b23906114a6565b60405180910390fd5b610b74816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611199565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610bc260025482611199565b60028190555050565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015606060405190810160405280602a81526020017f496e73756666696369656e742062616c616e636520746f20636f6d706c65746581526020017f207472616e736665722e00000000000000000000000000000000000000000000815250901515610caf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ca69190611464565b60405180910390fd5b506000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011015606060405190810160405280602581526020017f5472616e7366657220776f756c6420726573756c7420696e20616e206f76657281526020017f666c6f772e000000000000000000000000000000000000000000000000000000815250901515610dd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc99190611464565b60405180910390fd5b50816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610ec891906114c6565b60405180910390a36001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610ff5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fec90611486565b60405180910390fd5b610ffe836109d2565b9050808210156110285761101d60025461101883856111b7565b6111b7565b600281905550611044565b61103d60025461103884846111b7565b611199565b6002819055505b816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561111e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161111590611486565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415156111965780600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b60008082840190508381101515156111ad57fe5b8091505092915050565b60008282111515156111c557fe5b818303905092915050565b60006111dc8235611522565b905092915050565b60006111f08235611542565b905092915050565b60006020828403121561120a57600080fd5b6000611218848285016111d0565b91505092915050565b6000806040838503121561123457600080fd5b6000611242858286016111d0565b9250506020611253858286016111d0565b9150509250929050565b60008060006060848603121561127257600080fd5b6000611280868287016111d0565b9350506020611291868287016111d0565b92505060406112a2868287016111e4565b9150509250925092565b600080604083850312156112bf57600080fd5b60006112cd858286016111d0565b92505060206112de858286016111e4565b9150509250929050565b6000602082840312156112fa57600080fd5b6000611308848285016111e4565b91505092915050565b61131a816114ec565b82525050565b6113298161150c565b82525050565b600061133a826114e1565b80845261134e81602086016020860161154c565b6113578161157f565b602085010191505092915050565b6000603382527f4f6e6c7920636f6e7472616374206f776e657220697320616c6c6f776564207460208301527f6f2063616c6c2074686973206d6574686f642e000000000000000000000000006040830152606082019050919050565b6000603782527f4d696e74696e67206d6f7265207468616e20313030303030303030303030303060208301527f30303030303030206973206e6f7420616c6c6f7765642e0000000000000000006040830152606082019050919050565b61142881611518565b82525050565b60006020820190506114436000830184611311565b92915050565b600060208201905061145e6000830184611320565b92915050565b6000602082019050818103600083015261147e818461132f565b905092915050565b6000602082019050818103600083015261149f81611365565b9050919050565b600060208201905081810360008301526114bf816113c2565b9050919050565b60006020820190506114db600083018461141f565b92915050565b600081519050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b8381101561156a57808201518184015260208101905061154f565b83811115611579576000848401525b50505050565b6000601f19601f83011690509190505600a265627a7a723058208f9c89c6f85f64aec1e07cbf745526bbd793fd4abc535035dd77ee4efbc898c36c6578706572696d656e74616cf50037", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0xC5 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xCA JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0xF5 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x132 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x15D JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x19A JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x1C5 JUMPI DUP1 PUSH4 0x8DA5CB5B EQ PUSH2 0x202 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x22D JUMPI DUP1 PUSH4 0xA0712D68 EQ PUSH2 0x258 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x281 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x2BE JUMPI DUP1 PUSH4 0xE30443BC EQ PUSH2 0x2FB JUMPI DUP1 PUSH4 0xF2FDE38B EQ PUSH2 0x324 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0xD6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xDF PUSH2 0x34D JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xEC SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x101 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x11C PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x117 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12AC JUMP JUMPDEST PUSH2 0x3EB JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x129 SWAP2 SWAP1 PUSH2 0x1449 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x13E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x147 PUSH2 0x4DD JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x154 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x169 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x184 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x17F SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x125D JUMP JUMPDEST PUSH2 0x4E3 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x191 SWAP2 SWAP1 PUSH2 0x1449 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1A6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x1AF PUSH2 0x9CC JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x1BC SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1D1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x1EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x1E7 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x11F8 JUMP JUMPDEST PUSH2 0x9D2 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x1F9 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x20E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x217 PUSH2 0xA1A JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x224 SWAP2 SWAP1 PUSH2 0x142E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x239 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x242 PUSH2 0xA40 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x24F SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x264 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x27F PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x27A SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12E8 JUMP JUMPDEST PUSH2 0xADE JUMP JUMPDEST STOP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x28D JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x2A8 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x2A3 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12AC JUMP JUMPDEST PUSH2 0xBCB JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x2B5 SWAP2 SWAP1 PUSH2 0x1449 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x2CA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x2E5 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x2E0 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1221 JUMP JUMPDEST PUSH2 0xEDA JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x2F2 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x307 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x322 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x31D SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12AC JUMP JUMPDEST PUSH2 0xF61 JUMP JUMPDEST STOP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x330 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x34B PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH2 0x346 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x11F8 JUMP JUMPDEST PUSH2 0x108C JUMP JUMPDEST STOP JUMPDEST PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x3E3 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x3B8 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x3E3 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x3C6 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP DUP2 JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x1 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP5 PUSH1 0x40 MLOAD PUSH2 0x4CB SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x2 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x1 PUSH1 0x0 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP DUP3 PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2A DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x496E73756666696369656E742062616C616E636520746F20636F6D706C657465 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x207472616E736665722E00000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x647 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x63E SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP3 DUP2 LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2C DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x496E73756666696369656E7420616C6C6F77616E636520746F20636F6D706C65 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x7465207472616E736665722E0000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x6EC JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x6E3 SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD DUP4 PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD ADD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x5472616E7366657220776F756C6420726573756C7420696E20616E206F766572 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x666C6F772E000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x80F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x806 SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP3 PUSH1 0x0 DUP1 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP DUP3 PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD SUB SWAP3 POP POP DUP2 SWAP1 SSTORE POP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 LT ISZERO PUSH2 0x95B JUMPI DUP3 PUSH1 0x1 PUSH1 0x0 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD SUB SWAP3 POP POP DUP2 SWAP1 SSTORE POP JUMPDEST DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP6 PUSH1 0x40 MLOAD PUSH2 0x9B8 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 PUSH1 0x1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x6 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x3 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 JUMP JUMPDEST PUSH1 0x5 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0xAD6 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xAAB JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xAD6 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xAB9 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP DUP2 JUMP JUMPDEST PUSH9 0x56BC75E2D63100000 DUP2 GT ISZERO ISZERO ISZERO PUSH2 0xB2C JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xB23 SWAP1 PUSH2 0x14A6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xB74 DUP2 PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0x1199 JUMP JUMPDEST PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xBC2 PUSH1 0x2 SLOAD DUP3 PUSH2 0x1199 JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2A DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x496E73756666696369656E742062616C616E636520746F20636F6D706C657465 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x207472616E736665722E00000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0xCAF JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xCA6 SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD DUP3 PUSH1 0x0 DUP1 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD ADD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x5472616E7366657220776F756C6420726573756C7420696E20616E206F766572 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x666C6F772E000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0xDD2 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xDC9 SWAP2 SWAP1 PUSH2 0x1464 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP2 PUSH1 0x0 DUP1 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD SUB SWAP3 POP POP DUP2 SWAP1 SSTORE POP DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP5 PUSH1 0x40 MLOAD PUSH2 0xEC8 SWAP2 SWAP1 PUSH2 0x14C6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x3 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO ISZERO PUSH2 0xFF5 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xFEC SWAP1 PUSH2 0x1486 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xFFE DUP4 PUSH2 0x9D2 JUMP JUMPDEST SWAP1 POP DUP1 DUP3 LT ISZERO PUSH2 0x1028 JUMPI PUSH2 0x101D PUSH1 0x2 SLOAD PUSH2 0x1018 DUP4 DUP6 PUSH2 0x11B7 JUMP JUMPDEST PUSH2 0x11B7 JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH2 0x1044 JUMP JUMPDEST PUSH2 0x103D PUSH1 0x2 SLOAD PUSH2 0x1038 DUP5 DUP5 PUSH2 0x11B7 JUMP JUMPDEST PUSH2 0x1199 JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP JUMPDEST DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP POP POP POP JUMP JUMPDEST PUSH1 0x3 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO ISZERO PUSH2 0x111E JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x1115 SWAP1 PUSH2 0x1486 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO ISZERO PUSH2 0x1196 JUMPI DUP1 PUSH1 0x3 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO ISZERO ISZERO PUSH2 0x11AD JUMPI INVALID JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 DUP3 GT ISZERO ISZERO ISZERO PUSH2 0x11C5 JUMPI INVALID JUMPDEST DUP2 DUP4 SUB SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x11DC DUP3 CALLDATALOAD PUSH2 0x1522 JUMP JUMPDEST SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x11F0 DUP3 CALLDATALOAD PUSH2 0x1542 JUMP JUMPDEST SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x120A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1218 DUP5 DUP3 DUP6 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x1234 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1242 DUP6 DUP3 DUP7 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x1253 DUP6 DUP3 DUP7 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0x60 DUP5 DUP7 SUB SLT ISZERO PUSH2 0x1272 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1280 DUP7 DUP3 DUP8 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP4 POP POP PUSH1 0x20 PUSH2 0x1291 DUP7 DUP3 DUP8 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x40 PUSH2 0x12A2 DUP7 DUP3 DUP8 ADD PUSH2 0x11E4 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 POP SWAP3 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x12BF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x12CD DUP6 DUP3 DUP7 ADD PUSH2 0x11D0 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x12DE DUP6 DUP3 DUP7 ADD PUSH2 0x11E4 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x12FA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1308 DUP5 DUP3 DUP6 ADD PUSH2 0x11E4 JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH2 0x131A DUP2 PUSH2 0x14EC JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH2 0x1329 DUP2 PUSH2 0x150C JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x133A DUP3 PUSH2 0x14E1 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH2 0x134E DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x154C JUMP JUMPDEST PUSH2 0x1357 DUP2 PUSH2 0x157F JUMP JUMPDEST PUSH1 0x20 DUP6 ADD ADD SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x33 DUP3 MSTORE PUSH32 0x4F6E6C7920636F6E7472616374206F776E657220697320616C6C6F7765642074 PUSH1 0x20 DUP4 ADD MSTORE PUSH32 0x6F2063616C6C2074686973206D6574686F642E00000000000000000000000000 PUSH1 0x40 DUP4 ADD MSTORE PUSH1 0x60 DUP3 ADD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x37 DUP3 MSTORE PUSH32 0x4D696E74696E67206D6F7265207468616E203130303030303030303030303030 PUSH1 0x20 DUP4 ADD MSTORE PUSH32 0x30303030303030206973206E6F7420616C6C6F7765642E000000000000000000 PUSH1 0x40 DUP4 ADD MSTORE PUSH1 0x60 DUP3 ADD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH2 0x1428 DUP2 PUSH2 0x1518 JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH2 0x1443 PUSH1 0x0 DUP4 ADD DUP5 PUSH2 0x1311 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH2 0x145E PUSH1 0x0 DUP4 ADD DUP5 PUSH2 0x1320 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP DUP2 DUP2 SUB PUSH1 0x0 DUP4 ADD MSTORE PUSH2 0x147E DUP2 DUP5 PUSH2 0x132F JUMP JUMPDEST SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP DUP2 DUP2 SUB PUSH1 0x0 DUP4 ADD MSTORE PUSH2 0x149F DUP2 PUSH2 0x1365 JUMP JUMPDEST SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP DUP2 DUP2 SUB PUSH1 0x0 DUP4 ADD MSTORE PUSH2 0x14BF DUP2 PUSH2 0x13C2 JUMP JUMPDEST SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH2 0x14DB PUSH1 0x0 DUP4 ADD DUP5 PUSH2 0x141F JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 ISZERO ISZERO SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x156A JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x154F JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x1579 JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F NOT PUSH1 0x1F DUP4 ADD AND SWAP1 POP SWAP2 SWAP1 POP JUMP STOP LOG2 PUSH6 0x627A7A723058 KECCAK256 DUP16 SWAP13 DUP10 0xc6 0xf8 0x5f PUSH5 0xAEC1E07CBF PUSH21 0x5526BBD793FD4ABC535035DD77EE4EFBC898C36C65 PUSH25 0x706572696D656E74616CF50037000000000000000000000000 ", "sourceMap": "718:844:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;770:18;;8:9:-1;5:2;;;30:1;27;20:12;5:2;770:18:0;;;;;;;;;;;;;;;;;;;;2171:222:2;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2171:222:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1073:26;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1073:26:2;;;;;;;;;;;;;;;;;;;;1108:697:4;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1108:697:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;820:23:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;820:23:0;;;;;;;;;;;;;;;;;;;;2399:125:2;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2399:125:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;292:20:6;;8:9:-1;5:2;;;30:1;27;20:12;5:2;292:20:6;;;;;;;;;;;;;;;;;;;;794::0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;794:20:0;;;;;;;;;;;;;;;;;;;;905:321:1;;8:9:-1;5:2;;;30:1;27;20:12;5:2;905:321:1;;;;;;;;;;;;;;;;;;;1106:445:2;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1106:445:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2530:160;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2530:160:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1158:402:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1158:402:0;;;;;;;;;;;;;;;;;;;566:167:6;;8:9:-1;5:2;;;30:1;27;20:12;5:2;566:167:6;;;;;;;;;;;;;;;;;;;770:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;2171:222:2:-;2254:4;2306:6;2274:7;:19;2282:10;2274:19;;;;;;;;;;;;;;;:29;2294:8;2274:29;;;;;;;;;;;;;;;:38;;;;2348:8;2327:38;;2336:10;2327:38;;;2358:6;2327:38;;;;;;;;;;;;;;;2382:4;2375:11;;2171:222;;;;:::o;1073:26::-;;;;:::o;1108:697:4:-;1206:4;1226:17;1246:7;:14;1254:5;1246:14;;;;;;;;;;;;;;;:26;1261:10;1246:26;;;;;;;;;;;;;;;;1226:46;;1322:6;1303:8;:15;1312:5;1303:15;;;;;;;;;;;;;;;;:25;;1342:20;;;;;;;;;;;;;;;;;;;;;;;1282:90;;;;;;;;;;;;;;;;;;;;;;;;;;;1416:6;1403:9;:19;;1436:22;;;;;;;;;;;;;;;;;;;;;;;1382:86;;;;;;;;;;;;;;;;;;;;;;;;;;;1525:8;:13;1534:3;1525:13;;;;;;;;;;;;;;;;1515:6;1499:8;:13;1508:3;1499:13;;;;;;;;;;;;;;;;:22;:39;;1552:8;;;;;;;;;;;;;;;;;;;;;;;1478:92;;;;;;;;;;;;;;;;;;;;;;;;;;;1597:6;1580:8;:13;1589:3;1580:13;;;;;;;;;;;;;;;;:23;;;;;;;;;;;1632:6;1613:8;:15;1622:5;1613:15;;;;;;;;;;;;;;;;:25;;;;;;;;;;;762:10;1652:9;:20;1648:87;;;1718:6;1688:7;:14;1696:5;1688:14;;;;;;;;;;;;;;;:26;1703:10;1688:26;;;;;;;;;;;;;;;;:36;;;;;;;;;;;1648:87;1765:3;1749:28;;1758:5;1749:28;;;1770:6;1749:28;;;;;;;;;;;;;;;1794:4;1787:11;;1108:697;;;;;;:::o;820:23:0:-;;;;:::o;2399:125:2:-;2471:7;2501:8;:16;2510:6;2501:16;;;;;;;;;;;;;;;;2494:23;;2399:125;;;:::o;292:20:6:-;;;;;;;;;;;;;:::o;794::0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;905:321:1:-;995:21;985:6;:31;;964:133;;;;;;;;;;;;;;;;;;;;;;;;1130:37;1138:6;1146:8;:20;1155:10;1146:20;;;;;;;;;;;;;;;;1130:7;:37::i;:::-;1107:8;:20;1116:10;1107:20;;;;;;;;;;;;;;;:60;;;;1191:28;1199:11;;1212:6;1191:7;:28::i;:::-;1177:11;:42;;;;905:321;:::o;1106:445:2:-;1185:4;1250:6;1226:8;:20;1235:10;1226:20;;;;;;;;;;;;;;;;:30;;1270:20;;;;;;;;;;;;;;;;;;;;;;;1205:95;;;;;;;;;;;;;;;;;;;;;;;;;;;1357:8;:13;1366:3;1357:13;;;;;;;;;;;;;;;;1347:6;1331:8;:13;1340:3;1331:13;;;;;;;;;;;;;;;;:22;:39;;1384:8;;;;;;;;;;;;;;;;;;;;;;;1310:92;;;;;;;;;;;;;;;;;;;;;;;;;;;1436:6;1412:8;:20;1421:10;1412:20;;;;;;;;;;;;;;;;:30;;;;;;;;;;;1469:6;1452:8;:13;1461:3;1452:13;;;;;;;;;;;;;;;;:23;;;;;;;;;;;1511:3;1490:33;;1499:10;1490:33;;;1516:6;1490:33;;;;;;;;;;;;;;;1540:4;1533:11;;1106:445;;;;:::o;2530:160::-;2628:7;2658;:15;2666:6;2658:15;;;;;;;;;;;;;;;:25;2674:8;2658:25;;;;;;;;;;;;;;;;2651:32;;2530:160;;;;:::o;1158:402:0:-;1258:19;460:5:6;;;;;;;;;;;446:19;;:10;:19;;;425:117;;;;;;;;;;;;;;;;;;;;;;;;1280:18:0;1290:7;1280:9;:18::i;:::-;1258:40;;1321:11;1312:6;:20;1308:210;;;1362:50;1370:11;;1383:28;1391:11;1404:6;1383:7;:28::i;:::-;1362:7;:50::i;:::-;1348:11;:64;;;;1308:210;;;1457:50;1465:11;;1478:28;1486:6;1494:11;1478:7;:28::i;:::-;1457:7;:50::i;:::-;1443:11;:64;;;;1308:210;1547:6;1527:8;:17;1536:7;1527:17;;;;;;;;;;;;;;;:26;;;;1158:402;;;:::o;566:167:6:-;460:5;;;;;;;;;;;446:19;;:10;:19;;;425:117;;;;;;;;;;;;;;;;;;;;;;;;682:1;662:22;;:8;:22;;;;658:69;;;708:8;700:5;;:16;;;;;;;;;;;;;;;;;;658:69;566:167;:::o;570:166:7:-;650:7;673:6;686:1;682;:5;673:14;;709:1;704;:6;;697:14;;;;;;728:1;721:8;;570:166;;;;;:::o;418:146::-;498:7;533:1;528;:6;;521:14;;;;;;556:1;552;:5;545:12;;418:146;;;;:::o;5:118:-1:-;;72:46;110:6;97:20;72:46;;;63:55;;57:66;;;;;130:118;;197:46;235:6;222:20;197:46;;;188:55;;182:66;;;;;255:241;;359:2;347:9;338:7;334:23;330:32;327:2;;;375:1;372;365:12;327:2;410:1;427:53;472:7;463:6;452:9;448:22;427:53;;;417:63;;389:97;321:175;;;;;503:366;;;624:2;612:9;603:7;599:23;595:32;592:2;;;640:1;637;630:12;592:2;675:1;692:53;737:7;728:6;717:9;713:22;692:53;;;682:63;;654:97;782:2;800:53;845:7;836:6;825:9;821:22;800:53;;;790:63;;761:98;586:283;;;;;;876:491;;;;1014:2;1002:9;993:7;989:23;985:32;982:2;;;1030:1;1027;1020:12;982:2;1065:1;1082:53;1127:7;1118:6;1107:9;1103:22;1082:53;;;1072:63;;1044:97;1172:2;1190:53;1235:7;1226:6;1215:9;1211:22;1190:53;;;1180:63;;1151:98;1280:2;1298:53;1343:7;1334:6;1323:9;1319:22;1298:53;;;1288:63;;1259:98;976:391;;;;;;1374:366;;;1495:2;1483:9;1474:7;1470:23;1466:32;1463:2;;;1511:1;1508;1501:12;1463:2;1546:1;1563:53;1608:7;1599:6;1588:9;1584:22;1563:53;;;1553:63;;1525:97;1653:2;1671:53;1716:7;1707:6;1696:9;1692:22;1671:53;;;1661:63;;1632:98;1457:283;;;;;;1747:241;;1851:2;1839:9;1830:7;1826:23;1822:32;1819:2;;;1867:1;1864;1857:12;1819:2;1902:1;1919:53;1964:7;1955:6;1944:9;1940:22;1919:53;;;1909:63;;1881:97;1813:175;;;;;1995:110;2068:31;2093:5;2068:31;;;2063:3;2056:44;2050:55;;;2112:101;2179:28;2201:5;2179:28;;;2174:3;2167:41;2161:52;;;2220:292;;2318:35;2347:5;2318:35;;;2370:6;2365:3;2358:19;2382:63;2438:6;2431:4;2426:3;2422:14;2415:4;2408:5;2404:16;2382:63;;;2477:29;2499:6;2477:29;;;2470:4;2465:3;2461:14;2457:50;2450:57;;2298:214;;;;;;2520:397;;2675:2;2670:3;2663:15;2712:66;2707:2;2702:3;2698:12;2691:88;2813:66;2808:2;2803:3;2799:12;2792:88;2908:2;2903:3;2899:12;2892:19;;2656:261;;;;2926:397;;3081:2;3076:3;3069:15;3118:66;3113:2;3108:3;3104:12;3097:88;3219:66;3214:2;3209:3;3205:12;3198:88;3314:2;3309:3;3305:12;3298:19;;3062:261;;;;3331:110;3404:31;3429:5;3404:31;;;3399:3;3392:44;3386:55;;;3448:193;;3556:2;3545:9;3541:18;3533:26;;3570:61;3628:1;3617:9;3613:17;3604:6;3570:61;;;3527:114;;;;;3648:181;;3750:2;3739:9;3735:18;3727:26;;3764:55;3816:1;3805:9;3801:17;3792:6;3764:55;;;3721:108;;;;;3836:273;;3960:2;3949:9;3945:18;3937:26;;4010:9;4004:4;4000:20;3996:1;3985:9;3981:17;3974:47;4035:64;4094:4;4085:6;4035:64;;;4027:72;;3931:178;;;;;4116:387;;4297:2;4286:9;4282:18;4274:26;;4347:9;4341:4;4337:20;4333:1;4322:9;4318:17;4311:47;4372:121;4488:4;4372:121;;;4364:129;;4268:235;;;;4510:387;;4691:2;4680:9;4676:18;4668:26;;4741:9;4735:4;4731:20;4727:1;4716:9;4712:17;4705:47;4766:121;4882:4;4766:121;;;4758:129;;4662:235;;;;4904:193;;5012:2;5001:9;4997:18;4989:26;;5026:61;5084:1;5073:9;5069:17;5060:6;5026:61;;;4983:114;;;;;5104:88;;5181:5;5175:12;5165:22;;5159:33;;;;5199:128;;5279:42;5272:5;5268:54;5257:65;;5251:76;;;;5334:92;;5414:5;5407:13;5400:21;5389:32;;5383:43;;;;5433:79;;5502:5;5491:16;;5485:27;;;;5519:128;;5599:42;5592:5;5588:54;5577:65;;5571:76;;;;5654:79;;5723:5;5712:16;;5706:27;;;;5741:268;5806:1;5813:101;5827:6;5824:1;5821:13;5813:101;;;5903:1;5898:3;5894:11;5888:18;5884:1;5879:3;5875:11;5868:39;5849:2;5846:1;5842:10;5837:15;;5813:101;;;5929:6;5926:1;5923:13;5920:2;;;5994:1;5985:6;5980:3;5976:16;5969:27;5920:2;5790:219;;;;;6017:97;;6105:2;6101:7;6096:2;6089:5;6085:14;6081:28;6071:38;;6065:49;;;" } } @@ -344,19 +344,19 @@ } }, "sourceCodes": { - "current/test/DummyERC20Token/DummyERC20Token.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.23;\npragma experimental ABIEncoderV2;\n\nimport \"../Mintable/Mintable.sol\";\nimport \"../../utils/Ownable/Ownable.sol\";\n\ncontract DummyERC20Token is Mintable, Ownable {\n string public name;\n string public symbol;\n uint256 public decimals;\n\n constructor (\n string _name,\n string _symbol,\n uint256 _decimals,\n uint256 _totalSupply)\n public\n {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n totalSupply = _totalSupply;\n balances[msg.sender] = _totalSupply;\n }\n\n function setBalance(address _target, uint256 _value)\n public\n onlyOwner\n {\n uint256 currBalance = balanceOf(_target);\n if (_value < currBalance) {\n totalSupply = safeSub(totalSupply, safeSub(currBalance, _value));\n } else {\n totalSupply = safeAdd(totalSupply, safeSub(_value, currBalance));\n }\n balances[_target] = _value;\n }\n}\n", - "current/test/Mintable/Mintable.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.23;\npragma experimental ABIEncoderV2;\n\nimport \"../../tokens/UnlimitedAllowanceToken/UnlimitedAllowanceToken.sol\";\nimport \"../../utils/SafeMath/SafeMath.sol\";\n\n/*\n * Mintable\n * Base contract that creates a mintable UnlimitedAllowanceToken\n */\ncontract Mintable is UnlimitedAllowanceToken, SafeMath {\n function mint(uint256 _value)\n public\n {\n require(\n _value <= 100000000000000000000,\n \"Minting more than 100000000000000000000 is not allowed.\"\n );\n balances[msg.sender] = safeAdd(_value, balances[msg.sender]);\n totalSupply = safeAdd(totalSupply, _value);\n }\n}\n", - "current/tokens/ERC20Token/ERC20Token.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.23;\npragma experimental ABIEncoderV2;\n\nimport \"./IERC20Token.sol\";\n\ncontract ERC20Token is IERC20Token {\n\n string constant INSUFFICIENT_BALANCE = \"Insufficient balance to complete transfer.\";\n string constant INSUFFICIENT_ALLOWANCE = \"Insufficient allowance to complete transfer.\";\n string constant OVERFLOW = \"Transfer would result in an overflow.\";\n\n mapping (address => uint256) balances;\n mapping (address => mapping (address => uint256)) allowed;\n\n uint256 public totalSupply;\n\n function transfer(address _to, uint256 _value)\n public\n returns (bool)\n {\n require(\n balances[msg.sender] >= _value,\n INSUFFICIENT_BALANCE\n );\n require(\n balances[_to] + _value >= balances[_to],\n OVERFLOW\n );\n balances[msg.sender] -= _value;\n balances[_to] += _value;\n emit Transfer(msg.sender, _to, _value);\n return true;\n }\n\n function transferFrom(address _from, address _to, uint256 _value)\n public\n returns (bool)\n {\n require(\n balances[_from] >= _value,\n INSUFFICIENT_BALANCE\n );\n require(\n allowed[_from][msg.sender] >= _value,\n INSUFFICIENT_ALLOWANCE\n );\n require(\n balances[_to] + _value >= balances[_to],\n OVERFLOW\n );\n balances[_to] += _value;\n balances[_from] -= _value;\n allowed[_from][msg.sender] -= _value;\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function approve(address _spender, uint256 _value)\n public\n returns (bool)\n {\n allowed[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function balanceOf(address _owner)\n public view\n returns (uint256)\n {\n return balances[_owner];\n }\n\n function allowance(address _owner, address _spender)\n public\n view\n returns (uint256)\n {\n return allowed[_owner][_spender];\n }\n}\n\n", - "current/tokens/ERC20Token/IERC20Token.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.23;\npragma experimental ABIEncoderV2;\n\ncontract IERC20Token {\n\n /// @notice send `value` token to `to` from `msg.sender`\n /// @param _to The address of the recipient\n /// @param _value The amount of token to be transferred\n /// @return Whether the transfer was successful or not\n function transfer(address _to, uint256 _value)\n public\n returns (bool);\n\n /// @notice send `value` token to `to` from `from` on the condition it is approved by `from`\n /// @param _from The address of the sender\n /// @param _to The address of the recipient\n /// @param _value The amount of token to be transferred\n /// @return Whether the transfer was successful or not\n function transferFrom(address _from, address _to, uint256 _value)\n public\n returns (bool);\n \n /// @notice `msg.sender` approves `_spender` to spend `_value` tokens\n /// @param _spender The address of the account able to transfer the tokens\n /// @param _value The amount of wei to be approved for transfer\n /// @return Whether the approval was successful or not\n function approve(address _spender, uint256 _value)\n public\n returns (bool);\n\n /// @param _owner The address from which the balance will be retrieved\n /// @return The balance\n function balanceOf(address _owner)\n public view\n returns (uint256);\n\n /// @param _owner The address of the account owning tokens\n /// @param _spender The address of the account able to transfer the tokens\n /// @return Amount of remaining tokens allowed to spent\n function allowance(address _owner, address _spender)\n public view\n returns (uint256);\n\n event Transfer(\n address indexed _from,\n address indexed _to,\n uint256 _value\n );\n \n event Approval(\n address indexed _owner,\n address indexed _spender,\n uint256 _value\n );\n}\n", - "current/tokens/UnlimitedAllowanceToken/UnlimitedAllowanceToken.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.23;\npragma experimental ABIEncoderV2;\n\nimport \"../ERC20Token/ERC20Token.sol\";\n\ncontract UnlimitedAllowanceToken is ERC20Token {\n\n uint256 constant MAX_UINT = 2**256 - 1;\n\n /// @dev ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance. See https://github.com/ethereum/EIPs/issues/717\n /// @param _from Address to transfer from.\n /// @param _to Address to transfer to.\n /// @param _value Amount to transfer.\n /// @return Success of transfer.\n function transferFrom(address _from, address _to, uint256 _value)\n public\n returns (bool)\n {\n uint256 allowance = allowed[_from][msg.sender];\n require(\n balances[_from] >= _value,\n INSUFFICIENT_BALANCE\n );\n require(\n allowance >= _value,\n INSUFFICIENT_ALLOWANCE\n );\n require(\n balances[_to] + _value >= balances[_to],\n OVERFLOW\n );\n balances[_to] += _value;\n balances[_from] -= _value;\n if (allowance < MAX_UINT) {\n allowed[_from][msg.sender] -= _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n}\n", - "current/utils/Ownable/IOwnable.sol": "pragma solidity ^0.4.23;\npragma experimental ABIEncoderV2;\n\n/*\n * Ownable\n *\n * Base contract with an owner.\n * Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner.\n */\n\ncontract IOwnable {\n function transferOwnership(address newOwner)\n public;\n}\n", - "current/utils/Ownable/Ownable.sol": "pragma solidity ^0.4.23;\npragma experimental ABIEncoderV2;\n\n/*\n * Ownable\n *\n * Base contract with an owner.\n * Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner.\n */\n\nimport \"./IOwnable.sol\";\n\ncontract Ownable is IOwnable {\n address public owner;\n\n constructor ()\n public\n {\n owner = msg.sender;\n }\n\n modifier onlyOwner() {\n require(\n msg.sender == owner,\n \"Only contract owner is allowed to call this method.\"\n );\n _;\n }\n\n function transferOwnership(address newOwner)\n public\n onlyOwner\n {\n if (newOwner != address(0)) {\n owner = newOwner;\n }\n }\n}\n", - "current/utils/SafeMath/SafeMath.sol": "pragma solidity ^0.4.23;\npragma experimental ABIEncoderV2;\n\ncontract SafeMath {\n function safeMul(uint a, uint b)\n internal\n pure\n returns (uint256)\n {\n uint c = a * b;\n assert(a == 0 || c / a == b);\n return c;\n }\n\n function safeDiv(uint a, uint b)\n internal\n pure\n returns (uint256)\n {\n uint c = a / b;\n return c;\n }\n\n function safeSub(uint a, uint b)\n internal\n pure\n returns (uint256)\n {\n assert(b <= a);\n return a - b;\n }\n\n function safeAdd(uint a, uint b)\n internal\n pure\n returns (uint256)\n {\n uint c = a + b;\n assert(c >= a);\n return c;\n }\n\n function max64(uint64 a, uint64 b)\n internal\n pure\n returns (uint256)\n {\n return a >= b ? a : b;\n }\n\n function min64(uint64 a, uint64 b)\n internal\n pure\n returns (uint256)\n {\n return a < b ? a : b;\n }\n\n function max256(uint256 a, uint256 b)\n internal\n pure\n returns (uint256)\n {\n return a >= b ? a : b;\n }\n\n function min256(uint256 a, uint256 b)\n internal\n pure\n returns (uint256)\n {\n return a < b ? a : b;\n }\n}\n" + "current/test/DummyERC20Token/DummyERC20Token.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.24;\npragma experimental ABIEncoderV2;\n\nimport \"../Mintable/Mintable.sol\";\nimport \"../../utils/Ownable/Ownable.sol\";\n\ncontract DummyERC20Token is Mintable, Ownable {\n string public name;\n string public symbol;\n uint256 public decimals;\n\n constructor (\n string _name,\n string _symbol,\n uint256 _decimals,\n uint256 _totalSupply)\n public\n {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n totalSupply = _totalSupply;\n balances[msg.sender] = _totalSupply;\n }\n\n function setBalance(address _target, uint256 _value)\n public\n onlyOwner\n {\n uint256 currBalance = balanceOf(_target);\n if (_value < currBalance) {\n totalSupply = safeSub(totalSupply, safeSub(currBalance, _value));\n } else {\n totalSupply = safeAdd(totalSupply, safeSub(_value, currBalance));\n }\n balances[_target] = _value;\n }\n}\n", + "current/test/Mintable/Mintable.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.24;\npragma experimental ABIEncoderV2;\n\nimport \"../../tokens/UnlimitedAllowanceToken/UnlimitedAllowanceToken.sol\";\nimport \"../../utils/SafeMath/SafeMath.sol\";\n\n/*\n * Mintable\n * Base contract that creates a mintable UnlimitedAllowanceToken\n */\ncontract Mintable is UnlimitedAllowanceToken, SafeMath {\n function mint(uint256 _value)\n public\n {\n require(\n _value <= 100000000000000000000,\n \"Minting more than 100000000000000000000 is not allowed.\"\n );\n balances[msg.sender] = safeAdd(_value, balances[msg.sender]);\n totalSupply = safeAdd(totalSupply, _value);\n }\n}\n", + "current/tokens/ERC20Token/ERC20Token.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.24;\npragma experimental ABIEncoderV2;\n\nimport \"./IERC20Token.sol\";\n\ncontract ERC20Token is IERC20Token {\n\n string constant INSUFFICIENT_BALANCE = \"Insufficient balance to complete transfer.\";\n string constant INSUFFICIENT_ALLOWANCE = \"Insufficient allowance to complete transfer.\";\n string constant OVERFLOW = \"Transfer would result in an overflow.\";\n\n mapping (address => uint256) balances;\n mapping (address => mapping (address => uint256)) allowed;\n\n uint256 public totalSupply;\n\n function transfer(address _to, uint256 _value)\n public\n returns (bool)\n {\n require(\n balances[msg.sender] >= _value,\n INSUFFICIENT_BALANCE\n );\n require(\n balances[_to] + _value >= balances[_to],\n OVERFLOW\n );\n balances[msg.sender] -= _value;\n balances[_to] += _value;\n emit Transfer(msg.sender, _to, _value);\n return true;\n }\n\n function transferFrom(address _from, address _to, uint256 _value)\n public\n returns (bool)\n {\n require(\n balances[_from] >= _value,\n INSUFFICIENT_BALANCE\n );\n require(\n allowed[_from][msg.sender] >= _value,\n INSUFFICIENT_ALLOWANCE\n );\n require(\n balances[_to] + _value >= balances[_to],\n OVERFLOW\n );\n balances[_to] += _value;\n balances[_from] -= _value;\n allowed[_from][msg.sender] -= _value;\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function approve(address _spender, uint256 _value)\n public\n returns (bool)\n {\n allowed[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n function balanceOf(address _owner)\n public view\n returns (uint256)\n {\n return balances[_owner];\n }\n\n function allowance(address _owner, address _spender)\n public\n view\n returns (uint256)\n {\n return allowed[_owner][_spender];\n }\n}\n\n", + "current/tokens/ERC20Token/IERC20Token.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.24;\npragma experimental ABIEncoderV2;\n\ncontract IERC20Token {\n\n /// @notice send `value` token to `to` from `msg.sender`\n /// @param _to The address of the recipient\n /// @param _value The amount of token to be transferred\n /// @return Whether the transfer was successful or not\n function transfer(address _to, uint256 _value)\n public\n returns (bool);\n\n /// @notice send `value` token to `to` from `from` on the condition it is approved by `from`\n /// @param _from The address of the sender\n /// @param _to The address of the recipient\n /// @param _value The amount of token to be transferred\n /// @return Whether the transfer was successful or not\n function transferFrom(address _from, address _to, uint256 _value)\n public\n returns (bool);\n \n /// @notice `msg.sender` approves `_spender` to spend `_value` tokens\n /// @param _spender The address of the account able to transfer the tokens\n /// @param _value The amount of wei to be approved for transfer\n /// @return Whether the approval was successful or not\n function approve(address _spender, uint256 _value)\n public\n returns (bool);\n\n /// @param _owner The address from which the balance will be retrieved\n /// @return The balance\n function balanceOf(address _owner)\n public view\n returns (uint256);\n\n /// @param _owner The address of the account owning tokens\n /// @param _spender The address of the account able to transfer the tokens\n /// @return Amount of remaining tokens allowed to spent\n function allowance(address _owner, address _spender)\n public view\n returns (uint256);\n\n event Transfer(\n address indexed _from,\n address indexed _to,\n uint256 _value\n );\n \n event Approval(\n address indexed _owner,\n address indexed _spender,\n uint256 _value\n );\n}\n", + "current/tokens/UnlimitedAllowanceToken/UnlimitedAllowanceToken.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.24;\npragma experimental ABIEncoderV2;\n\nimport \"../ERC20Token/ERC20Token.sol\";\n\ncontract UnlimitedAllowanceToken is ERC20Token {\n\n uint256 constant MAX_UINT = 2**256 - 1;\n\n /// @dev ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance. See https://github.com/ethereum/EIPs/issues/717\n /// @param _from Address to transfer from.\n /// @param _to Address to transfer to.\n /// @param _value Amount to transfer.\n /// @return Success of transfer.\n function transferFrom(address _from, address _to, uint256 _value)\n public\n returns (bool)\n {\n uint256 allowance = allowed[_from][msg.sender];\n require(\n balances[_from] >= _value,\n INSUFFICIENT_BALANCE\n );\n require(\n allowance >= _value,\n INSUFFICIENT_ALLOWANCE\n );\n require(\n balances[_to] + _value >= balances[_to],\n OVERFLOW\n );\n balances[_to] += _value;\n balances[_from] -= _value;\n if (allowance < MAX_UINT) {\n allowed[_from][msg.sender] -= _value;\n }\n emit Transfer(_from, _to, _value);\n return true;\n }\n}\n", + "current/utils/Ownable/IOwnable.sol": "pragma solidity ^0.4.24;\npragma experimental ABIEncoderV2;\n\n/*\n * Ownable\n *\n * Base contract with an owner.\n * Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner.\n */\n\ncontract IOwnable {\n function transferOwnership(address newOwner)\n public;\n}\n", + "current/utils/Ownable/Ownable.sol": "pragma solidity ^0.4.24;\npragma experimental ABIEncoderV2;\n\n/*\n * Ownable\n *\n * Base contract with an owner.\n * Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner.\n */\n\nimport \"./IOwnable.sol\";\n\ncontract Ownable is IOwnable {\n address public owner;\n\n constructor ()\n public\n {\n owner = msg.sender;\n }\n\n modifier onlyOwner() {\n require(\n msg.sender == owner,\n \"Only contract owner is allowed to call this method.\"\n );\n _;\n }\n\n function transferOwnership(address newOwner)\n public\n onlyOwner\n {\n if (newOwner != address(0)) {\n owner = newOwner;\n }\n }\n}\n", + "current/utils/SafeMath/SafeMath.sol": "pragma solidity ^0.4.24;\npragma experimental ABIEncoderV2;\n\ncontract SafeMath {\n function safeMul(uint a, uint b)\n internal\n pure\n returns (uint256)\n {\n uint c = a * b;\n assert(a == 0 || c / a == b);\n return c;\n }\n\n function safeDiv(uint a, uint b)\n internal\n pure\n returns (uint256)\n {\n uint c = a / b;\n return c;\n }\n\n function safeSub(uint a, uint b)\n internal\n pure\n returns (uint256)\n {\n assert(b <= a);\n return a - b;\n }\n\n function safeAdd(uint a, uint b)\n internal\n pure\n returns (uint256)\n {\n uint c = a + b;\n assert(c >= a);\n return c;\n }\n\n function max64(uint64 a, uint64 b)\n internal\n pure\n returns (uint256)\n {\n return a >= b ? a : b;\n }\n\n function min64(uint64 a, uint64 b)\n internal\n pure\n returns (uint256)\n {\n return a < b ? a : b;\n }\n\n function max256(uint256 a, uint256 b)\n internal\n pure\n returns (uint256)\n {\n return a >= b ? a : b;\n }\n\n function min256(uint256 a, uint256 b)\n internal\n pure\n returns (uint256)\n {\n return a < b ? a : b;\n }\n}\n" }, - "sourceTreeHashHex": "0x72097ec50fe2cc41973383063c508ca0864d63f9cd33cd7f21e29639c07efa15", + "sourceTreeHashHex": "0x4830433daa189b8c48beea455c8f20379bb7b5a33b1607b73e3938501a24bd2b", "compiler": { "name": "solc", - "version": "0.4.23", + "version": "0.4.24", "settings": { "outputSelection": { "*": { diff --git a/packages/migrations/package.json b/packages/migrations/package.json index ab5204d86..08f7aa6b2 100644 --- a/packages/migrations/package.json +++ b/packages/migrations/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/migrations", - "version": "0.0.5", + "version": "0.0.6", "engines": { "node": ">=6.12" }, @@ -9,10 +9,10 @@ "types": "lib/index.d.ts", "scripts": { "watch": "tsc -w", - "prebuild": "run-s clean compile copy_artifacts generate_contract_wrappers", + "prebuild": "run-s clean copy_artifacts generate_contract_wrappers", "copy_artifacts": "copyfiles 'artifacts/1.0.0/**/*' ./lib", "build": "tsc", - "clean": "shx rm -rf lib", + "clean": "shx rm -rf lib src/contract_wrappers", "lint": "tslint --project .", "migrate": "run-s build compile script:migrate", "script:migrate": "node ./lib/migrate.js", @@ -25,10 +25,10 @@ }, "license": "Apache-2.0", "devDependencies": { - "@0xproject/abi-gen": "^0.2.13", - "@0xproject/dev-utils": "^0.4.1", - "@0xproject/tslint-config": "^0.4.17", - "@0xproject/types": "^0.6.3", + "@0xproject/abi-gen": "^0.3.0", + "@0xproject/dev-utils": "^0.4.2", + "@0xproject/tslint-config": "^0.4.18", + "@0xproject/types": "^0.7.0", "make-promises-safe": "^1.1.0", "npm-run-all": "^4.1.2", "shx": "^0.2.2", @@ -36,11 +36,11 @@ "typescript": "2.7.1" }, "dependencies": { - "@0xproject/base-contract": "^0.3.1", - "@0xproject/sol-compiler": "^0.4.3", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", - "@0xproject/web3-wrapper": "^0.6.3", + "@0xproject/base-contract": "^0.3.2", + "@0xproject/sol-compiler": "^0.5.0", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", + "@0xproject/web3-wrapper": "^0.6.4", "ethers": "^3.0.15", "lodash": "^4.17.4" }, diff --git a/packages/migrations/src/artifacts.ts b/packages/migrations/src/artifacts.ts index 61b0c3085..acc267256 100644 --- a/packages/migrations/src/artifacts.ts +++ b/packages/migrations/src/artifacts.ts @@ -5,7 +5,7 @@ import * as Exchange from '../artifacts/1.0.0/Exchange_v1.json'; import * as MultiSigWalletWithTimeLock from '../artifacts/1.0.0/MultiSigWalletWithTimeLock.json'; import * as MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress from '../artifacts/1.0.0/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json'; import * as TokenRegistry from '../artifacts/1.0.0/TokenRegistry.json'; -import * as TokenTransferProxy from '../artifacts/1.0.0/TokenTransferProxy.json'; +import * as TokenTransferProxy from '../artifacts/1.0.0/TokenTransferProxy_v1.json'; import * as EtherToken from '../artifacts/1.0.0/WETH9.json'; import * as ZRX from '../artifacts/1.0.0/ZRXToken.json'; diff --git a/packages/migrations/src/migrate.ts b/packages/migrations/src/migrate.ts index b00ba698f..1230f376e 100644 --- a/packages/migrations/src/migrate.ts +++ b/packages/migrations/src/migrate.ts @@ -11,8 +11,7 @@ import { runMigrationsAsync } from './migration'; from: devConstants.TESTRPC_FIRST_ADDRESS, }; const providerConfigs = { shouldUseInProcessGanache: false }; - const web3 = web3Factory.create(providerConfigs); - const provider = web3.currentProvider; + const provider: Provider = web3Factory.getRpcProvider(providerConfigs); const artifactsDir = 'artifacts/1.0.0'; await runMigrationsAsync(provider, artifactsDir, txDefaults); process.exit(0); diff --git a/packages/migrations/src/migration.ts b/packages/migrations/src/migration.ts index 57ac311d7..e29414a57 100644 --- a/packages/migrations/src/migration.ts +++ b/packages/migrations/src/migration.ts @@ -80,11 +80,12 @@ export const runMigrationsAsync = async (provider: Provider, artifactsDir: strin tokenInfo[0].swarmHash, { from: owner }, ); + const decimals = 18; await tokenReg.addToken.sendTransactionAsync( zrxToken.address, '0x Protocol Token', 'ZRX', - 18, + decimals, NULL_BYTES, NULL_BYTES, { @@ -96,7 +97,7 @@ export const runMigrationsAsync = async (provider: Provider, artifactsDir: strin etherToken.address, 'Ether Token', 'WETH', - 18, + decimals, NULL_BYTES, NULL_BYTES, { diff --git a/packages/monorepo-scripts/CHANGELOG.json b/packages/monorepo-scripts/CHANGELOG.json index 10fe8acb1..58d946cd6 100644 --- a/packages/monorepo-scripts/CHANGELOG.json +++ b/packages/monorepo-scripts/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1527008794, + "version": "0.1.20", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1525428773, "version": "0.1.19", "changes": [ diff --git a/packages/monorepo-scripts/CHANGELOG.md b/packages/monorepo-scripts/CHANGELOG.md index df70792b8..db5afd5af 100644 --- a/packages/monorepo-scripts/CHANGELOG.md +++ b/packages/monorepo-scripts/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.1.20 - _May 22, 2018_ + + * Dependencies updated + ## v0.1.19 - _May 4, 2018_ * Dependencies updated diff --git a/packages/monorepo-scripts/package.json b/packages/monorepo-scripts/package.json index 4fa9497b9..02a8e4a42 100644 --- a/packages/monorepo-scripts/package.json +++ b/packages/monorepo-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/monorepo-scripts", - "version": "0.1.19", + "version": "0.1.20", "engines": { "node": ">=6.12" }, diff --git a/packages/monorepo-scripts/src/postpublish_utils.ts b/packages/monorepo-scripts/src/postpublish_utils.ts index 22614f01b..f5785343d 100644 --- a/packages/monorepo-scripts/src/postpublish_utils.ts +++ b/packages/monorepo-scripts/src/postpublish_utils.ts @@ -158,6 +158,7 @@ export const postpublishUtils = { // HACK: tsconfig.json needs wildcard directory endings as `/**/*` // but TypeDoc needs it as `/**` in order to pick up files at the root if (_.endsWith(includePath, '/**/*')) { + // tslint:disable-next-line:custom-no-magic-numbers includePath = includePath.slice(0, -2); } return includePath; diff --git a/packages/monorepo-scripts/src/publish.ts b/packages/monorepo-scripts/src/publish.ts index 5c26475c9..73106821a 100644 --- a/packages/monorepo-scripts/src/publish.ts +++ b/packages/monorepo-scripts/src/publish.ts @@ -285,8 +285,8 @@ function shouldAddNewChangelogEntry(currentVersion: string, changelogs: Changelo return true; } const lastEntry = changelogs[0]; - const lastEntryCurrentVersion = lastEntry.version === currentVersion; - return lastEntryCurrentVersion; + const isLastEntryCurrentVersion = lastEntry.version === currentVersion; + return isLastEntryCurrentVersion; } function generateChangelogMd(changelogs: Changelog[]): string { diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index 9399379fa..1bdb25347 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -3,13 +3,11 @@ "version": "0.0.5", "changes": [ { - "note": "Add formatters package for converting signedOrder to orderAddresses & orderValues", - "note": "Add RemainingFillableCalculator to calculate the remaining fillable amount of an order", - "note": "Add AbstractBalanceAndProxyAllowanceFetcher and AbstractOrderFilledCancelledFetcher", "note": "Add orderStateUtils, a module for computing order state needed to decide if an order is still valid" } - ] + ], + "timestamp": 1527008794 }, { "timestamp": 1525477860, diff --git a/packages/order-utils/CHANGELOG.md b/packages/order-utils/CHANGELOG.md index d0bb706aa..5b10c13bc 100644 --- a/packages/order-utils/CHANGELOG.md +++ b/packages/order-utils/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.0.4 - _May 5, 2018_ +## v0.0.5 - _May 22, 2018_ + + * Add orderStateUtils, a module for computing order state needed to decide if an order is still valid + +## v0.0.4 - _May 4, 2018_ * Dependencies updated diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json index 63caaec34..117b57f45 100644 --- a/packages/order-utils/package.json +++ b/packages/order-utils/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/order-utils", - "version": "0.0.4", + "version": "0.0.5", "engines": { "node": ">=6.12" }, @@ -43,9 +43,9 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/order-utils/README.md", "devDependencies": { - "@0xproject/dev-utils": "^0.4.1", - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/dev-utils": "^0.4.2", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", "@types/lodash": "4.14.104", "chai": "^4.0.1", "chai-as-promised": "^7.1.0", @@ -62,12 +62,12 @@ "typescript": "2.7.1" }, "dependencies": { - "@0xproject/assert": "^0.2.9", - "@0xproject/json-schemas": "^0.7.23", - "@0xproject/types": "^0.6.3", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", - "@0xproject/web3-wrapper": "^0.6.3", + "@0xproject/assert": "^0.2.10", + "@0xproject/json-schemas": "^0.7.24", + "@0xproject/types": "^0.7.0", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", + "@0xproject/web3-wrapper": "^0.6.4", "@types/node": "^8.0.53", "bn.js": "^4.11.8", "ethereumjs-abi": "^0.6.4", diff --git a/packages/order-utils/src/order_hash.ts b/packages/order-utils/src/order_hash.ts index 1cde72a73..108344a04 100644 --- a/packages/order-utils/src/order_hash.ts +++ b/packages/order-utils/src/order_hash.ts @@ -17,7 +17,8 @@ const INVALID_TAKER_FORMAT = 'instance.taker is not of a type(s) string'; * We do not use BN anywhere else in the codebase. */ function bigNumberToBN(value: BigNumber): BN { - return new BN(value.toString(), 10); + const base = 10; + return new BN(value.toString(), base); } /** diff --git a/packages/order-utils/src/signature_utils.ts b/packages/order-utils/src/signature_utils.ts index b511573a8..ebd636b20 100644 --- a/packages/order-utils/src/signature_utils.ts +++ b/packages/order-utils/src/signature_utils.ts @@ -72,6 +72,7 @@ export async function signOrderHashAsync( // v + r + s OR r + s + v, and different clients (even different versions of the same client) // return the signature params in different orders. In order to support all client implementations, // we parse the signature in both ways, and evaluate if either one is a valid signature. + // tslint:disable-next-line:custom-no-magic-numbers const validVParamValues = [27, 28]; const ecSignatureVRS = parseSignatureHexAsVRS(signature); if (_.includes(validVParamValues, ecSignatureVRS.v)) { @@ -95,11 +96,19 @@ export async function signOrderHashAsync( function parseSignatureHexAsVRS(signatureHex: string): ECSignature { const signatureBuffer = ethUtil.toBuffer(signatureHex); let v = signatureBuffer[0]; - if (v < 27) { - v += 27; + // HACK: Sometimes v is returned as [0, 1] and sometimes as [27, 28] + // If it is returned as [0, 1], add 27 to both so it becomes [27, 28] + const lowestValidV = 27; + const isProperlyFormattedV = v >= lowestValidV; + if (!isProperlyFormattedV) { + v += lowestValidV; } - const r = signatureBuffer.slice(1, 33); - const s = signatureBuffer.slice(33, 65); + // signatureBuffer contains vrs + const vEndIndex = 1; + const rsIndex = 33; + const r = signatureBuffer.slice(vEndIndex, rsIndex); + const sEndIndex = 65; + const s = signatureBuffer.slice(rsIndex, sEndIndex); const ecSignature: ECSignature = { v, r: ethUtil.bufferToHex(r), diff --git a/packages/order-utils/test/signature_utils_test.ts b/packages/order-utils/test/signature_utils_test.ts index 4b4de9217..e24fa0ce5 100644 --- a/packages/order-utils/test/signature_utils_test.ts +++ b/packages/order-utils/test/signature_utils_test.ts @@ -47,12 +47,13 @@ describe('Signature utils', () => { }); describe('#generateSalt', () => { it('generates different salts', () => { - const equal = generatePseudoRandomSalt().eq(generatePseudoRandomSalt()); - expect(equal).to.be.false(); + const isEqual = generatePseudoRandomSalt().eq(generatePseudoRandomSalt()); + expect(isEqual).to.be.false(); }); it('generates salt in range [0..2^256)', () => { const salt = generatePseudoRandomSalt(); expect(salt.greaterThanOrEqualTo(0)).to.be.true(); + // tslint:disable-next-line:custom-no-magic-numbers const twoPow256 = new BigNumber(2).pow(256); expect(salt.lessThan(twoPow256)).to.be.true(); }); @@ -67,7 +68,8 @@ describe('Signature utils', () => { expect(isValid).to.be.false(); }); it('returns true if order hash is correct', () => { - const isValid = isValidOrderHash('0x' + Array(65).join('0')); + const orderHashLength = 65; + const isValid = isValidOrderHash('0x' + Array(orderHashLength).join('0')); expect(isValid).to.be.true(); }); }); @@ -111,10 +113,12 @@ describe('Signature utils', () => { if (payload.method === 'eth_sign') { const [address, message] = payload.params; const signature = await web3Wrapper.signMessageAsync(address, message); + // tslint:disable-next-line:custom-no-magic-numbers + const rsvHex = `0x${signature.substr(130)}${signature.substr(2, 128)}`; callback(null, { id: 42, jsonrpc: '2.0', - result: `0x${signature.substr(130)}${signature.substr(2, 128)}`, + result: rsvHex, }); } else { callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] }); diff --git a/packages/order-utils/test/utils/web3_wrapper.ts b/packages/order-utils/test/utils/web3_wrapper.ts index b0ccfa546..71a0dc1c2 100644 --- a/packages/order-utils/test/utils/web3_wrapper.ts +++ b/packages/order-utils/test/utils/web3_wrapper.ts @@ -2,8 +2,7 @@ import { devConstants, web3Factory } from '@0xproject/dev-utils'; import { Provider } from '@0xproject/types'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; -const web3 = web3Factory.create({ shouldUseInProcessGanache: true }); -const provider: Provider = web3.currentProvider; -const web3Wrapper = new Web3Wrapper(web3.currentProvider); +const provider: Provider = web3Factory.getRpcProvider({ shouldUseInProcessGanache: true }); +const web3Wrapper = new Web3Wrapper(provider); export { provider, web3Wrapper }; diff --git a/packages/order-watcher/CHANGELOG.json b/packages/order-watcher/CHANGELOG.json index 87f40bcb7..dde78445a 100644 --- a/packages/order-watcher/CHANGELOG.json +++ b/packages/order-watcher/CHANGELOG.json @@ -1,5 +1,15 @@ [ { + "timestamp": 1527008794, + "version": "0.0.2", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { + "timestamp": 1527008794, "version": "0.0.1", "changes": [ { diff --git a/packages/order-watcher/CHANGELOG.md b/packages/order-watcher/CHANGELOG.md new file mode 100644 index 000000000..999d62f44 --- /dev/null +++ b/packages/order-watcher/CHANGELOG.md @@ -0,0 +1,14 @@ +<!-- +This file is auto-generated using the monorepo-scripts package. Don't edit directly. +Edit the package's CHANGELOG.json file only. +--> + +CHANGELOG + +## v0.0.2 - _May 22, 2018_ + + * Dependencies updated + +## v0.0.1 - _May 22, 2018_ + + * Moved OrderWatcher out of 0x.js package (#579) diff --git a/packages/order-watcher/package.json b/packages/order-watcher/package.json index d65d3f175..c84858bfd 100644 --- a/packages/order-watcher/package.json +++ b/packages/order-watcher/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/order-watcher", - "version": "0.0.1", + "version": "0.0.2", "description": "An order watcher daemon that watches for order validity", "keywords": [ "0x", @@ -28,7 +28,7 @@ }, "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", + "contracts": "Exchange DummyToken ZRXToken Token WETH9 TokenTransferProxy_v1 MultiSigWallet MultiSigWalletWithTimeLock MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress MaliciousToken TokenRegistry Arbitrage EtherDelta AccountLevels", "postpublish": { "assets": [ "packages/order-watcher/_bundles/index.js", @@ -45,12 +45,12 @@ "node": ">=6.0.0" }, "devDependencies": { - "@0xproject/abi-gen": "^0.2.13", - "@0xproject/dev-utils": "^0.4.1", - "@0xproject/migrations": "^0.0.5", - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/sol-compiler": "^0.4.3", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/abi-gen": "^0.3.0", + "@0xproject/dev-utils": "^0.4.2", + "@0xproject/migrations": "^0.0.6", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/sol-compiler": "^0.5.0", + "@0xproject/tslint-config": "^0.4.18", "@types/bintrees": "^1.0.2", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", @@ -76,16 +76,16 @@ "typescript": "2.7.1" }, "dependencies": { - "@0xproject/assert": "^0.2.9", - "@0xproject/base-contract": "^0.3.1", - "@0xproject/contract-wrappers": "^0.0.1", - "@0xproject/fill-scenarios": "^0.0.1", - "@0xproject/json-schemas": "^0.7.23", - "@0xproject/order-utils": "^0.0.4", - "@0xproject/types": "^0.6.3", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", - "@0xproject/web3-wrapper": "^0.6.3", + "@0xproject/assert": "^0.2.10", + "@0xproject/base-contract": "^0.3.2", + "@0xproject/contract-wrappers": "^0.0.2", + "@0xproject/fill-scenarios": "^0.0.2", + "@0xproject/json-schemas": "^0.7.24", + "@0xproject/order-utils": "^0.0.5", + "@0xproject/types": "^0.7.0", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", + "@0xproject/web3-wrapper": "^0.6.4", "bintrees": "^1.0.2", "ethers": "^3.0.15", "lodash": "^4.17.4" diff --git a/packages/order-watcher/src/order_watcher/order_watcher.ts b/packages/order-watcher/src/order_watcher/order_watcher.ts index 3c93d6293..29936a066 100644 --- a/packages/order-watcher/src/order_watcher/order_watcher.ts +++ b/packages/order-watcher/src/order_watcher/order_watcher.ts @@ -60,6 +60,7 @@ interface OrderStateByOrderHash { [orderHash: string]: OrderState; } +// tslint:disable-next-line:custom-no-magic-numbers const DEFAULT_CLEANUP_JOB_INTERVAL_MS = 1000 * 60 * 60; // 1h /** @@ -130,7 +131,8 @@ export class OrderWatcher { assert.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker); this._orderByOrderHash[orderHash] = signedOrder; this._addToDependentOrderHashes(signedOrder, orderHash); - const expirationUnixTimestampMs = signedOrder.expirationUnixTimestampSec.times(1000); + const milisecondsInASecond = 1000; + const expirationUnixTimestampMs = signedOrder.expirationUnixTimestampSec.times(milisecondsInASecond); this._expirationWatcher.addOrder(orderHash, expirationUnixTimestampMs); } /** diff --git a/packages/order-watcher/src/utils/utils.ts b/packages/order-watcher/src/utils/utils.ts index af1125632..d34f6b99f 100644 --- a/packages/order-watcher/src/utils/utils.ts +++ b/packages/order-watcher/src/utils/utils.ts @@ -5,7 +5,8 @@ export const utils = { return new Error(`Unexpected switch value: ${value} encountered for ${name}`); }, getCurrentUnixTimestampSec(): BigNumber { - return new BigNumber(Date.now() / 1000).round(); + const milisecondsInASecond = 1000; + return new BigNumber(Date.now() / milisecondsInASecond).round(); }, getCurrentUnixTimestampMs(): BigNumber { return new BigNumber(Date.now()); diff --git a/packages/order-watcher/test/expiration_watcher_test.ts b/packages/order-watcher/test/expiration_watcher_test.ts index 8b006f58a..ef15bf006 100644 --- a/packages/order-watcher/test/expiration_watcher_test.ts +++ b/packages/order-watcher/test/expiration_watcher_test.ts @@ -22,6 +22,7 @@ import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); +const MILISECONDS_IN_SECOND = 1000; describe('ExpirationWatcher', () => { let contractWrappers: ContractWrappers; @@ -84,13 +85,13 @@ describe('ExpirationWatcher', () => { expirationUnixTimestampSec, ); const orderHash = getOrderHashHex(signedOrder); - expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(1000)); + expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(MILISECONDS_IN_SECOND)); const callbackAsync = callbackErrorReporter.reportNoErrorCallbackErrors(done)((hash: string) => { expect(hash).to.be.equal(orderHash); expect(utils.getCurrentUnixTimestampSec()).to.be.bignumber.gte(expirationUnixTimestampSec); }); expirationWatcher.subscribe(callbackAsync); - timer.tick(orderLifetimeSec * 1000); + timer.tick(orderLifetimeSec * MILISECONDS_IN_SECOND); })().catch(done); }); it("doesn't emit events before order expires", (done: DoneCallback) => { @@ -106,13 +107,13 @@ describe('ExpirationWatcher', () => { expirationUnixTimestampSec, ); const orderHash = getOrderHashHex(signedOrder); - expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(1000)); + expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(MILISECONDS_IN_SECOND)); const callbackAsync = callbackErrorReporter.reportNoErrorCallbackErrors(done)(async (hash: string) => { done(new Error('Emitted expiration went before the order actually expired')); }); expirationWatcher.subscribe(callbackAsync); const notEnoughTime = orderLifetimeSec - 1; - timer.tick(notEnoughTime * 1000); + timer.tick(notEnoughTime * MILISECONDS_IN_SECOND); done(); })().catch(done); }); @@ -140,8 +141,14 @@ describe('ExpirationWatcher', () => { ); const orderHash1 = getOrderHashHex(signedOrder1); const orderHash2 = getOrderHashHex(signedOrder2); - expirationWatcher.addOrder(orderHash2, signedOrder2.expirationUnixTimestampSec.times(1000)); - expirationWatcher.addOrder(orderHash1, signedOrder1.expirationUnixTimestampSec.times(1000)); + expirationWatcher.addOrder( + orderHash2, + signedOrder2.expirationUnixTimestampSec.times(MILISECONDS_IN_SECOND), + ); + expirationWatcher.addOrder( + orderHash1, + signedOrder1.expirationUnixTimestampSec.times(MILISECONDS_IN_SECOND), + ); const expirationOrder = [orderHash1, orderHash2]; const expectToBeCalledOnce = false; const callbackAsync = callbackErrorReporter.reportNoErrorCallbackErrors(done, expectToBeCalledOnce)( @@ -154,7 +161,7 @@ describe('ExpirationWatcher', () => { }, ); expirationWatcher.subscribe(callbackAsync); - timer.tick(order2Lifetime * 1000); + timer.tick(order2Lifetime * MILISECONDS_IN_SECOND); })().catch(done); }); it('emits events in correct order when expirations are equal', (done: DoneCallback) => { @@ -181,8 +188,14 @@ describe('ExpirationWatcher', () => { ); const orderHash1 = getOrderHashHex(signedOrder1); const orderHash2 = getOrderHashHex(signedOrder2); - expirationWatcher.addOrder(orderHash1, signedOrder1.expirationUnixTimestampSec.times(1000)); - expirationWatcher.addOrder(orderHash2, signedOrder2.expirationUnixTimestampSec.times(1000)); + expirationWatcher.addOrder( + orderHash1, + signedOrder1.expirationUnixTimestampSec.times(MILISECONDS_IN_SECOND), + ); + expirationWatcher.addOrder( + orderHash2, + signedOrder2.expirationUnixTimestampSec.times(MILISECONDS_IN_SECOND), + ); const expirationOrder = orderHash1 < orderHash2 ? [orderHash1, orderHash2] : [orderHash2, orderHash1]; const expectToBeCalledOnce = false; const callbackAsync = callbackErrorReporter.reportNoErrorCallbackErrors(done, expectToBeCalledOnce)( @@ -195,7 +208,7 @@ describe('ExpirationWatcher', () => { }, ); expirationWatcher.subscribe(callbackAsync); - timer.tick(order2Lifetime * 1000); + timer.tick(order2Lifetime * MILISECONDS_IN_SECOND); })().catch(done); }); }); diff --git a/packages/order-watcher/test/global_hooks.ts b/packages/order-watcher/test/global_hooks.ts index 03eab0e13..d4d033dd4 100644 --- a/packages/order-watcher/test/global_hooks.ts +++ b/packages/order-watcher/test/global_hooks.ts @@ -9,7 +9,8 @@ import { provider } from './utils/web3_wrapper'; before('migrate contracts', async function(): Promise<void> { // HACK: Since the migrations take longer then our global mocha timeout limit // we manually increase it for this before hook. - this.timeout(20000); + const mochaTestTimeoutMs = 20000; + this.timeout(mochaTestTimeoutMs); const txDefaults = { gas: devConstants.GAS_ESTIMATE, from: devConstants.TESTRPC_FIRST_ADDRESS, diff --git a/packages/order-watcher/test/order_watcher_test.ts b/packages/order-watcher/test/order_watcher_test.ts index dc8e544b1..0d33e7ea2 100644 --- a/packages/order-watcher/test/order_watcher_test.ts +++ b/packages/order-watcher/test/order_watcher_test.ts @@ -269,8 +269,8 @@ describe('OrderWatcher', () => { }); it('should trigger the callback when orders backing ZRX allowance changes', (done: DoneCallback) => { (async () => { - const makerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18); - const takerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(0), 18); + const makerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); + const takerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(0), decimals); signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync( makerToken.address, takerToken.address, diff --git a/packages/order-watcher/test/utils/web3_wrapper.ts b/packages/order-watcher/test/utils/web3_wrapper.ts index b0ccfa546..71a0dc1c2 100644 --- a/packages/order-watcher/test/utils/web3_wrapper.ts +++ b/packages/order-watcher/test/utils/web3_wrapper.ts @@ -2,8 +2,7 @@ import { devConstants, web3Factory } from '@0xproject/dev-utils'; import { Provider } from '@0xproject/types'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; -const web3 = web3Factory.create({ shouldUseInProcessGanache: true }); -const provider: Provider = web3.currentProvider; -const web3Wrapper = new Web3Wrapper(web3.currentProvider); +const provider: Provider = web3Factory.getRpcProvider({ shouldUseInProcessGanache: true }); +const web3Wrapper = new Web3Wrapper(provider); export { provider, web3Wrapper }; diff --git a/packages/react-docs-example/package.json b/packages/react-docs-example/package.json index 2cbf3ef73..a0538b933 100644 --- a/packages/react-docs-example/package.json +++ b/packages/react-docs-example/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@0xproject/react-docs-example", - "version": "0.0.11", + "version": "0.0.12", "engines": { "node": ">=6.12" }, @@ -26,7 +26,7 @@ "url": "https://github.com/0xProject/0x-monorepo.git" }, "devDependencies": { - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/tslint-config": "^0.4.18", "@types/lodash": "4.14.104", "@types/material-ui": "0.18.0", "@types/node": "^8.0.53", @@ -50,7 +50,7 @@ "webpack-dev-server": "^2.11.1" }, "dependencies": { - "@0xproject/react-docs": "^0.0.11", + "@0xproject/react-docs": "^0.0.12", "basscss": "^8.0.3", "lodash": "^4.17.4", "material-ui": "^0.17.1", diff --git a/packages/react-docs/CHANGELOG.json b/packages/react-docs/CHANGELOG.json index 0cb767dfc..32fa49264 100644 --- a/packages/react-docs/CHANGELOG.json +++ b/packages/react-docs/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1527009133, + "version": "0.0.12", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1525477860, "version": "0.0.11", "changes": [ diff --git a/packages/react-docs/CHANGELOG.md b/packages/react-docs/CHANGELOG.md index 8a0afbeed..e46198f6c 100644 --- a/packages/react-docs/CHANGELOG.md +++ b/packages/react-docs/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.0.11 - _May 5, 2018_ +## v0.0.12 - _May 22, 2018_ + + * Dependencies updated + +## v0.0.11 - _May 4, 2018_ * Dependencies updated diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json index 9245cfb1e..531c0d90c 100644 --- a/packages/react-docs/package.json +++ b/packages/react-docs/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/react-docs", - "version": "0.0.11", + "version": "0.0.12", "engines": { "node": ">=6.12" }, @@ -25,9 +25,9 @@ "url": "https://github.com/0xProject/0x-monorepo.git" }, "devDependencies": { - "@0xproject/dev-utils": "^0.4.1", - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/dev-utils": "^0.4.2", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", "copyfiles": "^1.2.0", "make-promises-safe": "^1.1.0", "shx": "^0.2.2", @@ -35,8 +35,8 @@ "typescript": "2.7.1" }, "dependencies": { - "@0xproject/react-shared": "^0.1.6", - "@0xproject/utils": "^0.6.1", + "@0xproject/react-shared": "^0.1.7", + "@0xproject/utils": "^0.6.2", "@types/lodash": "4.14.104", "@types/material-ui": "0.18.0", "@types/node": "^8.0.53", diff --git a/packages/react-docs/src/docs_info.ts b/packages/react-docs/src/docs_info.ts index e9c84b7c9..6f4f39f00 100644 --- a/packages/react-docs/src/docs_info.ts +++ b/packages/react-docs/src/docs_info.ts @@ -64,8 +64,8 @@ export class DocsInfo { finalMenu.contracts = _.filter(finalMenu.contracts, (contractName: string) => { const versionIntroducedIfExists = this._docsInfo.menuSubsectionToVersionWhenIntroduced[contractName]; if (!_.isUndefined(versionIntroducedIfExists)) { - const existsInSelectedVersion = compareVersions(selectedVersion, versionIntroducedIfExists) >= 0; - return existsInSelectedVersion; + const doesExistInSelectedVersion = compareVersions(selectedVersion, versionIntroducedIfExists) >= 0; + return doesExistInSelectedVersion; } else { return true; } diff --git a/packages/react-docs/tslint.json b/packages/react-docs/tslint.json index ee918e360..c78434416 100644 --- a/packages/react-docs/tslint.json +++ b/packages/react-docs/tslint.json @@ -3,6 +3,7 @@ "rules": { "no-object-literal-type-assertion": false, "completed-docs": false, - "prefer-function-over-method": false + "prefer-function-over-method": false, + "custom-no-magic-numbers": false } } diff --git a/packages/react-shared/CHANGELOG.json b/packages/react-shared/CHANGELOG.json index 3e03f81f1..5227bbf72 100644 --- a/packages/react-shared/CHANGELOG.json +++ b/packages/react-shared/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1527009133, + "version": "0.1.7", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "version": "0.2.0", "changes": [ { diff --git a/packages/react-shared/CHANGELOG.md b/packages/react-shared/CHANGELOG.md index 51d804b63..68eac96cf 100644 --- a/packages/react-shared/CHANGELOG.md +++ b/packages/react-shared/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.1.6 - _May 5, 2018_ +## v0.1.7 - _May 22, 2018_ + + * Dependencies updated + +## v0.1.6 - _May 4, 2018_ * Dependencies updated diff --git a/packages/react-shared/package.json b/packages/react-shared/package.json index af0920d27..d28972325 100644 --- a/packages/react-shared/package.json +++ b/packages/react-shared/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/react-shared", - "version": "0.1.6", + "version": "0.1.7", "engines": { "node": ">=6.12" }, @@ -25,9 +25,9 @@ "url": "https://github.com/0xProject/0x-monorepo.git" }, "devDependencies": { - "@0xproject/dev-utils": "^0.4.1", - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/dev-utils": "^0.4.2", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", "copyfiles": "^1.2.0", "make-promises-safe": "^1.1.0", "shx": "^0.2.2", diff --git a/packages/react-shared/tslint.json b/packages/react-shared/tslint.json index ee918e360..c78434416 100644 --- a/packages/react-shared/tslint.json +++ b/packages/react-shared/tslint.json @@ -3,6 +3,7 @@ "rules": { "no-object-literal-type-assertion": false, "completed-docs": false, - "prefer-function-over-method": false + "prefer-function-over-method": false, + "custom-no-magic-numbers": false } } diff --git a/packages/sol-compiler/CHANGELOG.json b/packages/sol-compiler/CHANGELOG.json index a1b53fb9e..33fd99e4f 100644 --- a/packages/sol-compiler/CHANGELOG.json +++ b/packages/sol-compiler/CHANGELOG.json @@ -5,8 +5,13 @@ { "note": "Properly export the executable binary", "pr": 588 + }, + { + "note": "Add the ability to define a specific solidity version", + "pr": 589 } - ] + ], + "timestamp": 1527009133 }, { "timestamp": 1525477860, diff --git a/packages/sol-compiler/CHANGELOG.md b/packages/sol-compiler/CHANGELOG.md index 4eb0ed453..ee9b53f4e 100644 --- a/packages/sol-compiler/CHANGELOG.md +++ b/packages/sol-compiler/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.4.3 - _May 5, 2018_ +## v0.5.0 - _May 22, 2018_ + + * Properly export the executable binary (#588) + +## v0.4.3 - _May 4, 2018_ * Dependencies updated diff --git a/packages/sol-compiler/package.json b/packages/sol-compiler/package.json index 31a10f8b7..c94e59eb4 100644 --- a/packages/sol-compiler/package.json +++ b/packages/sol-compiler/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/sol-compiler", - "version": "0.4.3", + "version": "0.5.0", "engines": { "node": ">=6.12" }, @@ -49,9 +49,9 @@ }, "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", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/dev-utils": "^0.4.2", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", "@types/mkdirp": "^0.5.2", "@types/require-from-string": "^1.2.0", "@types/semver": "^5.5.0", @@ -72,12 +72,12 @@ "zeppelin-solidity": "1.8.0" }, "dependencies": { - "@0xproject/json-schemas": "^0.7.23", - "@0xproject/sol-resolver": "^0.0.4", - "@0xproject/types": "^0.6.3", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", - "@0xproject/web3-wrapper": "^0.6.3", + "@0xproject/json-schemas": "^0.7.24", + "@0xproject/sol-resolver": "^0.0.5", + "@0xproject/types": "^0.7.0", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", + "@0xproject/web3-wrapper": "^0.6.4", "@types/yargs": "^11.0.0", "chalk": "^2.3.0", "ethereumjs-util": "^5.1.1", diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index efb30091b..2ebc5228e 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -74,6 +74,7 @@ export class Compiler { private _contractsDir: string; private _compilerSettings: solc.CompilerSettings; private _artifactsDir: string; + private _solcVersionIfExists: string | undefined; private _specifiedContracts: string[] | TYPE_ALL_FILES_IDENTIFIER; /** * Instantiates a new instance of the Compiler class. @@ -85,6 +86,7 @@ export class Compiler { ? JSON.parse(fs.readFileSync(CONFIG_FILE).toString()) : {}; this._contractsDir = opts.contractsDir || config.contractsDir || DEFAULT_CONTRACTS_DIR; + this._solcVersionIfExists = opts.solcVersion || config.solcVersion; this._compilerSettings = opts.compilerSettings || config.compilerSettings || DEFAULT_COMPILER_SETTINGS; this._artifactsDir = opts.artifactsDir || config.artifactsDir || DEFAULT_ARTIFACTS_DIR; this._specifiedContracts = opts.contracts || config.contracts || ALL_CONTRACTS_IDENTIFIER; @@ -139,9 +141,12 @@ export class Compiler { if (!shouldCompile) { return; } - const solcVersionRange = parseSolidityVersionRange(contractSource.source); - const availableCompilerVersions = _.keys(binPaths); - const solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); + let solcVersion = this._solcVersionIfExists; + if (_.isUndefined(solcVersion)) { + const solcVersionRange = parseSolidityVersionRange(contractSource.source); + const availableCompilerVersions = _.keys(binPaths); + solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); + } const fullSolcVersion = binPaths[solcVersion]; const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); let solcjs: string; @@ -152,7 +157,8 @@ export class Compiler { logUtils.log(`Downloading ${fullSolcVersion}...`); const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; const response = await fetch(url); - if (response.status !== 200) { + const SUCCESS_STATUS = 200; + if (response.status !== SUCCESS_STATUS) { throw new Error(`Failed to load ${fullSolcVersion}`); } solcjs = await response.text(); @@ -228,7 +234,7 @@ export class Compiler { sourceTreeHashHex, compiler: { name: 'solc', - version: solcVersion, + version: fullSolcVersion, settings: this._compilerSettings, }, }; diff --git a/packages/sol-compiler/src/index.ts b/packages/sol-compiler/src/index.ts index 4b4c51de2..15c166992 100644 --- a/packages/sol-compiler/src/index.ts +++ b/packages/sol-compiler/src/index.ts @@ -1,2 +1,3 @@ export { Compiler } from './compiler'; +export { CompilerOptions } from './utils/types'; export { ContractArtifact, ContractNetworks } from './utils/types'; diff --git a/packages/sol-compiler/src/utils/types.ts b/packages/sol-compiler/src/utils/types.ts index b12a11b79..d43347fa6 100644 --- a/packages/sol-compiler/src/utils/types.ts +++ b/packages/sol-compiler/src/utils/types.ts @@ -55,6 +55,7 @@ export interface CompilerOptions { artifactsDir?: string; compilerSettings?: solc.CompilerSettings; contracts?: string[] | '*'; + solcVersion?: string; } export interface ContractSourceData { diff --git a/packages/sol-compiler/test/compiler_test.ts b/packages/sol-compiler/test/compiler_test.ts index dc8eb1c4e..991965caa 100644 --- a/packages/sol-compiler/test/compiler_test.ts +++ b/packages/sol-compiler/test/compiler_test.ts @@ -39,8 +39,13 @@ describe('#Compiler', function(): void { 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(2, -86); - const exchangeBinaryWithoutMetadata = exchange_binary.slice(0, -86); + const metadataByteLength = 43; + const metadataHexLength = metadataByteLength * 2; + const unlinkedBinaryWithoutMetadata = exchangeArtifact.compilerOutput.evm.bytecode.object.slice( + 2, + -metadataHexLength, + ); + const exchangeBinaryWithoutMetadata = exchange_binary.slice(0, -metadataHexLength); expect(unlinkedBinaryWithoutMetadata).to.equal(exchangeBinaryWithoutMetadata); }); }); diff --git a/packages/sol-compiler/test/util/provider.ts b/packages/sol-compiler/test/util/provider.ts index e0fcb362a..2bd178129 100644 --- a/packages/sol-compiler/test/util/provider.ts +++ b/packages/sol-compiler/test/util/provider.ts @@ -3,7 +3,6 @@ import { Provider } from '@0xproject/types'; import * as Web3 from 'web3'; const providerConfigs = { shouldUseInProcessGanache: true }; -const web3Instance = web3Factory.create(providerConfigs); -const provider: Provider = web3Instance.currentProvider; +const provider: Provider = web3Factory.getRpcProvider(providerConfigs); export { provider }; diff --git a/packages/sol-cov/CHANGELOG.json b/packages/sol-cov/CHANGELOG.json index 468957fe3..0d3303231 100644 --- a/packages/sol-cov/CHANGELOG.json +++ b/packages/sol-cov/CHANGELOG.json @@ -1,5 +1,36 @@ [ { + "timestamp": 1527009134, + "version": "0.1.0", + "changes": [ + { + "note": "Add artifact adapter as a parameter for CoverageSubprovider. Export AbstractArtifactAdapter", + "pr": 589 + }, + { + "note": "Implement SolCompilerArtifactAdapter and TruffleArtifactAdapter", + "pr": 589 + }, + { + "note": "Properly parse multi-level traces", + "pr": 589 + }, + { + "note": "Add support for solidity libraries", + "pr": 589 + } + ] + }, + { + "timestamp": 1527009133, + "version": "0.0.11", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1525477860, "version": "0.0.10", "changes": [ diff --git a/packages/sol-cov/CHANGELOG.md b/packages/sol-cov/CHANGELOG.md index 9e2995328..f0312d297 100644 --- a/packages/sol-cov/CHANGELOG.md +++ b/packages/sol-cov/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.0.10 - _May 5, 2018_ +## v0.0.11 - _May 22, 2018_ + + * Dependencies updated + +## v0.0.10 - _May 4, 2018_ * Dependencies updated diff --git a/packages/sol-cov/package.json b/packages/sol-cov/package.json index 28ceae0fa..f18315a26 100644 --- a/packages/sol-cov/package.json +++ b/packages/sol-cov/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/sol-cov", - "version": "0.0.10", + "version": "0.0.11", "engines": { "node": ">=6.12" }, @@ -46,25 +46,30 @@ }, "homepage": "https://github.com/0xProject/0x.js/packages/sol-cov/README.md", "dependencies": { - "@0xproject/subproviders": "^0.10.1", - "@0xproject/types": "^0.6.3", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", + "@0xproject/sol-compiler": "^0.5.0", + "@0xproject/subproviders": "^0.10.2", + "@0xproject/types": "^0.7.0", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", "ethereumjs-util": "^5.1.1", "glob": "^7.1.2", "istanbul": "^0.4.5", "lodash": "^4.17.4", + "loglevel": "^1.6.1", "mkdirp": "^0.5.1", + "rimraf": "^2.6.2", "semaphore-async-await": "^1.5.1", - "solidity-parser-antlr": "^0.2.8" + "solidity-parser-antlr": "^0.2.11" }, "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", "@types/istanbul": "^0.4.30", + "@types/loglevel": "^1.5.3", "@types/mkdirp": "^0.5.1", "@types/mocha": "^2.2.42", "@types/node": "^8.0.53", + "@types/rimraf": "^2.0.2", "chai": "^4.0.1", "copyfiles": "^1.2.0", "dirty-chai": "^2.0.1", diff --git a/packages/sol-cov/src/artifact_adapters/abstract_artifact_adapter.ts b/packages/sol-cov/src/artifact_adapters/abstract_artifact_adapter.ts new file mode 100644 index 000000000..fcc6562ad --- /dev/null +++ b/packages/sol-cov/src/artifact_adapters/abstract_artifact_adapter.ts @@ -0,0 +1,5 @@ +import { ContractData } from '../types'; + +export abstract class AbstractArtifactAdapter { + public abstract async collectContractsDataAsync(): Promise<ContractData[]>; +} diff --git a/packages/sol-cov/src/artifact_adapters/sol_compiler_artifact_adapter.ts b/packages/sol-cov/src/artifact_adapters/sol_compiler_artifact_adapter.ts new file mode 100644 index 000000000..d08828bf6 --- /dev/null +++ b/packages/sol-cov/src/artifact_adapters/sol_compiler_artifact_adapter.ts @@ -0,0 +1,49 @@ +import * as fs from 'fs'; +import * as glob from 'glob'; +import * as _ from 'lodash'; +import * as path from 'path'; + +import { ContractData } from '../types'; + +import { AbstractArtifactAdapter } from './abstract_artifact_adapter'; + +const CONFIG_FILE = 'compiler.json'; + +export class SolCompilerArtifactAdapter extends AbstractArtifactAdapter { + private _artifactsPath: string; + private _sourcesPath: string; + constructor(artifactsPath?: string, sourcesPath?: string) { + super(); + const config = JSON.parse(fs.readFileSync(CONFIG_FILE).toString()); + if (_.isUndefined(artifactsPath) && _.isUndefined(config.artifactsDir)) { + throw new Error(`artifactsDir not found in ${CONFIG_FILE}`); + } + this._artifactsPath = config.artifactsDir; + if (_.isUndefined(sourcesPath) && _.isUndefined(config.contractsDir)) { + throw new Error(`contractsDir not found in ${CONFIG_FILE}`); + } + this._sourcesPath = config.contractsDir; + } + public async collectContractsDataAsync(): Promise<ContractData[]> { + const artifactsGlob = `${this._artifactsPath}/**/*.json`; + const artifactFileNames = glob.sync(artifactsGlob, { absolute: true }); + const contractsData: ContractData[] = []; + for (const artifactFileName of artifactFileNames) { + const artifact = JSON.parse(fs.readFileSync(artifactFileName).toString()); + let sources = _.keys(artifact.sources); + sources = _.map(sources, relativeFilePath => path.resolve(this._sourcesPath, relativeFilePath)); + const contractName = artifact.contractName; + const sourceCodes = _.map(sources, (source: string) => fs.readFileSync(source).toString()); + const contractData = { + sourceCodes, + sources, + bytecode: artifact.compilerOutput.evm.bytecode.object, + sourceMap: artifact.compilerOutput.evm.bytecode.sourceMap, + runtimeBytecode: artifact.compilerOutput.evm.deployedBytecode.object, + sourceMapRuntime: artifact.compilerOutput.evm.deployedBytecode.sourceMap, + }; + contractsData.push(contractData); + } + return contractsData; + } +} diff --git a/packages/sol-cov/src/artifact_adapters/truffle_artifact_adapter.ts b/packages/sol-cov/src/artifact_adapters/truffle_artifact_adapter.ts new file mode 100644 index 000000000..c7f21b6eb --- /dev/null +++ b/packages/sol-cov/src/artifact_adapters/truffle_artifact_adapter.ts @@ -0,0 +1,43 @@ +import { Compiler, CompilerOptions } from '@0xproject/sol-compiler'; +import * as fs from 'fs'; +import * as glob from 'glob'; +import * as _ from 'lodash'; +import * as path from 'path'; +import * as rimraf from 'rimraf'; + +import { ContractData } from '../types'; + +import { AbstractArtifactAdapter } from './abstract_artifact_adapter'; +import { SolCompilerArtifactAdapter } from './sol_compiler_artifact_adapter'; + +export class TruffleArtifactAdapter extends AbstractArtifactAdapter { + private _solcVersion: string; + private _sourcesPath: string; + constructor(sourcesPath: string, solcVersion: string) { + super(); + this._solcVersion = solcVersion; + this._sourcesPath = sourcesPath; + } + public async collectContractsDataAsync(): Promise<ContractData[]> { + const artifactsDir = '.0x-artifacts'; + const compilerOptions: CompilerOptions = { + contractsDir: this._sourcesPath, + artifactsDir, + compilerSettings: { + outputSelection: { + ['*']: { + ['*']: ['abi', 'evm.bytecode.object', 'evm.deployedBytecode.object'], + }, + }, + }, + contracts: '*', + solcVersion: this._solcVersion, + }; + const compiler = new Compiler(compilerOptions); + await compiler.compileAsync(); + const solCompilerArtifactAdapter = new SolCompilerArtifactAdapter(artifactsDir, this._sourcesPath); + const contractsDataFrom0xArtifacts = await solCompilerArtifactAdapter.collectContractsDataAsync(); + rimraf.sync(artifactsDir); + return contractsDataFrom0xArtifacts; + } +} diff --git a/packages/sol-cov/src/collect_contract_data.ts b/packages/sol-cov/src/collect_contract_data.ts deleted file mode 100644 index 2c2a12835..000000000 --- a/packages/sol-cov/src/collect_contract_data.ts +++ /dev/null @@ -1,31 +0,0 @@ -import * as fs from 'fs'; -import * as glob from 'glob'; -import * as _ from 'lodash'; -import * as path from 'path'; - -import { ContractData } from './types'; - -export const collectContractsData = (artifactsPath: string, sourcesPath: string) => { - const artifactsGlob = `${artifactsPath}/**/*.json`; - const artifactFileNames = glob.sync(artifactsGlob, { absolute: true }); - const contractsData: ContractData[] = []; - _.forEach(artifactFileNames, artifactFileName => { - const artifact = JSON.parse(fs.readFileSync(artifactFileName).toString()); - const sources = _.keys(artifact.sources); - const contractName = artifact.contractName; - // We don't compute coverage for dependencies - const sourceCodes = _.map(sources, (source: string) => - fs.readFileSync(path.join(sourcesPath, source)).toString(), - ); - const contractData = { - sourceCodes, - sources, - bytecode: artifact.compilerOutput.evm.bytecode.object, - sourceMap: artifact.compilerOutput.evm.bytecode.sourceMap, - runtimeBytecode: artifact.compilerOutput.evm.deployedBytecode.object, - sourceMapRuntime: artifact.compilerOutput.evm.deployedBytecode.sourceMap, - }; - contractsData.push(contractData); - }); - return contractsData; -}; diff --git a/packages/sol-cov/src/constants.ts b/packages/sol-cov/src/constants.ts index 64d2228a3..34d62b537 100644 --- a/packages/sol-cov/src/constants.ts +++ b/packages/sol-cov/src/constants.ts @@ -1,6 +1,6 @@ // tslint:disable:number-literal-format export const constants = { - NEW_CONTRACT: 'NEW_CONTRACT', + NEW_CONTRACT: 'NEW_CONTRACT' as 'NEW_CONTRACT', PUSH1: 0x60, PUSH2: 0x61, PUSH32: 0x7f, diff --git a/packages/sol-cov/src/coverage_manager.ts b/packages/sol-cov/src/coverage_manager.ts index 800ca96dd..31b0e6fbc 100644 --- a/packages/sol-cov/src/coverage_manager.ts +++ b/packages/sol-cov/src/coverage_manager.ts @@ -1,12 +1,13 @@ import { promisify } from '@0xproject/utils'; -import { addHexPrefix } from 'ethereumjs-util'; +import { addHexPrefix, stripHexPrefix } from 'ethereumjs-util'; import * as fs from 'fs'; import { Collector } from 'istanbul'; import * as _ from 'lodash'; +import { getLogger, levels, Logger, LogLevel } from 'loglevel'; import * as mkdirp from 'mkdirp'; import * as path from 'path'; -import { collectContractsData } from './collect_contract_data'; +import { AbstractArtifactAdapter } from './artifact_adapters/abstract_artifact_adapter'; import { collectCoverageEntries } from './collect_coverage_entries'; import { constants } from './constants'; import { parseSourceMap } from './source_maps'; @@ -34,41 +35,23 @@ import { utils } from './utils'; const mkdirpAsync = promisify<undefined>(mkdirp); export class CoverageManager { - private _sourcesPath: string; + private _artifactAdapter: AbstractArtifactAdapter; + private _logger: Logger; private _traceInfos: TraceInfo[] = []; - private _contractsData: ContractData[] = []; private _getContractCodeAsync: (address: string) => Promise<string>; - constructor( - artifactsPath: string, - sourcesPath: string, - getContractCodeAsync: (address: string) => Promise<string>, - ) { - this._getContractCodeAsync = getContractCodeAsync; - this._sourcesPath = sourcesPath; - 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 stringifiedCoverage = JSON.stringify(finalCoverage, null, '\t'); - await mkdirpAsync('coverage'); - fs.writeFileSync('coverage/coverage.json', stringifiedCoverage); - } - private _getSingleFileCoverageForTrace( + private static _getSingleFileCoverageForTrace( contractData: ContractData, coveredPcs: number[], pcToSourceRange: { [programCounter: number]: SourceRange }, fileIndex: number, ): Coverage { - const fileName = contractData.sources[fileIndex]; + const absoluteFileName = contractData.sources[fileIndex]; const coverageEntriesDescription = collectCoverageEntries(contractData.sourceCodes[fileIndex]); let sourceRanges = _.map(coveredPcs, coveredPc => pcToSourceRange[coveredPc]); sourceRanges = _.compact(sourceRanges); // Some PC's don't map to a source range and we just ignore them. // By default lodash does a shallow object comparasion. We JSON.stringify them and compare as strings. sourceRanges = _.uniqBy(sourceRanges, s => JSON.stringify(s)); // We don't care if one PC was covered multiple times within a single transaction - sourceRanges = _.filter(sourceRanges, sourceRange => sourceRange.fileName === fileName); + sourceRanges = _.filter(sourceRanges, sourceRange => sourceRange.fileName === absoluteFileName); const branchCoverage: BranchCoverage = {}; const branchIds = _.keys(coverageEntriesDescription.branchMap); for (const branchId of branchIds) { @@ -118,7 +101,6 @@ export class CoverageManager { ); statementCoverage[modifierStatementId] = isModifierCovered; } - const absoluteFileName = path.join(this._sourcesPath, fileName); const partialCoverage = { [absoluteFileName]: { ...coverageEntriesDescription, @@ -131,18 +113,63 @@ export class CoverageManager { }; return partialCoverage; } + private static _bytecodeToBytecodeRegex(bytecode: string): string { + const bytecodeRegex = bytecode + // Library linking placeholder: __ConvertLib____________________________ + .replace(/_.*_/, '.*') + // Last 86 characters is solidity compiler metadata that's different between compilations + .replace(/.{86}$/, '') + // Libraries contain their own address at the beginning of the code and it's impossible to know it in advance + .replace(/^0x730000000000000000000000000000000000000000/, '0x73........................................'); + return bytecodeRegex; + } + private static _getContractDataIfExists(contractsData: ContractData[], bytecode: string): ContractData | undefined { + if (!bytecode.startsWith('0x')) { + throw new Error(`0x hex prefix missing: ${bytecode}`); + } + const contractData = _.find(contractsData, contractDataCandidate => { + const bytecodeRegex = CoverageManager._bytecodeToBytecodeRegex(contractDataCandidate.bytecode); + const runtimeBytecodeRegex = CoverageManager._bytecodeToBytecodeRegex( + contractDataCandidate.runtimeBytecode, + ); + // We use that function to find by bytecode or runtimeBytecode. Those are quasi-random strings so + // collisions are practically impossible and it allows us to reuse that code + return !_.isNull(bytecode.match(bytecodeRegex)) || !_.isNull(bytecode.match(runtimeBytecodeRegex)); + }); + return contractData; + } + constructor( + artifactAdapter: AbstractArtifactAdapter, + getContractCodeAsync: (address: string) => Promise<string>, + isVerbose: boolean, + ) { + this._getContractCodeAsync = getContractCodeAsync; + this._artifactAdapter = artifactAdapter; + this._logger = getLogger('sol-cov'); + this._logger.setLevel(isVerbose ? levels.TRACE : levels.ERROR); + } + public appendTraceInfo(traceInfo: TraceInfo): void { + this._traceInfos.push(traceInfo); + } + public async writeCoverageAsync(): Promise<void> { + const finalCoverage = await this._computeCoverageAsync(); + const stringifiedCoverage = JSON.stringify(finalCoverage, null, '\t'); + await mkdirpAsync('coverage'); + fs.writeFileSync('coverage/coverage.json', stringifiedCoverage); + } private async _computeCoverageAsync(): Promise<Coverage> { + const contractsData = await this._artifactAdapter.collectContractsDataAsync(); const collector = new Collector(); for (const traceInfo of this._traceInfos) { if (traceInfo.address !== constants.NEW_CONTRACT) { // Runtime transaction - let runtimeBytecode = (traceInfo as TraceInfoExistingContract).runtimeBytecode; - runtimeBytecode = addHexPrefix(runtimeBytecode); - const contractData = _.find(this._contractsData, { runtimeBytecode }) as ContractData; + const runtimeBytecode = (traceInfo as TraceInfoExistingContract).runtimeBytecode; + const contractData = CoverageManager._getContractDataIfExists(contractsData, runtimeBytecode); if (_.isUndefined(contractData)) { - throw new Error(`Transaction to an unknown address: ${traceInfo.address}`); + this._logger.warn(`Transaction to an unknown address: ${traceInfo.address}`); + continue; } - const bytecodeHex = contractData.runtimeBytecode.slice(2); + const bytecodeHex = stripHexPrefix(runtimeBytecode); const sourceMap = contractData.sourceMapRuntime; const pcToSourceRange = parseSourceMap( contractData.sourceCodes, @@ -151,7 +178,7 @@ export class CoverageManager { contractData.sources, ); for (let fileIndex = 0; fileIndex < contractData.sources.length; fileIndex++) { - const singleFileCoverageForTrace = this._getSingleFileCoverageForTrace( + const singleFileCoverageForTrace = CoverageManager._getSingleFileCoverageForTrace( contractData, traceInfo.coveredPcs, pcToSourceRange, @@ -161,15 +188,13 @@ export class CoverageManager { } } else { // Contract creation transaction - let bytecode = (traceInfo as TraceInfoNewContract).bytecode; - bytecode = addHexPrefix(bytecode); - const contractData = _.find(this._contractsData, contractDataCandidate => - bytecode.startsWith(contractDataCandidate.bytecode), - ) as ContractData; + const bytecode = (traceInfo as TraceInfoNewContract).bytecode; + const contractData = CoverageManager._getContractDataIfExists(contractsData, bytecode); if (_.isUndefined(contractData)) { - throw new Error(`Unknown contract creation transaction`); + this._logger.warn(`Unknown contract creation transaction`); + continue; } - const bytecodeHex = contractData.bytecode.slice(2); + const bytecodeHex = stripHexPrefix(bytecode); const sourceMap = contractData.sourceMap; const pcToSourceRange = parseSourceMap( contractData.sourceCodes, @@ -178,7 +203,7 @@ export class CoverageManager { contractData.sources, ); for (let fileIndex = 0; fileIndex < contractData.sources.length; fileIndex++) { - const singleFileCoverageForTrace = this._getSingleFileCoverageForTrace( + const singleFileCoverageForTrace = CoverageManager._getSingleFileCoverageForTrace( contractData, traceInfo.coveredPcs, pcToSourceRange, diff --git a/packages/sol-cov/src/coverage_subprovider.ts b/packages/sol-cov/src/coverage_subprovider.ts index 08efeaa24..438339a3f 100644 --- a/packages/sol-cov/src/coverage_subprovider.ts +++ b/packages/sol-cov/src/coverage_subprovider.ts @@ -1,11 +1,14 @@ import { Callback, ErrorCallback, NextCallback, Subprovider } from '@0xproject/subproviders'; import { BlockParam, CallData, JSONRPCRequestPayload, TransactionTrace, TxData } from '@0xproject/types'; +import * as fs from 'fs'; import * as _ from 'lodash'; import { Lock } from 'semaphore-async-await'; +import { AbstractArtifactAdapter } from './artifact_adapters/abstract_artifact_adapter'; import { constants } from './constants'; import { CoverageManager } from './coverage_manager'; -import { TraceInfoExistingContract, TraceInfoNewContract } from './types'; +import { getTracesByContractAddress } from './trace'; +import { BlockParamLiteral, TraceInfoExistingContract, TraceInfoNewContract } from './types'; interface MaybeFakeTxData extends TxData { isFakeTransaction?: boolean; @@ -26,15 +29,15 @@ export class CoverageSubprovider extends Subprovider { private _defaultFromAddress: string; /** * Instantiates a CoverageSubprovider instance - * @param artifactsPath Path to the smart contract artifacts - * @param sourcesPath Path to the smart contract source files + * @param artifactAdapter Adapter for used artifacts format (0x, truffle, giveth, etc.) * @param defaultFromAddress default from address to use when sending transactions + * @param isVerbose If true, we will log any unknown transactions. Otherwise we will ignore them */ - constructor(artifactsPath: string, sourcesPath: string, defaultFromAddress: string) { + constructor(artifactAdapter: AbstractArtifactAdapter, defaultFromAddress: string, isVerbose: boolean = true) { super(); this._lock = new Lock(); this._defaultFromAddress = defaultFromAddress; - this._coverageManager = new CoverageManager(artifactsPath, sourcesPath, this._getContractCodeAsync.bind(this)); + this._coverageManager = new CoverageManager(artifactAdapter, this._getContractCodeAsync.bind(this), isVerbose); } /** * Write the test coverage results to a file in Istanbul format. @@ -86,7 +89,7 @@ export class CoverageSubprovider extends Subprovider { } else { const payload = { method: 'eth_getBlockByNumber', - params: ['latest', true], + params: [BlockParamLiteral.Latest, true], }; const jsonRPCResponsePayload = await this.emitPayloadAsync(payload); const transactions = jsonRPCResponsePayload.result.transactions; @@ -115,29 +118,54 @@ export class CoverageSubprovider extends Subprovider { private async _recordTxTraceAsync(address: string, data: string | undefined, txHash: string): Promise<void> { let payload = { method: 'debug_traceTransaction', - params: [txHash, { disableMemory: true, disableStack: true, disableStorage: true }], // TODO For now testrpc just ignores those parameters https://github.com/trufflesuite/ganache-cli/issues/489 + params: [txHash, { disableMemory: true, disableStack: false, disableStorage: true }], }; - const jsonRPCResponsePayload = await this.emitPayloadAsync(payload); + let jsonRPCResponsePayload = await this.emitPayloadAsync(payload); const trace: TransactionTrace = jsonRPCResponsePayload.result; - const coveredPcs = _.map(trace.structLogs, log => log.pc); + const tracesByContractAddress = getTracesByContractAddress(trace.structLogs, address); + const subcallAddresses = _.keys(tracesByContractAddress); if (address === constants.NEW_CONTRACT) { - const traceInfo: TraceInfoNewContract = { - coveredPcs, - txHash, - address: address as 'NEW_CONTRACT', - bytecode: data as string, - }; - this._coverageManager.appendTraceInfo(traceInfo); + for (const subcallAddress of subcallAddresses) { + let traceInfo: TraceInfoNewContract | TraceInfoExistingContract; + if (subcallAddress === 'NEW_CONTRACT') { + const traceForThatSubcall = tracesByContractAddress[subcallAddress]; + const coveredPcs = _.map(traceForThatSubcall, log => log.pc); + traceInfo = { + coveredPcs, + txHash, + address: constants.NEW_CONTRACT, + bytecode: data as string, + }; + } else { + payload = { method: 'eth_getCode', params: [subcallAddress, BlockParamLiteral.Latest] }; + jsonRPCResponsePayload = await this.emitPayloadAsync(payload); + const runtimeBytecode = jsonRPCResponsePayload.result; + const traceForThatSubcall = tracesByContractAddress[subcallAddress]; + const coveredPcs = _.map(traceForThatSubcall, log => log.pc); + traceInfo = { + coveredPcs, + txHash, + address: subcallAddress, + runtimeBytecode, + }; + } + this._coverageManager.appendTraceInfo(traceInfo); + } } else { - payload = { method: 'eth_getCode', params: [address, 'latest'] }; - const runtimeBytecode = (await this.emitPayloadAsync(payload)).result; - const traceInfo: TraceInfoExistingContract = { - coveredPcs, - txHash, - address, - runtimeBytecode, - }; - this._coverageManager.appendTraceInfo(traceInfo); + for (const subcallAddress of subcallAddresses) { + payload = { method: 'eth_getCode', params: [subcallAddress, BlockParamLiteral.Latest] }; + jsonRPCResponsePayload = await this.emitPayloadAsync(payload); + const runtimeBytecode = jsonRPCResponsePayload.result; + const traceForThatSubcall = tracesByContractAddress[subcallAddress]; + const coveredPcs = _.map(traceForThatSubcall, log => log.pc); + const traceInfo: TraceInfoExistingContract = { + coveredPcs, + txHash, + address: subcallAddress, + runtimeBytecode, + }; + this._coverageManager.appendTraceInfo(traceInfo); + } } } private async _recordCallTraceAsync(callData: Partial<CallData>, blockNumber: BlockParam): Promise<void> { @@ -168,7 +196,7 @@ export class CoverageSubprovider extends Subprovider { private async _getContractCodeAsync(address: string): Promise<string> { const payload = { method: 'eth_getCode', - params: [address, 'latest'], + params: [address, BlockParamLiteral.Latest], }; const jsonRPCResponsePayload = await this.emitPayloadAsync(payload); const contractCode: string = jsonRPCResponsePayload.result; diff --git a/packages/sol-cov/src/index.ts b/packages/sol-cov/src/index.ts index e5c5e5be3..7a2afbe80 100644 --- a/packages/sol-cov/src/index.ts +++ b/packages/sol-cov/src/index.ts @@ -1 +1,5 @@ export { CoverageSubprovider } from './coverage_subprovider'; +export { SolCompilerArtifactAdapter } from './artifact_adapters/sol_compiler_artifact_adapter'; +export { TruffleArtifactAdapter } from './artifact_adapters/truffle_artifact_adapter'; +export { AbstractArtifactAdapter } from './artifact_adapters/abstract_artifact_adapter'; +export { ContractData } from './types'; diff --git a/packages/sol-cov/src/trace.ts b/packages/sol-cov/src/trace.ts new file mode 100644 index 000000000..6caea1610 --- /dev/null +++ b/packages/sol-cov/src/trace.ts @@ -0,0 +1,105 @@ +import { OpCode, StructLog, TransactionTrace } from '@0xproject/types'; +import { addressUtils, BigNumber, logUtils } from '@0xproject/utils'; +import { addHexPrefix, stripHexPrefix } from 'ethereumjs-util'; +import * as fs from 'fs'; +import * as _ from 'lodash'; + +export interface TraceByContractAddress { + [contractAddress: string]: StructLog[]; +} + +function getAddressFromStackEntry(stackEntry: string): string { + const hexBase = 16; + return addressUtils.padZeros(new BigNumber(addHexPrefix(stackEntry)).toString(hexBase)); +} + +export function getTracesByContractAddress(structLogs: StructLog[], startAddress: string): TraceByContractAddress { + const traceByContractAddress: TraceByContractAddress = {}; + let currentTraceSegment = []; + const callStack = [startAddress]; + // tslint:disable-next-line:prefer-for-of + for (let i = 0; i < structLogs.length; i++) { + const structLog = structLogs[i]; + if (structLog.depth !== callStack.length - 1) { + throw new Error("Malformed trace. Trace depth doesn't match call stack depth"); + } + // After that check we have a guarantee that call stack is never empty + // If it would: callStack.length - 1 === structLog.depth === -1 + // That means that we can always safely pop from it + currentTraceSegment.push(structLog); + + const isCallLike = _.includes( + [OpCode.CallCode, OpCode.StaticCall, OpCode.Call, OpCode.DelegateCall], + structLog.op, + ); + const isEndOpcode = _.includes( + [OpCode.Return, OpCode.Stop, OpCode.Revert, OpCode.Invalid, OpCode.SelfDestruct], + structLog.op, + ); + if (isCallLike) { + const currentAddress = _.last(callStack) as string; + const jumpAddressOffset = 1; + const newAddress = getAddressFromStackEntry( + structLog.stack[structLog.stack.length - jumpAddressOffset - 1], + ); + if (structLog === _.last(structLogs)) { + throw new Error('Malformed trace. CALL-like opcode can not be the last one'); + } + // Sometimes calls don't change the execution context (current address). When we do a transfer to an + // externally owned account - it does the call and immediately returns because there is no fallback + // function. We manually check if the call depth had changed to handle that case. + const nextStructLog = structLogs[i + 1]; + if (nextStructLog.depth !== structLog.depth) { + callStack.push(newAddress); + traceByContractAddress[currentAddress] = (traceByContractAddress[currentAddress] || []).concat( + currentTraceSegment, + ); + currentTraceSegment = []; + } + } else if (isEndOpcode) { + const currentAddress = callStack.pop() as string; + traceByContractAddress[currentAddress] = (traceByContractAddress[currentAddress] || []).concat( + currentTraceSegment, + ); + currentTraceSegment = []; + if (structLog.op === OpCode.SelfDestruct) { + // After contract execution, we look at all sub-calls to external contracts, and for each one, fetch + // the bytecode and compute the coverage for the call. If the contract is destroyed with a call + // to `selfdestruct`, we are unable to fetch it's bytecode and compute coverage. + // TODO: Refactor this logic to fetch the sub-called contract bytecode before the selfdestruct is called + // in order to handle this edge-case. + logUtils.warn( + "Detected a selfdestruct. Sol-cov currently doesn't support that scenario. We'll just skip the trace part for a destructed contract", + ); + } + } else if (structLog.op === OpCode.Create) { + // TODO: Extract the new contract address from the stack and handle that scenario + logUtils.warn( + "Detected a contract created from within another contract. Sol-cov currently doesn't support that scenario. We'll just skip that trace", + ); + return traceByContractAddress; + } else { + if (structLog !== _.last(structLogs)) { + const nextStructLog = structLogs[i + 1]; + if (nextStructLog.depth === structLog.depth) { + continue; + } else if (nextStructLog.depth === structLog.depth - 1) { + const currentAddress = callStack.pop() as string; + traceByContractAddress[currentAddress] = (traceByContractAddress[currentAddress] || []).concat( + currentTraceSegment, + ); + currentTraceSegment = []; + } else { + throw new Error('Malformed trace. Unexpected call depth change'); + } + } + } + } + if (callStack.length !== 0) { + throw new Error('Malformed trace. Call stack non empty at the end'); + } + if (currentTraceSegment.length !== 0) { + throw new Error('Malformed trace. Current trace segment non empty at the end'); + } + return traceByContractAddress; +} diff --git a/packages/sol-cov/src/types.ts b/packages/sol-cov/src/types.ts index 01359d858..4c3de55a1 100644 --- a/packages/sol-cov/src/types.ts +++ b/packages/sol-cov/src/types.ts @@ -98,3 +98,7 @@ export interface TraceInfoExistingContract extends TraceInfoBase { } export type TraceInfo = TraceInfoNewContract | TraceInfoExistingContract; + +export enum BlockParamLiteral { + Latest = 'latest', +} diff --git a/packages/sol-cov/test/collect_coverage_entries_test.ts b/packages/sol-cov/test/collect_coverage_entries_test.ts index 82012edfa..a03be19cd 100644 --- a/packages/sol-cov/test/collect_coverage_entries_test.ts +++ b/packages/sol-cov/test/collect_coverage_entries_test.ts @@ -40,12 +40,14 @@ describe('Collect coverage entries', () => { const coverageEntries = collectCoverageEntries(simpleStorageContract); const fnIds = _.keys(coverageEntries.fnMap); expect(coverageEntries.fnMap[fnIds[0]].name).to.be.equal('set'); + // tslint:disable-next-line:custom-no-magic-numbers expect(coverageEntries.fnMap[fnIds[0]].line).to.be.equal(5); const setFunction = `function set(uint x) { storedData = x; }`; expect(getRange(simpleStorageContract, coverageEntries.fnMap[fnIds[0]].loc)).to.be.equal(setFunction); expect(coverageEntries.fnMap[fnIds[1]].name).to.be.equal('get'); + // tslint:disable-next-line:custom-no-magic-numbers expect(coverageEntries.fnMap[fnIds[1]].line).to.be.equal(8); const getFunction = `function get() constant returns (uint retVal) { return storedData; @@ -122,6 +124,7 @@ describe('Collect coverage entries', () => { const branchDescriptions = _.values(coverageEntries.branchMap); const branchLines = _.map(branchDescriptions, branchDescription => branchDescription.line); + // tslint:disable-next-line:custom-no-magic-numbers expect(branchLines).to.be.deep.equal([94, 115, 119, 130, 151, 187]); const branchTypes = _.map(branchDescriptions, branchDescription => branchDescription.type); expect(branchTypes).to.be.deep.equal(['if', 'if', 'if', 'if', 'binary-expr', 'if']); diff --git a/packages/sol-cov/test/instructions_test.ts b/packages/sol-cov/test/instructions_test.ts index f66612f5f..8012674f5 100644 --- a/packages/sol-cov/test/instructions_test.ts +++ b/packages/sol-cov/test/instructions_test.ts @@ -12,6 +12,7 @@ const expect = chai.expect; describe('instructions', () => { describe('#getPcToInstructionIndexMapping', () => { it('correctly maps pcs to instruction indexed', () => { + // tslint:disable-next-line:custom-no-magic-numbers const bytecode = new Uint8Array([constants.PUSH1, 42, constants.PUSH2, 1, 2, constants.TIMESTAMP]); const pcToInstruction = getPcToInstructionIndexMapping(bytecode); const expectedPcToInstruction = { '0': 0, '2': 1, '5': 2 }; diff --git a/packages/sol-cov/test/collect_contracts_data_test.ts b/packages/sol-cov/test/sol_compiler_artifact_adapter_test.ts index d84ac5a39..0ebad669b 100644 --- a/packages/sol-cov/test/collect_contracts_data_test.ts +++ b/packages/sol-cov/test/sol_compiler_artifact_adapter_test.ts @@ -4,16 +4,17 @@ import 'make-promises-safe'; import 'mocha'; import * as path from 'path'; -import { collectContractsData } from '../src/collect_contract_data'; +import { SolCompilerArtifactAdapter } from '../src/artifact_adapters/sol_compiler_artifact_adapter'; const expect = chai.expect; -describe('Collect contracts data', () => { +describe('SolCompilerArtifactAdapter', () => { describe('#collectContractsData', () => { - it('correctly collects contracts data', () => { + it('correctly collects contracts data', async () => { const artifactsPath = path.resolve(__dirname, 'fixtures/artifacts'); const sourcesPath = path.resolve(__dirname, 'fixtures/contracts'); - const contractsData = collectContractsData(artifactsPath, sourcesPath); + const zeroExArtifactsAdapter = new SolCompilerArtifactAdapter(artifactsPath, sourcesPath); + const contractsData = await zeroExArtifactsAdapter.collectContractsDataAsync(); _.forEach(contractsData, contractData => { expect(contractData).to.have.keys([ 'sourceCodes', diff --git a/packages/sol-cov/test/trace_test.ts b/packages/sol-cov/test/trace_test.ts new file mode 100644 index 000000000..c140cba0d --- /dev/null +++ b/packages/sol-cov/test/trace_test.ts @@ -0,0 +1,57 @@ +import { OpCode, StructLog } from '@0xproject/types'; +import * as chai from 'chai'; +import * as fs from 'fs'; +import * as _ from 'lodash'; +import 'mocha'; +import * as path from 'path'; + +import { getTracesByContractAddress } from '../src/trace'; + +const expect = chai.expect; + +const DEFAULT_STRUCT_LOG: StructLog = { + depth: 0, + error: '', + gas: 0, + gasCost: 0, + memory: [], + op: OpCode.Invalid, + pc: 0, + stack: [], + storage: {}, +}; + +function addDefaultStructLogFields(compactStructLog: Partial<StructLog> & { op: OpCode; depth: number }): StructLog { + return { ...DEFAULT_STRUCT_LOG, ...compactStructLog }; +} + +describe('Trace', () => { + describe('#getTracesByContractAddress', () => { + it('correctly splits trace by contract address', () => { + const delegateCallAddress = '0x0000000000000000000000000000000000000002'; + const trace = [ + { + op: OpCode.DelegateCall, + stack: [delegateCallAddress, '0x'], + depth: 0, + }, + { + op: OpCode.Return, + depth: 1, + }, + { + op: OpCode.Return, + depth: 0, + }, + ]; + const fullTrace = _.map(trace, compactStructLog => addDefaultStructLogFields(compactStructLog)); + const startAddress = '0x0000000000000000000000000000000000000001'; + const traceByContractAddress = getTracesByContractAddress(fullTrace, startAddress); + const expectedTraceByContractAddress = { + [startAddress]: [fullTrace[0], fullTrace[2]], + [delegateCallAddress]: [fullTrace[1]], + }; + expect(traceByContractAddress).to.be.deep.equal(expectedTraceByContractAddress); + }); + }); +}); diff --git a/packages/sol-resolver/CHANGELOG.json b/packages/sol-resolver/CHANGELOG.json index 0126fa170..895bd2104 100644 --- a/packages/sol-resolver/CHANGELOG.json +++ b/packages/sol-resolver/CHANGELOG.json @@ -1,5 +1,27 @@ [ { + "version": "0.0.5", + "changes": [ + { + "note": "Fix a bug in FsResolver where it tries to read directories as files", + "pr": 589 + }, + { + "note": "Fix a bug in NameResolver where it is not ignoring .sol files", + "pr": 589 + } + ] + }, + { + "timestamp": 1527009133, + "version": "0.0.5", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1525477860, "version": "0.0.4", "changes": [ diff --git a/packages/sol-resolver/CHANGELOG.md b/packages/sol-resolver/CHANGELOG.md index 4780544fa..bd94b1b41 100644 --- a/packages/sol-resolver/CHANGELOG.md +++ b/packages/sol-resolver/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.0.4 - _May 5, 2018_ +## v0.0.5 - _May 22, 2018_ + + * Dependencies updated + +## v0.0.4 - _May 4, 2018_ * Dependencies updated diff --git a/packages/sol-resolver/package.json b/packages/sol-resolver/package.json index 54d8308de..64a0f19ab 100644 --- a/packages/sol-resolver/package.json +++ b/packages/sol-resolver/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/sol-resolver", - "version": "0.0.4", + "version": "0.0.5", "engines": { "node": ">=6.12" }, @@ -24,8 +24,8 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/resolver/README.md", "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", "copyfiles": "^1.2.0", "make-promises-safe": "^1.1.0", "shx": "^0.2.2", @@ -33,7 +33,7 @@ "typescript": "2.7.1" }, "dependencies": { - "@0xproject/types": "^0.6.3", + "@0xproject/types": "^0.7.0", "@0xproject/typescript-typings": "^0.0.3", "lodash": "^4.17.4" }, diff --git a/packages/sol-resolver/src/resolvers/fs_resolver.ts b/packages/sol-resolver/src/resolvers/fs_resolver.ts index 4f05fba88..63fc3448e 100644 --- a/packages/sol-resolver/src/resolvers/fs_resolver.ts +++ b/packages/sol-resolver/src/resolvers/fs_resolver.ts @@ -7,7 +7,7 @@ import { Resolver } from './resolver'; export class FSResolver extends Resolver { // tslint:disable-next-line:prefer-function-over-method public resolveIfExists(importPath: string): ContractSource | undefined { - if (fs.existsSync(importPath)) { + if (fs.existsSync(importPath) && fs.lstatSync(importPath).isFile()) { const fileContent = fs.readFileSync(importPath).toString(); return { source: fileContent, diff --git a/packages/sol-resolver/src/resolvers/name_resolver.ts b/packages/sol-resolver/src/resolvers/name_resolver.ts index 76bed802e..e489c70a7 100644 --- a/packages/sol-resolver/src/resolvers/name_resolver.ts +++ b/packages/sol-resolver/src/resolvers/name_resolver.ts @@ -6,6 +6,8 @@ import { ContractSource } from '../types'; import { EnumerableResolver } from './enumerable_resolver'; +const SOLIDITY_FILE_EXTENSION = '.sol'; + export class NameResolver extends EnumerableResolver { private _contractsDir: string; constructor(contractsDir: string) { @@ -13,7 +15,6 @@ export class NameResolver extends EnumerableResolver { this._contractsDir = contractsDir; } public resolveIfExists(lookupContractName: string): ContractSource | undefined { - const SOLIDITY_FILE_EXTENSION = '.sol'; let contractSource: ContractSource | undefined; const onFile = (filePath: string) => { const contractName = path.basename(filePath, SOLIDITY_FILE_EXTENSION); @@ -32,7 +33,6 @@ export class NameResolver extends EnumerableResolver { return contractSource; } public getAll(): ContractSource[] { - const SOLIDITY_FILE_EXTENSION = '.sol'; const contractSources: ContractSource[] = []; const onFile = (filePath: string) => { const contractName = path.basename(filePath, SOLIDITY_FILE_EXTENSION); @@ -59,7 +59,12 @@ export class NameResolver extends EnumerableResolver { const absoluteEntryPath = path.join(dirPath, fileName); const isDirectory = fs.lstatSync(absoluteEntryPath).isDirectory(); const entryPath = path.relative(this._contractsDir, absoluteEntryPath); - const isComplete = isDirectory ? this._traverseContractsDir(absoluteEntryPath, onFile) : onFile(entryPath); + let isComplete; + if (isDirectory) { + isComplete = this._traverseContractsDir(absoluteEntryPath, onFile); + } else if (fileName.endsWith(SOLIDITY_FILE_EXTENSION)) { + isComplete = onFile(entryPath); + } if (isComplete) { return isComplete; } diff --git a/packages/sra-report/CHANGELOG.json b/packages/sra-report/CHANGELOG.json index 90a807c85..015279157 100644 --- a/packages/sra-report/CHANGELOG.json +++ b/packages/sra-report/CHANGELOG.json @@ -6,7 +6,8 @@ "note": "Properly export the executable binary", "pr": 588 } - ] + ], + "timestamp": 1527009133 }, { "timestamp": 1525477860, diff --git a/packages/sra-report/CHANGELOG.md b/packages/sra-report/CHANGELOG.md index e390e76ef..208a1e174 100644 --- a/packages/sra-report/CHANGELOG.md +++ b/packages/sra-report/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.0.14 - _May 5, 2018_ +## v0.1.0 - _May 22, 2018_ + + * Properly export the executable binary (#588) + +## v0.0.14 - _May 4, 2018_ * Dependencies updated diff --git a/packages/sra-report/package.json b/packages/sra-report/package.json index 9622acd2e..810acab1c 100644 --- a/packages/sra-report/package.json +++ b/packages/sra-report/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/sra-report", - "version": "0.0.14", + "version": "0.1.0", "engines": { "node": ">=6.12" }, @@ -31,20 +31,21 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/sra-report/README.md", "dependencies": { - "0x.js": "^0.37.2", - "@0xproject/assert": "^0.2.9", - "@0xproject/connect": "^0.6.12", - "@0xproject/json-schemas": "^0.7.23", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", + "@0xproject/assert": "^0.2.10", + "@0xproject/types": "^0.7.0", + "@0xproject/order-utils": "^0.0.5", + "@0xproject/connect": "^0.6.13", + "@0xproject/json-schemas": "^0.7.24", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", "chalk": "^2.3.0", "lodash": "^4.17.4", "newman": "^3.9.3", "yargs": "^10.0.3" }, "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.48", "@types/nock": "^9.1.2", diff --git a/packages/sra-report/src/index.ts b/packages/sra-report/src/index.ts index 9a203b654..3b72ad44e 100644 --- a/packages/sra-report/src/index.ts +++ b/packages/sra-report/src/index.ts @@ -13,7 +13,18 @@ import { postmanEnvironmentFactory } from './postman_environment_factory'; import { utils } from './utils'; const DEFAULT_NETWORK_ID = 1; -const SUPPORTED_NETWORK_IDS = [1, 3, 4, 42]; +const networkNameToId: { [networkName: string]: number } = { + mainnet: 1, + ropsten: 3, + rinkeby: 4, + kovan: 42, +}; +const SUPPORTED_NETWORK_IDS = [ + networkNameToId.mainnet, + networkNameToId.ropsten, + networkNameToId.rinkeby, + networkNameToId.kovan, +]; // extract command line arguments const args = yargs diff --git a/packages/sra-report/src/postman_environment_factory.ts b/packages/sra-report/src/postman_environment_factory.ts index 42389aea2..f8fe02d72 100644 --- a/packages/sra-report/src/postman_environment_factory.ts +++ b/packages/sra-report/src/postman_environment_factory.ts @@ -1,6 +1,7 @@ -import { SignedOrder, ZeroEx } from '0x.js'; import { HttpClient } from '@0xproject/connect'; import { Schema, schemas as schemasByName } from '@0xproject/json-schemas'; +import { getOrderHashHex } from '@0xproject/order-utils'; +import { SignedOrder } from '@0xproject/types'; import { logUtils } from '@0xproject/utils'; import chalk from 'chalk'; import * as _ from 'lodash'; @@ -11,6 +12,12 @@ import { addresses as rinkebyAddresses } from './contract_addresses/rinkeby_addr import { addresses as ropstenAddresses } from './contract_addresses/ropsten_addresses'; const ENVIRONMENT_NAME = 'SRA Report'; +const networkNameToId: { [networkName: string]: number } = { + mainnet: 1, + ropsten: 3, + rinkeby: 4, + kovan: 42, +}; export interface EnvironmentValue { key: string; @@ -92,7 +99,7 @@ async function createOrderEnvironmentValuesAsync(url: string): Promise<Environme createEnvironmentValue('orderMaker', orderIfExists.maker), createEnvironmentValue('orderTaker', orderIfExists.taker), createEnvironmentValue('orderFeeRecipient', orderIfExists.feeRecipient), - createEnvironmentValue('orderHash', ZeroEx.getOrderHashHex(orderIfExists)), + createEnvironmentValue('orderHash', getOrderHashHex(orderIfExists)), ]; } else { logUtils.log(`${chalk.red(`No orders from /orders found`)}`); @@ -107,13 +114,13 @@ async function createOrderEnvironmentValuesAsync(url: string): Promise<Environme } function getContractAddresses(networkId: number): Addresses { switch (networkId) { - case 1: + case networkNameToId.mainnet: return mainnetAddresses; - case 3: + case networkNameToId.ropsten: return ropstenAddresses; - case 4: + case networkNameToId.rinkeby: return rinkebyAddresses; - case 42: + case networkNameToId.kovan: return kovanAddresses; default: throw new Error('Unsupported network id'); diff --git a/packages/sra-report/test/test_runner.ts b/packages/sra-report/test/test_runner.ts index 5ea3cdc4d..fe238e98a 100644 --- a/packages/sra-report/test/test_runner.ts +++ b/packages/sra-report/test/test_runner.ts @@ -24,6 +24,7 @@ const expect = chai.expect; const CONTENT_TYPE_ASSERTION_NAME = 'Has Content-Type header with value application/json'; const SCHEMA_ASSERTION_NAME = 'Schema is valid'; +const SUCCESS_STATUS = 200; const baseNewmanRunOptions = { collection: sraReportCollectionJSON, environment: postmanEnvironmentJSON, @@ -46,7 +47,7 @@ export const testRunner = { }; describe(CONTENT_TYPE_ASSERTION_NAME, () => { it('fails when there are no headers', async () => { - nockInterceptor.reply(200, {}); + nockInterceptor.reply(SUCCESS_STATUS, {}); const summary = await utils.newmanRunAsync(newmanRunOptions); const error = findAssertionErrorIfExists( summary, @@ -61,7 +62,7 @@ export const testRunner = { const headers = { 'Content-Type': 'text/html', }; - nockInterceptor.reply(200, {}, headers); + nockInterceptor.reply(SUCCESS_STATUS, {}, headers); const summary = await utils.newmanRunAsync(newmanRunOptions); const error = findAssertionErrorIfExists( summary, @@ -76,7 +77,7 @@ export const testRunner = { const headers = { 'Content-Type': 'charset=utf-8; application/json', }; - nockInterceptor.reply(200, {}, headers); + nockInterceptor.reply(SUCCESS_STATUS, {}, headers); const summary = await utils.newmanRunAsync(newmanRunOptions); const error = findAssertionErrorIfExists( summary, @@ -100,7 +101,7 @@ export const testRunner = { }; describe(SCHEMA_ASSERTION_NAME, () => { it('fails when schema is invalid', async () => { - nockInterceptor.reply(200, malformedJson); + nockInterceptor.reply(SUCCESS_STATUS, malformedJson); const summary = await utils.newmanRunAsync(newmanRunOptions); const error = findAssertionErrorIfExists(summary, postmanCollectionRequestName, SCHEMA_ASSERTION_NAME); const errorMessage = _.get(error, 'message'); @@ -108,7 +109,7 @@ export const testRunner = { expect(errorMessage).to.equal('expected false to be true'); }); it('passes when schema is valid', async () => { - nockInterceptor.reply(200, correctJson); + nockInterceptor.reply(SUCCESS_STATUS, correctJson); const summary = await utils.newmanRunAsync(newmanRunOptions); const error = findAssertionErrorIfExists(summary, postmanCollectionRequestName, SCHEMA_ASSERTION_NAME); const errorMessage = _.get(error, 'message'); diff --git a/packages/subproviders/CHANGELOG.json b/packages/subproviders/CHANGELOG.json index 799c2c99a..d3bf79ac4 100644 --- a/packages/subproviders/CHANGELOG.json +++ b/packages/subproviders/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1527009133, + "version": "0.10.2", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1525477860, "version": "0.10.1", "changes": [ diff --git a/packages/subproviders/CHANGELOG.md b/packages/subproviders/CHANGELOG.md index 22a5f90e8..8c4990a7c 100644 --- a/packages/subproviders/CHANGELOG.md +++ b/packages/subproviders/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.10.1 - _May 5, 2018_ +## v0.10.2 - _May 22, 2018_ + + * Dependencies updated + +## v0.10.1 - _May 4, 2018_ * Dependencies updated diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json index 21e47b85a..3cd5f0e9b 100644 --- a/packages/subproviders/package.json +++ b/packages/subproviders/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/subproviders", - "version": "0.10.1", + "version": "0.10.2", "engines": { "node": ">=6.12" }, @@ -39,10 +39,10 @@ } }, "dependencies": { - "@0xproject/assert": "^0.2.9", - "@0xproject/types": "^0.6.3", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", + "@0xproject/assert": "^0.2.10", + "@0xproject/types": "^0.7.0", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", "@ledgerhq/hw-app-eth": "^4.3.0", "@ledgerhq/hw-transport-u2f": "^4.3.0", "bip39": "^2.5.0", @@ -57,9 +57,9 @@ "web3-provider-engine": "^14.0.4" }, "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/tslint-config": "^0.4.17", - "@0xproject/utils": "^0.6.1", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", + "@0xproject/utils": "^0.6.2", "@types/bip39": "^2.4.0", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", diff --git a/packages/subproviders/src/index.ts b/packages/subproviders/src/index.ts index ff28b8a8d..6cc650a4d 100644 --- a/packages/subproviders/src/index.ts +++ b/packages/subproviders/src/index.ts @@ -4,6 +4,7 @@ export { ECSignature } from '@0xproject/types'; import { LedgerEthereumClient } from './types'; +export { prependSubprovider } from './utils/subprovider_utils'; export { EmptyWalletSubprovider } from './subproviders/empty_wallet_subprovider'; export { FakeGasEstimateSubprovider } from './subproviders/fake_gas_estimate_subprovider'; export { InjectedWeb3Subprovider } from './subproviders/injected_web3'; diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts index 347eda55f..467299db0 100644 --- a/packages/subproviders/src/subproviders/ledger.ts +++ b/packages/subproviders/src/subproviders/ledger.ts @@ -113,9 +113,12 @@ export class LedgerSubprovider extends BaseWalletSubprovider { const tx = new EthereumTx(txParams); // Set the EIP155 bits - tx.raw[6] = Buffer.from([this._networkId]); // v - tx.raw[7] = Buffer.from([]); // r - tx.raw[8] = Buffer.from([]); // s + const vIndex = 6; + tx.raw[vIndex] = Buffer.from([this._networkId]); // v + const rIndex = 7; + tx.raw[rIndex] = Buffer.from([]); // r + const sIndex = 8; + tx.raw[sIndex] = Buffer.from([]); // s const txHex = tx.serialize().toString('hex'); try { @@ -127,7 +130,8 @@ export class LedgerSubprovider extends BaseWalletSubprovider { tx.v = Buffer.from(result.v, 'hex'); // EIP155: v should be chain_id * 2 + {35, 36} - const signedChainId = Math.floor((tx.v[0] - 35) / 2); + const eip55Constant = 35; + const signedChainId = Math.floor((tx.v[0] - eip55Constant) / 2); if (signedChainId !== this._networkId) { await this._destroyLedgerClientAsync(); const err = new Error(LedgerSubproviderErrors.TooOldLedgerFirmware); @@ -169,8 +173,10 @@ export class LedgerSubprovider extends BaseWalletSubprovider { fullDerivationPath, ethUtil.stripHexPrefix(data), ); - const v = result.v - 27; - let vHex = v.toString(16); + const lowestValidV = 27; + const v = result.v - lowestValidV; + const hexBase = 16; + let vHex = v.toString(hexBase); if (vHex.length < 2) { vHex = `0${v}`; } diff --git a/packages/subproviders/src/subproviders/nonce_tracker.ts b/packages/subproviders/src/subproviders/nonce_tracker.ts index 907330111..345e5e975 100644 --- a/packages/subproviders/src/subproviders/nonce_tracker.ts +++ b/packages/subproviders/src/subproviders/nonce_tracker.ts @@ -93,7 +93,8 @@ export class NonceTrackerSubprovider extends Subprovider { // Increment the nonce from the previous successfully submitted transaction let nonce = ethUtil.bufferToInt(transaction.nonce); nonce++; - let nextHexNonce = nonce.toString(16); + const hexBase = 16; + let nextHexNonce = nonce.toString(hexBase); if (nextHexNonce.length % 2) { nextHexNonce = `0${nextHexNonce}`; } diff --git a/packages/subproviders/src/subproviders/subprovider.ts b/packages/subproviders/src/subproviders/subprovider.ts index 56d2381a0..cb6dffc4a 100644 --- a/packages/subproviders/src/subproviders/subprovider.ts +++ b/packages/subproviders/src/subproviders/subprovider.ts @@ -13,10 +13,11 @@ export abstract class Subprovider { // Ported from: https://github.com/MetaMask/provider-engine/blob/master/util/random-id.js private static _getRandomId(): number { const extraDigits = 3; + const baseTen = 10; // 13 time digits - const datePart = new Date().getTime() * Math.pow(10, extraDigits); + const datePart = new Date().getTime() * Math.pow(baseTen, extraDigits); // 3 random digits - const extraPart = Math.floor(Math.random() * Math.pow(10, extraDigits)); + const extraPart = Math.floor(Math.random() * Math.pow(baseTen, extraDigits)); // 16 digits return datePart + extraPart; } diff --git a/packages/subproviders/src/utils/subprovider_utils.ts b/packages/subproviders/src/utils/subprovider_utils.ts new file mode 100644 index 000000000..24ebedd06 --- /dev/null +++ b/packages/subproviders/src/utils/subprovider_utils.ts @@ -0,0 +1,15 @@ +import ProviderEngine = require('web3-provider-engine'); + +import { Subprovider } from '../subproviders/subprovider'; + +/** + * Prepends a subprovider to a provider + * @param provider Given provider + * @param subprovider Subprovider to prepend + */ +export function prependSubprovider(provider: ProviderEngine, subprovider: Subprovider): void { + subprovider.setEngine(provider); + // HACK: We use implementation details of provider engine here + // https://github.com/MetaMask/provider-engine/blob/master/index.js#L68 + (provider as any)._providers = [subprovider, ...(provider as any)._providers]; +} diff --git a/packages/subproviders/src/utils/wallet_utils.ts b/packages/subproviders/src/utils/wallet_utils.ts index cd5cd9ba0..c36fdb9fc 100644 --- a/packages/subproviders/src/utils/wallet_utils.ts +++ b/packages/subproviders/src/utils/wallet_utils.ts @@ -30,10 +30,10 @@ class DerivedHDKeyInfoIterator implements IterableIterator<DerivedHDKeyInfo> { baseDerivationPath, derivationPath: fullDerivationPath, }; - const done = this._index === this._searchLimit; + const isDone = this._index === this._searchLimit; this._index++; return { - done, + done: isDone, value: derivedKey, }; } diff --git a/packages/subproviders/test/integration/ledger_subprovider_test.ts b/packages/subproviders/test/integration/ledger_subprovider_test.ts index 70fd2cfce..d3e9d0fde 100644 --- a/packages/subproviders/test/integration/ledger_subprovider_test.ts +++ b/packages/subproviders/test/integration/ledger_subprovider_test.ts @@ -20,6 +20,8 @@ import { reportCallbackErrors } from '../utils/report_callback_errors'; chaiSetup.configure(); const expect = chai.expect; +const DEFAULT_NUM_ACCOUNTS = 10; +const EXPECTED_SIGNATURE_LENGTH = 132; async function ledgerEthereumNodeJsClientFactoryAsync(): Promise<LedgerEthereumClient> { const ledgerConnection = await TransportNodeHid.create(); @@ -41,7 +43,7 @@ describe('LedgerSubprovider', () => { it('returns default number of accounts', async () => { const accounts = await ledgerSubprovider.getAccountsAsync(); expect(accounts[0]).to.not.be.an('undefined'); - expect(accounts.length).to.be.equal(10); + expect(accounts.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); }); it('returns the expected accounts from a ledger set up with the test mnemonic', async () => { const accounts = await ledgerSubprovider.getAccountsAsync(); @@ -105,7 +107,7 @@ describe('LedgerSubprovider', () => { }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); - expect(response.result.length).to.be.equal(10); + expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); done(); }); ledgerProvider.sendAsync(payload, callback); @@ -123,7 +125,7 @@ describe('LedgerSubprovider', () => { }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); - expect(response.result.length).to.be.equal(132); + expect(response.result.length).to.be.equal(EXPECTED_SIGNATURE_LENGTH); expect(response.result.substr(0, 2)).to.be.equal('0x'); done(); }); @@ -143,7 +145,7 @@ describe('LedgerSubprovider', () => { }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); - expect(response.result.length).to.be.equal(132); + expect(response.result.length).to.be.equal(EXPECTED_SIGNATURE_LENGTH); expect(response.result.substr(0, 2)).to.be.equal('0x'); done(); }); @@ -197,7 +199,8 @@ describe('LedgerSubprovider', () => { const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); const result = response.result; - expect(result.length).to.be.equal(66); + const signedTxLength = 66; + expect(result.length).to.be.equal(signedTxLength); expect(result.substr(0, 2)).to.be.equal('0x'); done(); }); diff --git a/packages/subproviders/test/unit/ledger_subprovider_test.ts b/packages/subproviders/test/unit/ledger_subprovider_test.ts index 6455454cb..8571f7d11 100644 --- a/packages/subproviders/test/unit/ledger_subprovider_test.ts +++ b/packages/subproviders/test/unit/ledger_subprovider_test.ts @@ -21,6 +21,7 @@ import { reportCallbackErrors } from '../utils/report_callback_errors'; chaiSetup.configure(); const expect = chai.expect; const FAKE_ADDRESS = '0xb088a3bc93f71b4de97b9de773e9647645983688'; +const DEFAULT_NUM_ACCOUNTS = 10; describe('LedgerSubprovider', () => { const networkId: number = 42; @@ -73,7 +74,7 @@ describe('LedgerSubprovider', () => { it('returns default number of accounts', async () => { const accounts = await ledgerSubprovider.getAccountsAsync(); expect(accounts[0]).to.be.equal(FAKE_ADDRESS); - expect(accounts.length).to.be.equal(10); + expect(accounts.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); }); it('returns requested number of accounts', async () => { const numberOfAccounts = 20; @@ -119,7 +120,7 @@ describe('LedgerSubprovider', () => { }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); - expect(response.result.length).to.be.equal(10); + expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); expect(response.result[0]).to.be.equal(FAKE_ADDRESS); done(); }); @@ -176,7 +177,8 @@ describe('LedgerSubprovider', () => { }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); - expect(response.result.raw.length).to.be.equal(192); + const rawTxLength = 192; + expect(response.result.raw.length).to.be.equal(rawTxLength); expect(response.result.raw.substr(0, 2)).to.be.equal('0x'); done(); }); diff --git a/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts b/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts index 52b636ac2..90565181e 100644 --- a/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts +++ b/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts @@ -18,6 +18,7 @@ import { reportCallbackErrors } from '../utils/report_callback_errors'; chaiSetup.configure(); const expect = chai.expect; +const DEFAULT_NUM_ACCOUNTS = 10; describe('MnemonicWalletSubprovider', () => { let subprovider: MnemonicWalletSubprovider; @@ -33,7 +34,7 @@ describe('MnemonicWalletSubprovider', () => { const accounts = await subprovider.getAccountsAsync(); expect(accounts[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0); expect(accounts[1]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_1); - expect(accounts.length).to.be.equal(10); + expect(accounts.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); }); it('signs a personal message', async () => { const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING)); @@ -90,7 +91,7 @@ describe('MnemonicWalletSubprovider', () => { const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); expect(response.result[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0); - expect(response.result.length).to.be.equal(10); + expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); done(); }); provider.sendAsync(payload, callback); diff --git a/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts b/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts index f9c47f141..fdbbb332c 100644 --- a/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts +++ b/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts @@ -14,6 +14,7 @@ import { reportCallbackErrors } from '../utils/report_callback_errors'; const expect = chai.expect; chaiSetup.configure(); +const DEFAULT_NUM_ACCOUNTS = 10; describe('RedundantSubprovider', () => { let provider: Web3ProviderEngine; @@ -32,7 +33,7 @@ describe('RedundantSubprovider', () => { }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); - expect(response.result.length).to.be.equal(10); + expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); done(); }); provider.sendAsync(payload, callback); @@ -55,7 +56,7 @@ describe('RedundantSubprovider', () => { }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); - expect(response.result.length).to.be.equal(10); + expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); done(); }); provider.sendAsync(payload, callback); diff --git a/packages/testnet-faucets/package.json b/packages/testnet-faucets/package.json index db5fe75c7..c565d5b7d 100644 --- a/packages/testnet-faucets/package.json +++ b/packages/testnet-faucets/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@0xproject/testnet-faucets", - "version": "1.0.29", + "version": "1.0.30", "engines": { "node": ">=6.12" }, @@ -18,11 +18,11 @@ "author": "Fabio Berger", "license": "Apache-2.0", "dependencies": { - "0x.js": "^0.37.2", - "@0xproject/subproviders": "^0.10.1", - "@0xproject/types": "^0.6.3", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", + "0x.js": "^0.38.0", + "@0xproject/subproviders": "^0.10.2", + "@0xproject/types": "^0.7.0", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", "body-parser": "^1.17.1", "ethereumjs-tx": "^1.3.3", "ethereumjs-util": "^5.1.1", @@ -33,7 +33,7 @@ "web3-provider-engine": "^14.0.4" }, "devDependencies": { - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/tslint-config": "^0.4.18", "@types/body-parser": "^1.16.1", "@types/express": "^4.0.35", "@types/lodash": "4.14.104", diff --git a/packages/testnet-faucets/src/ts/constants.ts b/packages/testnet-faucets/src/ts/constants.ts new file mode 100644 index 000000000..c6370e3f6 --- /dev/null +++ b/packages/testnet-faucets/src/ts/constants.ts @@ -0,0 +1,5 @@ +export const constants = { + SUCCESS_STATUS: 200, + SERVICE_UNAVAILABLE_STATUS: 503, + BAD_REQUEST_STATUS: 400, +}; diff --git a/packages/testnet-faucets/src/ts/handler.ts b/packages/testnet-faucets/src/ts/handler.ts index 3858b5339..d5f0dc2f9 100644 --- a/packages/testnet-faucets/src/ts/handler.ts +++ b/packages/testnet-faucets/src/ts/handler.ts @@ -15,6 +15,7 @@ import ProviderEngine = require('web3-provider-engine'); import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); import { configs } from './configs'; +import { constants } from './constants'; import { DispatchQueue } from './dispatch_queue'; import { dispenseAssetTasks } from './dispense_asset_tasks'; import { rpcUrls } from './rpc_urls'; @@ -80,7 +81,7 @@ export class Handler { }; }); const payload = JSON.stringify(queueInfo); - res.status(200).send(payload); + res.status(constants.SUCCESS_STATUS).send(payload); } public dispenseEther(req: express.Request, res: express.Response): void { this._dispenseAsset(req, res, RequestedAssetType.ETH); @@ -120,11 +121,11 @@ export class Handler { } const didAddToQueue = networkConfig.dispatchQueue.add(dispenserTask); if (!didAddToQueue) { - res.status(503).send('QUEUE_IS_FULL'); + res.status(constants.SERVICE_UNAVAILABLE_STATUS).send('QUEUE_IS_FULL'); return; } logUtils.log(`Added ${recipient} to queue: ${requestedAssetType} networkId: ${networkId}`); - res.status(200).end(); + res.status(constants.SUCCESS_STATUS).end(); } private async _dispenseOrderAsync( req: express.Request, @@ -133,7 +134,7 @@ export class Handler { ): Promise<void> { const networkConfig = _.get(this._networkConfigByNetworkId, req.params.networkId); if (_.isUndefined(networkConfig)) { - res.status(400).send('UNSUPPORTED_NETWORK_ID'); + res.status(constants.BAD_REQUEST_STATUS).send('UNSUPPORTED_NETWORK_ID'); return; } const zeroEx = networkConfig.zeroEx; @@ -173,6 +174,6 @@ export class Handler { const signedOrderHash = ZeroEx.getOrderHashHex(signedOrder); const payload = JSON.stringify(signedOrder); logUtils.log(`Dispensed signed order: ${payload}`); - res.status(200).send(payload); + res.status(constants.SUCCESS_STATUS).send(payload); } } diff --git a/packages/testnet-faucets/src/ts/parameter_transformer.ts b/packages/testnet-faucets/src/ts/parameter_transformer.ts index 58bf154dc..b9929a0d9 100644 --- a/packages/testnet-faucets/src/ts/parameter_transformer.ts +++ b/packages/testnet-faucets/src/ts/parameter_transformer.ts @@ -3,6 +3,7 @@ import { NextFunction, Request, Response } from 'express'; import * as _ from 'lodash'; import { configs } from './configs'; +import { constants } from './constants'; import { rpcUrls } from './rpc_urls'; const DEFAULT_NETWORK_ID = 42; // kovan @@ -11,7 +12,7 @@ export const parameterTransformer = { transform(req: Request, res: Response, next: NextFunction): void { const recipientAddress = req.params.recipient; if (_.isUndefined(recipientAddress) || !addressUtils.isAddress(recipientAddress)) { - res.status(400).send('INVALID_RECIPIENT_ADDRESS'); + res.status(constants.BAD_REQUEST_STATUS).send('INVALID_RECIPIENT_ADDRESS'); return; } const lowerCaseRecipientAddress = recipientAddress.toLowerCase(); @@ -19,7 +20,7 @@ export const parameterTransformer = { const networkId = _.get(req.query, 'networkId', DEFAULT_NETWORK_ID); const rpcUrlIfExists = _.get(rpcUrls, networkId); if (_.isUndefined(rpcUrlIfExists)) { - res.status(400).send('UNSUPPORTED_NETWORK_ID'); + res.status(constants.BAD_REQUEST_STATUS).send('UNSUPPORTED_NETWORK_ID'); return; } req.params.networkId = networkId; diff --git a/packages/testnet-faucets/src/ts/server.ts b/packages/testnet-faucets/src/ts/server.ts index 198a5fdc9..55c1d55d8 100644 --- a/packages/testnet-faucets/src/ts/server.ts +++ b/packages/testnet-faucets/src/ts/server.ts @@ -1,6 +1,7 @@ import * as bodyParser from 'body-parser'; import * as express from 'express'; +import { constants } from './constants'; import { errorReporter } from './error_reporter'; import { Handler } from './handler'; import { parameterTransformer } from './parameter_transformer'; @@ -18,7 +19,7 @@ app.use((req, res, next) => { const handler = new Handler(); app.get('/ping', (req: express.Request, res: express.Response) => { - res.status(200).send('pong'); + res.status(constants.SUCCESS_STATUS).send('pong'); }); app.get('/info', handler.getQueueInfo.bind(handler)); app.get('/ether/:recipient', parameterTransformer.transform, handler.dispenseEther.bind(handler)); @@ -28,5 +29,6 @@ app.get('/order/zrx/:recipient', parameterTransformer.transform, handler.dispens // Log to rollbar any errors unhandled by handlers app.use(errorReporter.errorHandler()); -const port = process.env.PORT || 3000; +const DEFAULT_PORT = 3000; +const port = process.env.PORT || DEFAULT_PORT; app.listen(port); diff --git a/packages/tslint-config/CHANGELOG.json b/packages/tslint-config/CHANGELOG.json index ac59f7b19..4868b3983 100644 --- a/packages/tslint-config/CHANGELOG.json +++ b/packages/tslint-config/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1527009133, + "version": "0.4.18", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1525428773, "version": "0.4.17", "changes": [ diff --git a/packages/tslint-config/CHANGELOG.md b/packages/tslint-config/CHANGELOG.md index 6f5042a52..56b65cadd 100644 --- a/packages/tslint-config/CHANGELOG.md +++ b/packages/tslint-config/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.4.18 - _May 22, 2018_ + + * Dependencies updated + ## v0.4.17 - _May 4, 2018_ * Dependencies updated diff --git a/packages/tslint-config/package.json b/packages/tslint-config/package.json index 317ae4591..a64feb836 100644 --- a/packages/tslint-config/package.json +++ b/packages/tslint-config/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/tslint-config", - "version": "0.4.17", + "version": "0.4.18", "engines": { "node": ">=6.12" }, @@ -34,7 +34,7 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/tslint-config/README.md", "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.19", + "@0xproject/monorepo-scripts": "^0.1.20", "@types/lodash": "4.14.104", "copyfiles": "^1.2.0", "make-promises-safe": "^1.1.0", @@ -45,7 +45,8 @@ "lodash": "^4.17.4", "tslint": "5.8.0", "tslint-eslint-rules": "^4.1.1", - "tslint-react": "^3.2.0" + "tslint-react": "^3.2.0", + "tsutils": "2.22.2" }, "publishConfig": { "access": "public" diff --git a/packages/tslint-config/rules/booleanNamingRule.ts b/packages/tslint-config/rules/booleanNamingRule.ts new file mode 100644 index 000000000..a8e1dc390 --- /dev/null +++ b/packages/tslint-config/rules/booleanNamingRule.ts @@ -0,0 +1,68 @@ +import * as _ from 'lodash'; +import * as Lint from 'tslint'; +import * as ts from 'typescript'; + +const VALID_BOOLEAN_PREFIXES = ['is', 'does', 'should', 'was', 'has', 'can', 'did', 'would', 'are']; + +export class Rule extends Lint.Rules.TypedRule { + public static FAILURE_STRING = `Boolean variable names should begin with: ${VALID_BOOLEAN_PREFIXES.join(', ')}`; + + public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] { + return this.applyWithFunction(sourceFile, walk, undefined, program.getTypeChecker()); + } +} + +function walk(ctx: Lint.WalkContext<void>, tc: ts.TypeChecker): void { + traverse(ctx.sourceFile); + + function traverse(node: ts.Node): void { + checkNodeForViolations(ctx, node, tc); + return ts.forEachChild(node, traverse); + } +} + +function checkNodeForViolations(ctx: Lint.WalkContext<void>, node: ts.Node, tc: ts.TypeChecker): void { + switch (node.kind) { + // Handle: const { timestamp } = ... + case ts.SyntaxKind.BindingElement: { + const bindingElementNode = node as ts.BindingElement; + if (bindingElementNode.name.kind === ts.SyntaxKind.Identifier) { + handleBooleanNaming(bindingElementNode, tc, ctx); + } + break; + } + + // Handle regular assignments: const block = ... + case ts.SyntaxKind.VariableDeclaration: + const variableDeclarationNode = node as ts.VariableDeclaration; + if (variableDeclarationNode.name.kind === ts.SyntaxKind.Identifier) { + handleBooleanNaming(node as ts.VariableDeclaration, tc, ctx); + } + break; + + default: + _.noop(); + } +} + +function handleBooleanNaming( + node: ts.VariableDeclaration | ts.BindingElement, + tc: ts.TypeChecker, + ctx: Lint.WalkContext<void>, +): void { + const nodeName = node.name; + const variableName = nodeName.getText(); + const lowercasedName = _.toLower(variableName); + const typeNode = tc.getTypeAtLocation(node); + const typeName = (typeNode as any).intrinsicName; + if (typeName === 'boolean') { + const hasProperName = !_.isUndefined( + _.find(VALID_BOOLEAN_PREFIXES, prefix => { + return _.startsWith(lowercasedName, prefix); + }), + ); + if (!hasProperName) { + ctx.addFailureAtNode(node, Rule.FAILURE_STRING); + } + } +} diff --git a/packages/tslint-config/rules/customNoMagicNumbersRule.ts b/packages/tslint-config/rules/customNoMagicNumbersRule.ts new file mode 100644 index 000000000..e358221eb --- /dev/null +++ b/packages/tslint-config/rules/customNoMagicNumbersRule.ts @@ -0,0 +1,76 @@ +import * as Lint from 'tslint'; +import { isPrefixUnaryExpression } from 'tsutils'; +import * as ts from 'typescript'; + +/** + * A modified version of the no-magic-numbers rule that allows for magic numbers + * when instantiating a BigNumber instance. + * E.g We want to be able to write: + * const amount = new BigNumber(5); + * Original source: https://github.com/palantir/tslint/blob/42b058a6baa688f8be8558b277eb056c3ff79818/src/rules/noMagicNumbersRule.ts + */ +export class Rule extends Lint.Rules.AbstractRule { + public static ALLOWED_NODES = new Set<ts.SyntaxKind>([ + ts.SyntaxKind.ExportAssignment, + ts.SyntaxKind.FirstAssignment, + ts.SyntaxKind.LastAssignment, + ts.SyntaxKind.PropertyAssignment, + ts.SyntaxKind.ShorthandPropertyAssignment, + ts.SyntaxKind.VariableDeclaration, + ts.SyntaxKind.VariableDeclarationList, + ts.SyntaxKind.EnumMember, + ts.SyntaxKind.PropertyDeclaration, + ts.SyntaxKind.Parameter, + ]); + + public static DEFAULT_ALLOWED = [-1, 0, 1]; + + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + const allowedNumbers = this.ruleArguments.length > 0 ? this.ruleArguments : Rule.DEFAULT_ALLOWED; + return this.applyWithWalker( + new CustomNoMagicNumbersWalker(sourceFile, this.ruleName, new Set(allowedNumbers.map(String))), + ); + } +} + +// tslint:disable-next-line:max-classes-per-file +class CustomNoMagicNumbersWalker extends Lint.AbstractWalker<Set<string>> { + public static FAILURE_STRING = "'magic numbers' are not allowed"; + private static _isNegativeNumberLiteral( + node: ts.Node, + ): node is ts.PrefixUnaryExpression & { operand: ts.NumericLiteral } { + return ( + isPrefixUnaryExpression(node) && + node.operator === ts.SyntaxKind.MinusToken && + node.operand.kind === ts.SyntaxKind.NumericLiteral + ); + } + public walk(sourceFile: ts.SourceFile): void { + const cb = (node: ts.Node): void => { + if (node.kind === ts.SyntaxKind.NumericLiteral) { + return this.checkNumericLiteral(node, (node as ts.NumericLiteral).text); + } + if (CustomNoMagicNumbersWalker._isNegativeNumberLiteral(node)) { + return this.checkNumericLiteral(node, `-${(node.operand as ts.NumericLiteral).text}`); + } + return ts.forEachChild(node, cb); + }; + return ts.forEachChild(sourceFile, cb); + } + + // tslint:disable:no-non-null-assertion + // tslint:disable-next-line:underscore-private-and-protected + private checkNumericLiteral(node: ts.Node, num: string): void { + if (!Rule.ALLOWED_NODES.has(node.parent!.kind) && !this.options.has(num)) { + if (node.parent!.kind === ts.SyntaxKind.NewExpression) { + const className = (node.parent! as any).expression.escapedText; + const BIG_NUMBER_NEW_EXPRESSION = 'BigNumber'; + if (className === BIG_NUMBER_NEW_EXPRESSION) { + return; // noop + } + } + this.addFailureAtNode(node, CustomNoMagicNumbersWalker.FAILURE_STRING); + } + } + // tslint:enable:no-non-null-assertion +} diff --git a/packages/tslint-config/tslint.json b/packages/tslint-config/tslint.json index 1d717430d..77a1f41cc 100644 --- a/packages/tslint-config/tslint.json +++ b/packages/tslint-config/tslint.json @@ -5,7 +5,10 @@ "arrow-parens": [true, "ban-single-arg-parens"], "arrow-return-shorthand": true, "async-suffix": true, + "boolean-naming": true, + "no-switch-case-fall-through": true, "await-promise": true, + "custom-no-magic-numbers": [true, 0, 1, 2, 3, -1], "binary-expression-operand-order": true, "callable-types": true, "class-name": true, diff --git a/packages/types/CHANGELOG.json b/packages/types/CHANGELOG.json index afcfd862c..8abc5bd99 100644 --- a/packages/types/CHANGELOG.json +++ b/packages/types/CHANGELOG.json @@ -3,11 +3,16 @@ "version": "0.7.0", "changes": [ { + "note": "Make OpCode type an enum", + "pr": 589 + }, + { "note": "Moved ExchangeContractErrs, DoneCallback, Token, OrderRelevantState, OrderStateValid, OrderStateInvalid, OrderState, OrderAddresses and OrderValues types from 0x.js", "pr": 579 } - ] + ], + "timestamp": 1527009133 }, { "timestamp": 1525477860, diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md index edfd42269..68e5ed438 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.6.3 - _May 5, 2018_ +## v0.7.0 - _May 22, 2018_ + + * Moved ExchangeContractErrs, DoneCallback, Token, OrderRelevantState, OrderStateValid, OrderStateInvalid, OrderState, OrderAddresses and OrderValues types from 0x.js (#579) + +## v0.6.3 - _May 4, 2018_ * Dependencies updated diff --git a/packages/types/package.json b/packages/types/package.json index edd17c42c..0968c6b7a 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/types", - "version": "0.6.3", + "version": "0.7.0", "engines": { "node": ">=6.12" }, @@ -24,8 +24,8 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/types/README.md", "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", "copyfiles": "^1.2.0", "make-promises-safe": "^1.1.0", "shx": "^0.2.2", diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index f28c2f9a3..055c47e0a 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -58,7 +58,18 @@ export interface DataItem { components?: DataItem[]; } -export type OpCode = string; +export enum OpCode { + DelegateCall = 'DELEGATECALL', + Revert = 'REVERT', + Create = 'CREATE', + Stop = 'STOP', + Invalid = 'INVALID', + CallCode = 'CALLCODE', + StaticCall = 'STATICCALL', + Return = 'RETURN', + Call = 'CALL', + SelfDestruct = 'SELFDESTRUCT', +} export interface StructLog { depth: number; diff --git a/packages/typescript-typings/CHANGELOG.json b/packages/typescript-typings/CHANGELOG.json index 84b92b56c..2e2998bb3 100644 --- a/packages/typescript-typings/CHANGELOG.json +++ b/packages/typescript-typings/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1527009133, + "version": "0.3.2", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1525477860, "version": "0.3.1", "changes": [ diff --git a/packages/typescript-typings/CHANGELOG.md b/packages/typescript-typings/CHANGELOG.md index ad7622071..e12ce63f2 100644 --- a/packages/typescript-typings/CHANGELOG.md +++ b/packages/typescript-typings/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.3.1 - _May 5, 2018_ +## v0.3.2 - _May 22, 2018_ + + * Dependencies updated + +## v0.3.1 - _May 4, 2018_ * Dependencies updated diff --git a/packages/typescript-typings/package.json b/packages/typescript-typings/package.json index 986acfcee..932f89ec5 100644 --- a/packages/typescript-typings/package.json +++ b/packages/typescript-typings/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/typescript-typings", - "version": "0.3.1", + "version": "0.3.2", "engines": { "node": ">=6.12" }, @@ -25,11 +25,11 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/typescript-typings#readme", "dependencies": { - "@0xproject/types": "^0.6.3", + "@0xproject/types": "^0.7.0", "bignumber.js": "~4.1.0" }, "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.19", + "@0xproject/monorepo-scripts": "^0.1.20", "copyfiles": "^1.2.0", "make-promises-safe": "^1.1.0", "shx": "^0.2.2" diff --git a/packages/typescript-typings/types/web3-provider-engine/index.d.ts b/packages/typescript-typings/types/web3-provider-engine/index.d.ts index 15a8d0005..8d5aef749 100644 --- a/packages/typescript-typings/types/web3-provider-engine/index.d.ts +++ b/packages/typescript-typings/types/web3-provider-engine/index.d.ts @@ -1,8 +1,12 @@ declare module 'web3-provider-engine' { - class Web3ProviderEngine { + import { Provider, JSONRPCRequestPayload, JSONRPCResponsePayload } from '@0xproject/types'; + class Web3ProviderEngine implements Provider { public on(event: string, handler: () => void): void; - public send(payload: any): void; - public sendAsync(payload: any, callback: (error: any, response: any) => void): void; + public send(payload: JSONRPCRequestPayload): void; + public sendAsync( + payload: JSONRPCRequestPayload, + callback: (error: null | Error, response: JSONRPCResponsePayload) => void, + ): void; public addProvider(provider: any): void; public start(): void; public stop(): void; @@ -19,13 +23,13 @@ declare module 'web3-provider-engine/subproviders/subprovider' { export = Subprovider; } declare module 'web3-provider-engine/subproviders/rpc' { - import { JSONRPCRequestPayload } from '@0xproject/types'; + import { JSONRPCRequestPayload, JSONRPCResponsePayload } from '@0xproject/types'; class RpcSubprovider { constructor(options: { rpcUrl: string }); public handleRequest( payload: JSONRPCRequestPayload, next: () => void, - end: (err: Error | null, data?: any) => void, + end: (err: Error | null, data?: JSONRPCResponsePayload) => void, ): void; } export = RpcSubprovider; @@ -37,13 +41,13 @@ declare module 'web3-provider-engine/util/rpc-cache-utils' { export = ProviderEngineRpcUtils; } declare module 'web3-provider-engine/subproviders/fixture' { - import { JSONRPCRequestPayload } from '@0xproject/types'; + import { JSONRPCRequestPayload, JSONRPCResponsePayload } from '@0xproject/types'; class FixtureSubprovider { constructor(staticResponses: any); public handleRequest( payload: JSONRPCRequestPayload, next: () => void, - end: (err: Error | null, data?: any) => void, + end: (err: Error | null, data?: JSONRPCResponsePayload) => void, ): void; } export = FixtureSubprovider; diff --git a/packages/utils/CHANGELOG.json b/packages/utils/CHANGELOG.json index d3c7da7b9..616a17d62 100644 --- a/packages/utils/CHANGELOG.json +++ b/packages/utils/CHANGELOG.json @@ -1,5 +1,23 @@ [ { + "timestamp": 1527009133, + "version": "0.6.2", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { + "version": "0.7.0", + "changes": [ + { + "note": "Add logUtils.warn", + "pr": 589 + } + ] + }, + { "timestamp": 1525477860, "version": "0.6.1", "changes": [ diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md index 92e466b17..0c01bf4f1 100644 --- a/packages/utils/CHANGELOG.md +++ b/packages/utils/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.6.1 - _May 5, 2018_ +## v0.6.2 - _May 22, 2018_ + + * Dependencies updated + +## v0.6.1 - _May 4, 2018_ * Dependencies updated diff --git a/packages/utils/package.json b/packages/utils/package.json index 66dc682fa..24551dd93 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/utils", - "version": "0.6.1", + "version": "0.6.2", "engines": { "node": ">=6.12" }, @@ -24,8 +24,8 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/utils/README.md", "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", "@types/lodash": "4.14.104", "copyfiles": "^1.2.0", "make-promises-safe": "^1.1.0", @@ -35,9 +35,10 @@ "typescript": "2.7.1" }, "dependencies": { - "@0xproject/types": "^0.6.3", - "@0xproject/typescript-typings": "^0.3.1", + "@0xproject/types": "^0.7.0", + "@0xproject/typescript-typings": "^0.3.2", "@types/node": "^8.0.53", + "ethereumjs-util": "^5.1.1", "bignumber.js": "~4.1.0", "ethers": "^3.0.15", "js-sha3": "^0.7.0", diff --git a/packages/utils/src/abi_decoder.ts b/packages/utils/src/abi_decoder.ts index d329f917a..d2d8364ca 100644 --- a/packages/utils/src/abi_decoder.ts +++ b/packages/utils/src/abi_decoder.ts @@ -12,20 +12,12 @@ import { import * as ethers from 'ethers'; import * as _ from 'lodash'; +import { addressUtils } from './address_utils'; import { BigNumber } from './configured_bignumber'; export class AbiDecoder { private _savedABIs: AbiDefinition[] = []; private _methodIds: { [signatureHash: string]: EventAbi } = {}; - private static _padZeros(address: string): string { - let formatted = address; - if (_.startsWith(formatted, '0x')) { - formatted = formatted.slice(2); - } - - formatted = _.padStart(formatted, 40, '0'); - return `0x${formatted}`; - } constructor(abiArrays: AbiDefinition[][]) { _.forEach(abiArrays, this.addABI.bind(this)); } @@ -45,16 +37,17 @@ export class AbiDecoder { const dataTypes = _.map(nonIndexedInputs, input => input.type); const decodedData = ethersInterface.events[event.name].parse(log.data); - let failedToDecode = false; + let didFailToDecode = false; _.forEach(event.inputs, (param: EventParameter, i: number) => { // Indexed parameters are stored in topics. Non-indexed ones in decodedData let value: BigNumber | string | number = param.indexed ? log.topics[topicsIndex++] : decodedData[i]; if (_.isUndefined(value)) { - failedToDecode = true; + didFailToDecode = true; return; } if (param.type === SolidityTypes.Address) { - value = AbiDecoder._padZeros(new BigNumber(value).toString(16)); + const baseHex = 16; + value = addressUtils.padZeros(new BigNumber(value).toString(baseHex)); } else if (param.type === SolidityTypes.Uint256 || param.type === SolidityTypes.Uint) { value = new BigNumber(value); } else if (param.type === SolidityTypes.Uint8) { @@ -63,7 +56,7 @@ export class AbiDecoder { decodedParams[param.name] = value; }); - if (failedToDecode) { + if (didFailToDecode) { return log; } else { return { diff --git a/packages/utils/src/address_utils.ts b/packages/utils/src/address_utils.ts index f94985441..1fc960408 100644 --- a/packages/utils/src/address_utils.ts +++ b/packages/utils/src/address_utils.ts @@ -1,7 +1,10 @@ +import { addHexPrefix, stripHexPrefix } from 'ethereumjs-util'; import * as jsSHA3 from 'js-sha3'; +import * as _ from 'lodash'; const BASIC_ADDRESS_REGEX = /^(0x)?[0-9a-f]{40}$/i; const SAME_CASE_ADDRESS_REGEX = /^(0x)?([0-9a-f]{40}|[0-9A-F]{40})$/; +const ADDRESS_LENGTH = 40; export const addressUtils = { isChecksumAddress(address: string): boolean { @@ -9,11 +12,15 @@ export const addressUtils = { const unprefixedAddress = address.replace('0x', ''); const addressHash = jsSHA3.keccak256(unprefixedAddress.toLowerCase()); - for (let i = 0; i < 40; i++) { + for (let i = 0; i < ADDRESS_LENGTH; i++) { // The nth letter should be uppercase if the nth digit of casemap is 1 + const hexBase = 16; + const lowercaseRange = 7; if ( - (parseInt(addressHash[i], 16) > 7 && unprefixedAddress[i].toUpperCase() !== unprefixedAddress[i]) || - (parseInt(addressHash[i], 16) <= 7 && unprefixedAddress[i].toLowerCase() !== unprefixedAddress[i]) + (parseInt(addressHash[i], hexBase) > lowercaseRange && + unprefixedAddress[i].toUpperCase() !== unprefixedAddress[i]) || + (parseInt(addressHash[i], hexBase) <= lowercaseRange && + unprefixedAddress[i].toLowerCase() !== unprefixedAddress[i]) ) { return false; } @@ -33,4 +40,7 @@ export const addressUtils = { return isValidChecksummedAddress; } }, + padZeros(address: string): string { + return addHexPrefix(_.padStart(stripHexPrefix(address), ADDRESS_LENGTH, '0')); + }, }; diff --git a/packages/utils/src/interval_utils.ts b/packages/utils/src/interval_utils.ts index 6984bf42d..6784d5b35 100644 --- a/packages/utils/src/interval_utils.ts +++ b/packages/utils/src/interval_utils.ts @@ -6,18 +6,18 @@ export const intervalUtils = { intervalMs: number, onError: (err: Error) => void, ): NodeJS.Timer { - let locked = false; + let isLocked = false; const intervalId = setInterval(async () => { - if (locked) { + if (isLocked) { return; } else { - locked = true; + isLocked = true; try { await fn(); } catch (err) { onError(err); } - locked = false; + isLocked = false; } }, intervalMs); return intervalId; diff --git a/packages/utils/src/log_utils.ts b/packages/utils/src/log_utils.ts index d0f0e34c9..87f8479b5 100644 --- a/packages/utils/src/log_utils.ts +++ b/packages/utils/src/log_utils.ts @@ -2,4 +2,7 @@ export const logUtils = { log(...args: any[]): void { console.log(...args); // tslint:disable-line:no-console }, + warn(...args: any[]): void { + console.warn(...args); // tslint:disable-line:no-console + }, }; diff --git a/packages/web3-wrapper/CHANGELOG.json b/packages/web3-wrapper/CHANGELOG.json index 35e4383fd..b753ffbac 100644 --- a/packages/web3-wrapper/CHANGELOG.json +++ b/packages/web3-wrapper/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1527009133, + "version": "0.6.4", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1525477860, "version": "0.6.3", "changes": [ diff --git a/packages/web3-wrapper/CHANGELOG.md b/packages/web3-wrapper/CHANGELOG.md index 3358c9a01..4b8fb7bac 100644 --- a/packages/web3-wrapper/CHANGELOG.md +++ b/packages/web3-wrapper/CHANGELOG.md @@ -5,7 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG -## v0.6.3 - _May 5, 2018_ +## v0.6.4 - _May 22, 2018_ + + * Dependencies updated + +## v0.6.3 - _May 4, 2018_ * Dependencies updated diff --git a/packages/web3-wrapper/package.json b/packages/web3-wrapper/package.json index ed2fce7dc..18bbf14a0 100644 --- a/packages/web3-wrapper/package.json +++ b/packages/web3-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/web3-wrapper", - "version": "0.6.3", + "version": "0.6.4", "engines": { "node": ">=6.12" }, @@ -43,8 +43,8 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/web3-wrapper/README.md", "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/tslint-config": "^0.4.17", + "@0xproject/monorepo-scripts": "^0.1.20", + "@0xproject/tslint-config": "^0.4.18", "@types/lodash": "4.14.104", "chai": "^4.0.1", "chai-as-promised": "^7.1.0", @@ -62,9 +62,9 @@ "typescript": "2.7.1" }, "dependencies": { - "@0xproject/types": "^0.6.3", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", + "@0xproject/types": "^0.7.0", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", "ethers": "^3.0.15", "lodash": "^4.17.4", "web3": "^0.20.0" diff --git a/packages/web3-wrapper/src/web3_wrapper.ts b/packages/web3-wrapper/src/web3_wrapper.ts index c60d5fe33..91a1af870 100644 --- a/packages/web3-wrapper/src/web3_wrapper.ts +++ b/packages/web3-wrapper/src/web3_wrapper.ts @@ -19,6 +19,8 @@ import * as Web3 from 'web3'; import { Web3WrapperErrors } from './types'; +const BASE_TEN = 10; + /** * A wrapper around the Web3.js 0.x library that provides a consistent, clean promise-based interface. */ @@ -48,7 +50,7 @@ export class Web3Wrapper { * @return The amount in units. */ public static toUnitAmount(amount: BigNumber, decimals: number): BigNumber { - const aUnit = new BigNumber(10).pow(decimals); + const aUnit = new BigNumber(BASE_TEN).pow(decimals); const unit = amount.div(aUnit); return unit; } @@ -61,7 +63,7 @@ export class Web3Wrapper { * @return The amount in baseUnits. */ public static toBaseUnitAmount(amount: BigNumber, decimals: number): BigNumber { - const unit = new BigNumber(10).pow(decimals); + const unit = new BigNumber(BASE_TEN).pow(decimals); const baseUnitAmount = amount.times(unit); const hasDecimals = baseUnitAmount.decimalPlaces() !== 0; if (hasDecimals) { @@ -180,8 +182,8 @@ export class Web3Wrapper { public async doesContractExistAtAddressAsync(address: string): Promise<boolean> { const code = await promisify<string>(this._web3.eth.getCode)(address); // Regex matches 0x0, 0x00, 0x in order to accommodate poorly implemented clients - const codeIsEmpty = /^0x0{0,40}$/i.test(code); - return !codeIsEmpty; + const isCodeEmpty = /^0x0{0,40}$/i.test(code); + return !isCodeEmpty; } /** * Sign a message with a specific address's private key (`eth_sign`) @@ -336,16 +338,16 @@ export class Web3Wrapper { pollingIntervalMs: number = 1000, timeoutMs?: number, ): Promise<TransactionReceiptWithDecodedLogs> { - let timeoutExceeded = false; + let wasTimeoutExceeded = false; if (timeoutMs) { - setTimeout(() => (timeoutExceeded = true), timeoutMs); + setTimeout(() => (wasTimeoutExceeded = true), timeoutMs); } const txReceiptPromise = new Promise( (resolve: (receipt: TransactionReceiptWithDecodedLogs) => void, reject) => { const intervalId = intervalUtils.setAsyncExcludingInterval( async () => { - if (timeoutExceeded) { + if (wasTimeoutExceeded) { intervalUtils.clearAsyncExcludingInterval(intervalId); return reject(Web3WrapperErrors.TransactionMiningTimeout); } diff --git a/packages/website/package.json b/packages/website/package.json index 3ef66d269..a91437646 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/website", - "version": "0.0.32", + "version": "0.0.33", "engines": { "node": ">=6.12" }, @@ -11,20 +11,20 @@ "clean": "shx rm -f public/bundle*", "lint": "tslint --project . 'ts/**/*.ts' 'ts/**/*.tsx'", "watch": "webpack-dev-server --content-base public --https", - "deploy_dogfood": "npm run build; aws s3 sync ./public/. s3://dogfood-0xproject --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", + "deploy_dogfood": "npm run build; aws s3 sync ./public/. s3://dogfood.0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", "deploy_staging": "npm run build; aws s3 sync ./public/. s3://staging-0xproject --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", "deploy_live": "npm run build; aws s3 sync ./public/. s3://0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers" }, "author": "Fabio Berger", "license": "Apache-2.0", "dependencies": { - "0x.js": "^0.37.2", - "@0xproject/react-docs": "^0.0.11", - "@0xproject/react-shared": "^0.1.6", - "@0xproject/subproviders": "^0.10.1", - "@0xproject/typescript-typings": "^0.3.1", - "@0xproject/utils": "^0.6.1", - "@0xproject/web3-wrapper": "^0.6.3", + "@0xproject/react-docs": "^0.0.12", + "@0xproject/react-shared": "^0.1.7", + "@0xproject/subproviders": "^0.10.2", + "@0xproject/contract-wrappers": "^0.0.2", + "@0xproject/typescript-typings": "^0.3.2", + "@0xproject/utils": "^0.6.2", + "@0xproject/web3-wrapper": "^0.6.4", "accounting": "^0.4.1", "basscss": "^8.0.3", "blockies": "^0.0.2", @@ -88,6 +88,7 @@ "tslint": "5.8.0", "tslint-config-0xproject": "^0.0.2", "typescript": "2.7.1", + "uglifyjs-webpack-plugin": "^1.2.5", "webpack": "^3.1.0", "webpack-dev-middleware": "^1.10.0", "webpack-dev-server": "^2.5.0" diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 32acb9d43..d18f3b398 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -1,20 +1,15 @@ import { - BlockParam, BlockRange, + ContractWrappers, DecodedLogEvent, - ECSignature, ExchangeContractEventArgs, ExchangeEvents, IndexedFilterValues, LogCancelContractEventArgs, LogFillContractEventArgs, - LogWithDecodedArgs, - Order, - SignedOrder, Token as ZeroExToken, - TransactionReceiptWithDecodedLogs, - ZeroEx, -} from '0x.js'; +} from '@0xproject/contract-wrappers'; +import { isValidOrderHash, signOrderHashAsync } from '@0xproject/order-utils'; import { EtherscanLinkSuffixes, utils as sharedUtils } from '@0xproject/react-shared'; import { InjectedWeb3Subprovider, @@ -23,7 +18,15 @@ import { RedundantSubprovider, Subprovider, } from '@0xproject/subproviders'; -import { Provider } from '@0xproject/types'; +import { + BlockParam, + ECSignature, + LogWithDecodedArgs, + Order, + Provider, + SignedOrder, + TransactionReceiptWithDecodedLogs, +} from '@0xproject/types'; import { BigNumber, intervalUtils, logUtils, promisify } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; @@ -72,7 +75,7 @@ const providerToName: { [provider: string]: string } = { export class Blockchain { public networkId: number; public nodeVersion: string; - private _zeroEx: ZeroEx; + private _contractWrappers: ContractWrappers; private _dispatcher: Dispatcher; private _web3Wrapper?: Web3Wrapper; private _blockchainWatcher?: BlockchainWatcher; @@ -164,8 +167,8 @@ export class Blockchain { } } public async isAddressInTokenRegistryAsync(tokenAddress: string): Promise<boolean> { - utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); - const tokenIfExists = await this._zeroEx.tokenRegistry.getTokenIfExistsAsync(tokenAddress); + utils.assert(!_.isUndefined(this._contractWrappers), 'Contract Wrappers must be instantiated.'); + const tokenIfExists = await this._contractWrappers.tokenRegistry.getTokenIfExistsAsync(tokenAddress); return !_.isUndefined(tokenIfExists); } public getLedgerDerivationPathIfExists(): string { @@ -182,7 +185,7 @@ export class Blockchain { this._ledgerSubprovider.setPath(path); } public async updateProviderToLedgerAsync(networkId: number): Promise<void> { - utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); + utils.assert(!_.isUndefined(this._contractWrappers), 'Contract Wrappers must be instantiated.'); const isU2FSupported = await utils.isU2FSupportedAsync(); if (!isU2FSupported) { @@ -225,12 +228,12 @@ export class Blockchain { this.networkId, shouldPollUserAddress, ); - this._zeroEx.setProvider(provider, this.networkId); + this._contractWrappers.setProvider(provider, this.networkId); this._blockchainWatcher.startEmittingNetworkConnectionAndUserBalanceState(); this._dispatcher.updateProviderType(ProviderType.Ledger); } public async updateProviderToInjectedAsync(): Promise<void> { - utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); + utils.assert(!_.isUndefined(this._contractWrappers), 'Contract Wrappers must be instantiated.'); if (_.isUndefined(this._cachedProvider)) { return; // Going from injected to injected, so we noop @@ -253,7 +256,7 @@ export class Blockchain { const userAddresses = await this._web3Wrapper.getAvailableAddressesAsync(); this._userAddressIfExists = userAddresses[0]; - this._zeroEx.setProvider(provider, this.networkId); + this._contractWrappers.setProvider(provider, this.networkId); await this.fetchTokenInformationAsync(); this._blockchainWatcher.startEmittingNetworkConnectionAndUserBalanceState(); @@ -264,10 +267,10 @@ export class Blockchain { public async setProxyAllowanceAsync(token: Token, amountInBaseUnits: BigNumber): Promise<void> { utils.assert(this.isValidAddress(token.address), BlockchainCallErrs.TokenAddressIsInvalid); utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses); - utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); + utils.assert(!_.isUndefined(this._contractWrappers), 'Contract Wrappers must be instantiated.'); this._showFlashMessageIfLedger(); - const txHash = await this._zeroEx.token.setProxyAllowanceAsync( + const txHash = await this._contractWrappers.token.setProxyAllowanceAsync( token.address, this._userAddressIfExists, amountInBaseUnits, @@ -278,11 +281,11 @@ export class Blockchain { await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash); } public async transferAsync(token: Token, toAddress: string, amountInBaseUnits: BigNumber): Promise<void> { - utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); + utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.'); utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses); this._showFlashMessageIfLedger(); - const txHash = await this._zeroEx.token.transferAsync( + const txHash = await this._contractWrappers.token.transferAsync( token.address, this._userAddressIfExists, toAddress, @@ -326,13 +329,13 @@ export class Blockchain { return zeroExSignedOrder; } public async fillOrderAsync(signedOrder: SignedOrder, fillTakerTokenAmount: BigNumber): Promise<BigNumber> { - utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); + utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.'); utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses); const shouldThrowOnInsufficientBalanceOrAllowance = true; this._showFlashMessageIfLedger(); - const txHash = await this._zeroEx.exchange.fillOrderAsync( + const txHash = await this._contractWrappers.exchange.fillOrderAsync( signedOrder, fillTakerTokenAmount, shouldThrowOnInsufficientBalanceOrAllowance, @@ -343,7 +346,7 @@ export class Blockchain { ); const receipt = await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash); const logs: Array<LogWithDecodedArgs<ExchangeContractEventArgs>> = receipt.logs as any; - this._zeroEx.exchange.throwLogErrorsAsErrors(logs); + this._contractWrappers.exchange.throwLogErrorsAsErrors(logs); const logFill = _.find(logs, { event: 'LogFill' }); const args = (logFill.args as any) as LogFillContractEventArgs; const filledTakerTokenAmount = args.filledTakerTokenAmount; @@ -351,32 +354,32 @@ export class Blockchain { } public async cancelOrderAsync(signedOrder: SignedOrder, cancelTakerTokenAmount: BigNumber): Promise<BigNumber> { this._showFlashMessageIfLedger(); - const txHash = await this._zeroEx.exchange.cancelOrderAsync(signedOrder, cancelTakerTokenAmount, { + const txHash = await this._contractWrappers.exchange.cancelOrderAsync(signedOrder, cancelTakerTokenAmount, { gasPrice: this._defaultGasPrice, }); const receipt = await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash); const logs: Array<LogWithDecodedArgs<ExchangeContractEventArgs>> = receipt.logs as any; - this._zeroEx.exchange.throwLogErrorsAsErrors(logs); + this._contractWrappers.exchange.throwLogErrorsAsErrors(logs); const logCancel = _.find(logs, { event: ExchangeEvents.LogCancel }); const args = (logCancel.args as any) as LogCancelContractEventArgs; const cancelledTakerTokenAmount = args.cancelledTakerTokenAmount; return cancelledTakerTokenAmount; } public async getUnavailableTakerAmountAsync(orderHash: string): Promise<BigNumber> { - utils.assert(ZeroEx.isValidOrderHash(orderHash), 'Must be valid orderHash'); - utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); - const unavailableTakerAmount = await this._zeroEx.exchange.getUnavailableTakerAmountAsync(orderHash); + utils.assert(isValidOrderHash(orderHash), 'Must be valid orderHash'); + utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.'); + const unavailableTakerAmount = await this._contractWrappers.exchange.getUnavailableTakerAmountAsync(orderHash); return unavailableTakerAmount; } public getExchangeContractAddressIfExists(): string | undefined { - return this._zeroEx.exchange.getContractAddress(); + return this._contractWrappers.exchange.getContractAddress(); } public async validateFillOrderThrowIfInvalidAsync( signedOrder: SignedOrder, fillTakerTokenAmount: BigNumber, takerAddress: string, ): Promise<void> { - await this._zeroEx.exchange.validateFillOrderThrowIfInvalidAsync( + await this._contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync( signedOrder, fillTakerTokenAmount, takerAddress, @@ -386,7 +389,7 @@ export class Blockchain { order: Order, cancelTakerTokenAmount: BigNumber, ): Promise<void> { - await this._zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(order, cancelTakerTokenAmount); + await this._contractWrappers.exchange.validateCancelOrderThrowIfInvalidAsync(order, cancelTakerTokenAmount); } public isValidAddress(address: string): boolean { const lowercaseAddress = address.toLowerCase(); @@ -421,7 +424,7 @@ export class Blockchain { return newTokenBalancePromise; } public async signOrderHashAsync(orderHash: string): Promise<ECSignature> { - utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); + utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.'); const makerAddress = this._userAddressIfExists; // If makerAddress is undefined, this means they have a web3 instance injected into their browser // but no account addresses associated with it. @@ -438,11 +441,8 @@ export class Blockchain { if ((isParityNode && !isLedgerSigner) || isTestRpc || isLedgerSigner) { shouldAddPersonalMessagePrefix = false; } - const ecSignature = await this._zeroEx.signOrderHashAsync( - orderHash, - makerAddress, - shouldAddPersonalMessagePrefix, - ); + const provider = this._contractWrappers.getProvider(); + const ecSignature = await signOrderHashAsync(provider, orderHash, makerAddress, shouldAddPersonalMessagePrefix); this._dispatcher.updateECSignature(ecSignature); return ecSignature; } @@ -461,11 +461,11 @@ export class Blockchain { return balanceInWei; } public async convertEthToWrappedEthTokensAsync(etherTokenAddress: string, amount: BigNumber): Promise<void> { - utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); + utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.'); utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses); this._showFlashMessageIfLedger(); - const txHash = await this._zeroEx.etherToken.depositAsync( + const txHash = await this._contractWrappers.etherToken.depositAsync( etherTokenAddress, amount, this._userAddressIfExists, @@ -476,11 +476,11 @@ export class Blockchain { await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash); } public async convertWrappedEthTokensToEthAsync(etherTokenAddress: string, amount: BigNumber): Promise<void> { - utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); + utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.'); utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses); this._showFlashMessageIfLedger(); - const txHash = await this._zeroEx.etherToken.withdrawAsync( + const txHash = await this._contractWrappers.etherToken.withdrawAsync( etherTokenAddress, amount, this._userAddressIfExists, @@ -507,7 +507,7 @@ export class Blockchain { ownerAddressIfExists: string, tokenAddress: string, ): Promise<BigNumber[]> { - utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); + utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.'); if (_.isUndefined(ownerAddressIfExists)) { const zero = new BigNumber(0); @@ -516,14 +516,16 @@ export class Blockchain { let balance = new BigNumber(0); let allowance = new BigNumber(0); if (this._doesUserAddressExist()) { - balance = await this._zeroEx.token.getBalanceAsync(tokenAddress, ownerAddressIfExists); - allowance = await this._zeroEx.token.getProxyAllowanceAsync(tokenAddress, ownerAddressIfExists); + balance = await this._contractWrappers.token.getBalanceAsync(tokenAddress, ownerAddressIfExists); + allowance = await this._contractWrappers.token.getProxyAllowanceAsync(tokenAddress, ownerAddressIfExists); } return [balance, allowance]; } public async getUserAccountsAsync(): Promise<string[]> { - utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); - const userAccountsIfExists = await this._zeroEx.getAvailableAddressesAsync(); + utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.'); + const provider = this._contractWrappers.getProvider(); + const web3Wrapper = new Web3Wrapper(provider); + const userAccountsIfExists = await web3Wrapper.getAvailableAddressesAsync(); return userAccountsIfExists; } // HACK: When a user is using a Ledger, we simply dispatch the selected userAddress, which @@ -619,7 +621,9 @@ export class Blockchain { etherScanLinkIfExists, }), ); - const receipt = await this._zeroEx.awaitTransactionMinedAsync(txHash); + const provider = this._contractWrappers.getProvider(); + const web3Wrapper = new Web3Wrapper(provider); + const receipt = await web3Wrapper.awaitTransactionMinedAsync(txHash); return receipt; } private _doesUserAddressExist(): boolean { @@ -633,7 +637,7 @@ export class Blockchain { return; // short-circuit } - if (!_.isUndefined(this._zeroEx)) { + if (!_.isUndefined(this._contractWrappers)) { // Since we do not have an index on the `taker` address and want to show // transactions where an account is either the `maker` or `taker`, we loop // through all fill events, and filter/cache them client-side. @@ -642,14 +646,14 @@ export class Blockchain { } } private async _startListeningForExchangeLogFillEventsAsync(indexFilterValues: IndexedFilterValues): Promise<void> { - utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); + utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.'); utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses); // Fetch historical logs await this._fetchHistoricalExchangeLogFillEventsAsync(indexFilterValues); // Start a subscription for new logs - this._zeroEx.exchange.subscribe( + this._contractWrappers.exchange.subscribe( ExchangeEvents.LogFill, indexFilterValues, async (err: Error, decodedLogEvent: DecodedLogEvent<LogFillContractEventArgs>) => { @@ -684,7 +688,7 @@ export class Blockchain { fromBlock, toBlock: 'latest' as BlockParam, }; - const decodedLogs = await this._zeroEx.exchange.getLogsAsync<LogFillContractEventArgs>( + const decodedLogs = await this._contractWrappers.exchange.getLogsAsync<LogFillContractEventArgs>( ExchangeEvents.LogFill, blockRange, indexFilterValues, @@ -741,11 +745,11 @@ export class Blockchain { } } private _stopWatchingExchangeLogFillEvents(): void { - this._zeroEx.exchange.unsubscribeAll(); + this._contractWrappers.exchange.unsubscribeAll(); } private async _getTokenRegistryTokensByAddressAsync(): Promise<TokenByAddress> { - utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); - const tokenRegistryTokens = await this._zeroEx.tokenRegistry.getTokensAsync(); + utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.'); + const tokenRegistryTokens = await this._contractWrappers.tokenRegistry.getTokensAsync(); const tokenByAddress: TokenByAddress = {}; _.each(tokenRegistryTokens, (t: ZeroExToken, i: number) => { @@ -794,7 +798,7 @@ export class Blockchain { const zeroExConfigs = { networkId: this.networkId, }; - this._zeroEx = new ZeroEx(provider, zeroExConfigs); + this._contractWrappers = new ContractWrappers(provider, zeroExConfigs); this._updateProviderName(injectedWeb3); const shouldPollUserAddress = true; this._web3Wrapper = new Web3Wrapper(provider); diff --git a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx index 069a75560..d647bba80 100644 --- a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx +++ b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx @@ -1,6 +1,6 @@ -import { ZeroEx } from '0x.js'; import { colors } from '@0xproject/react-shared'; import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import Dialog from 'material-ui/Dialog'; import FlatButton from 'material-ui/FlatButton'; @@ -78,7 +78,7 @@ export class EthWethConversionDialog extends React.Component< ? 'Convert your Ether into a tokenized, tradable form.' : "Convert your Wrapped Ether back into it's native form."; const isWrappedVersion = this.props.direction === Side.Receive; - const etherBalanceInEth = ZeroEx.toUnitAmount(this.props.etherBalanceInWei, constants.DECIMAL_PLACES_ETH); + const etherBalanceInEth = Web3Wrapper.toUnitAmount(this.props.etherBalanceInWei, constants.DECIMAL_PLACES_ETH); return ( <div> <div className="pb2">{explanation}</div> diff --git a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx index 3c839d6f5..196414407 100644 --- a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx +++ b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx @@ -1,6 +1,6 @@ -import { ZeroEx } from '0x.js'; import { colors, constants as sharedConstants } from '@0xproject/react-shared'; import { BigNumber, logUtils } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import Dialog from 'material-ui/Dialog'; import FlatButton from 'material-ui/FlatButton'; @@ -168,7 +168,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps, // We specifically prefix kovan ETH. // TODO: We should probably add prefixes for all networks const isKovanNetwork = networkName === 'Kovan'; - const balanceInEth = ZeroEx.toUnitAmount(balanceInWei, constants.DECIMAL_PLACES_ETH); + const balanceInEth = Web3Wrapper.toUnitAmount(balanceInWei, constants.DECIMAL_PLACES_ETH); const balanceString = `${balanceInEth.toString()} ${isKovanNetwork ? 'Kovan ' : ''}ETH`; return ( <TableRow key={userAddress} style={{ height: 40 }}> diff --git a/packages/website/ts/components/eth_weth_conversion_button.tsx b/packages/website/ts/components/eth_weth_conversion_button.tsx index e8db42a7a..4b91a2ebd 100644 --- a/packages/website/ts/components/eth_weth_conversion_button.tsx +++ b/packages/website/ts/components/eth_weth_conversion_button.tsx @@ -1,5 +1,5 @@ -import { ZeroEx } from '0x.js'; import { BigNumber, logUtils } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import RaisedButton from 'material-ui/RaisedButton'; import * as React from 'react'; @@ -95,11 +95,11 @@ export class EthWethConversionButton extends React.Component< try { if (direction === Side.Deposit) { await this.props.blockchain.convertEthToWrappedEthTokensAsync(token.address, value); - const ethAmount = ZeroEx.toUnitAmount(value, constants.DECIMAL_PLACES_ETH); + const ethAmount = Web3Wrapper.toUnitAmount(value, constants.DECIMAL_PLACES_ETH); this.props.dispatcher.showFlashMessage(`Successfully wrapped ${ethAmount.toString()} ETH to WETH`); } else { await this.props.blockchain.convertWrappedEthTokensToEthAsync(token.address, value); - const tokenAmount = ZeroEx.toUnitAmount(value, token.decimals); + const tokenAmount = Web3Wrapper.toUnitAmount(value, token.decimals); this.props.dispatcher.showFlashMessage(`Successfully unwrapped ${tokenAmount.toString()} WETH to ETH`); } if (!this.props.isOutdatedWrappedEther) { diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx index f19b05861..a5758a66a 100644 --- a/packages/website/ts/components/eth_wrappers.tsx +++ b/packages/website/ts/components/eth_wrappers.tsx @@ -1,6 +1,6 @@ -import { ZeroEx } from '0x.js'; import { colors, EtherscanLinkSuffixes, utils as sharedUtils } from '@0xproject/react-shared'; import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import Divider from 'material-ui/Divider'; import { Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn } from 'material-ui/Table'; @@ -85,7 +85,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt } public render(): React.ReactNode { const etherToken = this._getEthToken(); - const wethBalance = ZeroEx.toUnitAmount(this.state.ethTokenState.balance, constants.DECIMAL_PLACES_ETH); + const wethBalance = Web3Wrapper.toUnitAmount(this.state.ethTokenState.balance, constants.DECIMAL_PLACES_ETH); const isBidirectional = true; const etherscanUrl = sharedUtils.getEtherScanLinkIfExists( etherToken.address, @@ -93,7 +93,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt EtherscanLinkSuffixes.Address, ); const tokenLabel = this._renderToken('Wrapped Ether', etherToken.address, configs.ICON_URL_BY_SYMBOL.WETH); - const userEtherBalanceInEth = ZeroEx.toUnitAmount( + const userEtherBalanceInEth = Web3Wrapper.toUnitAmount( this.props.userEtherBalanceInWei, constants.DECIMAL_PLACES_ETH, ); @@ -265,7 +265,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt const outdatedEtherTokenState = this.state.outdatedWETHStateByAddress[outdatedWETHIfExists.address]; const isStateLoaded = outdatedEtherTokenState.isLoaded; const balanceInEthIfExists = isStateLoaded - ? ZeroEx.toUnitAmount(outdatedEtherTokenState.balance, constants.DECIMAL_PLACES_ETH).toFixed( + ? Web3Wrapper.toUnitAmount(outdatedEtherTokenState.balance, constants.DECIMAL_PLACES_ETH).toFixed( configs.AMOUNT_DISPLAY_PRECSION, ) : undefined; diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx index 59c32cebc..0168ec8f6 100644 --- a/packages/website/ts/components/fill_order.tsx +++ b/packages/website/ts/components/fill_order.tsx @@ -1,6 +1,8 @@ -import { Order as ZeroExOrder, ZeroEx } from '0x.js'; +import { getOrderHashHex, isValidSignature } from '@0xproject/order-utils'; import { colors, constants as sharedConstants } from '@0xproject/react-shared'; +import { Order as ZeroExOrder } from '@0xproject/types'; import { BigNumber, logUtils } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as accounting from 'accounting'; import * as _ from 'lodash'; import { Card, CardHeader, CardText } from 'material-ui/Card'; @@ -433,15 +435,15 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> { takerTokenAddress: parsedOrder.signedOrder.takerTokenAddress, takerTokenAmount: takerAmount, }; - orderHash = ZeroEx.getOrderHashHex(zeroExOrder); + orderHash = getOrderHashHex(zeroExOrder); const exchangeContractAddr = this.props.blockchain.getExchangeContractAddressIfExists(); const signature = parsedOrder.signedOrder.ecSignature; - const isValidSignature = ZeroEx.isValidSignature(orderHash, signature, parsedOrder.signedOrder.maker); + const isSignatureValid = isValidSignature(orderHash, signature, parsedOrder.signedOrder.maker); if (exchangeContractAddr !== parsedOrder.signedOrder.exchangeContractAddress) { orderJSONErrMsg = 'This order was made on another network or using a deprecated Exchange contract'; parsedOrder = undefined; - } else if (!isValidSignature) { + } else if (!isSignatureValid) { orderJSONErrMsg = 'Order signature is invalid'; parsedOrder = undefined; } else { @@ -600,7 +602,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> { const takerTokenAmount = new BigNumber(parsedOrder.signedOrder.takerTokenAmount); const signedOrder = this.props.blockchain.portalOrderToZeroExOrder(parsedOrder); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); + const orderHash = getOrderHashHex(signedOrder); const unavailableTakerAmount = await this.props.blockchain.getUnavailableTakerAmountAsync(orderHash); const availableTakerTokenAmount = takerTokenAmount.minus(unavailableTakerAmount); try { @@ -646,7 +648,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> { } } private _formatCurrencyAmount(amount: BigNumber, decimals: number): number { - const unitAmount = ZeroEx.toUnitAmount(amount, decimals); + const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals); const roundedUnitAmount = Math.round(unitAmount.toNumber() * 100000) / 100000; return roundedUnitAmount; } diff --git a/packages/website/ts/components/fill_order_json.tsx b/packages/website/ts/components/fill_order_json.tsx index 97297d5a1..90eedbb18 100644 --- a/packages/website/ts/components/fill_order_json.tsx +++ b/packages/website/ts/components/fill_order_json.tsx @@ -1,4 +1,4 @@ -import { ZeroEx } from '0x.js'; +import { generatePseudoRandomSalt } from '@0xproject/order-utils'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; import Paper from 'material-ui/Paper'; @@ -38,7 +38,7 @@ export class FillOrderJSON extends React.Component<FillOrderJSONProps, FillOrder s: '937862111edcba395f8a9e0cc1b2c5e12320...', v: 27, }; - const hintSalt = ZeroEx.generatePseudoRandomSalt(); + const hintSalt = generatePseudoRandomSalt(); const feeRecipient = constants.NULL_ADDRESS; const hintOrder = utils.generateOrder( exchangeContract, diff --git a/packages/website/ts/components/flash_messages/token_send_completed.tsx b/packages/website/ts/components/flash_messages/token_send_completed.tsx index bb5adfa4e..f3f1ea2fc 100644 --- a/packages/website/ts/components/flash_messages/token_send_completed.tsx +++ b/packages/website/ts/components/flash_messages/token_send_completed.tsx @@ -1,6 +1,6 @@ -import { ZeroEx } from '0x.js'; import { colors } from '@0xproject/react-shared'; import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import * as React from 'react'; import { Token } from 'ts/types'; @@ -22,7 +22,7 @@ export class TokenSendCompleted extends React.Component<TokenSendCompletedProps, Verify on Etherscan </a> ); - const amountInUnits = ZeroEx.toUnitAmount(this.props.amountInBaseUnits, this.props.token.decimals); + const amountInUnits = Web3Wrapper.toUnitAmount(this.props.amountInBaseUnits, this.props.token.decimals); const truncatedAddress = utils.getAddressBeginAndEnd(this.props.toAddress); return ( <div> diff --git a/packages/website/ts/components/generate_order/generate_order_form.tsx b/packages/website/ts/components/generate_order/generate_order_form.tsx index d46c29058..5f968a5e4 100644 --- a/packages/website/ts/components/generate_order/generate_order_form.tsx +++ b/packages/website/ts/components/generate_order/generate_order_form.tsx @@ -1,5 +1,6 @@ -import { ECSignature, Order, ZeroEx } from '0x.js'; +import { generatePseudoRandomSalt, getOrderHashHex } from '@0xproject/order-utils'; import { colors, constants as sharedConstants } from '@0xproject/react-shared'; +import { ECSignature, Order } from '@0xproject/types'; import { BigNumber, logUtils } from '@0xproject/utils'; import * as _ from 'lodash'; import Dialog from 'material-ui/Dialog'; @@ -78,7 +79,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G specified, anyone is able to fill it.'; const exchangeContractIfExists = this.props.blockchain.getExchangeContractAddressIfExists(); const initialTakerAddress = - this.props.orderTakerAddress === ZeroEx.NULL_ADDRESS ? '' : this.props.orderTakerAddress; + this.props.orderTakerAddress === constants.NULL_ADDRESS ? '' : this.props.orderTakerAddress; return ( <div className="clearfix mb2 lg-px4 md-px4 sm-px2"> <h3>Generate an order</h3> @@ -224,7 +225,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G // Upon closing the order JSON dialog, we update the orderSalt stored in the Redux store // with a new value so that if a user signs the identical order again, the newly signed // orderHash will not collide with the previously generated orderHash. - this.props.dispatcher.updateOrderSalt(ZeroEx.generatePseudoRandomSalt()); + this.props.dispatcher.updateOrderSalt(generatePseudoRandomSalt()); this.setState({ signingState: SigningState.UNSIGNED, }); @@ -305,7 +306,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G takerTokenAddress: hashData.receiveTokenContractAddr, takerTokenAmount: hashData.receiveAmount, }; - const orderHash = ZeroEx.getOrderHashHex(zeroExOrder); + const orderHash = getOrderHashHex(zeroExOrder); let globalErrMsg = ''; try { @@ -348,7 +349,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G } private _updateOrderAddress(address?: string): void { if (!_.isUndefined(address)) { - const normalizedAddress = _.isEmpty(address) ? ZeroEx.NULL_ADDRESS : address; + const normalizedAddress = _.isEmpty(address) ? constants.NULL_ADDRESS : address; this.props.dispatcher.updateOrderTakerAddress(normalizedAddress); } } diff --git a/packages/website/ts/components/generate_order/new_token_form.tsx b/packages/website/ts/components/generate_order/new_token_form.tsx index 10f71b430..a9b8e9589 100644 --- a/packages/website/ts/components/generate_order/new_token_form.tsx +++ b/packages/website/ts/components/generate_order/new_token_form.tsx @@ -157,14 +157,14 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor const maxLength = 30; const tokens = _.values(this.props.tokenByAddress); const tokenWithNameIfExists = _.find(tokens, { name }); - const tokenWithNameExists = !_.isUndefined(tokenWithNameIfExists); + const doesTokenWithNameExists = !_.isUndefined(tokenWithNameIfExists); if (name === '') { nameErrText = 'Name is required'; } else if (!this._isValidName(name)) { nameErrText = 'Name should only contain letters, digits and spaces'; } else if (name.length > maxLength) { nameErrText = `Max length is ${maxLength}`; - } else if (tokenWithNameExists) { + } else if (doesTokenWithNameExists) { nameErrText = 'Token with this name already exists'; } @@ -177,14 +177,14 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor let symbolErrText = ''; const maxLength = 5; const tokens = _.values(this.props.tokenByAddress); - const tokenWithSymbolExists = !_.isUndefined(_.find(tokens, { symbol })); + const doesTokenWithSymbolExists = !_.isUndefined(_.find(tokens, { symbol })); if (symbol === '') { symbolErrText = 'Symbol is required'; } else if (!this._isAlphanumeric(symbol)) { symbolErrText = 'Can only include alphanumeric characters'; } else if (symbol.length > maxLength) { symbolErrText = `Max length is ${maxLength}`; - } else if (tokenWithSymbolExists) { + } else if (doesTokenWithSymbolExists) { symbolErrText = 'Token with symbol already exists'; } diff --git a/packages/website/ts/components/inputs/eth_amount_input.tsx b/packages/website/ts/components/inputs/eth_amount_input.tsx index fa684d85c..1f0f27410 100644 --- a/packages/website/ts/components/inputs/eth_amount_input.tsx +++ b/packages/website/ts/components/inputs/eth_amount_input.tsx @@ -1,5 +1,5 @@ -import { ZeroEx } from '0x.js'; import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import * as React from 'react'; import { BalanceBoundedInput } from 'ts/components/inputs/balance_bounded_input'; @@ -34,7 +34,7 @@ export class EthAmountInput extends React.Component<EthAmountInputProps, EthAmou }; public render(): React.ReactNode { const amount = this.props.amount - ? ZeroEx.toUnitAmount(this.props.amount, constants.DECIMAL_PLACES_ETH) + ? Web3Wrapper.toUnitAmount(this.props.amount, constants.DECIMAL_PLACES_ETH) : undefined; return ( <div className="flex overflow-hidden" style={this.props.style}> @@ -61,7 +61,7 @@ export class EthAmountInput extends React.Component<EthAmountInputProps, EthAmou private _onChange(isValid: boolean, amount?: BigNumber): void { const baseUnitAmountIfExists = _.isUndefined(amount) ? undefined - : ZeroEx.toBaseUnitAmount(amount, constants.DECIMAL_PLACES_ETH); + : Web3Wrapper.toBaseUnitAmount(amount, constants.DECIMAL_PLACES_ETH); this.props.onChange(isValid, baseUnitAmountIfExists); } private _getLabelStyle(): React.CSSProperties { diff --git a/packages/website/ts/components/inputs/hash_input.tsx b/packages/website/ts/components/inputs/hash_input.tsx index 37d4af138..8d9cdfc0b 100644 --- a/packages/website/ts/components/inputs/hash_input.tsx +++ b/packages/website/ts/components/inputs/hash_input.tsx @@ -1,5 +1,6 @@ -import { Order, ZeroEx } from '0x.js'; +import { getOrderHashHex } from '@0xproject/order-utils'; import { Styles } from '@0xproject/react-shared'; +import { Order } from '@0xproject/types'; import * as _ from 'lodash'; import * as React from 'react'; import ReactTooltip = require('react-tooltip'); @@ -57,7 +58,7 @@ export class HashInput extends React.Component<HashInputProps, HashInputState> { takerTokenAddress: hashData.receiveTokenContractAddr, takerTokenAmount: hashData.receiveAmount, }; - const orderHash = ZeroEx.getOrderHashHex(order); + const orderHash = getOrderHashHex(order); return orderHash; } } diff --git a/packages/website/ts/components/inputs/token_amount_input.tsx b/packages/website/ts/components/inputs/token_amount_input.tsx index f040928f1..a67120320 100644 --- a/packages/website/ts/components/inputs/token_amount_input.tsx +++ b/packages/website/ts/components/inputs/token_amount_input.tsx @@ -1,6 +1,6 @@ -import { ZeroEx } from '0x.js'; import { colors } from '@0xproject/react-shared'; import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import * as React from 'react'; import { Link } from 'react-router-dom'; @@ -75,14 +75,14 @@ export class TokenAmountInput extends React.Component<TokenAmountInputProps, Tok } public render(): React.ReactNode { const amount = this.props.amount - ? ZeroEx.toUnitAmount(this.props.amount, this.props.token.decimals) + ? Web3Wrapper.toUnitAmount(this.props.amount, this.props.token.decimals) : undefined; return ( <div className="flex overflow-hidden" style={this._getStyle()}> <BalanceBoundedInput label={this.props.label} amount={amount} - balance={ZeroEx.toUnitAmount(this.state.balance, this.props.token.decimals)} + balance={Web3Wrapper.toUnitAmount(this.state.balance, this.props.token.decimals)} onChange={this._onChange.bind(this)} onErrorMsgChange={this.props.onErrorMsgChange} validate={this._validate.bind(this)} @@ -103,7 +103,7 @@ export class TokenAmountInput extends React.Component<TokenAmountInputProps, Tok private _onChange(isValid: boolean, amount?: BigNumber): void { let baseUnitAmount; if (!_.isUndefined(amount)) { - baseUnitAmount = ZeroEx.toBaseUnitAmount(amount, this.props.token.decimals); + baseUnitAmount = Web3Wrapper.toBaseUnitAmount(amount, this.props.token.decimals); } this.props.onChange(isValid, baseUnitAmount); } diff --git a/packages/website/ts/components/order_json.tsx b/packages/website/ts/components/order_json.tsx index 6feefea50..35188c024 100644 --- a/packages/website/ts/components/order_json.tsx +++ b/packages/website/ts/components/order_json.tsx @@ -1,4 +1,4 @@ -import { ECSignature } from '0x.js'; +import { ECSignature } from '@0xproject/types'; import { BigNumber, logUtils } from '@0xproject/utils'; import * as _ from 'lodash'; import Paper from 'material-ui/Paper'; diff --git a/packages/website/ts/components/portal/menu.tsx b/packages/website/ts/components/portal/menu.tsx index e8353a3b0..6a3301549 100644 --- a/packages/website/ts/components/portal/menu.tsx +++ b/packages/website/ts/components/portal/menu.tsx @@ -61,13 +61,13 @@ export const Menu: React.StatelessComponent<MenuProps> = (props: MenuProps) => { return ( <div> {_.map(props.menuItemEntries, entry => { - const selected = entry.to === props.selectedPath; + const isSelected = entry.to === props.selectedPath; return ( <MenuItem key={entry.to} to={entry.to}> <MenuItemLabel title={entry.labelText} iconName={entry.iconName} - selected={selected} + selected={isSelected} theme={props.theme} /> </MenuItem> diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index b992204a7..1bd318c28 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -466,8 +466,8 @@ export class Portal extends React.Component<PortalProps, PortalState> { this.props.dispatcher.updateScreenWidth(newScreenWidth); } private _isSmallScreen(): boolean { - const result = this.props.screenWidth === ScreenWidths.Sm; - return result; + const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm; + return isSmallScreen; } } diff --git a/packages/website/ts/components/relayer_index/relayer_index.tsx b/packages/website/ts/components/relayer_index/relayer_index.tsx index 8da4e0e10..9ef6eaf59 100644 --- a/packages/website/ts/components/relayer_index/relayer_index.tsx +++ b/packages/website/ts/components/relayer_index/relayer_index.tsx @@ -60,8 +60,8 @@ export class RelayerIndex extends React.Component<RelayerIndexProps, RelayerInde this._isUnmounted = true; } public render(): React.ReactNode { - const readyToRender = _.isUndefined(this.state.error) && !_.isUndefined(this.state.relayerInfos); - if (!readyToRender) { + const isReadyToRender = _.isUndefined(this.state.error) && !_.isUndefined(this.state.relayerInfos); + if (!isReadyToRender) { return ( // TODO: consolidate this loading component with the one in portal <div className="center"> diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx index 83948e5c2..f5a51dabb 100644 --- a/packages/website/ts/components/token_balances.tsx +++ b/packages/website/ts/components/token_balances.tsx @@ -1,4 +1,3 @@ -import { ZeroEx } from '0x.js'; import { colors, constants as sharedConstants, @@ -8,6 +7,7 @@ import { utils as sharedUtils, } from '@0xproject/react-shared'; import { BigNumber, logUtils } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import Dialog from 'material-ui/Dialog'; import Divider from 'material-ui/Divider'; @@ -111,7 +111,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala if (nextProps.userEtherBalanceInWei !== this.props.userEtherBalanceInWei) { if (this.state.isBalanceSpinnerVisible) { const receivedAmountInWei = nextProps.userEtherBalanceInWei.minus(this.props.userEtherBalanceInWei); - const receivedAmountInEth = ZeroEx.toUnitAmount(receivedAmountInWei, constants.DECIMAL_PLACES_ETH); + const receivedAmountInEth = Web3Wrapper.toUnitAmount(receivedAmountInWei, constants.DECIMAL_PLACES_ETH); const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; this.props.dispatcher.showFlashMessage( `Received ${receivedAmountInEth.toString(10)} ${networkName} Ether`, @@ -180,7 +180,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala token balances in order to execute trades.<br> \ Toggling sets an allowance for the<br> \ smart contract so you can start trading that token.'; - const userEtherBalanceInEth = ZeroEx.toUnitAmount( + const userEtherBalanceInEth = Web3Wrapper.toUnitAmount( this.props.userEtherBalanceInWei, constants.DECIMAL_PLACES_ETH, ); @@ -445,7 +445,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala }); } private _renderAmount(amount: BigNumber, decimals: number): React.ReactNode { - const unitAmount = ZeroEx.toUnitAmount(amount, decimals); + const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals); return unitAmount.toNumber().toFixed(configs.AMOUNT_DISPLAY_PRECSION); } private _renderTokenName(token: Token): React.ReactNode { @@ -508,7 +508,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala try { await this.props.blockchain.mintTestTokensAsync(token); await this._refetchTokenStateAsync(token.address); - const amount = ZeroEx.toUnitAmount(constants.MINT_AMOUNT, token.decimals); + const amount = Web3Wrapper.toUnitAmount(constants.MINT_AMOUNT, token.decimals); this.props.dispatcher.showFlashMessage(`Successfully minted ${amount.toString(10)} ${token.symbol}`); return true; } catch (err) { diff --git a/packages/website/ts/components/trade_history/trade_history_item.tsx b/packages/website/ts/components/trade_history/trade_history_item.tsx index adca4d58c..321a8b0e1 100644 --- a/packages/website/ts/components/trade_history/trade_history_item.tsx +++ b/packages/website/ts/components/trade_history/trade_history_item.tsx @@ -1,6 +1,6 @@ -import { ZeroEx } from '0x.js'; import { colors, EtherscanLinkSuffixes } from '@0xproject/react-shared'; import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import Paper from 'material-ui/Paper'; import * as moment from 'moment'; @@ -90,10 +90,16 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra } private _renderAmounts(makerToken: Token, takerToken: Token): React.ReactNode { const fill = this.props.fill; - const filledTakerTokenAmountInUnits = ZeroEx.toUnitAmount(fill.filledTakerTokenAmount, takerToken.decimals); - const filledMakerTokenAmountInUnits = ZeroEx.toUnitAmount(fill.filledMakerTokenAmount, takerToken.decimals); + const filledTakerTokenAmountInUnits = Web3Wrapper.toUnitAmount( + fill.filledTakerTokenAmount, + takerToken.decimals, + ); + const filledMakerTokenAmountInUnits = Web3Wrapper.toUnitAmount( + fill.filledMakerTokenAmount, + takerToken.decimals, + ); let exchangeRate = filledTakerTokenAmountInUnits.div(filledMakerTokenAmountInUnits); - const fillMakerTokenAmount = ZeroEx.toBaseUnitAmount(filledMakerTokenAmountInUnits, makerToken.decimals); + const fillMakerTokenAmount = Web3Wrapper.toBaseUnitAmount(filledMakerTokenAmountInUnits, makerToken.decimals); let receiveAmount; let receiveToken; @@ -160,7 +166,7 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra ); } private _renderAmount(amount: BigNumber, symbol: string, decimals: number): React.ReactNode { - const unitAmount = ZeroEx.toUnitAmount(amount, decimals); + const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals); return ( <span> {unitAmount.toFixed(configs.AMOUNT_DISPLAY_PRECSION)} {symbol} diff --git a/packages/website/ts/components/visual_order.tsx b/packages/website/ts/components/visual_order.tsx index 76a283547..a8d18006e 100644 --- a/packages/website/ts/components/visual_order.tsx +++ b/packages/website/ts/components/visual_order.tsx @@ -1,4 +1,4 @@ -import { ZeroEx } from '0x.js'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import * as React from 'react'; import { Party } from 'ts/components/ui/party'; @@ -63,7 +63,7 @@ export class VisualOrder extends React.Component<VisualOrderProps, VisualOrderSt ); } private _renderAmount(assetToken: AssetToken, token: Token): React.ReactNode { - const unitAmount = ZeroEx.toUnitAmount(assetToken.amount, token.decimals); + const unitAmount = Web3Wrapper.toUnitAmount(assetToken.amount, token.decimals); return ( <div style={{ fontSize: 13 }}> {unitAmount.toNumber().toFixed(configs.AMOUNT_DISPLAY_PRECSION)} {token.symbol} diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 113f3c864..d0354580d 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -1,4 +1,3 @@ -import { ZeroEx } from '0x.js'; import { constants as sharedConstants, EtherscanLinkSuffixes, @@ -6,6 +5,7 @@ import { utils as sharedUtils, } from '@0xproject/react-shared'; import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import FlatButton from 'material-ui/FlatButton'; import FloatingActionButton from 'material-ui/FloatingActionButton'; @@ -450,7 +450,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> { ); } private _renderAmount(amount: BigNumber, decimals: number, symbol: string): React.ReactNode { - const unitAmount = ZeroEx.toUnitAmount(amount, decimals); + const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals); const formattedAmount = unitAmount.toPrecision(TOKEN_AMOUNT_DISPLAY_PRECISION); const result = `${formattedAmount} ${symbol}`; return <div style={styles.amountLabel}>{result}</div>; @@ -459,7 +459,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> { if (_.isUndefined(price)) { return null; } - const unitAmount = ZeroEx.toUnitAmount(amount, decimals); + const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals); const value = unitAmount.mul(price); const formattedAmount = value.toFixed(USD_DECIMAL_PLACES); const result = `$${formattedAmount}`; diff --git a/packages/website/ts/components/wallet/wrap_ether_item.tsx b/packages/website/ts/components/wallet/wrap_ether_item.tsx index aab1d4439..34b5b8824 100644 --- a/packages/website/ts/components/wallet/wrap_ether_item.tsx +++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx @@ -1,6 +1,6 @@ -import { ZeroEx } from '0x.js'; import { Styles } from '@0xproject/react-shared'; import { BigNumber, logUtils } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import FlatButton from 'material-ui/FlatButton'; import { ListItem } from 'material-ui/List'; @@ -90,7 +90,10 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther }; } public render(): React.ReactNode { - const etherBalanceInEth = ZeroEx.toUnitAmount(this.props.userEtherBalanceInWei, constants.DECIMAL_PLACES_ETH); + const etherBalanceInEth = Web3Wrapper.toUnitAmount( + this.props.userEtherBalanceInWei, + constants.DECIMAL_PLACES_ETH, + ); const isWrappingEth = this.props.direction === Side.Deposit; const topLabelText = isWrappingEth ? 'Convert ETH into WETH 1:1' : 'Convert WETH into ETH 1:1'; @@ -192,11 +195,11 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther const amountToConvert = this.state.currentInputAmount; if (this.props.direction === Side.Deposit) { await this.props.blockchain.convertEthToWrappedEthTokensAsync(etherToken.address, amountToConvert); - const ethAmount = ZeroEx.toUnitAmount(amountToConvert, constants.DECIMAL_PLACES_ETH); + const ethAmount = Web3Wrapper.toUnitAmount(amountToConvert, constants.DECIMAL_PLACES_ETH); this.props.dispatcher.showFlashMessage(`Successfully wrapped ${ethAmount.toString()} ETH to WETH`); } else { await this.props.blockchain.convertWrappedEthTokensToEthAsync(etherToken.address, amountToConvert); - const tokenAmount = ZeroEx.toUnitAmount(amountToConvert, etherToken.decimals); + const tokenAmount = Web3Wrapper.toUnitAmount(amountToConvert, etherToken.decimals); this.props.dispatcher.showFlashMessage(`Successfully unwrapped ${tokenAmount.toString()} WETH to ETH`); } await this.props.refetchEthTokenStateAsync(); diff --git a/packages/website/ts/containers/generate_order_form.ts b/packages/website/ts/containers/generate_order_form.ts index 8c5deb690..98c9b8cd6 100644 --- a/packages/website/ts/containers/generate_order_form.ts +++ b/packages/website/ts/containers/generate_order_form.ts @@ -1,4 +1,4 @@ -import { ECSignature } from '0x.js'; +import { ECSignature } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; import * as React from 'react'; diff --git a/packages/website/ts/redux/dispatcher.ts b/packages/website/ts/redux/dispatcher.ts index 981522360..340b80d49 100644 --- a/packages/website/ts/redux/dispatcher.ts +++ b/packages/website/ts/redux/dispatcher.ts @@ -1,4 +1,4 @@ -import { ECSignature } from '0x.js'; +import { ECSignature } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { Dispatch } from 'redux'; import { State } from 'ts/redux/reducer'; diff --git a/packages/website/ts/redux/reducer.ts b/packages/website/ts/redux/reducer.ts index bb8f1472b..fba6afa5d 100644 --- a/packages/website/ts/redux/reducer.ts +++ b/packages/website/ts/redux/reducer.ts @@ -1,4 +1,5 @@ -import { ECSignature, ZeroEx } from '0x.js'; +import { constants, generatePseudoRandomSalt } from '@0xproject/order-utils'; +import { ECSignature } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; import * as moment from 'moment'; @@ -65,8 +66,8 @@ const INITIAL_STATE: State = { s: '', v: 27, }, - orderTakerAddress: ZeroEx.NULL_ADDRESS, - orderSalt: ZeroEx.generatePseudoRandomSalt(), + orderTakerAddress: constants.NULL_ADDRESS, + orderSalt: generatePseudoRandomSalt(), nodeVersion: undefined, screenWidth: utils.getScreenWidth(), shouldBlockchainErrDialogBeOpen: false, diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts index 33e4d6c30..294a58f64 100644 --- a/packages/website/ts/types.ts +++ b/packages/website/ts/types.ts @@ -1,4 +1,4 @@ -import { ECSignature } from '0x.js'; +import { ECSignature } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; diff --git a/packages/website/ts/utils/configs.ts b/packages/website/ts/utils/configs.ts index 9fec814b7..e72a7f201 100644 --- a/packages/website/ts/utils/configs.ts +++ b/packages/website/ts/utils/configs.ts @@ -19,7 +19,7 @@ export const configs = { // WARNING: ZRX & WETH MUST always be default trackedTokens DEFAULT_TRACKED_TOKEN_SYMBOLS: ['WETH', 'ZRX'], DOMAIN_STAGING: 'staging-0xproject.s3-website-us-east-1.amazonaws.com', - DOMAIN_DOGFOOD: 'dogfood-0xproject.s3-website-us-east-1.amazonaws.com', + DOMAIN_DOGFOOD: 'dogfood.0xproject.com', DOMAIN_DEVELOPMENT: '0xproject.localhost:3572', DOMAIN_PRODUCTION: '0xproject.com', ENVIRONMENT: isDevelopment ? Environments.DEVELOPMENT : Environments.PRODUCTION, diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index c370ac90c..e79a873e0 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -1,7 +1,7 @@ -import { ContractWrappersError, ECSignature, ExchangeContractErrs, ZeroEx } from '0x.js'; +import { ContractWrappersError, ExchangeContractErrs } from '@0xproject/contract-wrappers'; import { OrderError } from '@0xproject/order-utils'; import { constants as sharedConstants, EtherscanLinkSuffixes, Networks } from '@0xproject/react-shared'; -import { Provider } from '@0xproject/types'; +import { ECSignature, Provider } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import deepEqual = require('deep-equal'); import * as _ from 'lodash'; diff --git a/packages/website/tslint.json b/packages/website/tslint.json index d6a5f5031..b55ffe90f 100644 --- a/packages/website/tslint.json +++ b/packages/website/tslint.json @@ -4,6 +4,7 @@ "no-implicit-dependencies": false, "no-object-literal-type-assertion": false, "completed-docs": false, - "prefer-function-over-method": false + "prefer-function-over-method": false, + "custom-no-magic-numbers": false } } diff --git a/packages/website/webpack.config.js b/packages/website/webpack.config.js index e28e9e064..f9abeb27c 100644 --- a/packages/website/webpack.config.js +++ b/packages/website/webpack.config.js @@ -1,5 +1,6 @@ const path = require('path'); const webpack = require('webpack'); +const UglifyJsPlugin = require('uglifyjs-webpack-plugin') module.exports = { entry: ['./ts/index.tsx'], @@ -76,9 +77,14 @@ module.exports = { NODE_ENV: JSON.stringify(process.env.NODE_ENV), }, }), - new webpack.optimize.UglifyJsPlugin({ - mangle: { - except: ['BigNumber'], + // TODO: Revert to webpack bundled version with webpack v4. + // The v3 series bundled version does not support ES6 and + // fails to build. + new UglifyJsPlugin({ + uglifyOptions: { + mangle: { + reserved: ['BigNumber'], + }, }, }), ] |