From 6a5965d73bb542634631d7af76c150795d899744 Mon Sep 17 00:00:00 2001 From: Alex Browne Date: Thu, 26 Jul 2018 14:11:03 -0700 Subject: Add strictArgumentEncodingCheck to BaseContract and use it in contract templates --- packages/base-contract/src/index.ts | 17 ++++ packages/base-contract/test/base_contract_test.ts | 110 ++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 packages/base-contract/test/base_contract_test.ts (limited to 'packages/base-contract') diff --git a/packages/base-contract/src/index.ts b/packages/base-contract/src/index.ts index a240fb8b6..e354f109e 100644 --- a/packages/base-contract/src/index.ts +++ b/packages/base-contract/src/index.ts @@ -82,6 +82,23 @@ export class BaseContract { } return txDataWithDefaults; } + // 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 as any).utils.AbiCoder.defaultCoder; + const params = abiUtils.parseEthersParams(inputAbi); + const rawEncoded = coder.encode(params.names, params.types, args); + const rawDecoded = coder.decode(params.names, params.types, rawEncoded); + for (let i = 0; i < rawDecoded.length; i++) { + const original = args[i]; + const decoded = rawDecoded[i]; + if (!abiUtils.isAbiDataEqual(params.names[i], params.types[i], original, decoded)) { + throw new Error(`Cannot safely encode argument: ${params.names[i]} (${original}) of type ${params.types[i]}. (Possible type overflow or other encoding error)`); + } + } + } protected _lookupEthersInterface(functionSignature: string): ethers.Interface { const ethersInterface = this._ethersInterfacesByFunctionSignature[functionSignature]; if (_.isUndefined(ethersInterface)) { diff --git a/packages/base-contract/test/base_contract_test.ts b/packages/base-contract/test/base_contract_test.ts new file mode 100644 index 000000000..57aacdc8a --- /dev/null +++ b/packages/base-contract/test/base_contract_test.ts @@ -0,0 +1,110 @@ +import * as chai from 'chai'; +import 'mocha'; + +import { BaseContract } from '../src'; + +const { expect } = chai; + +describe('BaseContract', () => { + describe('strictArgumentEncodingCheck', () => { + it('works for simple types', () => { + BaseContract.strictArgumentEncodingCheck([{ name: 'to', type: 'address' }], ['0xe834ec434daba538cd1b9fe1582052b880bd7e63']); + }); + it('works for array types', () => { + const inputAbi = [{ + name: 'takerAssetFillAmounts', + type: 'uint256[]', + }]; + const args = [ + [ + '9000000000000000000', + '79000000000000000000', + '979000000000000000000', + '7979000000000000000000', + ], + ]; + BaseContract.strictArgumentEncodingCheck(inputAbi, args); + }); + it('works for tuple/struct types', () => { + const inputAbi = [ + { + components: [ + { + name: 'makerAddress', + type: 'address', + }, + { + name: 'takerAddress', + type: 'address', + }, + { + name: 'feeRecipientAddress', + type: 'address', + }, + { + name: 'senderAddress', + type: 'address', + }, + { + name: 'makerAssetAmount', + type: 'uint256', + }, + { + name: 'takerAssetAmount', + type: 'uint256', + }, + { + name: 'makerFee', + type: 'uint256', + }, + { + name: 'takerFee', + type: 'uint256', + }, + { + name: 'expirationTimeSeconds', + type: 'uint256', + }, + { + name: 'salt', + type: 'uint256', + }, + { + name: 'makerAssetData', + type: 'bytes', + }, + { + name: 'takerAssetData', + type: 'bytes', + }, + ], + name: 'order', + type: 'tuple', + }, + ]; + const args = [ + { + makerAddress: '0x6ecbe1db9ef729cbe972c83fb886247691fb6beb', + takerAddress: '0x0000000000000000000000000000000000000000', + feeRecipientAddress: '0xe834ec434daba538cd1b9fe1582052b880bd7e63', + senderAddress: '0x0000000000000000000000000000000000000000', + makerAssetAmount: '0', + takerAssetAmount: '200000000000000000000', + makerFee: '1000000000000000000', + takerFee: '1000000000000000000', + expirationTimeSeconds: '1532563026', + salt: '59342956082154660870994022243365949771115859664887449740907298019908621891376', + makerAssetData: '0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48', + takerAssetData: '0xf47261b00000000000000000000000001d7022f5b17d2f8b695918fb48fa1089c9f85401', + }, + ]; + BaseContract.strictArgumentEncodingCheck(inputAbi, args); + }); + it('throws for integer overflows', () => { + expect(() => BaseContract.strictArgumentEncodingCheck([{ name: 'amount', type: 'uint8' }], ['256'])).to.throw(); + }); + it('throws for fixed byte array overflows', () => { + expect(() => BaseContract.strictArgumentEncodingCheck([{ name: 'hash', type: 'bytes8' }], ['0x001122334455667788'])).to.throw(); + }); + }); +}); -- cgit v1.2.3 From 6a6739ebbec291b61226c047fde7b3d0bb4a7250 Mon Sep 17 00:00:00 2001 From: Alex Browne Date: Thu, 26 Jul 2018 14:32:52 -0700 Subject: Apply prettier --- packages/base-contract/src/index.ts | 6 ++++- packages/base-contract/test/base_contract_test.ts | 30 +++++++++++++---------- 2 files changed, 22 insertions(+), 14 deletions(-) (limited to 'packages/base-contract') diff --git a/packages/base-contract/src/index.ts b/packages/base-contract/src/index.ts index e354f109e..31d2e4019 100644 --- a/packages/base-contract/src/index.ts +++ b/packages/base-contract/src/index.ts @@ -95,7 +95,11 @@ export class BaseContract { const original = args[i]; const decoded = rawDecoded[i]; if (!abiUtils.isAbiDataEqual(params.names[i], params.types[i], original, decoded)) { - throw new Error(`Cannot safely encode argument: ${params.names[i]} (${original}) of type ${params.types[i]}. (Possible type overflow or other encoding error)`); + throw new Error( + `Cannot safely encode argument: ${params.names[i]} (${original}) of type ${ + params.types[i] + }. (Possible type overflow or other encoding error)`, + ); } } } diff --git a/packages/base-contract/test/base_contract_test.ts b/packages/base-contract/test/base_contract_test.ts index 57aacdc8a..2c31d1f11 100644 --- a/packages/base-contract/test/base_contract_test.ts +++ b/packages/base-contract/test/base_contract_test.ts @@ -8,20 +8,20 @@ const { expect } = chai; describe('BaseContract', () => { describe('strictArgumentEncodingCheck', () => { it('works for simple types', () => { - BaseContract.strictArgumentEncodingCheck([{ name: 'to', type: 'address' }], ['0xe834ec434daba538cd1b9fe1582052b880bd7e63']); + BaseContract.strictArgumentEncodingCheck( + [{ name: 'to', type: 'address' }], + ['0xe834ec434daba538cd1b9fe1582052b880bd7e63'], + ); }); it('works for array types', () => { - const inputAbi = [{ - name: 'takerAssetFillAmounts', - type: 'uint256[]', - }]; + const inputAbi = [ + { + name: 'takerAssetFillAmounts', + type: 'uint256[]', + }, + ]; const args = [ - [ - '9000000000000000000', - '79000000000000000000', - '979000000000000000000', - '7979000000000000000000', - ], + ['9000000000000000000', '79000000000000000000', '979000000000000000000', '7979000000000000000000'], ]; BaseContract.strictArgumentEncodingCheck(inputAbi, args); }); @@ -101,10 +101,14 @@ describe('BaseContract', () => { BaseContract.strictArgumentEncodingCheck(inputAbi, args); }); it('throws for integer overflows', () => { - expect(() => BaseContract.strictArgumentEncodingCheck([{ name: 'amount', type: 'uint8' }], ['256'])).to.throw(); + expect(() => + BaseContract.strictArgumentEncodingCheck([{ name: 'amount', type: 'uint8' }], ['256']), + ).to.throw(); }); it('throws for fixed byte array overflows', () => { - expect(() => BaseContract.strictArgumentEncodingCheck([{ name: 'hash', type: 'bytes8' }], ['0x001122334455667788'])).to.throw(); + expect(() => + BaseContract.strictArgumentEncodingCheck([{ name: 'hash', type: 'bytes8' }], ['0x001122334455667788']), + ).to.throw(); }); }); }); -- cgit v1.2.3 From 52e094addcecc6136c9582a51dd52b8f44f769f7 Mon Sep 17 00:00:00 2001 From: Alex Browne Date: Mon, 6 Aug 2018 16:58:46 -0700 Subject: Move some ethers-related types to typescript-typings/ethers --- packages/base-contract/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/base-contract') diff --git a/packages/base-contract/src/index.ts b/packages/base-contract/src/index.ts index 31d2e4019..12f974445 100644 --- a/packages/base-contract/src/index.ts +++ b/packages/base-contract/src/index.ts @@ -87,7 +87,7 @@ export class BaseContract { // 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 as any).utils.AbiCoder.defaultCoder; + const coder = ethers.utils.AbiCoder.defaultCoder; const params = abiUtils.parseEthersParams(inputAbi); const rawEncoded = coder.encode(params.names, params.types, args); const rawDecoded = coder.decode(params.names, params.types, rawEncoded); -- cgit v1.2.3 From 09af23f950b6143cc3aec3c5843963e70d2a5b5c Mon Sep 17 00:00:00 2001 From: Alex Browne Date: Tue, 7 Aug 2018 11:01:41 -0700 Subject: Update CHANGELOG.json for base-contract --- packages/base-contract/CHANGELOG.json | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'packages/base-contract') diff --git a/packages/base-contract/CHANGELOG.json b/packages/base-contract/CHANGELOG.json index 9dddde18a..b041e13da 100644 --- a/packages/base-contract/CHANGELOG.json +++ b/packages/base-contract/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "2.0.0-rc.1", + "changes": [ + { + "pr": 915, + "note": "Added strict encoding/decoding checks for sendTransaction and call" + } + ] + }, { "timestamp": 1532619515, "version": "1.0.4", -- cgit v1.2.3 From f3761af5678503320b7a3e989a743b847ef4245f Mon Sep 17 00:00:00 2001 From: Alex Browne Date: Thu, 9 Aug 2018 11:33:32 -0700 Subject: fix: Update dependencies --- packages/base-contract/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/base-contract') diff --git a/packages/base-contract/package.json b/packages/base-contract/package.json index 851b81262..1e7f21f0d 100644 --- a/packages/base-contract/package.json +++ b/packages/base-contract/package.json @@ -36,7 +36,7 @@ "chai": "^4.0.1", "copyfiles": "^1.2.0", "make-promises-safe": "^1.1.0", - "mocha": "^4.0.1", + "mocha": "^4.1.0", "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.11.0", @@ -48,7 +48,7 @@ "@0xproject/web3-wrapper": "^1.1.2", "ethereum-types": "^1.0.3", "ethers": "3.0.22", - "lodash": "^4.17.4" + "lodash": "^4.17.5" }, "publishConfig": { "access": "public" -- cgit v1.2.3