Migrate all contract-related tooling and tests to accept a chain ID in domain separators.

This commit is contained in:
Lawrence Forman 2019-03-22 16:18:49 -04:00 committed by Amir Bandeali
parent 92fe720ac3
commit 2d28fde24d
39 changed files with 282 additions and 64 deletions

View File

@ -21,7 +21,7 @@ import {
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
import { RevertReason, SignedOrder } from '@0x/types'; import { RevertReason, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types'; import { LogWithDecodedArgs } from 'ethereum-types';
@ -33,6 +33,7 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
web3Wrapper.abiDecoder.addABI(exchangeArtifacts.Exchange.compilerOutput.abi); web3Wrapper.abiDecoder.addABI(exchangeArtifacts.Exchange.compilerOutput.abi);
// tslint:disable:no-unnecessary-type-assertion // tslint:disable:no-unnecessary-type-assertion
describe('Coordinator tests', () => { describe('Coordinator tests', () => {
let chainId: number;
let makerAddress: string; let makerAddress: string;
let owner: string; let owner: string;
let takerAddress: string; let takerAddress: string;
@ -58,6 +59,7 @@ describe('Coordinator tests', () => {
await blockchainLifecycle.revertAsync(); await blockchainLifecycle.revertAsync();
}); });
before(async () => { before(async () => {
chainId = await providerUtils.getChainIdAsync(provider);
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = accounts.slice(0, 4)); const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = accounts.slice(0, 4));
@ -75,6 +77,7 @@ describe('Coordinator tests', () => {
provider, provider,
txDefaults, txDefaults,
assetDataUtils.encodeERC20AssetData(zrxToken.address), assetDataUtils.encodeERC20AssetData(zrxToken.address),
new BigNumber(chainId),
); );
await web3Wrapper.awaitTransactionSuccessAsync( await web3Wrapper.awaitTransactionSuccessAsync(
@ -92,12 +95,14 @@ describe('Coordinator tests', () => {
provider, provider,
txDefaults, txDefaults,
exchange.address, exchange.address,
new BigNumber(chainId),
); );
// Configure order defaults // Configure order defaults
const defaultOrderParams = { const defaultOrderParams = {
...devConstants.STATIC_ORDER_PARAMS, ...devConstants.STATIC_ORDER_PARAMS,
exchangeAddress: exchange.address, exchangeAddress: exchange.address,
chainId,
senderAddress: coordinatorContract.address, senderAddress: coordinatorContract.address,
makerAddress, makerAddress,
feeRecipientAddress, feeRecipientAddress,
@ -108,9 +113,21 @@ describe('Coordinator tests', () => {
const takerPrivateKey = devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)]; const takerPrivateKey = devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)];
const feeRecipientPrivateKey = devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(feeRecipientAddress)]; const feeRecipientPrivateKey = devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(feeRecipientAddress)];
orderFactory = new OrderFactory(makerPrivateKey, defaultOrderParams); orderFactory = new OrderFactory(makerPrivateKey, defaultOrderParams);
makerTransactionFactory = new TransactionFactory(makerPrivateKey, exchange.address); makerTransactionFactory = new TransactionFactory(
takerTransactionFactory = new TransactionFactory(takerPrivateKey, exchange.address); makerPrivateKey,
approvalFactory = new ApprovalFactory(feeRecipientPrivateKey, coordinatorContract.address); exchange.address,
chainId,
);
takerTransactionFactory = new TransactionFactory(
takerPrivateKey,
exchange.address,
chainId,
);
approvalFactory = new ApprovalFactory(
feeRecipientPrivateKey,
coordinatorContract.address,
chainId,
);
}); });
beforeEach(async () => { beforeEach(async () => {
await blockchainLifecycle.startAsync(); await blockchainLifecycle.startAsync();

View File

@ -1,7 +1,7 @@
import { addressUtils, chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils'; import { addressUtils, chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { transactionHashUtils } from '@0x/order-utils'; import { transactionHashUtils } from '@0x/order-utils';
import { BigNumber } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
import { artifacts, CoordinatorContract, hashUtils } from '../src'; import { artifacts, CoordinatorContract, hashUtils } from '../src';
@ -12,6 +12,7 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('Libs tests', () => { describe('Libs tests', () => {
let coordinatorContract: CoordinatorContract; let coordinatorContract: CoordinatorContract;
let chainId: number;
const exchangeAddress = addressUtils.generatePseudoRandomAddress(); const exchangeAddress = addressUtils.generatePseudoRandomAddress();
before(async () => { before(async () => {
@ -21,11 +22,13 @@ describe('Libs tests', () => {
await blockchainLifecycle.revertAsync(); await blockchainLifecycle.revertAsync();
}); });
before(async () => { before(async () => {
chainId = await providerUtils.getChainIdAsync(provider);
coordinatorContract = await CoordinatorContract.deployFrom0xArtifactAsync( coordinatorContract = await CoordinatorContract.deployFrom0xArtifactAsync(
artifacts.Coordinator, artifacts.Coordinator,
provider, provider,
txDefaults, txDefaults,
exchangeAddress, exchangeAddress,
new BigNumber(chainId),
); );
}); });
beforeEach(async () => { beforeEach(async () => {
@ -39,6 +42,7 @@ describe('Libs tests', () => {
it('should return the correct transaction hash', async () => { it('should return the correct transaction hash', async () => {
const tx = { const tx = {
verifyingContractAddress: exchangeAddress, verifyingContractAddress: exchangeAddress,
chainId,
salt: new BigNumber(0), salt: new BigNumber(0),
signerAddress: constants.NULL_ADDRESS, signerAddress: constants.NULL_ADDRESS,
data: '0x1234', data: '0x1234',
@ -53,6 +57,7 @@ describe('Libs tests', () => {
it('should return the correct approval hash', async () => { it('should return the correct approval hash', async () => {
const signedTx = { const signedTx = {
verifyingContractAddress: exchangeAddress, verifyingContractAddress: exchangeAddress,
chainId,
salt: new BigNumber(0), salt: new BigNumber(0),
signerAddress: constants.NULL_ADDRESS, signerAddress: constants.NULL_ADDRESS,
data: '0x1234', data: '0x1234',
@ -69,6 +74,7 @@ describe('Libs tests', () => {
const expectedApprovalHash = hashUtils.getApprovalHashHex( const expectedApprovalHash = hashUtils.getApprovalHashHex(
signedTx, signedTx,
coordinatorContract.address, coordinatorContract.address,
chainId,
txOrigin, txOrigin,
approvalExpirationTimeSeconds, approvalExpirationTimeSeconds,
); );

View File

@ -12,7 +12,7 @@ import {
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { transactionHashUtils } from '@0x/order-utils'; import { transactionHashUtils } from '@0x/order-utils';
import { RevertReason, SignatureType, SignedOrder } from '@0x/types'; import { RevertReason, SignatureType, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
import * as ethUtil from 'ethereumjs-util'; import * as ethUtil from 'ethereumjs-util';
@ -23,6 +23,7 @@ const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('Mixins tests', () => { describe('Mixins tests', () => {
let chainId: number;
let transactionSignerAddress: string; let transactionSignerAddress: string;
let approvalSignerAddress1: string; let approvalSignerAddress1: string;
let approvalSignerAddress2: string; let approvalSignerAddress2: string;
@ -40,16 +41,19 @@ describe('Mixins tests', () => {
await blockchainLifecycle.revertAsync(); await blockchainLifecycle.revertAsync();
}); });
before(async () => { before(async () => {
chainId = await providerUtils.getChainIdAsync(provider);
mixins = await CoordinatorContract.deployFrom0xArtifactAsync( mixins = await CoordinatorContract.deployFrom0xArtifactAsync(
artifacts.Coordinator, artifacts.Coordinator,
provider, provider,
txDefaults, txDefaults,
exchangeAddress, exchangeAddress,
new BigNumber(chainId),
); );
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
[transactionSignerAddress, approvalSignerAddress1, approvalSignerAddress2] = accounts.slice(0, 3); [transactionSignerAddress, approvalSignerAddress1, approvalSignerAddress2] = accounts.slice(0, 3);
defaultOrder = { defaultOrder = {
exchangeAddress: devConstants.NULL_ADDRESS, exchangeAddress: devConstants.NULL_ADDRESS,
chainId,
makerAddress: devConstants.NULL_ADDRESS, makerAddress: devConstants.NULL_ADDRESS,
takerAddress: devConstants.NULL_ADDRESS, takerAddress: devConstants.NULL_ADDRESS,
senderAddress: mixins.address, senderAddress: mixins.address,
@ -68,9 +72,21 @@ describe('Mixins tests', () => {
devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(transactionSignerAddress)]; devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(transactionSignerAddress)];
const approvalSignerPrivateKey1 = devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(approvalSignerAddress1)]; const approvalSignerPrivateKey1 = devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(approvalSignerAddress1)];
const approvalSignerPrivateKey2 = devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(approvalSignerAddress2)]; const approvalSignerPrivateKey2 = devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(approvalSignerAddress2)];
transactionFactory = new TransactionFactory(transactionSignerPrivateKey, exchangeAddress); transactionFactory = new TransactionFactory(
approvalFactory1 = new ApprovalFactory(approvalSignerPrivateKey1, mixins.address); transactionSignerPrivateKey,
approvalFactory2 = new ApprovalFactory(approvalSignerPrivateKey2, mixins.address); exchangeAddress,
chainId,
);
approvalFactory1 = new ApprovalFactory(
approvalSignerPrivateKey1,
mixins.address,
chainId,
);
approvalFactory2 = new ApprovalFactory(
approvalSignerPrivateKey2,
mixins.address,
chainId,
);
}); });
beforeEach(async () => { beforeEach(async () => {
await blockchainLifecycle.startAsync(); await blockchainLifecycle.startAsync();

View File

@ -8,10 +8,16 @@ import { hashUtils, SignedCoordinatorApproval } from './index';
export class ApprovalFactory { export class ApprovalFactory {
private readonly _privateKey: Buffer; private readonly _privateKey: Buffer;
private readonly _verifyingContractAddress: string; private readonly _verifyingContractAddress: string;
private readonly _chainId: number;
constructor(privateKey: Buffer, verifyingContractAddress: string) { constructor(
privateKey: Buffer,
verifyingContractAddress: string,
chainId: number,
) {
this._privateKey = privateKey; this._privateKey = privateKey;
this._verifyingContractAddress = verifyingContractAddress; this._verifyingContractAddress = verifyingContractAddress;
this._chainId = chainId;
} }
public newSignedApproval( public newSignedApproval(
@ -23,6 +29,7 @@ export class ApprovalFactory {
const approvalHashBuff = hashUtils.getApprovalHashBuffer( const approvalHashBuff = hashUtils.getApprovalHashBuffer(
transaction, transaction,
this._verifyingContractAddress, this._verifyingContractAddress,
this._chainId,
txOrigin, txOrigin,
approvalExpirationTimeSeconds, approvalExpirationTimeSeconds,
); );

View File

@ -6,7 +6,6 @@ import * as _ from 'lodash';
export const hashUtils = { export const hashUtils = {
getApprovalHashBuffer( getApprovalHashBuffer(
transaction: SignedZeroExTransaction, transaction: SignedZeroExTransaction,
chainId: BigNumber,
verifyingContractAddress: string, verifyingContractAddress: string,
txOrigin: string, txOrigin: string,
approvalExpirationTimeSeconds: BigNumber, approvalExpirationTimeSeconds: BigNumber,
@ -22,7 +21,6 @@ export const hashUtils = {
}, },
getApprovalHashHex( getApprovalHashHex(
transaction: SignedZeroExTransaction, transaction: SignedZeroExTransaction,
chainId: BigNumber,
verifyingContractAddress: string, verifyingContractAddress: string,
txOrigin: string, txOrigin: string,
approvalExpirationTimeSeconds: BigNumber, approvalExpirationTimeSeconds: BigNumber,
@ -30,7 +28,6 @@ export const hashUtils = {
const hashHex = `0x${hashUtils const hashHex = `0x${hashUtils
.getApprovalHashBuffer( .getApprovalHashBuffer(
transaction, transaction,
chainId,
verifyingContractAddress, verifyingContractAddress,
txOrigin, txOrigin,
approvalExpirationTimeSeconds) approvalExpirationTimeSeconds)

View File

@ -34,7 +34,7 @@
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol" "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
}, },
"config": { "config": {
"abis": "./generated-artifacts/@(LibAbiEncoder|LibAssetProxyErrors|LibConstants|LibEIP712|LibFillResults|LibMath|LibOrder|TestLibs).json", "abis": "./generated-artifacts/@(LibAbiEncoder|LibAssetProxyErrors|LibConstants|LibEIP712|LibEIP712ExchangeDomainConstants|LibEIP712ExchangeDomain|LibFillResults|LibMath|LibOrder|TestLibs).json",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
}, },
"repository": { "repository": {

View File

@ -10,7 +10,7 @@ import {
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
import { SignedOrder } from '@0x/types'; import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
import { TestLibsContract } from '../generated-wrappers/test_libs'; import { TestLibsContract } from '../generated-wrappers/test_libs';
@ -22,6 +22,7 @@ const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('Exchange libs', () => { describe('Exchange libs', () => {
let chainId: number;
let signedOrder: SignedOrder; let signedOrder: SignedOrder;
let orderFactory: OrderFactory; let orderFactory: OrderFactory;
let libs: TestLibsContract; let libs: TestLibsContract;
@ -35,11 +36,18 @@ describe('Exchange libs', () => {
before(async () => { before(async () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
const makerAddress = accounts[0]; const makerAddress = accounts[0];
libs = await TestLibsContract.deployFrom0xArtifactAsync(artifacts.TestLibs, provider, txDefaults); chainId = await providerUtils.getChainIdAsync(provider);
libs = await TestLibsContract.deployFrom0xArtifactAsync(
artifacts.TestLibs,
provider,
txDefaults,
new BigNumber(chainId),
);
const defaultOrderParams = { const defaultOrderParams = {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
exchangeAddress: libs.address, exchangeAddress: libs.address,
chainId,
makerAddress, makerAddress,
feeRecipientAddress: addressUtils.generatePseudoRandomAddress(), feeRecipientAddress: addressUtils.generatePseudoRandomAddress(),
makerAssetData: assetDataUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()), makerAssetData: assetDataUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),

View File

@ -33,7 +33,7 @@ import {
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
import { RevertReason, SignatureType, SignedOrder } from '@0x/types'; import { RevertReason, SignatureType, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper'; import { Web3Wrapper } from '@0x/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types'; import { LogWithDecodedArgs } from 'ethereum-types';
@ -55,6 +55,7 @@ const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
// tslint:disable:no-unnecessary-type-assertion // tslint:disable:no-unnecessary-type-assertion
describe('Exchange core', () => { describe('Exchange core', () => {
let chainId: number;
let makerAddress: string; let makerAddress: string;
let owner: string; let owner: string;
let takerAddress: string; let takerAddress: string;
@ -102,6 +103,7 @@ describe('Exchange core', () => {
await blockchainLifecycle.revertAsync(); await blockchainLifecycle.revertAsync();
}); });
before(async () => { before(async () => {
chainId = await providerUtils.getChainIdAsync(provider);
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = _.slice(accounts, 0, 4)); const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = _.slice(accounts, 0, 4));
@ -136,6 +138,7 @@ describe('Exchange core', () => {
provider, provider,
txDefaults, txDefaults,
assetDataUtils.encodeERC20AssetData(zrxToken.address), assetDataUtils.encodeERC20AssetData(zrxToken.address),
new BigNumber(chainId),
); );
maliciousWallet = maliciousValidator = await TestStaticCallReceiverContract.deployFrom0xArtifactAsync( maliciousWallet = maliciousValidator = await TestStaticCallReceiverContract.deployFrom0xArtifactAsync(
artifacts.TestStaticCallReceiver, artifacts.TestStaticCallReceiver,
@ -206,6 +209,7 @@ describe('Exchange core', () => {
const defaultOrderParams = { const defaultOrderParams = {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
exchangeAddress: exchange.address, exchangeAddress: exchange.address,
chainId,
makerAddress, makerAddress,
feeRecipientAddress, feeRecipientAddress,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),

View File

@ -12,7 +12,7 @@ import {
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { Order, RevertReason, SignedOrder } from '@0x/types'; import { Order, RevertReason, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -37,6 +37,7 @@ const emptyOrder: Order = {
takerAssetData: '0x', takerAssetData: '0x',
salt: new BigNumber(0), salt: new BigNumber(0),
exchangeAddress: constants.NULL_ADDRESS, exchangeAddress: constants.NULL_ADDRESS,
chainId: 0, // To be filled in later.
feeRecipientAddress: constants.NULL_ADDRESS, feeRecipientAddress: constants.NULL_ADDRESS,
expirationTimeSeconds: new BigNumber(0), expirationTimeSeconds: new BigNumber(0),
}; };
@ -49,6 +50,7 @@ const emptySignedOrder: SignedOrder = {
const overflowErrorForCall = new Error(RevertReason.Uint256Overflow); const overflowErrorForCall = new Error(RevertReason.Uint256Overflow);
describe('Exchange core internal functions', () => { describe('Exchange core internal functions', () => {
let chainId: number;
let testExchange: TestExchangeInternalsContract; let testExchange: TestExchangeInternalsContract;
let overflowErrorForSendTransaction: Error | undefined; let overflowErrorForSendTransaction: Error | undefined;
let divisionByZeroErrorForCall: Error | undefined; let divisionByZeroErrorForCall: Error | undefined;
@ -61,10 +63,15 @@ describe('Exchange core internal functions', () => {
await blockchainLifecycle.revertAsync(); await blockchainLifecycle.revertAsync();
}); });
before(async () => { before(async () => {
chainId = await providerUtils.getChainIdAsync(provider);
emptyOrder.chainId = chainId;
emptySignedOrder.chainId = chainId;
testExchange = await TestExchangeInternalsContract.deployFrom0xArtifactAsync( testExchange = await TestExchangeInternalsContract.deployFrom0xArtifactAsync(
artifacts.TestExchangeInternals, artifacts.TestExchangeInternals,
provider, provider,
txDefaults, txDefaults,
new BigNumber(chainId),
); );
overflowErrorForSendTransaction = new Error( overflowErrorForSendTransaction = new Error(
await getRevertReasonOrErrorMessageForSendTransactionAsync(RevertReason.Uint256Overflow), await getRevertReasonOrErrorMessageForSendTransactionAsync(RevertReason.Uint256Overflow),

View File

@ -15,7 +15,7 @@ import {
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils'; import { assetDataUtils } from '@0x/order-utils';
import { RevertReason } from '@0x/types'; import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper'; import { Web3Wrapper } from '@0x/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -34,6 +34,7 @@ chaiSetup.configure();
const expect = chai.expect; const expect = chai.expect;
describe('matchOrders', () => { describe('matchOrders', () => {
let chainId: number;
let makerAddressLeft: string; let makerAddressLeft: string;
let makerAddressRight: string; let makerAddressRight: string;
let owner: string; let owner: string;
@ -76,6 +77,8 @@ describe('matchOrders', () => {
await blockchainLifecycle.revertAsync(); await blockchainLifecycle.revertAsync();
}); });
before(async () => { before(async () => {
// Get the chain ID.
chainId = await providerUtils.getChainIdAsync(provider);
// Create accounts // Create accounts
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
// Hack(albrow): Both Prettier and TSLint insert a trailing comma below // Hack(albrow): Both Prettier and TSLint insert a trailing comma below
@ -119,6 +122,7 @@ describe('matchOrders', () => {
provider, provider,
txDefaults, txDefaults,
assetDataUtils.encodeERC20AssetData(zrxToken.address), assetDataUtils.encodeERC20AssetData(zrxToken.address),
new BigNumber(chainId)
); );
exchangeWrapper = new ExchangeWrapper(exchange, provider); exchangeWrapper = new ExchangeWrapper(exchange, provider);
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner); await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
@ -153,6 +157,7 @@ describe('matchOrders', () => {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
makerAddress: makerAddressLeft, makerAddress: makerAddressLeft,
exchangeAddress: exchange.address, exchangeAddress: exchange.address,
chainId,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
feeRecipientAddress: feeRecipientAddressLeft, feeRecipientAddress: feeRecipientAddressLeft,
@ -161,6 +166,7 @@ describe('matchOrders', () => {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
makerAddress: makerAddressRight, makerAddress: makerAddressRight,
exchangeAddress: exchange.address, exchangeAddress: exchange.address,
chainId,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
@ -175,6 +181,7 @@ describe('matchOrders', () => {
artifacts.TestExchangeInternals, artifacts.TestExchangeInternals,
provider, provider,
txDefaults, txDefaults,
new BigNumber(chainId),
); );
}); });
beforeEach(async () => { beforeEach(async () => {

View File

@ -12,6 +12,7 @@ import {
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, orderHashUtils, signatureUtils } from '@0x/order-utils'; import { assetDataUtils, orderHashUtils, signatureUtils } from '@0x/order-utils';
import { RevertReason, SignatureType, SignedOrder } from '@0x/types'; import { RevertReason, SignatureType, SignedOrder } from '@0x/types';
import { BigNumber, providerUtils } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types'; import { LogWithDecodedArgs } from 'ethereum-types';
import ethUtil = require('ethereumjs-util'); import ethUtil = require('ethereumjs-util');
@ -31,6 +32,7 @@ const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
// tslint:disable:no-unnecessary-type-assertion // tslint:disable:no-unnecessary-type-assertion
describe('MixinSignatureValidator', () => { describe('MixinSignatureValidator', () => {
let chainId: number;
let signedOrder: SignedOrder; let signedOrder: SignedOrder;
let orderFactory: OrderFactory; let orderFactory: OrderFactory;
let signatureValidator: TestSignatureValidatorContract; let signatureValidator: TestSignatureValidatorContract;
@ -51,6 +53,7 @@ describe('MixinSignatureValidator', () => {
await blockchainLifecycle.revertAsync(); await blockchainLifecycle.revertAsync();
}); });
before(async () => { before(async () => {
chainId = await providerUtils.getChainIdAsync(provider);
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
const makerAddress = accounts[0]; const makerAddress = accounts[0];
signerAddress = makerAddress; signerAddress = makerAddress;
@ -59,6 +62,7 @@ describe('MixinSignatureValidator', () => {
artifacts.TestSignatureValidator, artifacts.TestSignatureValidator,
provider, provider,
txDefaults, txDefaults,
new BigNumber(chainId),
); );
testWallet = await WalletContract.deployFrom0xArtifactAsync( testWallet = await WalletContract.deployFrom0xArtifactAsync(
artifacts.Wallet, artifacts.Wallet,
@ -98,6 +102,7 @@ describe('MixinSignatureValidator', () => {
const defaultOrderParams = { const defaultOrderParams = {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
exchangeAddress: signatureValidator.address, exchangeAddress: signatureValidator.address,
chainId,
makerAddress, makerAddress,
feeRecipientAddress: addressUtils.generatePseudoRandomAddress(), feeRecipientAddress: addressUtils.generatePseudoRandomAddress(),
makerAssetData: assetDataUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()), makerAssetData: assetDataUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),

View File

@ -15,7 +15,7 @@ import {
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils'; import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils';
import { OrderWithoutExchangeAddress, RevertReason, SignedOrder, SignedZeroExTransaction } from '@0x/types'; import { OrderWithoutExchangeAddress, RevertReason, SignedOrder, SignedZeroExTransaction } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -26,6 +26,7 @@ const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('Exchange transactions', () => { describe('Exchange transactions', () => {
let chainId: number;
let senderAddress: string; let senderAddress: string;
let owner: string; let owner: string;
let makerAddress: string; let makerAddress: string;
@ -66,6 +67,7 @@ describe('Exchange transactions', () => {
await blockchainLifecycle.revertAsync(); await blockchainLifecycle.revertAsync();
}); });
before(async () => { before(async () => {
chainId = await providerUtils.getChainIdAsync(provider);
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
const usedAddresses = ([owner, senderAddress, makerAddress, takerAddress, feeRecipientAddress] = _.slice( const usedAddresses = ([owner, senderAddress, makerAddress, takerAddress, feeRecipientAddress] = _.slice(
accounts, accounts,
@ -88,6 +90,7 @@ describe('Exchange transactions', () => {
provider, provider,
txDefaults, txDefaults,
assetDataUtils.encodeERC20AssetData(zrxToken.address), assetDataUtils.encodeERC20AssetData(zrxToken.address),
new BigNumber(chainId)
); );
exchangeWrapper = new ExchangeWrapper(exchange, provider); exchangeWrapper = new ExchangeWrapper(exchange, provider);
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner); await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
@ -104,6 +107,7 @@ describe('Exchange transactions', () => {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
senderAddress, senderAddress,
exchangeAddress: exchange.address, exchangeAddress: exchange.address,
chainId,
makerAddress, makerAddress,
feeRecipientAddress, feeRecipientAddress,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerTokenAddress), makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerTokenAddress),
@ -112,8 +116,16 @@ describe('Exchange transactions', () => {
makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)]; makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)]; takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)];
orderFactory = new OrderFactory(makerPrivateKey, defaultOrderParams); orderFactory = new OrderFactory(makerPrivateKey, defaultOrderParams);
makerTransactionFactory = new TransactionFactory(makerPrivateKey, exchange.address); makerTransactionFactory = new TransactionFactory(
takerTransactionFactory = new TransactionFactory(takerPrivateKey, exchange.address); makerPrivateKey,
exchange.address,
chainId,
);
takerTransactionFactory = new TransactionFactory(
takerPrivateKey,
exchange.address,
chainId,
);
}); });
describe('executeTransaction', () => { describe('executeTransaction', () => {
describe('fillOrder', () => { describe('fillOrder', () => {
@ -346,6 +358,7 @@ describe('Exchange transactions', () => {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
senderAddress: whitelist.address, senderAddress: whitelist.address,
exchangeAddress: exchange.address, exchangeAddress: exchange.address,
chainId,
makerAddress, makerAddress,
feeRecipientAddress, feeRecipientAddress,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerTokenAddress), makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerTokenAddress),

View File

@ -63,6 +63,7 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
const supportedProvider = web3Wrapper.getProvider(); const supportedProvider = web3Wrapper.getProvider();
const provider = providerUtils.standardizeOrThrow(supportedProvider); const provider = providerUtils.standardizeOrThrow(supportedProvider);
const chainId = await providerUtils.getChainIdAsync(provider);
const erc20Wrapper = new ERC20Wrapper(provider, userAddresses, ownerAddress); const erc20Wrapper = new ERC20Wrapper(provider, userAddresses, ownerAddress);
const erc721Wrapper = new ERC721Wrapper(provider, userAddresses, ownerAddress); const erc721Wrapper = new ERC721Wrapper(provider, userAddresses, ownerAddress);
@ -102,6 +103,7 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
provider, provider,
txDefaults, txDefaults,
zrxAssetData, zrxAssetData,
new BigNumber(chainId)
); );
const exchangeWrapper = new ExchangeWrapper(exchangeContract, provider); const exchangeWrapper = new ExchangeWrapper(exchangeContract, provider);
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, ownerAddress); await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, ownerAddress);
@ -129,12 +131,14 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
erc721Token, erc721Token,
erc721Balances, erc721Balances,
exchangeContract.address, exchangeContract.address,
chainId
); );
const testLibsContract = await TestLibsContract.deployFrom0xArtifactAsync( const testLibsContract = await TestLibsContract.deployFrom0xArtifactAsync(
libsArtifacts.TestLibs, libsArtifacts.TestLibs,
provider, provider,
txDefaults, txDefaults,
new BigNumber(chainId),
); );
const fillOrderCombinatorialUtils = new FillOrderCombinatorialUtils( const fillOrderCombinatorialUtils = new FillOrderCombinatorialUtils(
@ -404,7 +408,6 @@ export class FillOrderCombinatorialUtils {
try { try {
await orderValidationUtils.validateFillOrderThrowIfInvalidAsync( await orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
exchangeTransferSimulator, exchangeTransferSimulator,
provider,
signedOrder, signedOrder,
takerAssetFillAmount, takerAssetFillAmount,
this.takerAddress, this.takerAddress,
@ -627,7 +630,11 @@ export class FillOrderCombinatorialUtils {
balanceAndProxyAllowanceFetcher: SimpleAssetBalanceAndProxyAllowanceFetcher, balanceAndProxyAllowanceFetcher: SimpleAssetBalanceAndProxyAllowanceFetcher,
orderFilledCancelledFetcher: SimpleOrderFilledCancelledFetcher, orderFilledCancelledFetcher: SimpleOrderFilledCancelledFetcher,
): Promise<BigNumber> { ): Promise<BigNumber> {
const orderStateUtils = new OrderStateUtils(balanceAndProxyAllowanceFetcher, orderFilledCancelledFetcher); const orderStateUtils = new OrderStateUtils(
balanceAndProxyAllowanceFetcher,
orderFilledCancelledFetcher,
signedOrder.chainId,
);
const fillableTakerAssetAmount = await orderStateUtils.getMaxFillableTakerAssetAmountAsync( const fillableTakerAssetAmount = await orderStateUtils.getMaxFillableTakerAssetAmountAsync(
signedOrder, signedOrder,
this.takerAddress, this.takerAddress,

View File

@ -32,6 +32,7 @@ export class OrderFactoryFromScenario {
private readonly _erc721Token: DummyERC721TokenContract; private readonly _erc721Token: DummyERC721TokenContract;
private readonly _erc721Balances: ERC721TokenIdsByOwner; private readonly _erc721Balances: ERC721TokenIdsByOwner;
private readonly _exchangeAddress: string; private readonly _exchangeAddress: string;
private readonly _chainId: number;
constructor( constructor(
userAddresses: string[], userAddresses: string[],
zrxAddress: string, zrxAddress: string,
@ -41,6 +42,7 @@ export class OrderFactoryFromScenario {
erc721Token: DummyERC721TokenContract, erc721Token: DummyERC721TokenContract,
erc721Balances: ERC721TokenIdsByOwner, erc721Balances: ERC721TokenIdsByOwner,
exchangeAddress: string, exchangeAddress: string,
chainId: number
) { ) {
this._userAddresses = userAddresses; this._userAddresses = userAddresses;
this._zrxAddress = zrxAddress; this._zrxAddress = zrxAddress;
@ -50,6 +52,7 @@ export class OrderFactoryFromScenario {
this._erc721Token = erc721Token; this._erc721Token = erc721Token;
this._erc721Balances = erc721Balances; this._erc721Balances = erc721Balances;
this._exchangeAddress = exchangeAddress; this._exchangeAddress = exchangeAddress;
this._chainId = chainId;
} }
public generateOrder(orderScenario: OrderScenario): Order { public generateOrder(orderScenario: OrderScenario): Order {
const makerAddress = this._userAddresses[1]; const makerAddress = this._userAddresses[1];
@ -285,6 +288,7 @@ export class OrderFactoryFromScenario {
takerAssetData, takerAssetData,
salt: generatePseudoRandomSalt(), salt: generatePseudoRandomSalt(),
exchangeAddress: this._exchangeAddress, exchangeAddress: this._exchangeAddress,
chainId: this._chainId,
feeRecipientAddress, feeRecipientAddress,
expirationTimeSeconds, expirationTimeSeconds,
}; };

View File

@ -17,7 +17,7 @@ import {
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
import { RevertReason, SignedOrder } from '@0x/types'; import { RevertReason, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper'; import { Web3Wrapper } from '@0x/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -29,6 +29,7 @@ const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('Exchange wrappers', () => { describe('Exchange wrappers', () => {
let chainId: number;
let makerAddress: string; let makerAddress: string;
let owner: string; let owner: string;
let takerAddress: string; let takerAddress: string;
@ -62,6 +63,7 @@ describe('Exchange wrappers', () => {
await blockchainLifecycle.revertAsync(); await blockchainLifecycle.revertAsync();
}); });
before(async () => { before(async () => {
chainId = await providerUtils.getChainIdAsync(provider);
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = _.slice(accounts, 0, 4)); const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = _.slice(accounts, 0, 4));
@ -88,6 +90,7 @@ describe('Exchange wrappers', () => {
provider, provider,
txDefaults, txDefaults,
assetDataUtils.encodeERC20AssetData(zrxToken.address), assetDataUtils.encodeERC20AssetData(zrxToken.address),
new BigNumber(chainId)
); );
exchangeWrapper = new ExchangeWrapper(exchange, provider); exchangeWrapper = new ExchangeWrapper(exchange, provider);
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner); await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
@ -119,6 +122,7 @@ describe('Exchange wrappers', () => {
const defaultOrderParams = { const defaultOrderParams = {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
exchangeAddress: exchange.address, exchangeAddress: exchange.address,
chainId,
makerAddress, makerAddress,
feeRecipientAddress, feeRecipientAddress,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),

View File

@ -2,7 +2,7 @@ import { ExchangeContract, ExchangeWrapper } from '@0x/contracts-exchange';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils'; import { assetDataUtils } from '@0x/order-utils';
import { Order, RevertReason, SignedOrder } from '@0x/types'; import { Order, RevertReason, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper'; import { Web3Wrapper } from '@0x/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
@ -40,6 +40,7 @@ describe(ContractName.BalanceThresholdFilter, () => {
const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), DECIMALS_DEFAULT); const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), DECIMALS_DEFAULT);
const takerAssetFillAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(250), DECIMALS_DEFAULT); const takerAssetFillAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(250), DECIMALS_DEFAULT);
let chainId: number;
let validMakerAddress: string; let validMakerAddress: string;
let validMakerAddress2: string; let validMakerAddress2: string;
let owner: string; let owner: string;
@ -88,6 +89,8 @@ describe(ContractName.BalanceThresholdFilter, () => {
}; };
before(async () => { before(async () => {
// Get the chain ID.
chainId = await providerUtils.getChainIdAsync(provider);
// Create accounts // Create accounts
await blockchainLifecycle.startAsync(); await blockchainLifecycle.startAsync();
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
@ -131,6 +134,7 @@ describe(ContractName.BalanceThresholdFilter, () => {
provider, provider,
txDefaults, txDefaults,
zrxAssetData, zrxAssetData,
new BigNumber(chainId),
); );
exchangeWrapper = new ExchangeWrapper(exchangeInstance, provider); exchangeWrapper = new ExchangeWrapper(exchangeInstance, provider);
// Register proxies // Register proxies
@ -164,6 +168,7 @@ describe(ContractName.BalanceThresholdFilter, () => {
// Default order parameters // Default order parameters
defaultOrderParams = { defaultOrderParams = {
exchangeAddress: exchangeInstance.address, exchangeAddress: exchangeInstance.address,
chainId,
feeRecipientAddress, feeRecipientAddress,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress), takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress),
@ -197,25 +202,25 @@ describe(ContractName.BalanceThresholdFilter, () => {
erc20TakerBalanceThresholdWrapper = new BalanceThresholdWrapper( erc20TakerBalanceThresholdWrapper = new BalanceThresholdWrapper(
erc20BalanceThresholdFilterInstance, erc20BalanceThresholdFilterInstance,
exchangeInstance, exchangeInstance,
new TransactionFactory(takerPrivateKey, exchangeInstance.address), new TransactionFactory(takerPrivateKey, exchangeInstance.address, chainId),
provider, provider,
); );
erc721TakerBalanceThresholdWrapper = new BalanceThresholdWrapper( erc721TakerBalanceThresholdWrapper = new BalanceThresholdWrapper(
erc721BalanceThresholdFilterInstance, erc721BalanceThresholdFilterInstance,
exchangeInstance, exchangeInstance,
new TransactionFactory(takerPrivateKey, exchangeInstance.address), new TransactionFactory(takerPrivateKey, exchangeInstance.address, chainId),
provider, provider,
); );
erc721MakerBalanceThresholdWrapper = new BalanceThresholdWrapper( erc721MakerBalanceThresholdWrapper = new BalanceThresholdWrapper(
erc721BalanceThresholdFilterInstance, erc721BalanceThresholdFilterInstance,
exchangeInstance, exchangeInstance,
new TransactionFactory(makerPrivateKey, exchangeInstance.address), new TransactionFactory(makerPrivateKey, exchangeInstance.address, chainId),
provider, provider,
); );
erc721NonValidBalanceThresholdWrapper = new BalanceThresholdWrapper( erc721NonValidBalanceThresholdWrapper = new BalanceThresholdWrapper(
erc721BalanceThresholdFilterInstance, erc721BalanceThresholdFilterInstance,
exchangeInstance, exchangeInstance,
new TransactionFactory(invalidAddressPrivateKey, exchangeInstance.address), new TransactionFactory(invalidAddressPrivateKey, exchangeInstance.address, chainId),
provider, provider,
); );
}); });

View File

@ -18,7 +18,7 @@ import {
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils'; import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils';
import { RevertReason, SignedOrder } from '@0x/types'; import { RevertReason, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper'; import { Web3Wrapper } from '@0x/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -31,6 +31,7 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
const DECIMALS_DEFAULT = 18; const DECIMALS_DEFAULT = 18;
describe(ContractName.DutchAuction, () => { describe(ContractName.DutchAuction, () => {
let chainId: number;
let makerAddress: string; let makerAddress: string;
let owner: string; let owner: string;
let takerAddress: string; let takerAddress: string;
@ -62,6 +63,8 @@ describe(ContractName.DutchAuction, () => {
before(async () => { before(async () => {
await blockchainLifecycle.startAsync(); await blockchainLifecycle.startAsync();
chainId = await providerUtils.getChainIdAsync(provider);
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = accounts); const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = accounts);
@ -91,6 +94,7 @@ describe(ContractName.DutchAuction, () => {
provider, provider,
txDefaults, txDefaults,
zrxAssetData, zrxAssetData,
new BigNumber(chainId),
); );
const exchangeWrapper = new ExchangeWrapper(exchangeInstance, provider); const exchangeWrapper = new ExchangeWrapper(exchangeInstance, provider);
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner); await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
@ -145,6 +149,7 @@ describe(ContractName.DutchAuction, () => {
const sellerDefaultOrderParams = { const sellerDefaultOrderParams = {
salt: generatePseudoRandomSalt(), salt: generatePseudoRandomSalt(),
exchangeAddress: exchangeInstance.address, exchangeAddress: exchangeInstance.address,
chainId,
makerAddress, makerAddress,
feeRecipientAddress, feeRecipientAddress,
// taker address or sender address should be set to the ducth auction contract // taker address or sender address should be set to the ducth auction contract

View File

@ -23,7 +23,7 @@ import {
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils'; import { assetDataUtils } from '@0x/order-utils';
import { RevertReason } from '@0x/types'; import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper'; import { Web3Wrapper } from '@0x/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types'; import { LogWithDecodedArgs } from 'ethereum-types';
@ -36,6 +36,7 @@ chaiSetup.configure();
const expect = chai.expect; const expect = chai.expect;
// tslint:disable:no-unnecessary-type-assertion // tslint:disable:no-unnecessary-type-assertion
describe('OrderMatcher', () => { describe('OrderMatcher', () => {
let chainId: number;
let makerAddressLeft: string; let makerAddressLeft: string;
let makerAddressRight: string; let makerAddressRight: string;
let owner: string; let owner: string;
@ -69,6 +70,7 @@ describe('OrderMatcher', () => {
await blockchainLifecycle.revertAsync(); await blockchainLifecycle.revertAsync();
}); });
before(async () => { before(async () => {
chainId = await providerUtils.getChainIdAsync(provider);
// Create accounts // Create accounts
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
// Hack(albrow): Both Prettier and TSLint insert a trailing comma below // Hack(albrow): Both Prettier and TSLint insert a trailing comma below
@ -110,6 +112,7 @@ describe('OrderMatcher', () => {
provider, provider,
txDefaults, txDefaults,
assetDataUtils.encodeERC20AssetData(zrxToken.address), assetDataUtils.encodeERC20AssetData(zrxToken.address),
new BigNumber(chainId),
); );
exchangeWrapper = new ExchangeWrapper(exchange, provider); exchangeWrapper = new ExchangeWrapper(exchange, provider);
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner); await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
@ -165,6 +168,7 @@ describe('OrderMatcher', () => {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
makerAddress: makerAddressLeft, makerAddress: makerAddressLeft,
exchangeAddress: exchange.address, exchangeAddress: exchange.address,
chainId,
makerAssetData: leftMakerAssetData, makerAssetData: leftMakerAssetData,
takerAssetData: leftTakerAssetData, takerAssetData: leftTakerAssetData,
feeRecipientAddress: feeRecipientAddressLeft, feeRecipientAddress: feeRecipientAddressLeft,
@ -175,6 +179,7 @@ describe('OrderMatcher', () => {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
makerAddress: makerAddressRight, makerAddress: makerAddressRight,
exchangeAddress: exchange.address, exchangeAddress: exchange.address,
chainId,
makerAssetData: leftTakerAssetData, makerAssetData: leftTakerAssetData,
takerAssetData: leftMakerAssetData, takerAssetData: leftMakerAssetData,
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
@ -199,6 +204,7 @@ describe('OrderMatcher', () => {
provider, provider,
txDefaults, txDefaults,
constants.NULL_BYTES, constants.NULL_BYTES,
new BigNumber(chainId),
); );
return expectContractCreationFailedAsync( return expectContractCreationFailedAsync(
(OrderMatcherContract.deployFrom0xArtifactAsync( (OrderMatcherContract.deployFrom0xArtifactAsync(

View File

@ -8,9 +8,12 @@ export class TransactionFactory {
private readonly _signerBuff: Buffer; private readonly _signerBuff: Buffer;
private readonly _exchangeAddress: string; private readonly _exchangeAddress: string;
private readonly _privateKey: Buffer; private readonly _privateKey: Buffer;
constructor(privateKey: Buffer, exchangeAddress: string) { private readonly _chainId: number;
constructor(privateKey: Buffer, exchangeAddress: string, chainId: number) {
this._privateKey = privateKey; this._privateKey = privateKey;
this._exchangeAddress = exchangeAddress; this._exchangeAddress = exchangeAddress;
this._chainId = chainId;
this._signerBuff = ethUtil.privateToAddress(this._privateKey); this._signerBuff = ethUtil.privateToAddress(this._privateKey);
} }
public newSignedTransaction( public newSignedTransaction(
@ -24,6 +27,7 @@ export class TransactionFactory {
signerAddress, signerAddress,
data, data,
verifyingContractAddress: this._exchangeAddress, verifyingContractAddress: this._exchangeAddress,
chainId: this._chainId,
}; };
const transactionHashBuffer = transactionHashUtils.getTransactionHashBuffer(transaction); const transactionHashBuffer = transactionHashUtils.getTransactionHashBuffer(transaction);

View File

@ -11,7 +11,7 @@ import {
OrderValidationUtils, OrderValidationUtils,
} from '@0x/order-utils'; } from '@0x/order-utils';
import { AssetProxyId, Order, SignedOrder } from '@0x/types'; import { AssetProxyId, Order, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper'; import { Web3Wrapper } from '@0x/web3-wrapper';
import { BlockParamLiteral, ContractAbi, LogWithDecodedArgs } from 'ethereum-types'; import { BlockParamLiteral, ContractAbi, LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -1239,7 +1239,6 @@ export class ExchangeWrapper extends ContractWrapper {
const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher, this._web3Wrapper.getProvider()); const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher, this._web3Wrapper.getProvider());
await orderValidationUtils.validateFillOrderThrowIfInvalidAsync( await orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
exchangeTradeSimulator, exchangeTradeSimulator,
this._web3Wrapper.getProvider(),
signedOrder, signedOrder,
fillTakerAssetAmount, fillTakerAssetAmount,
takerAddress, takerAddress,
@ -1260,8 +1259,9 @@ export class ExchangeWrapper extends ContractWrapper {
* @return TransactionEncoder * @return TransactionEncoder
*/ */
public async transactionEncoderAsync(): Promise<TransactionEncoder> { public async transactionEncoderAsync(): Promise<TransactionEncoder> {
const chainId = await providerUtils.getChainIdAsync(this._web3Wrapper.getProvider());
const exchangeInstance = await this._getExchangeContractAsync(); const exchangeInstance = await this._getExchangeContractAsync();
const encoder = new TransactionEncoder(exchangeInstance); const encoder = new TransactionEncoder(exchangeInstance, chainId);
return encoder; return encoder;
} }
// tslint:enable:no-unused-variable // tslint:enable:no-unused-variable

View File

@ -15,8 +15,11 @@ import { assert } from './assert';
*/ */
export class TransactionEncoder { export class TransactionEncoder {
private readonly _exchangeInstance: ExchangeContract; private readonly _exchangeInstance: ExchangeContract;
constructor(exchangeInstance: ExchangeContract) { private readonly _chainId: number;
constructor(exchangeInstance: ExchangeContract, chainId: number) {
this._exchangeInstance = exchangeInstance; this._exchangeInstance = exchangeInstance;
this._chainId = chainId;
} }
/** /**
* Hashes the transaction data for use with the Exchange contract. * Hashes the transaction data for use with the Exchange contract.
@ -29,6 +32,7 @@ export class TransactionEncoder {
const exchangeAddress = this._getExchangeContract().address; const exchangeAddress = this._getExchangeContract().address;
const transaction = { const transaction = {
verifyingContractAddress: exchangeAddress, verifyingContractAddress: exchangeAddress,
chainId: this._chainId,
salt, salt,
signerAddress, signerAddress,
data, data,

View File

@ -14,8 +14,9 @@ const expect = chai.expect;
// utility for generating a set of order objects with mostly NULL values // utility for generating a set of order objects with mostly NULL values
// except for a specified makerAssetData and takerAssetData // except for a specified makerAssetData and takerAssetData
const FAKE_ORDERS_COUNT = 5; const FAKE_ORDERS_COUNT = 5;
const CHAIN_ID = 1337;
const generateFakeOrders = (makerAssetData: string, takerAssetData: string) => const generateFakeOrders = (makerAssetData: string, takerAssetData: string) =>
_.map(_.range(FAKE_ORDERS_COUNT), index => { _.map(_.range(FAKE_ORDERS_COUNT), () => {
const order = orderFactory.createOrder( const order = orderFactory.createOrder(
constants.NULL_ADDRESS, constants.NULL_ADDRESS,
constants.ZERO_AMOUNT, constants.ZERO_AMOUNT,
@ -23,6 +24,7 @@ const generateFakeOrders = (makerAssetData: string, takerAssetData: string) =>
constants.ZERO_AMOUNT, constants.ZERO_AMOUNT,
takerAssetData, takerAssetData,
constants.NULL_ADDRESS, constants.NULL_ADDRESS,
CHAIN_ID,
); );
return { return {
...order, ...order,

View File

@ -136,7 +136,7 @@ export const constants = {
], ],
}, },
COORDINATOR_DOMAIN_NAME: '0x Protocol Coordinator', COORDINATOR_DOMAIN_NAME: '0x Protocol Coordinator',
COORDINATOR_DOMAIN_VERSION: '1.0.0', COORDINATOR_DOMAIN_VERSION: '2.0.0',
COORDINATOR_APPROVAL_SCHEMA: { COORDINATOR_APPROVAL_SCHEMA: {
name: 'CoordinatorApproval', name: 'CoordinatorApproval',
parameters: [ parameters: [

View File

@ -61,6 +61,7 @@ export const eip712Utils = {
}); });
const domain = { const domain = {
verifyingContractAddress: order.exchangeAddress, verifyingContractAddress: order.exchangeAddress,
chainId: order.chainId,
}; };
const typedData = eip712Utils.createTypedData( const typedData = eip712Utils.createTypedData(
constants.EXCHANGE_ORDER_SCHEMA.name, constants.EXCHANGE_ORDER_SCHEMA.name,
@ -84,6 +85,7 @@ export const eip712Utils = {
}); });
const domain = { const domain = {
verifyingContractAddress: zeroExTransaction.verifyingContractAddress, verifyingContractAddress: zeroExTransaction.verifyingContractAddress,
chainId: zeroExTransaction.chainId,
}; };
const typedData = eip712Utils.createTypedData( const typedData = eip712Utils.createTypedData(
constants.EXCHANGE_ZEROEX_TRANSACTION_SCHEMA.name, constants.EXCHANGE_ZEROEX_TRANSACTION_SCHEMA.name,

View File

@ -1,5 +1,5 @@
import { Order, SignedOrder } from '@0x/types'; import { Order, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import { SupportedProvider } from 'ethereum-types'; import { SupportedProvider } from 'ethereum-types';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -10,14 +10,18 @@ import { signatureUtils } from './signature_utils';
import { CreateOrderOpts } from './types'; import { CreateOrderOpts } from './types';
export const orderFactory = { export const orderFactory = {
createOrderFromPartial(partialOrder: Partial<Order>): Order { createOrderFromPartial(partialOrder: Partial<Order>): Order {
const defaultOrder = generateEmptyOrder(); if (_.isNil(partialOrder.chainId))
throw new Error('chainId must be valid');
const defaultOrder = generateEmptyOrder(partialOrder.chainId);
return { return {
...defaultOrder, ...defaultOrder,
...partialOrder, ...partialOrder,
}; };
}, },
createSignedOrderFromPartial(partialSignedOrder: Partial<SignedOrder>): SignedOrder { createSignedOrderFromPartial(partialSignedOrder: Partial<SignedOrder>): SignedOrder {
const defaultOrder = generateEmptySignedOrder(); if (_.isNil(partialSignedOrder.chainId))
throw new Error('chainId must be valid');
const defaultOrder = generateEmptySignedOrder(partialSignedOrder.chainId);
return { return {
...defaultOrder, ...defaultOrder,
...partialSignedOrder, ...partialSignedOrder,
@ -30,6 +34,7 @@ export const orderFactory = {
takerAssetAmount: BigNumber, takerAssetAmount: BigNumber,
takerAssetData: string, takerAssetData: string,
exchangeAddress: string, exchangeAddress: string,
chainId: number,
createOrderOpts: CreateOrderOpts = generateDefaultCreateOrderOpts(), createOrderOpts: CreateOrderOpts = generateDefaultCreateOrderOpts(),
): Order { ): Order {
const defaultCreateOrderOpts = generateDefaultCreateOrderOpts(); const defaultCreateOrderOpts = generateDefaultCreateOrderOpts();
@ -48,6 +53,7 @@ export const orderFactory = {
salt: createOrderOpts.salt || defaultCreateOrderOpts.salt, salt: createOrderOpts.salt || defaultCreateOrderOpts.salt,
expirationTimeSeconds: expirationTimeSeconds:
createOrderOpts.expirationTimeSeconds || defaultCreateOrderOpts.expirationTimeSeconds, createOrderOpts.expirationTimeSeconds || defaultCreateOrderOpts.expirationTimeSeconds,
chainId: chainId,
}; };
return order; return order;
}, },
@ -68,6 +74,7 @@ export const orderFactory = {
takerAssetAmount, takerAssetAmount,
takerAssetData, takerAssetData,
exchangeAddress, exchangeAddress,
await providerUtils.getChainIdAsync(supportedProvider),
createOrderOpts, createOrderOpts,
); );
const orderHash = orderHashUtils.getOrderHashHex(order); const orderHash = orderHashUtils.getOrderHashHex(order);
@ -77,13 +84,13 @@ export const orderFactory = {
}, },
}; };
function generateEmptySignedOrder(): SignedOrder { function generateEmptySignedOrder(chainId: number): SignedOrder {
return { return {
...generateEmptyOrder(), ...generateEmptyOrder(chainId),
signature: constants.NULL_BYTES, signature: constants.NULL_BYTES,
}; };
} }
function generateEmptyOrder(): Order { function generateEmptyOrder(chainId: number): Order {
return { return {
senderAddress: constants.NULL_ADDRESS, senderAddress: constants.NULL_ADDRESS,
makerAddress: constants.NULL_ADDRESS, makerAddress: constants.NULL_ADDRESS,
@ -96,6 +103,7 @@ function generateEmptyOrder(): Order {
takerAssetData: constants.NULL_BYTES, takerAssetData: constants.NULL_BYTES,
salt: generatePseudoRandomSalt(), salt: generatePseudoRandomSalt(),
exchangeAddress: constants.NULL_ADDRESS, exchangeAddress: constants.NULL_ADDRESS,
chainId: chainId,
feeRecipientAddress: constants.NULL_ADDRESS, feeRecipientAddress: constants.NULL_ADDRESS,
expirationTimeSeconds: constants.INFINITE_TIMESTAMP_SEC, expirationTimeSeconds: constants.INFINITE_TIMESTAMP_SEC,
}; };

View File

@ -42,6 +42,7 @@ type OrderValidationResult = OrderValidResult | OrderInvalidResult;
export class OrderStateUtils { export class OrderStateUtils {
private readonly _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; private readonly _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher;
private readonly _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher; private readonly _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher;
private readonly _chainId: number;
private static _validateIfOrderIsValid( private static _validateIfOrderIsValid(
signedOrder: SignedOrder, signedOrder: SignedOrder,
sidedOrderRelevantState: SidedOrderRelevantState, sidedOrderRelevantState: SidedOrderRelevantState,
@ -102,14 +103,17 @@ export class OrderStateUtils {
* and proxyAllowances for Ethereum addresses. It must implement AbstractBalanceAndProxyAllowanceFetcher * and proxyAllowances for Ethereum addresses. It must implement AbstractBalanceAndProxyAllowanceFetcher
* @param orderFilledCancelledFetcher A class that is capable of fetching whether an order * @param orderFilledCancelledFetcher A class that is capable of fetching whether an order
* is cancelled and how much of it has been filled. It must implement AbstractOrderFilledCancelledFetcher * is cancelled and how much of it has been filled. It must implement AbstractOrderFilledCancelledFetcher
* @param chainId The chain ID of the network being used.
* @return Instance of OrderStateUtils * @return Instance of OrderStateUtils
*/ */
constructor( constructor(
balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher, balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher,
orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher, orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher,
chainId: number,
) { ) {
this._balanceAndProxyAllowanceFetcher = balanceAndProxyAllowanceFetcher; this._balanceAndProxyAllowanceFetcher = balanceAndProxyAllowanceFetcher;
this._orderFilledCancelledFetcher = orderFilledCancelledFetcher; this._orderFilledCancelledFetcher = orderFilledCancelledFetcher;
this._chainId = chainId;
} }
/** /**
* Get the orderState for an "open" order (i.e where takerAddress=NULL_ADDRESS) * Get the orderState for an "open" order (i.e where takerAddress=NULL_ADDRESS)

View File

@ -227,7 +227,6 @@ export class OrderValidationUtils {
/** /**
* Validate a call to FillOrder and throw if it wouldn't succeed * Validate a call to FillOrder and throw if it wouldn't succeed
* @param exchangeTradeEmulator ExchangeTradeEmulator to use * @param exchangeTradeEmulator ExchangeTradeEmulator to use
* @param supportedProvider Web3 provider to use for JSON RPC requests
* @param signedOrder SignedOrder of interest * @param signedOrder SignedOrder of interest
* @param fillTakerAssetAmount Amount we'd like to fill the order for * @param fillTakerAssetAmount Amount we'd like to fill the order for
* @param takerAddress The taker of the order * @param takerAddress The taker of the order
@ -235,7 +234,6 @@ export class OrderValidationUtils {
*/ */
public async validateFillOrderThrowIfInvalidAsync( public async validateFillOrderThrowIfInvalidAsync(
exchangeTradeEmulator: ExchangeTransferSimulator, exchangeTradeEmulator: ExchangeTransferSimulator,
supportedProvider: SupportedProvider,
signedOrder: SignedOrder, signedOrder: SignedOrder,
fillTakerAssetAmount: BigNumber, fillTakerAssetAmount: BigNumber,
takerAddress: string, takerAddress: string,
@ -247,10 +245,10 @@ export class OrderValidationUtils {
if (fillTakerAssetAmount.eq(0)) { if (fillTakerAssetAmount.eq(0)) {
throw new Error(RevertReason.InvalidTakerAmount); throw new Error(RevertReason.InvalidTakerAmount);
} }
const provider = providerUtils.standardizeOrThrow(supportedProvider);
const orderHash = orderHashUtils.getOrderHashHex(signedOrder); const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
const isValid = await signatureUtils.isValidSignatureAsync( const isValid = await signatureUtils.isValidSignatureAsync(
provider, this._provider,
orderHash, orderHash,
signedOrder.signature, signedOrder.signature,
signedOrder.makerAddress, signedOrder.makerAddress,

View File

@ -232,6 +232,7 @@ export const signatureUtils = {
if (err.message.includes('User denied message signature')) { if (err.message.includes('User denied message signature')) {
throw err; throw err;
} }
const chainId = await providerUtils.getChainIdAsync(supportedProvider);
const orderHash = orderHashUtils.getOrderHashHex(order); const orderHash = orderHashUtils.getOrderHashHex(order);
const signatureHex = await signatureUtils.ecSignHashAsync(supportedProvider, orderHash, signerAddress); const signatureHex = await signatureUtils.ecSignHashAsync(supportedProvider, orderHash, signerAddress);
const signedOrder = { const signedOrder = {
@ -255,6 +256,7 @@ export const signatureUtils = {
signerAddress: string, signerAddress: string,
): Promise<SignedOrder> { ): Promise<SignedOrder> {
const provider = providerUtils.standardizeOrThrow(supportedProvider); const provider = providerUtils.standardizeOrThrow(supportedProvider);
const chainId = await providerUtils.getChainIdAsync(provider);
assert.isETHAddressHex('signerAddress', signerAddress); assert.isETHAddressHex('signerAddress', signerAddress);
assert.doesConformToSchema('order', order, schemas.orderSchema, [schemas.hexSchema]); assert.doesConformToSchema('order', order, schemas.orderSchema, [schemas.hexSchema]);
const web3Wrapper = new Web3Wrapper(provider); const web3Wrapper = new Web3Wrapper(provider);

View File

@ -11,6 +11,8 @@ chaiSetup.configure();
const expect = chai.expect; const expect = chai.expect;
describe('EIP712 Utils', () => { describe('EIP712 Utils', () => {
const CHAIN_ID = 1337;
describe('createTypedData', () => { describe('createTypedData', () => {
it('adds in the EIP712DomainSeparator with default values', () => { it('adds in the EIP712DomainSeparator with default values', () => {
const primaryType = 'Test'; const primaryType = 'Test';
@ -18,7 +20,7 @@ describe('EIP712 Utils', () => {
primaryType, primaryType,
{ Test: [{ name: 'testValue', type: 'uint256' }] }, { Test: [{ name: 'testValue', type: 'uint256' }] },
{ testValue: '1' }, { testValue: '1' },
{ verifyingContractAddress: constants.NULL_ADDRESS }, { chainId: CHAIN_ID, verifyingContractAddress: constants.NULL_ADDRESS, },
); );
expect(typedData.domain).to.not.be.undefined(); expect(typedData.domain).to.not.be.undefined();
expect(typedData.types.EIP712Domain).to.not.be.undefined(); expect(typedData.types.EIP712Domain).to.not.be.undefined();
@ -36,7 +38,12 @@ describe('EIP712 Utils', () => {
primaryType, primaryType,
{ Test: [{ name: 'testValue', type: 'uint256' }] }, { Test: [{ name: 'testValue', type: 'uint256' }] },
{ testValue: '1' }, { testValue: '1' },
{ name: domainName, version: domainVersion, verifyingContractAddress: constants.NULL_ADDRESS }, {
name: domainName,
version: domainVersion,
chainId: CHAIN_ID,
verifyingContractAddress: constants.NULL_ADDRESS,
},
); );
expect(typedData.domain).to.not.be.undefined(); expect(typedData.domain).to.not.be.undefined();
expect(typedData.types.EIP712Domain).to.not.be.undefined(); expect(typedData.types.EIP712Domain).to.not.be.undefined();
@ -54,6 +61,7 @@ describe('EIP712 Utils', () => {
data: constants.NULL_BYTES, data: constants.NULL_BYTES,
signerAddress: constants.NULL_ADDRESS, signerAddress: constants.NULL_ADDRESS,
verifyingContractAddress: constants.NULL_ADDRESS, verifyingContractAddress: constants.NULL_ADDRESS,
chainId: CHAIN_ID,
}); });
expect(typedData.primaryType).to.eq(constants.EXCHANGE_ZEROEX_TRANSACTION_SCHEMA.name); expect(typedData.primaryType).to.eq(constants.EXCHANGE_ZEROEX_TRANSACTION_SCHEMA.name);
expect(typedData.types.EIP712Domain).to.not.be.undefined(); expect(typedData.types.EIP712Domain).to.not.be.undefined();

View File

@ -14,8 +14,9 @@ const expect = chai.expect;
describe('Order hashing', () => { describe('Order hashing', () => {
describe('#getOrderHashHex', () => { describe('#getOrderHashHex', () => {
const expectedOrderHash = '0x434c6b41e2fb6dfcfe1b45c4492fb03700798e9c1afc6f801ba6203f948c1fa7'; const expectedOrderHash = '0x2af69ce573fc9ffc734c88aaafc6907e2619572a462ca1ab2326e0e4bebec127';
const fakeExchangeContractAddress = '0x1dc4c1cefef38a777b15aa20260a54e584b16c48'; const fakeExchangeContractAddress = '0x1dc4c1cefef38a777b15aa20260a54e584b16c48';
const fakeChainID = 1337;
const order: Order = { const order: Order = {
makerAddress: constants.NULL_ADDRESS, makerAddress: constants.NULL_ADDRESS,
takerAddress: constants.NULL_ADDRESS, takerAddress: constants.NULL_ADDRESS,
@ -24,6 +25,7 @@ describe('Order hashing', () => {
makerAssetData: constants.NULL_ADDRESS, makerAssetData: constants.NULL_ADDRESS,
takerAssetData: constants.NULL_ADDRESS, takerAssetData: constants.NULL_ADDRESS,
exchangeAddress: fakeExchangeContractAddress, exchangeAddress: fakeExchangeContractAddress,
chainId: fakeChainID,
salt: new BigNumber(0), salt: new BigNumber(0),
makerFee: new BigNumber(0), makerFee: new BigNumber(0),
takerFee: new BigNumber(0), takerFee: new BigNumber(0),

View File

@ -14,6 +14,8 @@ chaiSetup.configure();
const expect = chai.expect; const expect = chai.expect;
describe('OrderStateUtils', () => { describe('OrderStateUtils', () => {
const CHAIN_ID = 1337;
describe('#getOpenOrderStateAsync', () => { describe('#getOpenOrderStateAsync', () => {
const buildMockBalanceFetcher = (takerBalance: BigNumber): AbstractBalanceAndProxyAllowanceFetcher => { const buildMockBalanceFetcher = (takerBalance: BigNumber): AbstractBalanceAndProxyAllowanceFetcher => {
const balanceFetcher = { const balanceFetcher = {
@ -58,7 +60,11 @@ describe('OrderStateUtils', () => {
1, 1,
); );
const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher); const orderStateUtils = new OrderStateUtils(
mockBalanceFetcher,
mockOrderFilledFetcher,
CHAIN_ID,
);
const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder); const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
expect(orderState.isValid).to.eq(true); expect(orderState.isValid).to.eq(true);
}); });
@ -77,7 +83,11 @@ describe('OrderStateUtils', () => {
1, 1,
); );
const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher); const orderStateUtils = new OrderStateUtils(
mockBalanceFetcher,
mockOrderFilledFetcher,
CHAIN_ID,
);
const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder); const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
expect(orderState.isValid).to.eq(false); expect(orderState.isValid).to.eq(false);
}); });
@ -97,7 +107,11 @@ describe('OrderStateUtils', () => {
1, 1,
); );
const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher); const orderStateUtils = new OrderStateUtils(
mockBalanceFetcher,
mockOrderFilledFetcher,
CHAIN_ID,
);
const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder); const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
expect(orderState.isValid).to.eq(false); expect(orderState.isValid).to.eq(false);
}); });
@ -117,7 +131,11 @@ describe('OrderStateUtils', () => {
1, 1,
); );
const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher); const orderStateUtils = new OrderStateUtils(
mockBalanceFetcher,
mockOrderFilledFetcher,
CHAIN_ID,
);
const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder); const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
expect(orderState.isValid).to.eq(false); expect(orderState.isValid).to.eq(false);
}); });
@ -136,7 +154,11 @@ describe('OrderStateUtils', () => {
1, 1,
); );
const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher); const orderStateUtils = new OrderStateUtils(
mockBalanceFetcher,
mockOrderFilledFetcher,
CHAIN_ID,
);
const transactionHash = '0xdeadbeef'; const transactionHash = '0xdeadbeef';
const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder, transactionHash); const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder, transactionHash);
expect(orderState.transactionHash).to.eq(transactionHash); expect(orderState.transactionHash).to.eq(transactionHash);

View File

@ -43,6 +43,7 @@ describe('RemainingFillableCalculator', () => {
return { return {
signature, signature,
exchangeAddress: zeroAddress, exchangeAddress: zeroAddress,
chainId: 1337,
feeRecipientAddress: zeroAddress, feeRecipientAddress: zeroAddress,
senderAddress: zeroAddress, senderAddress: zeroAddress,
makerAddress: zeroAddress, makerAddress: zeroAddress,

View File

@ -20,6 +20,7 @@ const expect = chai.expect;
describe('Signature utils', () => { describe('Signature utils', () => {
let makerAddress: string; let makerAddress: string;
const fakeExchangeContractAddress = '0x1dc4c1cefef38a777b15aa20260a54e584b16c48'; const fakeExchangeContractAddress = '0x1dc4c1cefef38a777b15aa20260a54e584b16c48';
const CHAIN_ID = 1337;
let order: Order; let order: Order;
let transaction: ZeroExTransaction; let transaction: ZeroExTransaction;
before(async () => { before(async () => {
@ -33,6 +34,7 @@ describe('Signature utils', () => {
makerAssetData: constants.NULL_ADDRESS, makerAssetData: constants.NULL_ADDRESS,
takerAssetData: constants.NULL_ADDRESS, takerAssetData: constants.NULL_ADDRESS,
exchangeAddress: fakeExchangeContractAddress, exchangeAddress: fakeExchangeContractAddress,
chainId: CHAIN_ID,
salt: new BigNumber(0), salt: new BigNumber(0),
makerFee: new BigNumber(0), makerFee: new BigNumber(0),
takerFee: new BigNumber(0), takerFee: new BigNumber(0),
@ -160,7 +162,7 @@ describe('Signature utils', () => {
describe('#ecSignOrderAsync', () => { describe('#ecSignOrderAsync', () => {
it('should default to eth_sign if eth_signTypedData is unavailable', async () => { it('should default to eth_sign if eth_signTypedData is unavailable', async () => {
const expectedSignature = const expectedSignature =
'0x1c3582f06356a1314dbf1c0e534c4d8e92e59b056ee607a7ff5a825f5f2cc5e6151c5cc7fdd420f5608e4d5bef108e42ad90c7a4b408caef32e24374cf387b0d7603'; '0x1bcbeb571648db1b7e0454175a6a4b4da1ac07cfc5fb5e4c8e4e10aa4aad368a11050ac85be1ca543eb4e1c07b852cbe6619cbab0cbbf05df364d80e126ffe731403';
const fakeProvider = { const fakeProvider = {
async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> { async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> {
@ -356,7 +358,7 @@ describe('Signature utils', () => {
}); });
it('should return the correct Signature for signatureHex concatenated as R + S + V', async () => { it('should return the correct Signature for signatureHex concatenated as R + S + V', async () => {
const expectedSignature = const expectedSignature =
'0x1cd472c439833774b55d248c31b6585f21aea1b9363ebb4ec58549e46b62eb5a6f696f5781f62de008ee7f77650ef940d99c97ec1dee67b3f5cea1bbfdfeb2eba602'; '0x1baf6c2d23afb5389e29e4274e3dc419939641e94f56a62260a004f2f79b9501c725a1d740c75d1f6e0bdc7b158c62e1ec36b7e9a16086f249fd821fa00d5652db02';
const fakeProvider = { const fakeProvider = {
async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> { async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> {
if (payload.method === 'eth_signTypedData') { if (payload.method === 'eth_signTypedData') {

View File

@ -14,10 +14,11 @@ const expect = chai.expect;
describe('0x transaction hashing', () => { describe('0x transaction hashing', () => {
describe('#getTransactionHashHex', () => { describe('#getTransactionHashHex', () => {
const expectedTransactionHash = '0x82c9bb2dcac4f868ec7a15c20ff6175cfc384c20ae6a872aa0342a840f108c2b'; const expectedTransactionHash = '0xbd640f97452817179076e736257ea85feac51530f1844ef05297af69e375522b';
const fakeVerifyingContractAddress = '0x5e72914535f202659083db3a02c984188fa26e9f'; const fakeVerifyingContractAddress = '0x5e72914535f202659083db3a02c984188fa26e9f';
const transaction: ZeroExTransaction = { const transaction: ZeroExTransaction = {
verifyingContractAddress: fakeVerifyingContractAddress, verifyingContractAddress: fakeVerifyingContractAddress,
chainId: 1337,
signerAddress: constants.NULL_ADDRESS, signerAddress: constants.NULL_ADDRESS,
salt: new BigNumber(0), salt: new BigNumber(0),
data: constants.NULL_BYTES, data: constants.NULL_BYTES,

View File

@ -11,6 +11,7 @@ const BASE_TEST_ORDER: Order = orderFactory.createOrder(
constants.ZERO_AMOUNT, constants.ZERO_AMOUNT,
constants.NULL_ERC20_ASSET_DATA, constants.NULL_ERC20_ASSET_DATA,
constants.NULL_ADDRESS, constants.NULL_ADDRESS,
0,
); );
const BASE_TEST_SIGNED_ORDER: SignedOrder = { const BASE_TEST_SIGNED_ORDER: SignedOrder = {
...BASE_TEST_ORDER, ...BASE_TEST_ORDER,

View File

@ -18,6 +18,7 @@ export interface Order {
takerAssetData: string; takerAssetData: string;
salt: BigNumber; salt: BigNumber;
exchangeAddress: string; exchangeAddress: string;
chainId: number;
feeRecipientAddress: string; feeRecipientAddress: string;
expirationTimeSeconds: BigNumber; expirationTimeSeconds: BigNumber;
} }
@ -51,6 +52,7 @@ export enum MarketOperation {
*/ */
export interface ZeroExTransaction { export interface ZeroExTransaction {
verifyingContractAddress: string; verifyingContractAddress: string;
chainId: number;
salt: BigNumber; salt: BigNumber;
signerAddress: string; signerAddress: string;
data: string; data: string;

View File

@ -2,6 +2,7 @@ import {
EIP1193Provider, EIP1193Provider,
JSONRPCErrorCallback, JSONRPCErrorCallback,
JSONRPCRequestPayload, JSONRPCRequestPayload,
JSONRPCResponsePayload,
SupportedProvider, SupportedProvider,
ZeroExProvider, ZeroExProvider,
} from 'ethereum-types'; } from 'ethereum-types';
@ -94,4 +95,30 @@ export const providerUtils = {
`Unsupported provider found. Please make sure it conforms to one of the supported providers. See 'Provider' type in 'ethereum-types' package.`, `Unsupported provider found. Please make sure it conforms to one of the supported providers. See 'Provider' type in 'ethereum-types' package.`,
); );
}, },
/**
* Retrieve the chain ID from a supported provider.
* @param supportedProvider A supported provider instance.
* @return A promise thar resolves to the chain ID of the network the provider
* is connected to.
*/
async getChainIdAsync(supportedProvider: SupportedProvider): Promise<number> {
const provider = this.standardizeOrThrow(supportedProvider);
return new Promise<number>((accept, reject) => {
provider.sendAsync({
jsonrpc: '2.0',
id: _.random(0, 2**64),
method: 'net_version',
params: []
},
(err : Error | null, result?: JSONRPCResponsePayload) => {
if (!_.isNil(err))
reject(err);
if (!result)
throw new Error('Invalid \'net_version\' response');
accept(_.toNumber(result.result));
}
);
});
},
}; };

View File

@ -71,8 +71,13 @@ export const signTypedDataUtils = {
return ethers.utils.defaultAbiCoder.encode(encodedTypes, encodedValues); return ethers.utils.defaultAbiCoder.encode(encodedTypes, encodedValues);
}, },
_normalizeValue(type: string, value: any): EIP712ObjectValue { _normalizeValue(type: string, value: any): EIP712ObjectValue {
const normalizedValue = type === 'uint256' && BigNumber.isBigNumber(value) ? value.toString() : value; if (type == 'uint256') {
return normalizedValue; if (BigNumber.isBigNumber(value)) {
return value.toString(10);
}
return new BigNumber(value).toString(10);
}
return value;
}, },
_typeHash(primaryType: string, types: EIP712Types): Buffer { _typeHash(primaryType: string, types: EIP712Types): Buffer {
return ethUtil.sha3(signTypedDataUtils._encodeType(primaryType, types)); return ethUtil.sha3(signTypedDataUtils._encodeType(primaryType, types));

View File

@ -36,7 +36,7 @@ describe('signTypedDataUtils', () => {
}, },
primaryType: 'Test', primaryType: 'Test',
}; };
const orderSignTypedDataHashHex = '0x55eaa6ec02f3224d30873577e9ddd069a288c16d6fb407210eecbc501fa76692'; const orderSignTypedDataHashHex = '0x78772b297e1b0b31089589a6608930cceba855af9d3ccf7b92cf47fa881e21f7';
const orderSignTypedData = { const orderSignTypedData = {
types: { types: {
EIP712Domain: [ EIP712Domain: [
@ -48,6 +48,10 @@ describe('signTypedDataUtils', () => {
name: 'version', name: 'version',
type: 'string', type: 'string',
}, },
{
name: 'chainId',
type: 'uint256',
},
{ {
name: 'verifyingContract', name: 'verifyingContract',
type: 'address', type: 'address',
@ -107,6 +111,7 @@ describe('signTypedDataUtils', () => {
domain: { domain: {
name: '0x Protocol', name: '0x Protocol',
version: '2', version: '2',
chainId: 1337,
verifyingContract: '0x0000000000000000000000000000000000000000', verifyingContract: '0x0000000000000000000000000000000000000000',
}, },
message: { message: {
@ -157,7 +162,7 @@ describe('signTypedDataUtils', () => {
}; };
const hash = signTypedDataUtils.generateTypedDataHash(uninitializedOrder).toString('hex'); const hash = signTypedDataUtils.generateTypedDataHash(uninitializedOrder).toString('hex');
const hashHex = `0x${hash}`; const hashHex = `0x${hash}`;
expect(hashHex).to.be.eq('0xfaa49b35faeb9197e9c3ba7a52075e6dad19739549f153b77dfcf59408a4b422'); expect(hashHex).to.be.eq('0x510449a190415c4770080d857a1c654b653a0c054c94a7a8e9f08f623f9e824f');
}); });
}); });
}); });