diff options
author | Leonid Logvinov <logvinov.leon@gmail.com> | 2018-09-27 18:47:00 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-27 18:47:00 +0800 |
commit | 9160cd4983d20a00ce7852d78c0a345720efd8e1 (patch) | |
tree | 39b0a21f8be47f978431d68457c8a8e9c3874e6f | |
parent | 70e412e3758616f1923b76e62b06a008c734e262 (diff) | |
parent | 63d79faa85df1cc090837fc49befb5076b50203b (diff) | |
download | dexon-0x-contracts-9160cd4983d20a00ce7852d78c0a345720efd8e1.tar.gz dexon-0x-contracts-9160cd4983d20a00ce7852d78c0a345720efd8e1.tar.zst dexon-0x-contracts-9160cd4983d20a00ce7852d78c0a345720efd8e1.zip |
Merge pull request #1069 from 0xProject/feature/ts-ethers
Upgrade to TS version of ethers
23 files changed, 106 insertions, 100 deletions
diff --git a/package.json b/package.json index e8a56401a..cf5f247d6 100644 --- a/package.json +++ b/package.json @@ -55,8 +55,5 @@ "source-map-support": "^0.5.6", "typescript": "3.0.1", "wsrun": "^2.2.0" - }, - "resolutions": { - "ethers": "0xproject/ethers.js#eip-838-reasons" } } diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json index 3b8b0f913..16650be3f 100644 --- a/packages/0x.js/package.json +++ b/packages/0x.js/package.json @@ -84,7 +84,7 @@ "@0xproject/utils": "^1.0.11", "@0xproject/web3-wrapper": "^3.0.1", "ethereum-types": "^1.0.8", - "ethers": "3.0.22", + "ethers": "4.0.0-beta.14", "lodash": "^4.17.5", "web3-provider-engine": "14.0.6" }, diff --git a/packages/base-contract/CHANGELOG.json b/packages/base-contract/CHANGELOG.json index 8403d824b..b97bc00e0 100644 --- a/packages/base-contract/CHANGELOG.json +++ b/packages/base-contract/CHANGELOG.json @@ -1,5 +1,18 @@ [ { + "version": "3.0.0", + "changes": [ + { + "note": "Change the way we detect BN to work with the newest ethers.js", + "pr": 1069 + }, + { + "note": "Add baseContract._throwIfRevertWithReasonCallResult", + "pr": 1069 + } + ] + }, + { "timestamp": 1537907159, "version": "2.0.5", "changes": [ diff --git a/packages/base-contract/package.json b/packages/base-contract/package.json index 3bba0e81b..b87092e49 100644 --- a/packages/base-contract/package.json +++ b/packages/base-contract/package.json @@ -44,7 +44,7 @@ "@0xproject/utils": "^1.0.11", "@0xproject/web3-wrapper": "^3.0.1", "ethereum-types": "^1.0.8", - "ethers": "3.0.22", + "ethers": "4.0.0-beta.14", "lodash": "^4.17.5" }, "publishConfig": { diff --git a/packages/base-contract/src/index.ts b/packages/base-contract/src/index.ts index 12f974445..981e6fca6 100644 --- a/packages/base-contract/src/index.ts +++ b/packages/base-contract/src/index.ts @@ -20,6 +20,11 @@ export interface EthersInterfaceByFunctionSignature { [key: string]: ethers.Interface; } +const REVERT_ERROR_SELECTOR = '08c379a0'; +const REVERT_ERROR_SELECTOR_OFFSET = 2; +const REVERT_ERROR_SELECTOR_BYTES_LENGTH = 4; +const REVERT_ERROR_SELECTOR_END = REVERT_ERROR_SELECTOR_OFFSET + REVERT_ERROR_SELECTOR_BYTES_LENGTH * 2; + export class BaseContract { protected _ethersInterfacesByFunctionSignature: EthersInterfaceByFunctionSignature; protected _web3Wrapper: Web3Wrapper; @@ -61,7 +66,7 @@ export class BaseContract { } } protected static _bnToBigNumber(_type: string, value: any): any { - return _.isObject(value) && value._bn ? new BigNumber(value.toString()) : value; + return _.isObject(value) && value._hex ? new BigNumber(value.toString()) : value; } protected static async _applyDefaultsToTxDataAsync<T extends Partial<TxData | TxDataPayable>>( txData: T, @@ -82,15 +87,24 @@ export class BaseContract { } return txDataWithDefaults; } + protected static _throwIfRevertWithReasonCallResult(rawCallResult: string): void { + if (rawCallResult.slice(REVERT_ERROR_SELECTOR_OFFSET, REVERT_ERROR_SELECTOR_END) === REVERT_ERROR_SELECTOR) { + const revertReason = ethers.utils.defaultAbiCoder.decode( + ['string'], + ethers.utils.hexDataSlice(rawCallResult, REVERT_ERROR_SELECTOR_BYTES_LENGTH), + ); + throw new Error(revertReason); + } + } // Throws if the given arguments cannot be safely/correctly encoded based on // the given inputAbi. An argument may not be considered safely encodeable // if it overflows the corresponding Solidity type, there is a bug in the // encoder, or the encoder performs unsafe type coercion. public static strictArgumentEncodingCheck(inputAbi: DataItem[], args: any[]): void { - const coder = ethers.utils.AbiCoder.defaultCoder; + const coder = new ethers.AbiCoder(); const params = abiUtils.parseEthersParams(inputAbi); - const rawEncoded = coder.encode(params.names, params.types, args); - const rawDecoded = coder.decode(params.names, params.types, rawEncoded); + const rawEncoded = coder.encode(inputAbi, args); + const rawDecoded = coder.decode(inputAbi, rawEncoded); for (let i = 0; i < rawDecoded.length; i++) { const original = args[i]; const decoded = rawDecoded[i]; diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json index c2b1ecdc9..1deb6a425 100644 --- a/packages/contract-wrappers/package.json +++ b/packages/contract-wrappers/package.json @@ -84,7 +84,7 @@ "ethereum-types": "^1.0.8", "ethereumjs-blockstream": "6.0.0", "ethereumjs-util": "^5.1.1", - "ethers": "3.0.22", + "ethers": "4.0.0-beta.14", "js-sha3": "^0.7.0", "lodash": "^4.17.5", "uuid": "^3.1.0" diff --git a/packages/contract_templates/contract.handlebars b/packages/contract_templates/contract.handlebars index 466893aa7..9ae39f44f 100644 --- a/packages/contract_templates/contract.handlebars +++ b/packages/contract_templates/contract.handlebars @@ -65,10 +65,12 @@ export class {{contractName}}Contract extends BaseContract { [{{> params inputs=ctor.inputs}}], BaseContract._bigNumberToString, ); - const txData = ethers.Contract.getDeployTransaction(bytecode, abi, {{> params inputs=ctor.inputs}}); + const iface = new ethers.Interface(abi); + const deployInfo = iface.deployFunction; + const txData = deployInfo.encode(bytecode, [{{> params inputs=ctor.inputs}}]); const web3Wrapper = new Web3Wrapper(provider); const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( - txData, + {data: txData}, txDefaults, web3Wrapper.estimateGasAsync.bind(web3Wrapper), ); diff --git a/packages/contract_templates/partials/callAsync.handlebars b/packages/contract_templates/partials/callAsync.handlebars index 94752691d..ddbbe7508 100644 --- a/packages/contract_templates/partials/callAsync.handlebars +++ b/packages/contract_templates/partials/callAsync.handlebars @@ -8,10 +8,8 @@ async callAsync( const inputAbi = self._lookupAbi(functionSignature).inputs; [{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self)); BaseContract.strictArgumentEncodingCheck(inputAbi, [{{> params inputs=inputs}}]); - const ethersFunction = self._lookupEthersInterface(functionSignature).functions.{{this.name}}( - {{> params inputs=inputs}} - ) as ethers.CallDescription; - const encodedData = ethersFunction.data; + const ethersFunction = self._lookupEthersInterface(functionSignature).functions.{{this.name}}; + const encodedData = ethersFunction.encode([{{> params inputs=inputs}}]); const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( { to: self.address, @@ -21,7 +19,8 @@ async callAsync( self._web3Wrapper.getContractDefaults(), ); const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); - let resultArray = ethersFunction.parse(rawCallResult); + BaseContract._throwIfRevertWithReasonCallResult(rawCallResult); + let resultArray = ethersFunction.decode(rawCallResult); const outputAbi = (_.find(self.abi, {name: '{{this.name}}'}) as MethodAbi).outputs; resultArray = BaseContract._formatABIDataItemList(outputAbi, resultArray, BaseContract._lowercaseAddress.bind(this)); resultArray = BaseContract._formatABIDataItemList(outputAbi, resultArray, BaseContract._bnToBigNumber.bind(this)); diff --git a/packages/contract_templates/partials/tx.handlebars b/packages/contract_templates/partials/tx.handlebars index 4340d662e..b39156583 100644 --- a/packages/contract_templates/partials/tx.handlebars +++ b/packages/contract_templates/partials/tx.handlebars @@ -12,9 +12,7 @@ public {{this.tsName}} = { const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs; [{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self)); BaseContract.strictArgumentEncodingCheck(inputAbi, [{{> params inputs=inputs}}]); - const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}( - {{> params inputs=inputs}} - ).data; + const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}.encode([{{> params inputs=inputs}}]); const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( { to: self.address, @@ -37,9 +35,7 @@ public {{this.tsName}} = { const self = this as any as {{contractName}}Contract; const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs; [{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString); - const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}( - {{> params inputs=inputs}} - ).data; + const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}.encode([{{> params inputs=inputs}}]); const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( { to: self.address, @@ -57,9 +53,7 @@ public {{this.tsName}} = { const self = this as any as {{contractName}}Contract; const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs; [{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString); - const abiEncodedTransactionData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}( - {{> params inputs=inputs}} - ).data; + const abiEncodedTransactionData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}.encode([{{> params inputs=inputs}}]); return abiEncodedTransactionData; }, {{> callAsync}} diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 536506435..5cc239ae7 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -83,7 +83,7 @@ "ethereum-types": "^1.0.8", "ethereumjs-abi": "0.6.5", "ethereumjs-util": "^5.1.1", - "ethers": "3.0.22", + "ethers": "4.0.0-beta.14", "js-combinatorics": "^0.5.3", "lodash": "^4.17.5" } diff --git a/packages/fill-scenarios/package.json b/packages/fill-scenarios/package.json index 164a85ebf..7b551f790 100644 --- a/packages/fill-scenarios/package.json +++ b/packages/fill-scenarios/package.json @@ -44,7 +44,7 @@ "@0xproject/utils": "^1.0.11", "@0xproject/web3-wrapper": "^3.0.1", "ethereum-types": "^1.0.8", - "ethers": "3.0.22", + "ethers": "4.0.0-beta.14", "lodash": "^4.17.5" }, "publishConfig": { diff --git a/packages/metacoin/package.json b/packages/metacoin/package.json index 3b32b4099..2c05be45e 100644 --- a/packages/metacoin/package.json +++ b/packages/metacoin/package.json @@ -40,7 +40,7 @@ "@types/mocha": "^5.2.2", "copyfiles": "^2.0.0", "ethereum-types": "^1.0.8", - "ethers": "3.0.22", + "ethers": "4.0.0-beta.14", "lodash": "^4.17.5", "run-s": "^0.0.0" }, diff --git a/packages/migrations/package.json b/packages/migrations/package.json index 81632e9d8..50cd1a2d0 100644 --- a/packages/migrations/package.json +++ b/packages/migrations/package.json @@ -53,7 +53,7 @@ "@0xproject/web3-wrapper": "^3.0.1", "@ledgerhq/hw-app-eth": "^4.3.0", "ethereum-types": "^1.0.8", - "ethers": "3.0.22", + "ethers": "4.0.0-beta.14", "lodash": "^4.17.5" }, "optionalDependencies": { diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json index f83b9cc14..7307f161d 100644 --- a/packages/order-utils/package.json +++ b/packages/order-utils/package.json @@ -69,7 +69,7 @@ "ethereum-types": "^1.0.8", "ethereumjs-abi": "0.6.5", "ethereumjs-util": "^5.1.1", - "ethers": "3.0.22", + "ethers": "4.0.0-beta.14", "lodash": "^4.17.5" }, "publishConfig": { diff --git a/packages/order-watcher/package.json b/packages/order-watcher/package.json index 61218b632..001f6c048 100644 --- a/packages/order-watcher/package.json +++ b/packages/order-watcher/package.json @@ -83,7 +83,7 @@ "bintrees": "^1.0.2", "ethereum-types": "^1.0.8", "ethereumjs-blockstream": "6.0.0", - "ethers": "3.0.22", + "ethers": "4.0.0-beta.14", "lodash": "^4.17.5" }, "publishConfig": { diff --git a/packages/typescript-typings/CHANGELOG.json b/packages/typescript-typings/CHANGELOG.json index 91e6a1e47..7ee78a480 100644 --- a/packages/typescript-typings/CHANGELOG.json +++ b/packages/typescript-typings/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "3.0.0", + "changes": [ + { + "note": "Remove types for ethers.js", + "pr": "1069" + } + ] + }, + { "timestamp": 1537907159, "version": "2.0.2", "changes": [ diff --git a/packages/typescript-typings/types/ethers/index.d.ts b/packages/typescript-typings/types/ethers/index.d.ts deleted file mode 100644 index 875563ba2..000000000 --- a/packages/typescript-typings/types/ethers/index.d.ts +++ /dev/null @@ -1,55 +0,0 @@ -declare module 'ethers' { - import { TxData } from 'ethereum-types'; - - export interface TransactionDescription { - name: string; - signature: string; - sighash: string; - data: string; - } - export interface CallDescription extends TransactionDescription { - parse: (...args: any[]) => any; - } - export interface FunctionDescription { - (...params: any[]): TransactionDescription | CallDescription; - inputs: { names: string[]; types: string[] }; - outputs: { names: string[]; types: string[] }; - type: string; - } - export interface EventDescription { - parse: (...args: any[]) => any; - inputs: { names: string[]; types: string[] }; - signature: string; - topics: string[]; - } - export class Interface { - public functions: { [functionName: string]: FunctionDescription }; - public events: { [eventName: string]: EventDescription }; - constructor(abi: any); - } - export class Contract { - public static getDeployTransaction(bytecode: string, abi: any, ...args: any[]): Partial<TxData>; - constructor(address: string, abi: any, provider: any); - } - const enum errors { - INVALID_ARGUMENT = 'INVALID_ARGUMENT', - } - - export type ParamName = null | string | NestedParamName; - - export interface NestedParamName { - name: string | null; - names: ParamName[]; - } - - export const utils: { - AbiCoder: { - defaultCoder: AbiCoder; - }; - }; - - export interface AbiCoder { - encode: (names: ParamName[] | string[], types: string[] | any[], args: any[] | undefined) => string; - decode: (names: ParamName[] | string[], types: string[] | string, data: string | undefined) => any; - } -} diff --git a/packages/utils/CHANGELOG.json b/packages/utils/CHANGELOG.json index d395a7dec..b4f438966 100644 --- a/packages/utils/CHANGELOG.json +++ b/packages/utils/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "2.0.0", + "changes": [ + { + "note": "Make abi_decoder compatible with ethers ^4.0.0", + "pr": 1069 + } + ] + }, + { "timestamp": 1537907159, "version": "1.0.11", "changes": [ diff --git a/packages/utils/package.json b/packages/utils/package.json index 1fd2f57fa..db265dd8f 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -49,7 +49,7 @@ "detect-node": "2.0.3", "ethereum-types": "^1.0.8", "ethereumjs-util": "^5.1.1", - "ethers": "3.0.22", + "ethers": "4.0.0-beta.14", "isomorphic-fetch": "^2.2.1", "js-sha3": "^0.7.0", "lodash": "^4.17.5" diff --git a/packages/utils/src/abi_decoder.ts b/packages/utils/src/abi_decoder.ts index 265eb105e..ea8c91d10 100644 --- a/packages/utils/src/abi_decoder.ts +++ b/packages/utils/src/abi_decoder.ts @@ -47,7 +47,7 @@ export class AbiDecoder { let decodedData: any[]; try { - decodedData = ethersInterface.events[event.name].parse(log.data); + decodedData = ethersInterface.events[event.name].decode(log.data); } catch (error) { if (error.code === ethers.errors.INVALID_ARGUMENT) { // Because we index events by Method ID, and Method IDs are derived from the method @@ -99,7 +99,7 @@ export class AbiDecoder { const ethersInterface = new ethers.Interface(abiArray); _.map(abiArray, (abi: AbiDefinition) => { if (abi.type === AbiType.Event) { - const topic = ethersInterface.events[abi.name].topics[0]; + const topic = ethersInterface.events[abi.name].topic; const numIndexedArgs = _.reduce(abi.inputs, (sum, input) => (input.indexed ? sum + 1 : sum), 0); this._methodIds[topic] = { ...this._methodIds[topic], diff --git a/packages/utils/src/abi_utils.ts b/packages/utils/src/abi_utils.ts index c9b70966c..598ea5fcc 100644 --- a/packages/utils/src/abi_utils.ts +++ b/packages/utils/src/abi_utils.ts @@ -1,14 +1,19 @@ import { AbiDefinition, AbiType, ContractAbi, DataItem, MethodAbi } from 'ethereum-types'; -import * as ethers from 'ethers'; import * as _ from 'lodash'; import { BigNumber } from './configured_bignumber'; +type ParamName = null | string | NestedParamName; +interface NestedParamName { + name: string | null; + names: ParamName[]; +} + // Note(albrow): This function is unexported in ethers.js. Copying it here for // now. // Source: https://github.com/ethers-io/ethers.js/blob/884593ab76004a808bf8097e9753fb5f8dcc3067/contracts/interface.js#L30 -function parseEthersParams(params: DataItem[]): { names: ethers.ParamName[]; types: string[] } { - const names: ethers.ParamName[] = []; +function parseEthersParams(params: DataItem[]): { names: ParamName[]; types: string[] } { + const names: ParamName[] = []; const types: string[] = []; params.forEach((param: DataItem) => { @@ -37,7 +42,7 @@ function parseEthersParams(params: DataItem[]): { names: ethers.ParamName[]; typ // returns true if x is equal to y and false otherwise. Performs some minimal // type conversion and data massaging for x and y, depending on type. name and // type should typically be derived from parseEthersParams. -function isAbiDataEqual(name: ethers.ParamName, type: string, x: any, y: any): boolean { +function isAbiDataEqual(name: ParamName, type: string, x: any, y: any): boolean { if (_.isUndefined(x) && _.isUndefined(y)) { return true; } else if (_.isUndefined(x) && !_.isUndefined(y)) { @@ -89,7 +94,7 @@ function isAbiDataEqual(name: ethers.ParamName, type: string, x: any, y: any): b // const nestedName = _.isString(name.names[i]) ? (name.names[i] as string) - : ((name.names[i] as ethers.NestedParamName).name as string); + : ((name.names[i] as NestedParamName).name as string); if (!isAbiDataEqual(name.names[i], types[i], x[nestedName], y[nestedName])) { return false; } diff --git a/packages/web3-wrapper/package.json b/packages/web3-wrapper/package.json index cf0b186f2..4c6e545a9 100644 --- a/packages/web3-wrapper/package.json +++ b/packages/web3-wrapper/package.json @@ -59,7 +59,7 @@ "@0xproject/utils": "^1.0.11", "ethereum-types": "^1.0.8", "ethereumjs-util": "^5.1.1", - "ethers": "3.0.22", + "ethers": "4.0.0-beta.14", "lodash": "^4.17.5" }, "publishConfig": { @@ -1071,6 +1071,10 @@ version "9.6.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.0.tgz#d3480ee666df9784b1001a1872a2f6ccefb6c2d7" +"@types/node@^10.3.2": + version "10.9.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.9.4.tgz#0f4cb2dc7c1de6096055357f70179043c33e9897" + "@types/node@^10.5.3": version "10.5.7" resolved "https://registry.npmjs.org/@types/node/-/node-10.5.7.tgz#960d9feb3ade2233bcc9843c918d740b4f78a7cf" @@ -5312,9 +5316,9 @@ ethereumjs-wallet@0.6.0: utf8 "^2.1.1" uuid "^2.0.1" -ethers@0xproject/ethers.js#eip-838-reasons, ethers@3.0.22: - version "3.0.18" - resolved "https://codeload.github.com/0xproject/ethers.js/tar.gz/b91342bd200d142af0165d6befddf783c8ae8447" +ethers@3.0.22: + version "3.0.22" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-3.0.22.tgz#7fab1ea16521705837aa43c15831877b2716b436" dependencies: aes-js "3.0.0" bn.js "^4.4.0" @@ -5327,6 +5331,21 @@ ethers@0xproject/ethers.js#eip-838-reasons, ethers@3.0.22: uuid "2.0.1" xmlhttprequest "1.8.0" +ethers@^4.0.0-beta.14: + version "4.0.0-beta.14" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.0-beta.14.tgz#76aa9257b9c93a7604ff4dc11f2a445d07f6459d" + dependencies: + "@types/node" "^10.3.2" + aes-js "3.0.0" + bn.js "^4.4.0" + elliptic "6.3.3" + hash.js "1.1.3" + js-sha3 "0.5.7" + scrypt-js "2.0.3" + setimmediate "1.0.4" + uuid "2.0.1" + xmlhttprequest "1.8.0" + ethjs-abi@0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/ethjs-abi/-/ethjs-abi-0.1.8.tgz#cd288583ed628cdfadaf8adefa3ba1dbcbca6c18" @@ -6726,7 +6745,7 @@ hash-base@^3.0.0: inherits "^2.0.1" safe-buffer "^5.0.1" -hash.js@^1.0.0, hash.js@^1.0.3: +hash.js@1.1.3, hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.3" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" dependencies: |