aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/0x.js/CHANGELOG.json8
-rw-r--r--packages/0x.js/package.json4
-rw-r--r--packages/0x.js/test/0x.js_test.ts7
-rw-r--r--packages/abi-gen/package.json2
-rw-r--r--packages/assert/package.json4
-rw-r--r--packages/base-contract/CHANGELOG.json9
-rw-r--r--packages/base-contract/package.json4
-rw-r--r--packages/base-contract/src/index.ts21
-rw-r--r--packages/base-contract/test/base_contract_test.ts114
-rw-r--r--packages/connect/package.json4
-rw-r--r--packages/contract-wrappers/CHANGELOG.json4
-rw-r--r--packages/contract-wrappers/package.json4
-rw-r--r--packages/contract_templates/partials/callAsync.handlebars1
-rw-r--r--packages/contract_templates/partials/tx.handlebars1
-rw-r--r--packages/contracts/package.json4
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol13
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol1
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/libs/LibAbiEncoder.sol17
-rw-r--r--packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol1
-rw-r--r--packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol22
-rw-r--r--packages/contracts/test/exchange/signature_validator.ts6
-rw-r--r--packages/contracts/test/utils/exchange_wrapper.ts25
-rw-r--r--packages/contracts/test/utils/fill_order_combinatorial_utils.ts55
-rw-r--r--packages/dev-utils/package.json4
-rw-r--r--packages/fill-scenarios/CHANGELOG.json3
-rw-r--r--packages/fill-scenarios/package.json2
-rw-r--r--packages/json-schemas/package.json2
-rw-r--r--packages/metacoin/package.json2
-rw-r--r--packages/migrations/package.json35
-rw-r--r--packages/monorepo-scripts/package.json2
-rw-r--r--packages/order-utils/CHANGELOG.json3
-rw-r--r--packages/order-utils/package.json4
-rw-r--r--packages/order-utils/test/signature_utils_test.ts3
-rw-r--r--packages/order-watcher/CHANGELOG.json8
-rw-r--r--packages/order-watcher/package.json4
-rw-r--r--packages/react-docs-example/package.json2
-rw-r--r--packages/react-docs/package.json2
-rw-r--r--packages/react-shared/package.json2
-rw-r--r--packages/sol-compiler/package.json4
-rw-r--r--packages/sol-cov/package.json4
-rw-r--r--packages/sol-resolver/package.json2
-rw-r--r--packages/sra-report/package.json4
-rw-r--r--packages/subproviders/package.json4
-rw-r--r--packages/testnet-faucets/package.json2
-rw-r--r--packages/tslint-config/package.json2
-rw-r--r--packages/typescript-typings/types/ethers/index.d.ts18
-rw-r--r--packages/utils/coverage/.gitkeep0
-rw-r--r--packages/utils/package.json16
-rw-r--r--packages/utils/src/abi_utils.ts153
-rw-r--r--packages/utils/test/abi_utils_test.ts19
-rw-r--r--packages/utils/tsconfig.json2
-rw-r--r--packages/web3-wrapper/package.json4
-rw-r--r--packages/website/package.json2
-rw-r--r--packages/website/public/images/team/amir.jpegbin21098 -> 0 bytes
-rw-r--r--packages/website/public/images/team/amir.pngbin0 -> 116488 bytes
-rw-r--r--packages/website/public/images/team/clay.pngbin0 -> 85774 bytes
-rw-r--r--packages/website/ts/pages/about/about.tsx13
57 files changed, 566 insertions, 92 deletions
diff --git a/packages/0x.js/CHANGELOG.json b/packages/0x.js/CHANGELOG.json
index 4f39a9b8c..913b7a76e 100644
--- a/packages/0x.js/CHANGELOG.json
+++ b/packages/0x.js/CHANGELOG.json
@@ -1,5 +1,13 @@
[
{
+ "version": "1.0.1-rc.3",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ]
+ },
+ {
"version": "1.0.1-rc.2",
"changes": [
{
diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json
index 7d3fa92c3..b023ce525 100644
--- a/packages/0x.js/package.json
+++ b/packages/0x.js/package.json
@@ -85,7 +85,7 @@
"dirty-chai": "^2.0.1",
"json-loader": "^0.5.4",
"make-promises-safe": "^1.1.0",
- "mocha": "^4.0.1",
+ "mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"opn-cli": "^3.1.0",
@@ -110,7 +110,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"
diff --git a/packages/0x.js/test/0x.js_test.ts b/packages/0x.js/test/0x.js_test.ts
index b4baecb1e..be2a94482 100644
--- a/packages/0x.js/test/0x.js_test.ts
+++ b/packages/0x.js/test/0x.js_test.ts
@@ -48,10 +48,11 @@ describe('ZeroEx library', () => {
const ethSignSignature =
'0x1B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403';
const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
+ const bytes32Zeros = '0x0000000000000000000000000000000000000000000000000000000000000000';
it("should return false if the data doesn't pertain to the signature & address", async () => {
- return expect((zeroEx.exchange as any).isValidSignatureAsync('0x0', address, ethSignSignature)).to.become(
- false,
- );
+ return expect(
+ (zeroEx.exchange as any).isValidSignatureAsync(bytes32Zeros, address, ethSignSignature),
+ ).to.become(false);
});
it("should return false if the address doesn't pertain to the signature & data", async () => {
const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
diff --git a/packages/abi-gen/package.json b/packages/abi-gen/package.json
index 393428771..8ce7cd600 100644
--- a/packages/abi-gen/package.json
+++ b/packages/abi-gen/package.json
@@ -38,7 +38,7 @@
"ethereum-types": "^1.0.3",
"glob": "^7.1.2",
"handlebars": "^4.0.11",
- "lodash": "^4.17.4",
+ "lodash": "^4.17.5",
"mkdirp": "^0.5.1",
"sleep": "^5.1.1",
"tmp": "^0.0.33",
diff --git a/packages/assert/package.json b/packages/assert/package.json
index f95190ad6..a1b5b449b 100644
--- a/packages/assert/package.json
+++ b/packages/assert/package.json
@@ -39,7 +39,7 @@
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
- "mocha": "^4.0.1",
+ "mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"shx": "^0.2.2",
@@ -50,7 +50,7 @@
"@0xproject/json-schemas": "^1.0.1-rc.3",
"@0xproject/typescript-typings": "^1.0.3",
"@0xproject/utils": "^1.0.4",
- "lodash": "^4.17.4",
+ "lodash": "^4.17.5",
"valid-url": "^1.0.9"
},
"publishConfig": {
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 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"
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();
+ });
+ });
+});
diff --git a/packages/connect/package.json b/packages/connect/package.json
index d2f18c410..ac9482b2c 100644
--- a/packages/connect/package.json
+++ b/packages/connect/package.json
@@ -56,7 +56,7 @@
"@0xproject/types": "^0.8.2",
"@0xproject/typescript-typings": "^1.0.3",
"@0xproject/utils": "^1.0.4",
- "lodash": "^4.17.4",
+ "lodash": "^4.17.5",
"query-string": "^5.0.1",
"sinon": "^4.0.0",
"websocket": "^1.0.25"
@@ -77,7 +77,7 @@
"dirty-chai": "^2.0.1",
"fetch-mock": "^5.13.1",
"make-promises-safe": "^1.1.0",
- "mocha": "^4.0.1",
+ "mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"shx": "^0.2.2",
diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json
index 02e1acf91..fb077ce73 100644
--- a/packages/contract-wrappers/CHANGELOG.json
+++ b/packages/contract-wrappers/CHANGELOG.json
@@ -3,6 +3,10 @@
"version": "1.0.1-rc.3",
"changes": [
{
+ "pr": 915,
+ "note": "Added strict encoding/decoding checks for sendTransaction and call"
+ },
+ {
"note": "Add ForwarderWrapper",
"pr": 934
},
diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json
index 64de5b0c2..b9ce21552 100644
--- a/packages/contract-wrappers/package.json
+++ b/packages/contract-wrappers/package.json
@@ -60,7 +60,7 @@
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
- "mocha": "^4.0.1",
+ "mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"opn-cli": "^3.1.0",
@@ -86,7 +86,7 @@
"ethereumjs-util": "^5.1.1",
"ethers": "3.0.22",
"js-sha3": "^0.7.0",
- "lodash": "^4.17.4",
+ "lodash": "^4.17.5",
"uuid": "^3.1.0"
},
"publishConfig": {
diff --git a/packages/contract_templates/partials/callAsync.handlebars b/packages/contract_templates/partials/callAsync.handlebars
index fcaae57c6..94752691d 100644
--- a/packages/contract_templates/partials/callAsync.handlebars
+++ b/packages/contract_templates/partials/callAsync.handlebars
@@ -7,6 +7,7 @@ async callAsync(
const functionSignature = '{{this.functionSignature}}';
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;
diff --git a/packages/contract_templates/partials/tx.handlebars b/packages/contract_templates/partials/tx.handlebars
index e297d05e6..4340d662e 100644
--- a/packages/contract_templates/partials/tx.handlebars
+++ b/packages/contract_templates/partials/tx.handlebars
@@ -11,6 +11,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.bind(self));
+ BaseContract.strictArgumentEncodingCheck(inputAbi, [{{> params inputs=inputs}}]);
const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}(
{{> params inputs=inputs}}
).data;
diff --git a/packages/contracts/package.json b/packages/contracts/package.json
index 1f5c15674..067a20775 100644
--- a/packages/contracts/package.json
+++ b/packages/contracts/package.json
@@ -62,7 +62,7 @@
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
- "mocha": "^4.0.1",
+ "mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"solc": "^0.4.24",
@@ -86,6 +86,6 @@
"ethereumjs-util": "^5.1.1",
"ethers": "3.0.22",
"js-combinatorics": "^0.5.3",
- "lodash": "^4.17.4"
+ "lodash": "^4.17.5"
}
}
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol
index ac7382715..44de54817 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol
@@ -96,14 +96,15 @@ contract MixinSignatureValidator is
"LENGTH_GREATER_THAN_0_REQUIRED"
);
- // Ensure signature is supported
+ // Pop last byte off of signature byte array.
uint8 signatureTypeRaw = uint8(signature.popLastByte());
+
+ // Ensure signature is supported
require(
signatureTypeRaw < uint8(SignatureType.NSignatureTypes),
"SIGNATURE_UNSUPPORTED"
);
- // Pop last byte off of signature byte array.
SignatureType signatureType = SignatureType(signatureTypeRaw);
// Variables are not scoped in Solidity.
@@ -141,7 +142,12 @@ contract MixinSignatureValidator is
v = uint8(signature[0]);
r = signature.readBytes32(1);
s = signature.readBytes32(33);
- recovered = ecrecover(hash, v, r, s);
+ recovered = ecrecover(
+ hash,
+ v,
+ r,
+ s
+ );
isValid = signerAddress == recovered;
return isValid;
@@ -197,7 +203,6 @@ contract MixinSignatureValidator is
// | 0x14 + x | 1 | Signature type is always "\x06" |
} else if (signatureType == SignatureType.Validator) {
// Pop last 20 bytes off of signature byte array.
-
address validatorAddress = signature.popLast20Bytes();
// Ensure signer has approved validator.
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol
index b5de1a5de..821d30279 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol
@@ -142,7 +142,6 @@ contract MixinTransactions is
// Compute hash
result := keccak256(memPtr, 128)
}
-
return result;
}
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibAbiEncoder.sol b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibAbiEncoder.sol
index 704c7061c..4aad37709 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibAbiEncoder.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibAbiEncoder.sol
@@ -24,20 +24,17 @@ import "./LibOrder.sol";
contract LibAbiEncoder {
- /// @dev ABI encodes calldata for `fillOrder` in memory and returns the address range.
- /// This range can be passed into `call` or `delegatecall` to invoke an external
- /// call to `fillOrder`.
+ /// @dev ABI encodes calldata for `fillOrder`.
/// @param order Order struct containing order specifications.
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
/// @param signature Proof that order has been created by maker.
- /// @return calldataBegin Memory address of ABI encoded calldata.
- /// @return calldataLength Lenfgth of ABI encoded calldata.
+ /// @return ABI encoded calldata for `fillOrder`.
function abiEncodeFillOrder(
LibOrder.Order memory order,
uint256 takerAssetFillAmount,
bytes memory signature
)
- public
+ internal
pure
returns (bytes memory fillOrderCalldata)
{
@@ -207,10 +204,10 @@ contract LibAbiEncoder {
}
// Set length of calldata
- mstore(
- fillOrderCalldata,
- sub(dataAreaEnd, add(fillOrderCalldata, 0x20))
- )
+ mstore(fillOrderCalldata, sub(dataAreaEnd, add(fillOrderCalldata, 0x20)))
+
+ // Increment free memory pointer
+ mstore(0x40, dataAreaEnd)
}
return fillOrderCalldata;
diff --git a/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol b/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol
index 923bac97d..d9cec9edc 100644
--- a/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol
+++ b/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol
@@ -22,6 +22,7 @@ pragma experimental ABIEncoderV2;
import "../../protocol/Exchange/Exchange.sol";
+// solhint-disable no-empty-blocks
contract TestExchangeInternals is
Exchange
{
diff --git a/packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol b/packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol
index 5a349527b..4a99dd9c1 100644
--- a/packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol
+++ b/packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol
@@ -22,13 +22,33 @@ pragma experimental ABIEncoderV2;
import "../../protocol/Exchange/libs/LibMath.sol";
import "../../protocol/Exchange/libs/LibOrder.sol";
import "../../protocol/Exchange/libs/LibFillResults.sol";
+import "../../protocol/Exchange/libs/LibAbiEncoder.sol";
contract TestLibs is
LibMath,
LibOrder,
- LibFillResults
+ LibFillResults,
+ LibAbiEncoder
{
+
+ function publicAbiEncodeFillOrder(
+ Order memory order,
+ uint256 takerAssetFillAmount,
+ bytes memory signature
+ )
+ public
+ pure
+ returns (bytes memory fillOrderCalldata)
+ {
+ fillOrderCalldata = abiEncodeFillOrder(
+ order,
+ takerAssetFillAmount,
+ signature
+ );
+ return fillOrderCalldata;
+ }
+
function publicGetPartialAmount(
uint256 numerator,
uint256 denominator,
diff --git a/packages/contracts/test/exchange/signature_validator.ts b/packages/contracts/test/exchange/signature_validator.ts
index f2bb42c75..bef0547bd 100644
--- a/packages/contracts/test/exchange/signature_validator.ts
+++ b/packages/contracts/test/exchange/signature_validator.ts
@@ -113,7 +113,7 @@ describe('MixinSignatureValidator', () => {
it('should revert when signature type is unsupported', async () => {
const unsupportedSignatureType = SignatureType.NSignatureTypes;
- const unsupportedSignatureHex = `0x${unsupportedSignatureType}`;
+ const unsupportedSignatureHex = '0x' + Buffer.from([unsupportedSignatureType]).toString('hex');
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
return expectContractCallFailed(
signatureValidator.publicIsValidSignature.callAsync(
@@ -126,7 +126,7 @@ describe('MixinSignatureValidator', () => {
});
it('should revert when SignatureType=Illegal', async () => {
- const unsupportedSignatureHex = `0x${SignatureType.Illegal}`;
+ const unsupportedSignatureHex = '0x' + Buffer.from([SignatureType.Illegal]).toString('hex');
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
return expectContractCallFailed(
signatureValidator.publicIsValidSignature.callAsync(
@@ -139,7 +139,7 @@ describe('MixinSignatureValidator', () => {
});
it('should return false when SignatureType=Invalid and signature has a length of zero', async () => {
- const signatureHex = `0x${SignatureType.Invalid}`;
+ const signatureHex = '0x' + Buffer.from([SignatureType.Invalid]).toString('hex');
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
const isValidSignature = await signatureValidator.publicIsValidSignature.callAsync(
orderHashHex,
diff --git a/packages/contracts/test/utils/exchange_wrapper.ts b/packages/contracts/test/utils/exchange_wrapper.ts
index 490ea959b..d57592d6d 100644
--- a/packages/contracts/test/utils/exchange_wrapper.ts
+++ b/packages/contracts/test/utils/exchange_wrapper.ts
@@ -8,7 +8,7 @@ import { ExchangeContract } from '../../generated_contract_wrappers/exchange';
import { formatters } from './formatters';
import { LogDecoder } from './log_decoder';
import { orderUtils } from './order_utils';
-import { OrderInfo, SignedTransaction } from './types';
+import { FillResults, OrderInfo, SignedTransaction } from './types';
export class ExchangeWrapper {
private readonly _exchange: ExchangeContract;
@@ -243,4 +243,27 @@ export class ExchangeWrapper {
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
+ public async getFillOrderResultsAsync(
+ signedOrder: SignedOrder,
+ from: string,
+ opts: { takerAssetFillAmount?: BigNumber } = {},
+ ): Promise<FillResults> {
+ const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
+ const fillResults = await this._exchange.fillOrder.callAsync(
+ params.order,
+ params.takerAssetFillAmount,
+ params.signature,
+ { from },
+ );
+ return fillResults;
+ }
+ public abiEncodeFillOrder(signedOrder: SignedOrder, opts: { takerAssetFillAmount?: BigNumber } = {}): string {
+ const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
+ const data = this._exchange.fillOrder.getABIEncodedTransactionData(
+ params.order,
+ params.takerAssetFillAmount,
+ params.signature,
+ );
+ return data;
+ }
}
diff --git a/packages/contracts/test/utils/fill_order_combinatorial_utils.ts b/packages/contracts/test/utils/fill_order_combinatorial_utils.ts
index bdd1e62a2..284c4a2db 100644
--- a/packages/contracts/test/utils/fill_order_combinatorial_utils.ts
+++ b/packages/contracts/test/utils/fill_order_combinatorial_utils.ts
@@ -15,6 +15,7 @@ import * as _ from 'lodash';
import 'make-promises-safe';
import { ExchangeContract, ExchangeFillEventArgs } from '../../generated_contract_wrappers/exchange';
+import { TestLibsContract } from '../../generated_contract_wrappers/test_libs';
import { artifacts } from './artifacts';
import { expectTransactionFailedAsync } from './assertions';
@@ -123,6 +124,8 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
exchangeContract.address,
);
+ const testLibsContract = await TestLibsContract.deployFrom0xArtifactAsync(artifacts.TestLibs, provider, txDefaults);
+
const fillOrderCombinatorialUtils = new FillOrderCombinatorialUtils(
orderFactory,
ownerAddress,
@@ -132,6 +135,7 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
zrxAssetData,
exchangeWrapper,
assetWrapper,
+ testLibsContract,
);
return fillOrderCombinatorialUtils;
}
@@ -145,6 +149,7 @@ export class FillOrderCombinatorialUtils {
public zrxAssetData: string;
public exchangeWrapper: ExchangeWrapper;
public assetWrapper: AssetWrapper;
+ public testLibsContract: TestLibsContract;
public static generateFillOrderCombinations(): FillScenario[] {
const takerScenarios = [
TakerScenario.Unspecified,
@@ -329,6 +334,7 @@ export class FillOrderCombinatorialUtils {
zrxAssetData: string,
exchangeWrapper: ExchangeWrapper,
assetWrapper: AssetWrapper,
+ testLibsContract: TestLibsContract,
) {
this.orderFactory = orderFactory;
this.ownerAddress = ownerAddress;
@@ -338,6 +344,7 @@ export class FillOrderCombinatorialUtils {
this.zrxAssetData = zrxAssetData;
this.exchangeWrapper = exchangeWrapper;
this.assetWrapper = assetWrapper;
+ this.testLibsContract = testLibsContract;
}
public async testFillOrderScenarioAsync(
provider: Provider,
@@ -410,6 +417,8 @@ export class FillOrderCombinatorialUtils {
lazyStore,
fillRevertReasonIfExists,
);
+
+ await this._abiEncodeFillOrderAndAssertOutcomeAsync(signedOrder, takerAssetFillAmount);
}
private async _fillOrderAndAssertOutcomeAsync(
signedOrder: SignedOrder,
@@ -456,6 +465,29 @@ export class FillOrderCombinatorialUtils {
signedOrder.takerAssetAmount,
signedOrder.makerAssetAmount,
);
+ const expMakerFeePaid = orderUtils.getPartialAmount(
+ expFilledTakerAmount,
+ signedOrder.takerAssetAmount,
+ signedOrder.makerFee,
+ );
+ const expTakerFeePaid = orderUtils.getPartialAmount(
+ expFilledTakerAmount,
+ signedOrder.takerAssetAmount,
+ signedOrder.takerFee,
+ );
+ const fillResults = await this.exchangeWrapper.getFillOrderResultsAsync(signedOrder, this.takerAddress, {
+ takerAssetFillAmount,
+ });
+ expect(fillResults.takerAssetFilledAmount).to.be.bignumber.equal(
+ expFilledTakerAmount,
+ 'takerAssetFilledAmount',
+ );
+ expect(fillResults.makerAssetFilledAmount).to.be.bignumber.equal(
+ expFilledMakerAmount,
+ 'makerAssetFilledAmount',
+ );
+ expect(fillResults.takerFeePaid).to.be.bignumber.equal(expTakerFeePaid, 'takerFeePaid');
+ expect(fillResults.makerFeePaid).to.be.bignumber.equal(expMakerFeePaid, 'makerFeePaid');
// - Let's fill the order!
const txReceipt = await this.exchangeWrapper.fillOrderAsync(signedOrder, this.takerAddress, {
@@ -479,17 +511,7 @@ export class FillOrderCombinatorialUtils {
expFilledTakerAmount,
'log.args.takerAssetFilledAmount',
);
- const expMakerFeePaid = orderUtils.getPartialAmount(
- expFilledTakerAmount,
- signedOrder.takerAssetAmount,
- signedOrder.makerFee,
- );
expect(log.args.makerFeePaid).to.be.bignumber.equal(expMakerFeePaid, 'log.args.makerFeePaid');
- const expTakerFeePaid = orderUtils.getPartialAmount(
- expFilledTakerAmount,
- signedOrder.takerAssetAmount,
- signedOrder.takerFee,
- );
expect(log.args.takerFeePaid).to.be.bignumber.equal(expTakerFeePaid, 'logs.args.takerFeePaid');
expect(log.args.orderHash).to.be.equal(orderHash, 'log.args.orderHash');
expect(log.args.makerAssetData).to.be.equal(makerAssetData, 'log.args.makerAssetData');
@@ -571,6 +593,19 @@ export class FillOrderCombinatorialUtils {
'ZRXAssetBalanceOfFeeRecipient',
);
}
+ private async _abiEncodeFillOrderAndAssertOutcomeAsync(
+ signedOrder: SignedOrder,
+ takerAssetFillAmount: BigNumber,
+ ): Promise<void> {
+ const params = orderUtils.createFill(signedOrder, takerAssetFillAmount);
+ const expectedAbiEncodedData = this.exchangeWrapper.abiEncodeFillOrder(signedOrder, { takerAssetFillAmount });
+ const libsAbiEncodedData = await this.testLibsContract.publicAbiEncodeFillOrder.callAsync(
+ params.order,
+ params.takerAssetFillAmount,
+ params.signature,
+ );
+ expect(libsAbiEncodedData).to.be.equal(expectedAbiEncodedData, 'ABIEncodedFillOrderData');
+ }
private async _getTakerAssetFillAmountAsync(
signedOrder: SignedOrder,
takerAssetFillAmountScenario: TakerAssetFillAmountScenario,
diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json
index 66f6472f1..95b9afa21 100644
--- a/packages/dev-utils/package.json
+++ b/packages/dev-utils/package.json
@@ -37,7 +37,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",
"nyc": "^11.0.1",
"shx": "^0.2.2",
@@ -51,7 +51,7 @@
"@0xproject/utils": "^1.0.4",
"@0xproject/web3-wrapper": "^1.1.2",
"ethereum-types": "^1.0.3",
- "lodash": "^4.17.4"
+ "lodash": "^4.17.5"
},
"publishConfig": {
"access": "public"
diff --git a/packages/fill-scenarios/CHANGELOG.json b/packages/fill-scenarios/CHANGELOG.json
index 04e076203..1c3864da2 100644
--- a/packages/fill-scenarios/CHANGELOG.json
+++ b/packages/fill-scenarios/CHANGELOG.json
@@ -6,6 +6,9 @@
"note":
"Updated to use latest orderFactory interface, fixed `feeRecipient` spelling error in public interface",
"pr": 936
+ },
+ {
+ "note": "Dependencies updated"
}
]
},
diff --git a/packages/fill-scenarios/package.json b/packages/fill-scenarios/package.json
index f7e1e1ec4..aafca38c4 100644
--- a/packages/fill-scenarios/package.json
+++ b/packages/fill-scenarios/package.json
@@ -49,7 +49,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"
diff --git a/packages/json-schemas/package.json b/packages/json-schemas/package.json
index 6f0376d1b..e56ad53dd 100644
--- a/packages/json-schemas/package.json
+++ b/packages/json-schemas/package.json
@@ -64,7 +64,7 @@
"dirty-chai": "^2.0.1",
"lodash.foreach": "^4.5.0",
"make-promises-safe": "^1.1.0",
- "mocha": "^4.0.1",
+ "mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"shx": "^0.2.2",
diff --git a/packages/metacoin/package.json b/packages/metacoin/package.json
index 890d14fba..8dc862b65 100644
--- a/packages/metacoin/package.json
+++ b/packages/metacoin/package.json
@@ -43,7 +43,7 @@
"copyfiles": "^2.0.0",
"ethereum-types": "^1.0.3",
"ethers": "3.0.22",
- "lodash": "^4.17.4",
+ "lodash": "^4.17.5",
"run-s": "^0.0.0"
},
"devDependencies": {
diff --git a/packages/migrations/package.json b/packages/migrations/package.json
index c4d14eaee..cca0f112a 100644
--- a/packages/migrations/package.json
+++ b/packages/migrations/package.json
@@ -13,8 +13,10 @@
"manual:postpublish": "yarn build; node ./scripts/postpublish.js",
"pre_build": "run-s copy_artifacts generate_contract_wrappers",
"copy_artifacts": "copyfiles 'artifacts/**/*' ./lib",
- "clean": "shx rm -rf lib src/contract_wrappers",
- "lint": "tslint --project . --exclude **/src/v2/contract_wrappers/**/* --exclude **/src/v1/contract_wrappers/**/*",
+ "clean":
+ "shx rm -rf lib src/1.0.0/contract_wrappers src/2.0.0/contract_wrappers src/2.0.0-beta-testnet/contract_wrappers",
+ "lint":
+ "tslint --project . --exclude **/src/v2/contract_wrappers/**/* --exclude **/src/v1/contract_wrappers/**/*",
"migrate:v1": "run-s build compile:v1 script:migrate:v1",
"migrate:v2": "run-s build compile:v2 script:migrate:v2",
"migrate:v2-beta-testnet": "run-s build compile:v2-beta-testnet script:migrate:v2-beta-testnet",
@@ -22,18 +24,27 @@
"script:migrate:v2": "node ./lib/migrate.js --contracts-version 2.0.0",
"script:migrate:v2-beta-testnet": "node ./lib/migrate.js --contracts-version 2.0.0-beta-testnet",
"generate_contract_wrappers": "run-p generate_contract_wrappers:*",
- "generate_contract_wrappers:v1": "abi-gen --abis ${npm_package_config_abis_v1} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/1.0.0/contract_wrappers --backend ethers",
- "generate_contract_wrappers:v2": "abi-gen --abis ${npm_package_config_abis_v2} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/2.0.0/contract_wrappers --backend ethers",
- "generate_contract_wrappers:v2-beta-testnet": "abi-gen --abis ${npm_package_config_abis_v2BetaTestnet} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/2.0.0-beta-testnet/contract_wrappers --backend ethers",
- "compile:v1": "sol-compiler --artifacts-dir artifacts/1.0.0 --contracts Exchange_v1,DummyERC20Token,ZRXToken,WETH9,TokenTransferProxy_v1,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,TokenRegistry",
- "compile:v2": "sol-compiler --artifacts-dir artifacts/2.0.0 --contracts ERC20Token,DummyERC20Token,ERC721Token,DummyERC721Token,ERC20Proxy,ERC721Proxy,Exchange,Forwarder,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,ZRXToken,WETH9,IWallet,IValidator",
- "compile:v2-beta-testnet": "sol-compiler --artifacts-dir artifacts/2.0.0-beta-testnet --contracts AssetProxyOwner,ERC20Proxy,ERC721Proxy,Exchange,Forwarder,IWallet,IValidator,ERC20Token,ERC721Token"
+ "generate_contract_wrappers:v1":
+ "abi-gen --abis ${npm_package_config_abis_v1} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/1.0.0/contract_wrappers --backend ethers",
+ "generate_contract_wrappers:v2":
+ "abi-gen --abis ${npm_package_config_abis_v2} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/2.0.0/contract_wrappers --backend ethers",
+ "generate_contract_wrappers:v2-beta-testnet":
+ "abi-gen --abis ${npm_package_config_abis_v2BetaTestnet} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/2.0.0-beta-testnet/contract_wrappers --backend ethers",
+ "compile:v1":
+ "sol-compiler --artifacts-dir artifacts/1.0.0 --contracts Exchange_v1,DummyERC20Token,ZRXToken,WETH9,TokenTransferProxy_v1,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,TokenRegistry",
+ "compile:v2":
+ "sol-compiler --artifacts-dir artifacts/2.0.0 --contracts ERC20Token,DummyERC20Token,ERC721Token,DummyERC721Token,ERC20Proxy,ERC721Proxy,Exchange,Forwarder,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,ZRXToken,WETH9,IWallet,IValidator",
+ "compile:v2-beta-testnet":
+ "sol-compiler --artifacts-dir artifacts/2.0.0-beta-testnet --contracts AssetProxyOwner,ERC20Proxy,ERC721Proxy,Exchange,Forwarder,IWallet,IValidator,ERC20Token,ERC721Token"
},
"config": {
"abis": {
- "v1": "artifacts/1.0.0/@(DummyERC20Token|TokenTransferProxy_v1|Exchange_v1|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|WETH9).json",
- "v2": "artifacts/2.0.0/@(ERC20Token|DummyERC20Token|ERC721Token|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|Forwarder|AssetProxyOwner|ZRXToken|WETH9|IWallet|IValidator).json",
- "v2BetaTestnet": "artifacts/2.0.0-beta-testnet/@(ERC20Token|ERC721Token|ERC20Proxy|ERC721Proxy|Exchange|Forwarder|AssetProxyOwner|IWallet|IValidator).json"
+ "v1":
+ "artifacts/1.0.0/@(DummyERC20Token|TokenTransferProxy_v1|Exchange_v1|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|WETH9).json",
+ "v2":
+ "artifacts/2.0.0/@(ERC20Token|DummyERC20Token|ERC721Token|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|Forwarder|AssetProxyOwner|ZRXToken|WETH9|IWallet|IValidator).json",
+ "v2BetaTestnet":
+ "artifacts/2.0.0-beta-testnet/@(ERC20Token|ERC721Token|ERC20Proxy|ERC721Proxy|Exchange|Forwarder|AssetProxyOwner|IWallet|IValidator).json"
}
},
"license": "Apache-2.0",
@@ -63,7 +74,7 @@
"@ledgerhq/hw-app-eth": "^4.3.0",
"ethereum-types": "^1.0.3",
"ethers": "3.0.22",
- "lodash": "^4.17.4"
+ "lodash": "^4.17.5"
},
"optionalDependencies": {
"@ledgerhq/hw-transport-node-hid": "^4.3.0"
diff --git a/packages/monorepo-scripts/package.json b/packages/monorepo-scripts/package.json
index c849c01ba..b5fae9835 100644
--- a/packages/monorepo-scripts/package.json
+++ b/packages/monorepo-scripts/package.json
@@ -49,7 +49,7 @@
"es6-promisify": "^5.0.0",
"glob": "^7.1.2",
"isomorphic-fetch": "2.2.1",
- "lodash": "^4.17.4",
+ "lodash": "^4.17.5",
"moment": "2.21.0",
"opn": "^5.3.0",
"promisify-child-process": "^1.0.5",
diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json
index 776bd67ec..fa82976ad 100644
--- a/packages/order-utils/CHANGELOG.json
+++ b/packages/order-utils/CHANGELOG.json
@@ -10,6 +10,9 @@
{
"note": "Added marketUtils",
"pr": 937
+ },
+ {
+ "note": "Dependencies updated"
}
]
},
diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json
index 7880b9352..98cbba0e1 100644
--- a/packages/order-utils/package.json
+++ b/packages/order-utils/package.json
@@ -64,7 +64,7 @@
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
- "mocha": "^4.0.1",
+ "mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"sinon": "^4.0.0",
@@ -87,7 +87,7 @@
"ethereumjs-abi": "0.6.5",
"ethereumjs-util": "^5.1.1",
"ethers": "3.0.22",
- "lodash": "^4.17.4"
+ "lodash": "^4.17.5"
},
"publishConfig": {
"access": "public"
diff --git a/packages/order-utils/test/signature_utils_test.ts b/packages/order-utils/test/signature_utils_test.ts
index 5714f9671..baae2b414 100644
--- a/packages/order-utils/test/signature_utils_test.ts
+++ b/packages/order-utils/test/signature_utils_test.ts
@@ -22,7 +22,8 @@ describe('Signature utils', () => {
let address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
it("should return false if the data doesn't pertain to the signature & address", async () => {
- expect(await isValidSignatureAsync(provider, '0x0', ethSignSignature, address)).to.be.false();
+ const bytes32Zeros = '0x0000000000000000000000000000000000000000000000000000000000000000';
+ expect(await isValidSignatureAsync(provider, bytes32Zeros, ethSignSignature, address)).to.be.false();
});
it("should return false if the address doesn't pertain to the signature & data", async () => {
const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
diff --git a/packages/order-watcher/CHANGELOG.json b/packages/order-watcher/CHANGELOG.json
index 08c1f7f58..0c9ef7a8a 100644
--- a/packages/order-watcher/CHANGELOG.json
+++ b/packages/order-watcher/CHANGELOG.json
@@ -1,5 +1,13 @@
[
{
+ "version": "1.0.1-rc.3",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ]
+ },
+ {
"version": "1.0.1-rc.2",
"changes": [
{
diff --git a/packages/order-watcher/package.json b/packages/order-watcher/package.json
index c000b4fec..081b24c18 100644
--- a/packages/order-watcher/package.json
+++ b/packages/order-watcher/package.json
@@ -59,7 +59,7 @@
"dirty-chai": "^2.0.1",
"json-loader": "^0.5.4",
"make-promises-safe": "^1.1.0",
- "mocha": "^4.0.1",
+ "mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"opn-cli": "^3.1.0",
@@ -84,7 +84,7 @@
"ethereum-types": "^1.0.3",
"ethereumjs-blockstream": "5.0.0",
"ethers": "3.0.22",
- "lodash": "^4.17.4"
+ "lodash": "^4.17.5"
},
"publishConfig": {
"access": "public"
diff --git a/packages/react-docs-example/package.json b/packages/react-docs-example/package.json
index 4eb109b3e..2f2c9a457 100644
--- a/packages/react-docs-example/package.json
+++ b/packages/react-docs-example/package.json
@@ -52,7 +52,7 @@
"dependencies": {
"@0xproject/react-docs": "^1.0.4",
"basscss": "^8.0.3",
- "lodash": "^4.17.4",
+ "lodash": "^4.17.5",
"material-ui": "^0.17.1",
"react": "15.6.1",
"react-dom": "15.6.1",
diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json
index 44044e54d..5f8c07a1c 100644
--- a/packages/react-docs/package.json
+++ b/packages/react-docs/package.json
@@ -46,7 +46,7 @@
"@types/react-scroll": "0.0.31",
"basscss": "^8.0.3",
"compare-versions": "^3.0.1",
- "lodash": "^4.17.4",
+ "lodash": "^4.17.5",
"material-ui": "^0.17.1",
"react": "15.6.1",
"react-dom": "15.6.1",
diff --git a/packages/react-shared/package.json b/packages/react-shared/package.json
index 839bfccc5..09a01bb91 100644
--- a/packages/react-shared/package.json
+++ b/packages/react-shared/package.json
@@ -44,7 +44,7 @@
"@types/react-scroll": "0.0.31",
"basscss": "^8.0.3",
"is-mobile": "^0.2.2",
- "lodash": "^4.17.4",
+ "lodash": "^4.17.5",
"material-ui": "^0.17.1",
"react": "15.6.1",
"react-dom": "15.6.1",
diff --git a/packages/sol-compiler/package.json b/packages/sol-compiler/package.json
index c31d180c2..fcf9775c1 100644
--- a/packages/sol-compiler/package.json
+++ b/packages/sol-compiler/package.json
@@ -64,7 +64,7 @@
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
- "mocha": "^4.0.1",
+ "mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"shx": "^0.2.2",
@@ -87,7 +87,7 @@
"chalk": "^2.3.0",
"ethereum-types": "^1.0.3",
"ethereumjs-util": "^5.1.1",
- "lodash": "^4.17.4",
+ "lodash": "^4.17.5",
"mkdirp": "^0.5.1",
"require-from-string": "^2.0.1",
"semver": "5.5.0",
diff --git a/packages/sol-cov/package.json b/packages/sol-cov/package.json
index 41758b30d..ae53191cf 100644
--- a/packages/sol-cov/package.json
+++ b/packages/sol-cov/package.json
@@ -61,7 +61,7 @@
"ethereumjs-util": "^5.1.1",
"glob": "^7.1.2",
"istanbul": "^0.4.5",
- "lodash": "^4.17.4",
+ "lodash": "^4.17.5",
"loglevel": "^1.6.1",
"mkdirp": "^0.5.1",
"rimraf": "^2.6.2",
@@ -82,7 +82,7 @@
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
- "mocha": "^4.0.1",
+ "mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"shx": "^0.2.2",
diff --git a/packages/sol-resolver/package.json b/packages/sol-resolver/package.json
index 618f78eec..4ce33cf59 100644
--- a/packages/sol-resolver/package.json
+++ b/packages/sol-resolver/package.json
@@ -35,7 +35,7 @@
"dependencies": {
"@0xproject/types": "^1.0.1-rc.3",
"@0xproject/typescript-typings": "^1.0.3",
- "lodash": "^4.17.4"
+ "lodash": "^4.17.5"
},
"publishConfig": {
"access": "public"
diff --git a/packages/sra-report/package.json b/packages/sra-report/package.json
index 55063a7f0..7f359f145 100644
--- a/packages/sra-report/package.json
+++ b/packages/sra-report/package.json
@@ -43,7 +43,7 @@
"@0xproject/typescript-typings": "^1.0.3",
"@0xproject/utils": "^1.0.4",
"chalk": "^2.3.0",
- "lodash": "^4.17.4",
+ "lodash": "^4.17.5",
"newman": "^3.9.3",
"yargs": "^10.0.3"
},
@@ -60,7 +60,7 @@
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
- "mocha": "^4.0.1",
+ "mocha": "^4.1.0",
"nock": "^9.2.3",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json
index d59326b6f..662610357 100644
--- a/packages/subproviders/package.json
+++ b/packages/subproviders/package.json
@@ -57,7 +57,7 @@
"ganache-core": "0xProject/ganache-core",
"hdkey": "^0.7.1",
"json-rpc-error": "2.0.0",
- "lodash": "^4.17.4",
+ "lodash": "^4.17.5",
"semaphore-async-await": "^1.5.1",
"web3-provider-engine": "14.0.6"
},
@@ -77,7 +77,7 @@
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
- "mocha": "^4.0.1",
+ "mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"shx": "^0.2.2",
diff --git a/packages/testnet-faucets/package.json b/packages/testnet-faucets/package.json
index 3b68c06ee..32dd69c30 100644
--- a/packages/testnet-faucets/package.json
+++ b/packages/testnet-faucets/package.json
@@ -27,7 +27,7 @@
"ethereumjs-tx": "^1.3.5",
"ethereumjs-util": "^5.1.1",
"express": "^4.15.2",
- "lodash": "^4.17.4",
+ "lodash": "^4.17.5",
"rollbar": "^0.6.5"
},
"devDependencies": {
diff --git a/packages/tslint-config/package.json b/packages/tslint-config/package.json
index 040db472a..79776cac0 100644
--- a/packages/tslint-config/package.json
+++ b/packages/tslint-config/package.json
@@ -42,7 +42,7 @@
"typescript": "2.9.2"
},
"dependencies": {
- "lodash": "^4.17.4",
+ "lodash": "^4.17.5",
"tslint": "5.11.0",
"tslint-eslint-rules": "^4.1.1",
"tslint-react": "^3.2.0",
diff --git a/packages/typescript-typings/types/ethers/index.d.ts b/packages/typescript-typings/types/ethers/index.d.ts
index f869196e0..875563ba2 100644
--- a/packages/typescript-typings/types/ethers/index.d.ts
+++ b/packages/typescript-typings/types/ethers/index.d.ts
@@ -34,4 +34,22 @@ declare module 'ethers' {
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/coverage/.gitkeep b/packages/utils/coverage/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/packages/utils/coverage/.gitkeep
diff --git a/packages/utils/package.json b/packages/utils/package.json
index ee150cb0e..ac10e7208 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -5,12 +5,17 @@
"node": ">=6.12"
},
"description": "0x TS utils",
- "main": "lib/index.js",
- "types": "lib/index.d.ts",
+ "main": "lib/src/index.js",
+ "types": "lib/src/index.d.ts",
"scripts": {
"watch_without_deps": "tsc -w",
"build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts",
"clean": "shx rm -rf lib scripts",
+ "test": "yarn run_mocha",
+ "test:circleci": "yarn test:coverage",
+ "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --bail --exit",
+ "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
+ "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"lint": "tslint --project .",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js"
},
@@ -27,12 +32,15 @@
"@0xproject/monorepo-scripts": "^1.0.4",
"@0xproject/tslint-config": "^1.0.4",
"@types/lodash": "4.14.104",
+ "@types/mocha": "^2.2.42",
"copyfiles": "^1.2.0",
"make-promises-safe": "^1.1.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"tslint": "5.11.0",
- "typescript": "2.9.2"
+ "typescript": "2.9.2",
+ "chai": "^4.0.1",
+ "mocha": "^4.1.0"
},
"dependencies": {
"@0xproject/types": "^1.0.1-rc.3",
@@ -46,7 +54,7 @@
"ethers": "3.0.22",
"isomorphic-fetch": "^2.2.1",
"js-sha3": "^0.7.0",
- "lodash": "^4.17.4"
+ "lodash": "^4.17.5"
},
"publishConfig": {
"access": "public"
diff --git a/packages/utils/src/abi_utils.ts b/packages/utils/src/abi_utils.ts
index 421dd405c..c9b70966c 100644
--- a/packages/utils/src/abi_utils.ts
+++ b/packages/utils/src/abi_utils.ts
@@ -1,7 +1,160 @@
import { AbiDefinition, AbiType, ContractAbi, DataItem, MethodAbi } from 'ethereum-types';
+import * as ethers from 'ethers';
import * as _ from 'lodash';
+import { BigNumber } from './configured_bignumber';
+
+// 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[] = [];
+ const types: string[] = [];
+
+ params.forEach((param: DataItem) => {
+ if (param.components != null) {
+ let suffix = '';
+ const arrayBracket = param.type.indexOf('[');
+ if (arrayBracket >= 0) {
+ suffix = param.type.substring(arrayBracket);
+ }
+
+ const result = parseEthersParams(param.components);
+ names.push({ name: param.name || null, names: result.names });
+ types.push('tuple(' + result.types.join(',') + ')' + suffix);
+ } else {
+ names.push(param.name || null);
+ types.push(param.type);
+ }
+ });
+
+ return {
+ names,
+ types,
+ };
+}
+
+// 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 {
+ if (_.isUndefined(x) && _.isUndefined(y)) {
+ return true;
+ } else if (_.isUndefined(x) && !_.isUndefined(y)) {
+ return false;
+ } else if (!_.isUndefined(x) && _.isUndefined(y)) {
+ return false;
+ }
+ if (_.endsWith(type, '[]')) {
+ // For array types, we iterate through the elements and check each one
+ // individually. Strangely, name does not need to be changed in this
+ // case.
+ if (x.length !== y.length) {
+ return false;
+ }
+ const newType = _.trimEnd(type, '[]');
+ for (let i = 0; i < x.length; i++) {
+ if (!isAbiDataEqual(name, newType, x[i], y[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+ if (_.startsWith(type, 'tuple(')) {
+ if (_.isString(name)) {
+ throw new Error('Internal error: type was tuple but names was a string');
+ } else if (_.isNull(name)) {
+ throw new Error('Internal error: type was tuple but names was null');
+ }
+ // For tuples, we iterate through the underlying values and check each
+ // one individually.
+ const types = splitTupleTypes(type);
+ if (types.length !== name.names.length) {
+ throw new Error(
+ `Internal error: parameter types/names length mismatch (${types.length} != ${name.names.length})`,
+ );
+ }
+ for (let i = 0; i < types.length; i++) {
+ // For tuples, name is an object with a names property that is an
+ // array. As an example, for orders, name looks like:
+ //
+ // {
+ // name: 'orders',
+ // names: [
+ // 'makerAddress',
+ // // ...
+ // 'takerAssetData'
+ // ]
+ // }
+ //
+ const nestedName = _.isString(name.names[i])
+ ? (name.names[i] as string)
+ : ((name.names[i] as ethers.NestedParamName).name as string);
+ if (!isAbiDataEqual(name.names[i], types[i], x[nestedName], y[nestedName])) {
+ return false;
+ }
+ }
+ return true;
+ } else if (type === 'address' || type === 'bytes') {
+ // HACK(albrow): ethers.js returns the checksummed address even when
+ // initially passed in a non-checksummed address. To account for that,
+ // we convert to lowercase before comparing.
+ return _.isEqual(_.toLower(x), _.toLower(y));
+ } else if (_.startsWith(type, 'uint') || _.startsWith(type, 'int')) {
+ return new BigNumber(x).eq(new BigNumber(y));
+ }
+ return _.isEqual(x, y);
+}
+
+// splitTupleTypes splits a tuple type string (of the form `tuple(X)` where X is
+// any other type or list of types) into its component types. It works with
+// nested tuples, so, e.g., `tuple(tuple(uint256,address),bytes32)` will yield:
+// `['tuple(uint256,address)', 'bytes32']`. It expects exactly one tuple type as
+// an argument (not an array).
+function splitTupleTypes(type: string): string[] {
+ if (_.endsWith(type, '[]')) {
+ throw new Error('Internal error: array types are not supported');
+ } else if (!_.startsWith(type, 'tuple(')) {
+ throw new Error('Internal error: expected tuple type but got non-tuple type: ' + type);
+ }
+ // Trim the outtermost tuple().
+ const trimmedType = type.substring('tuple('.length, type.length - 1);
+ const types: string[] = [];
+ let currToken = '';
+ let parenCount = 0;
+ // Tokenize the type string while keeping track of parentheses.
+ for (const char of trimmedType) {
+ switch (char) {
+ case '(':
+ parenCount += 1;
+ currToken += char;
+ break;
+ case ')':
+ parenCount -= 1;
+ currToken += char;
+ break;
+ case ',':
+ if (parenCount === 0) {
+ types.push(currToken);
+ currToken = '';
+ break;
+ } else {
+ currToken += char;
+ break;
+ }
+ default:
+ currToken += char;
+ break;
+ }
+ }
+ types.push(currToken);
+ return types;
+}
+
export const abiUtils = {
+ parseEthersParams,
+ isAbiDataEqual,
+ splitTupleTypes,
parseFunctionParam(param: DataItem): string {
if (param.type === 'tuple') {
// Parse out tuple types into {type_1, type_2, ..., type_N}
diff --git a/packages/utils/test/abi_utils_test.ts b/packages/utils/test/abi_utils_test.ts
new file mode 100644
index 000000000..0ebee64c4
--- /dev/null
+++ b/packages/utils/test/abi_utils_test.ts
@@ -0,0 +1,19 @@
+import * as chai from 'chai';
+import 'mocha';
+
+import { abiUtils } from '../src';
+
+const expect = chai.expect;
+
+describe('abiUtils', () => {
+ describe('splitTupleTypes', () => {
+ it('handles basic types', () => {
+ const got = abiUtils.splitTupleTypes('tuple(bytes,uint256,address)');
+ expect(got).to.deep.equal(['bytes', 'uint256', 'address']);
+ });
+ it('handles nested tuple types', () => {
+ const got = abiUtils.splitTupleTypes('tuple(tuple(bytes,uint256),address)');
+ expect(got).to.deep.equal(['tuple(bytes,uint256)', 'address']);
+ });
+ });
+});
diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json
index c56d255d5..8b4cd47a2 100644
--- a/packages/utils/tsconfig.json
+++ b/packages/utils/tsconfig.json
@@ -3,5 +3,5 @@
"compilerOptions": {
"outDir": "lib"
},
- "include": ["./src/**/*"]
+ "include": ["src/**/*", "test/**/*"]
}
diff --git a/packages/web3-wrapper/package.json b/packages/web3-wrapper/package.json
index 300382c7f..e1c3245b1 100644
--- a/packages/web3-wrapper/package.json
+++ b/packages/web3-wrapper/package.json
@@ -55,7 +55,7 @@
"dirty-chai": "^2.0.1",
"ganache-core": "0xProject/ganache-core",
"make-promises-safe": "^1.1.0",
- "mocha": "^4.0.1",
+ "mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"shx": "^0.2.2",
@@ -71,7 +71,7 @@
"ethereum-types": "^1.0.3",
"ethereumjs-util": "^5.1.1",
"ethers": "3.0.22",
- "lodash": "^4.17.4"
+ "lodash": "^4.17.5"
},
"publishConfig": {
"access": "public"
diff --git a/packages/website/package.json b/packages/website/package.json
index 4a19fed6d..456a281cd 100644
--- a/packages/website/package.json
+++ b/packages/website/package.json
@@ -36,7 +36,7 @@
"find-versions": "^2.0.0",
"jsonschema": "^1.2.0",
"less": "^2.7.2",
- "lodash": "^4.17.4",
+ "lodash": "^4.17.5",
"material-ui": "^0.17.1",
"moment": "2.21.0",
"numeral": "^2.0.6",
diff --git a/packages/website/public/images/team/amir.jpeg b/packages/website/public/images/team/amir.jpeg
deleted file mode 100644
index 7ee16263a..000000000
--- a/packages/website/public/images/team/amir.jpeg
+++ /dev/null
Binary files differ
diff --git a/packages/website/public/images/team/amir.png b/packages/website/public/images/team/amir.png
new file mode 100644
index 000000000..2bb795d50
--- /dev/null
+++ b/packages/website/public/images/team/amir.png
Binary files differ
diff --git a/packages/website/public/images/team/clay.png b/packages/website/public/images/team/clay.png
new file mode 100644
index 000000000..2bc828572
--- /dev/null
+++ b/packages/website/public/images/team/clay.png
Binary files differ
diff --git a/packages/website/ts/pages/about/about.tsx b/packages/website/ts/pages/about/about.tsx
index b9bc906bd..aef4d0df9 100644
--- a/packages/website/ts/pages/about/about.tsx
+++ b/packages/website/ts/pages/about/about.tsx
@@ -27,7 +27,7 @@ const teamRow1: ProfileInfo[] = [
title: 'Co-founder & CTO',
description: `Smart contract R&D. Previously fixed income trader at DRW. \
Finance at University of Illinois, Urbana-Champaign.`,
- image: '/images/team/amir.jpeg',
+ image: '/images/team/amir.png',
linkedIn: 'https://www.linkedin.com/in/abandeali1/',
github: 'https://github.com/abandeali1',
medium: 'https://medium.com/@abandeali1',
@@ -191,6 +191,16 @@ const teamRow6: ProfileInfo[] = [
},
];
+const teamRow7: ProfileInfo[] = [
+ {
+ name: 'Clay Robbins',
+ title: 'Business Development Lead',
+ description: `Growth & Business Development. Previously product and partnerships at Square. Economics at Dartmouth College.`,
+ image: 'images/team/clay.png',
+ linkedIn: 'https://www.linkedin.com/in/robbinsclay/',
+ },
+];
+
const advisors: ProfileInfo[] = [
{
name: 'Fred Ehrsam',
@@ -286,6 +296,7 @@ export class About extends React.Component<AboutProps, AboutState> {
<div className="clearfix">{this._renderProfiles(teamRow4)}</div>
<div className="clearfix">{this._renderProfiles(teamRow5)}</div>
<div className="clearfix">{this._renderProfiles(teamRow6)}</div>
+ <div className="clearfix">{this._renderProfiles(teamRow7)}</div>
</div>
<div className="pt3 pb2">
<div