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

View File

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

View File

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

View File

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

View File

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

View File

@ -34,7 +34,7 @@
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
},
"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."
},
"repository": {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -18,7 +18,7 @@ import {
import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils';
import { RevertReason, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { BigNumber, providerUtils } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import * as chai from 'chai';
import * as _ from 'lodash';
@ -31,6 +31,7 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
const DECIMALS_DEFAULT = 18;
describe(ContractName.DutchAuction, () => {
let chainId: number;
let makerAddress: string;
let owner: string;
let takerAddress: string;
@ -62,6 +63,8 @@ describe(ContractName.DutchAuction, () => {
before(async () => {
await blockchainLifecycle.startAsync();
chainId = await providerUtils.getChainIdAsync(provider);
const accounts = await web3Wrapper.getAvailableAddressesAsync();
const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = accounts);
@ -91,6 +94,7 @@ describe(ContractName.DutchAuction, () => {
provider,
txDefaults,
zrxAssetData,
new BigNumber(chainId),
);
const exchangeWrapper = new ExchangeWrapper(exchangeInstance, provider);
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
@ -145,6 +149,7 @@ describe(ContractName.DutchAuction, () => {
const sellerDefaultOrderParams = {
salt: generatePseudoRandomSalt(),
exchangeAddress: exchangeInstance.address,
chainId,
makerAddress,
feeRecipientAddress,
// 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 { assetDataUtils } from '@0x/order-utils';
import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { BigNumber, providerUtils } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
@ -36,6 +36,7 @@ chaiSetup.configure();
const expect = chai.expect;
// tslint:disable:no-unnecessary-type-assertion
describe('OrderMatcher', () => {
let chainId: number;
let makerAddressLeft: string;
let makerAddressRight: string;
let owner: string;
@ -69,6 +70,7 @@ describe('OrderMatcher', () => {
await blockchainLifecycle.revertAsync();
});
before(async () => {
chainId = await providerUtils.getChainIdAsync(provider);
// Create accounts
const accounts = await web3Wrapper.getAvailableAddressesAsync();
// Hack(albrow): Both Prettier and TSLint insert a trailing comma below
@ -110,6 +112,7 @@ describe('OrderMatcher', () => {
provider,
txDefaults,
assetDataUtils.encodeERC20AssetData(zrxToken.address),
new BigNumber(chainId),
);
exchangeWrapper = new ExchangeWrapper(exchange, provider);
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
@ -165,6 +168,7 @@ describe('OrderMatcher', () => {
...constants.STATIC_ORDER_PARAMS,
makerAddress: makerAddressLeft,
exchangeAddress: exchange.address,
chainId,
makerAssetData: leftMakerAssetData,
takerAssetData: leftTakerAssetData,
feeRecipientAddress: feeRecipientAddressLeft,
@ -175,6 +179,7 @@ describe('OrderMatcher', () => {
...constants.STATIC_ORDER_PARAMS,
makerAddress: makerAddressRight,
exchangeAddress: exchange.address,
chainId,
makerAssetData: leftTakerAssetData,
takerAssetData: leftMakerAssetData,
feeRecipientAddress: feeRecipientAddressRight,
@ -199,6 +204,7 @@ describe('OrderMatcher', () => {
provider,
txDefaults,
constants.NULL_BYTES,
new BigNumber(chainId),
);
return expectContractCreationFailedAsync(
(OrderMatcherContract.deployFrom0xArtifactAsync(

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -42,6 +42,7 @@ type OrderValidationResult = OrderValidResult | OrderInvalidResult;
export class OrderStateUtils {
private readonly _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher;
private readonly _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher;
private readonly _chainId: number;
private static _validateIfOrderIsValid(
signedOrder: SignedOrder,
sidedOrderRelevantState: SidedOrderRelevantState,
@ -102,14 +103,17 @@ export class OrderStateUtils {
* and proxyAllowances for Ethereum addresses. It must implement AbstractBalanceAndProxyAllowanceFetcher
* @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
* @param chainId The chain ID of the network being used.
* @return Instance of OrderStateUtils
*/
constructor(
balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher,
orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher,
chainId: number,
) {
this._balanceAndProxyAllowanceFetcher = balanceAndProxyAllowanceFetcher;
this._orderFilledCancelledFetcher = orderFilledCancelledFetcher;
this._chainId = chainId;
}
/**
* 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
* @param exchangeTradeEmulator ExchangeTradeEmulator to use
* @param supportedProvider Web3 provider to use for JSON RPC requests
* @param signedOrder SignedOrder of interest
* @param fillTakerAssetAmount Amount we'd like to fill the order for
* @param takerAddress The taker of the order
@ -235,7 +234,6 @@ export class OrderValidationUtils {
*/
public async validateFillOrderThrowIfInvalidAsync(
exchangeTradeEmulator: ExchangeTransferSimulator,
supportedProvider: SupportedProvider,
signedOrder: SignedOrder,
fillTakerAssetAmount: BigNumber,
takerAddress: string,
@ -247,10 +245,10 @@ export class OrderValidationUtils {
if (fillTakerAssetAmount.eq(0)) {
throw new Error(RevertReason.InvalidTakerAmount);
}
const provider = providerUtils.standardizeOrThrow(supportedProvider);
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
const isValid = await signatureUtils.isValidSignatureAsync(
provider,
this._provider,
orderHash,
signedOrder.signature,
signedOrder.makerAddress,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,6 +2,7 @@ import {
EIP1193Provider,
JSONRPCErrorCallback,
JSONRPCRequestPayload,
JSONRPCResponsePayload,
SupportedProvider,
ZeroExProvider,
} 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.`,
);
},
/**
* 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);
},
_normalizeValue(type: string, value: any): EIP712ObjectValue {
const normalizedValue = type === 'uint256' && BigNumber.isBigNumber(value) ? value.toString() : value;
return normalizedValue;
if (type == 'uint256') {
if (BigNumber.isBigNumber(value)) {
return value.toString(10);
}
return new BigNumber(value).toString(10);
}
return value;
},
_typeHash(primaryType: string, types: EIP712Types): Buffer {
return ethUtil.sha3(signTypedDataUtils._encodeType(primaryType, types));

View File

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