aboutsummaryrefslogtreecommitdiffstats
path: root/packages/base-contract
diff options
context:
space:
mode:
Diffstat (limited to 'packages/base-contract')
-rw-r--r--packages/base-contract/CHANGELOG.json10
-rw-r--r--packages/base-contract/CHANGELOG.md10
-rw-r--r--packages/base-contract/package.json18
-rw-r--r--packages/base-contract/src/index.ts21
-rw-r--r--packages/base-contract/test/base_contract_test.ts114
5 files changed, 161 insertions, 12 deletions
diff --git a/packages/base-contract/CHANGELOG.json b/packages/base-contract/CHANGELOG.json
index 9dddde18a..39e3cbe5e 100644
--- a/packages/base-contract/CHANGELOG.json
+++ b/packages/base-contract/CHANGELOG.json
@@ -1,5 +1,15 @@
[
{
+ "version": "2.0.0-rc.1",
+ "changes": [
+ {
+ "pr": 915,
+ "note": "Added strict encoding/decoding checks for sendTransaction and call"
+ }
+ ],
+ "timestamp": 1534210131
+ },
+ {
"timestamp": 1532619515,
"version": "1.0.4",
"changes": [
diff --git a/packages/base-contract/CHANGELOG.md b/packages/base-contract/CHANGELOG.md
index 306dce065..002ad931b 100644
--- a/packages/base-contract/CHANGELOG.md
+++ b/packages/base-contract/CHANGELOG.md
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v2.0.0-rc.1 - _August 13, 2018_
+
+ * Added strict encoding/decoding checks for sendTransaction and call (#915)
+
## v1.0.4 - _July 26, 2018_
* Dependencies updated
@@ -21,7 +25,7 @@ CHANGELOG
* Dependencies updated
-## v1.0.0 - _July 20, 2018_
+## v1.0.0 - _July 19, 2018_
* Dependencies updated
@@ -37,7 +41,7 @@ CHANGELOG
* Update EthersJs to fix the `value.toLowerCase()` is not a function bug caused by `ethers.js` breaking patch version https://github.com/ethers-io/ethers.js/issues/201
-## v0.3.3 - _June 1, 2018_
+## v0.3.3 - _May 31, 2018_
* Incorrect publish that was unpublished
@@ -45,7 +49,7 @@ CHANGELOG
* Dependencies updated
-## v0.3.1 - _May 5, 2018_
+## v0.3.1 - _May 4, 2018_
* Dependencies updated
diff --git a/packages/base-contract/package.json b/packages/base-contract/package.json
index 74a83664f..419db34f9 100644
--- a/packages/base-contract/package.json
+++ b/packages/base-contract/package.json
@@ -1,6 +1,6 @@
{
"name": "@0xproject/base-contract",
- "version": "1.0.4",
+ "version": "2.0.0-rc.1",
"engines": {
"node": ">=6.12"
},
@@ -29,24 +29,24 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/base-contract/README.md",
"devDependencies": {
- "@0xproject/tslint-config": "^1.0.4",
+ "@0xproject/tslint-config": "^1.0.5",
"@types/lodash": "4.14.104",
"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",
- "typescript": "2.7.1"
+ "typescript": "2.9.2"
},
"dependencies": {
- "@0xproject/typescript-typings": "^1.0.3",
- "@0xproject/utils": "^1.0.4",
- "@0xproject/web3-wrapper": "^1.1.2",
- "ethereum-types": "^1.0.3",
+ "@0xproject/typescript-typings": "^1.0.4",
+ "@0xproject/utils": "^1.0.5",
+ "@0xproject/web3-wrapper": "^1.2.0",
+ "ethereum-types": "^1.0.4",
"ethers": "3.0.22",
- "lodash": "^4.17.4"
+ "lodash": "^4.17.5"
},
"publishConfig": {
"access": "public"
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();
+ });
+ });
+});