diff options
author | Fabio Berger <me@fabioberger.com> | 2018-08-14 04:01:32 +0800 |
---|---|---|
committer | Fabio Berger <me@fabioberger.com> | 2018-08-14 04:01:32 +0800 |
commit | 9d3c287918389d07f884245bd1bc968955768b6f (patch) | |
tree | 460fded537c7d64154972b7d14332f88554d14c0 /packages/base-contract | |
parent | c2b5fe3d844d35966c5498326000bd8317fb547c (diff) | |
parent | 15e15f994a1b18cf2e9be151194c826d53a01601 (diff) | |
download | dexon-sol-tools-9d3c287918389d07f884245bd1bc968955768b6f.tar dexon-sol-tools-9d3c287918389d07f884245bd1bc968955768b6f.tar.gz dexon-sol-tools-9d3c287918389d07f884245bd1bc968955768b6f.tar.bz2 dexon-sol-tools-9d3c287918389d07f884245bd1bc968955768b6f.tar.lz dexon-sol-tools-9d3c287918389d07f884245bd1bc968955768b6f.tar.xz dexon-sol-tools-9d3c287918389d07f884245bd1bc968955768b6f.tar.zst dexon-sol-tools-9d3c287918389d07f884245bd1bc968955768b6f.zip |
Merge branch 'sol-cov-fixes' of github.com:0xProject/0x-monorepo into sol-cov-fixes
* 'sol-cov-fixes' of github.com:0xProject/0x-monorepo: (49 commits)
Add @return comments
Import marshaller directly
Update comment about ethers checksummed address behavior
Add packages/coverage/.gitkeep file
Update CI config and package.json to run @0xproject/utils tests on CI
Update remaining CHANGELOG.json files
Change amir picture
Update CHANGELOG.json for contract-wrappers
Update ethers typings for TypeScript 2.9.2
Update CHANGELOG.json for base-contract
Move some ethers-related types to typescript-typings/ethers
Apply prettier
Add strictArgumentEncodingCheck to BaseContract and use it in contract templates
fix(monorepo-scripts): Fix typo in git tag command
feat(monorepo-scripts): Add confirmation prompt before publishing
fix comments and styling for MixinSignatureValidator
Update TypeScript to version 2.9.2
Use asm for hashEIP712Message, increment free memory pointer after asm hashing functions
Fix comments, styling, and optimize hashOrder
Remove assertion comments
...
Diffstat (limited to 'packages/base-contract')
-rw-r--r-- | packages/base-contract/CHANGELOG.json | 9 | ||||
-rw-r--r-- | packages/base-contract/package.json | 2 | ||||
-rw-r--r-- | packages/base-contract/src/index.ts | 21 | ||||
-rw-r--r-- | packages/base-contract/test/base_contract_test.ts | 114 |
4 files changed, 145 insertions, 1 deletions
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,5 +1,14 @@ [ { + "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", "changes": [ diff --git a/packages/base-contract/package.json b/packages/base-contract/package.json index 7ac629bbf..851b81262 100644 --- a/packages/base-contract/package.json +++ b/packages/base-contract/package.json @@ -40,7 +40,7 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "tslint": "5.11.0", - "typescript": "2.7.1" + "typescript": "2.9.2" }, "dependencies": { "@0xproject/typescript-typings": "^1.0.3", diff --git a/packages/base-contract/src/index.ts b/packages/base-contract/src/index.ts index a240fb8b6..12f974445 100644 --- a/packages/base-contract/src/index.ts +++ b/packages/base-contract/src/index.ts @@ -82,6 +82,27 @@ 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.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..2c31d1f11 --- /dev/null +++ b/packages/base-contract/test/base_contract_test.ts @@ -0,0 +1,114 @@ +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(); + }); + }); +}); |