Skip to content
This repository has been archived by the owner on Jul 9, 2021. It is now read-only.

[3.0] Add chain ID to EIP 712 domains #1742

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
13a33aa
Update exchange and coordinator contracts to incorporate chainID in t…
dorothy-zbornak Mar 21, 2019
12a047a
Update tooling/types to incorporate chainID in domain separators.
dorothy-zbornak Mar 21, 2019
fc7432a
Refactor EIP712 contracts to reduce code duplication.
dorothy-zbornak Mar 21, 2019
f182f91
Fix missing comma in `LibEIP712.sol` domain schema.
dorothy-zbornak Mar 22, 2019
beb78b6
Unpin `@0x/contracts-exchange` dependency in `/contracts/coordinator`.
dorothy-zbornak Mar 22, 2019
fa7d549
Remove unused `LibOrder` inheritance from `MixinBalanceThresholdFilte…
dorothy-zbornak Mar 22, 2019
4bcace3
Migrate all contract-related tooling and tests to accept a chain ID i…
dorothy-zbornak Mar 22, 2019
a4b8797
Update `exchange-forwarder` tests.
dorothy-zbornak Mar 25, 2019
4d107dc
Remove unused `chainId` variables in `signature_utils.ts`.
dorothy-zbornak Mar 26, 2019
d078816
All glory to the linter gods.
dorothy-zbornak Mar 26, 2019
4af99b0
Remove lingering invalid calls to `OrderStateUtils()`
dorothy-zbornak Mar 26, 2019
dc9365a
Clearer usage of chainId constants in `order-utils` tests.
dorothy-zbornak Mar 26, 2019
5c8d81f
Unpin coordinator deps.
dorothy-zbornak Mar 26, 2019
7021204
Ran prettier
dorothy-zbornak Mar 26, 2019
c486093
Update generated wrappers for coordinator and exchange.
dorothy-zbornak Mar 26, 2019
43e685c
Update for Coordinator and Exchange
dorothy-zbornak Mar 26, 2019
aa26e03
Add `chainId` to order JSON schema
dorothy-zbornak Mar 26, 2019
0f938a2
Update migrations for coordinator and exchange contracts.
dorothy-zbornak Mar 26, 2019
cfa8f97
Update `contract-wrappers` tests.
dorothy-zbornak Mar 26, 2019
52f7d67
Bump up minor versions in changelogs for `exchange` and `exchange-lib…
dorothy-zbornak Mar 26, 2019
c86139d
Update coordinator `decodeOrdersFromFillData` tests to include chainId
dorothy-zbornak Mar 27, 2019
1b01deb
Add `chainId` to order `json-schemas` tests.
dorothy-zbornak Mar 27, 2019
325573d
Remove unused `providerUtils` import.
dorothy-zbornak Mar 27, 2019
c0b2e1a
Update changelogs
dorothy-zbornak Mar 27, 2019
b87a97f
Add test to `exchange-libs` to ensure that a different chainId result…
dorothy-zbornak Mar 28, 2019
dd59b7b
Add more LibEIP712 tests to `exchange-libs`
dorothy-zbornak Mar 28, 2019
fa7100f
Fix typo in `exchange-libs` test.
dorothy-zbornak Mar 28, 2019
2fb810d
Make `contracts/exchange-libs/.../LibEIP712.sol` stateless
dorothy-zbornak Mar 30, 2019
82da3ae
Remove deleted coordinator test contracts that accidentally survived …
dorothy-zbornak Mar 30, 2019
918d7f1
`contracts/exchange-libs/contracts/test/TestLibs` now inherits from `…
dorothy-zbornak Mar 30, 2019
43ce523
Switch eip712 domain field `verifyingContract` to `verifyingContractA…
dorothy-zbornak Mar 30, 2019
1b35012
Add `eip712DomainSchema` to `json-schemas`.
dorothy-zbornak Apr 1, 2019
b16d11d
Rename `eip712domain` field in `Order` and `ZeroExTransaction` to jus…
dorothy-zbornak Apr 1, 2019
ecc94ff
Update `packages/utils` tests to conform to new domain schema
dorothy-zbornak Apr 1, 2019
15dae71
Update `order-utils` package for new `Order` structure
dorothy-zbornak Apr 1, 2019
169efc1
Update `fill-scenarios`, `contract-wrappers`, `contract-artifacts`, `…
dorothy-zbornak Apr 1, 2019
f41ec75
Update `contracts/test-utils` to use new `Order` structure and domain…
dorothy-zbornak Apr 1, 2019
a4bb957
Update `coordinator`, `exchange-forwarder`, `exchange-libs`, `exchang…
dorothy-zbornak Apr 1, 2019
dc12278
Fix removing `domain` and `signature` fields from order
dorothy-zbornak Apr 1, 2019
ae7d951
Rename `orderWithoutExchangeAddress` -> `orderWithoutDomain` in `cont…
dorothy-zbornak Apr 1, 2019
1de8b36
Rename `orderWithoutExchangeAddress` -> `orderWithoutDomain` in `cont…
dorothy-zbornak Apr 1, 2019
04aa608
Ran prettier
dorothy-zbornak Apr 1, 2019
8bc25d1
Fix import order in `contracts/test-utils`
dorothy-zbornak Apr 1, 2019
968f1f9
Update changelogs.
dorothy-zbornak Apr 1, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions contracts/coordinator/CHANGELOG.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@
{
"note": "Make `assertValidTransactionOrdersApproval` internal",
"pr": 1729
},
{
"note": "Add chainId to domain separator",
"pr": 1742
},
{
"note": "Inherit Exchange domain constants from `exchange-libs` to reduce code duplication",
"pr": 1742
},
{
"note": "Update domain separator",
"pr": 1742
}
]
},
Expand Down
7 changes: 5 additions & 2 deletions contracts/coordinator/contracts/src/Coordinator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ contract Coordinator is
MixinCoordinatorApprovalVerifier,
MixinCoordinatorCore
{
constructor (address _exchange)
/// @param exchange Address of the 0x Exchange contract.
/// @param chainId Chain ID of the network this contract is deployed on.
constructor (address exchange, uint256 chainId)
public
LibConstants(_exchange)
LibConstants(exchange)
LibEIP712Domain(chainId)
{}
}
8 changes: 5 additions & 3 deletions contracts/coordinator/contracts/src/libs/LibConstants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ pragma solidity ^0.5.5;
import "../interfaces/ITransactions.sol";


// solhint-disable var-name-mixedcase
contract LibConstants {

// solhint-disable-next-line var-name-mixedcase
// The 0x Exchange contract.
ITransactions internal EXCHANGE;

constructor (address _exchange)
/// @param exchange Address of the 0x Exchange contract.
constructor (address exchange)
public
{
EXCHANGE = ITransactions(_exchange);
EXCHANGE = ITransactions(exchange);
}
}
87 changes: 21 additions & 66 deletions contracts/coordinator/contracts/src/libs/LibEIP712Domain.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,61 +18,46 @@

pragma solidity ^0.5.5;

import "@0x/contracts-exchange-libs/contracts/src/LibEIP712.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomainConstants.sol";
import "./LibConstants.sol";


// solhint-disable var-name-mixedcase
contract LibEIP712Domain is
LibConstants
LibConstants,
LibEIP712,
LibEIP712ExchangeDomainConstants
{

// EIP191 header for EIP712 prefix
string constant internal EIP191_HEADER = "\x19\x01";

// EIP712 Domain Name value for the Coordinator
string constant internal EIP712_COORDINATOR_DOMAIN_NAME = "0x Protocol Coordinator";

// EIP712 Domain Version value for the Coordinator
string constant internal EIP712_COORDINATOR_DOMAIN_VERSION = "1.0.0";

// EIP712 Domain Name value for the Exchange
string constant internal EIP712_EXCHANGE_DOMAIN_NAME = "0x Protocol";

// EIP712 Domain Version value for the Exchange
string constant internal EIP712_EXCHANGE_DOMAIN_VERSION = "2";

// Hash of the EIP712 Domain Separator Schema
bytes32 constant internal EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256(abi.encodePacked(
"EIP712Domain(",
"string name,",
"string version,",
"address verifyingContract",
")"
));
string constant internal EIP712_COORDINATOR_DOMAIN_VERSION = "2.0.0";

// Hash of the EIP712 Domain Separator data for the Coordinator
// solhint-disable-next-line var-name-mixedcase
bytes32 public EIP712_COORDINATOR_DOMAIN_HASH;

// Hash of the EIP712 Domain Separator data for the Exchange
// solhint-disable-next-line var-name-mixedcase
bytes32 public EIP712_EXCHANGE_DOMAIN_HASH;

constructor ()
/// @param chainId Chain ID of the network this contract is deployed on.
constructor (uint256 chainId)
public
{
EIP712_COORDINATOR_DOMAIN_HASH = keccak256(abi.encodePacked(
EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH,
keccak256(bytes(EIP712_COORDINATOR_DOMAIN_NAME)),
keccak256(bytes(EIP712_COORDINATOR_DOMAIN_VERSION)),
uint256(address(this))
));

EIP712_EXCHANGE_DOMAIN_HASH = keccak256(abi.encodePacked(
EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH,
keccak256(bytes(EIP712_EXCHANGE_DOMAIN_NAME)),
keccak256(bytes(EIP712_EXCHANGE_DOMAIN_VERSION)),
uint256(address(EXCHANGE))
));
EIP712_COORDINATOR_DOMAIN_HASH = hashEIP712Domain(
dorothy-zbornak marked this conversation as resolved.
Show resolved Hide resolved
EIP712_COORDINATOR_DOMAIN_NAME,
EIP712_COORDINATOR_DOMAIN_VERSION,
chainId,
address(this)
);
EIP712_EXCHANGE_DOMAIN_HASH = hashEIP712Domain(
EIP712_EXCHANGE_DOMAIN_NAME,
EIP712_EXCHANGE_DOMAIN_VERSION,
chainId,
address(EXCHANGE)
);
}

/// @dev Calculates EIP712 encoding for a hash struct in the EIP712 domain
Expand All @@ -98,34 +83,4 @@ contract LibEIP712Domain is
{
return hashEIP712Message(EIP712_EXCHANGE_DOMAIN_HASH, hashStruct);
}

/// @dev Calculates EIP712 encoding for a hash struct with a given domain hash.
/// @param eip712DomainHash Hash of the domain domain separator data.
/// @param hashStruct The EIP712 hash struct.
/// @return EIP712 hash applied to the Exchange EIP712 Domain.
function hashEIP712Message(bytes32 eip712DomainHash, bytes32 hashStruct)
internal
pure
returns (bytes32 result)
{
// Assembly for more efficient computing:
// keccak256(abi.encodePacked(
// EIP191_HEADER,
// EIP712_DOMAIN_HASH,
// hashStruct
// ));

assembly {
// Load free memory pointer
let memPtr := mload(64)

mstore(memPtr, 0x1901000000000000000000000000000000000000000000000000000000000000) // EIP191 header
mstore(add(memPtr, 2), eip712DomainHash) // EIP712 domain hash
mstore(add(memPtr, 34), hashStruct) // Hash of struct

// Compute hash
result := keccak256(memPtr, 66)
}
return result;
}
}
2 changes: 1 addition & 1 deletion contracts/coordinator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
"@0x/base-contract": "^5.0.4",
"@0x/contracts-asset-proxy": "^2.1.0",
"@0x/contracts-erc20": "^2.1.0",
"@0x/contracts-exchange": "1.0.2",
"@0x/contracts-exchange": "^2.1.0",
"@0x/contracts-exchange-libs": "^2.1.0",
"@0x/contracts-utils": "^3.1.0",
"@0x/order-utils": "^7.1.1",
Expand Down
15 changes: 11 additions & 4 deletions contracts/coordinator/test/coordinator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -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;
Expand All @@ -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));

Expand All @@ -75,6 +77,7 @@ describe('Coordinator tests', () => {
provider,
txDefaults,
assetDataUtils.encodeERC20AssetData(zrxToken.address),
new BigNumber(chainId),
);

await web3Wrapper.awaitTransactionSuccessAsync(
Expand All @@ -92,24 +95,28 @@ describe('Coordinator tests', () => {
provider,
txDefaults,
exchange.address,
new BigNumber(chainId),
);

// Configure order defaults
const defaultOrderParams = {
...devConstants.STATIC_ORDER_PARAMS,
exchangeAddress: exchange.address,
senderAddress: coordinatorContract.address,
makerAddress,
feeRecipientAddress,
makerAssetData: assetDataUtils.encodeERC20AssetData(erc20TokenA.address),
takerAssetData: assetDataUtils.encodeERC20AssetData(erc20TokenB.address),
domain: {
verifyingContractAddress: exchange.address,
chainId,
},
};
const makerPrivateKey = devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
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);
makerTransactionFactory = new TransactionFactory(makerPrivateKey, exchange.address, chainId);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker, but this should probably be changes later to just take a domain parameter.

takerTransactionFactory = new TransactionFactory(takerPrivateKey, exchange.address, chainId);
approvalFactory = new ApprovalFactory(feeRecipientPrivateKey, coordinatorContract.address);
});
beforeEach(async () => {
Expand Down
15 changes: 12 additions & 3 deletions contracts/coordinator/test/libs.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -12,6 +12,7 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);

describe('Libs tests', () => {
let coordinatorContract: CoordinatorContract;
let chainId: number;
const exchangeAddress = addressUtils.generatePseudoRandomAddress();

before(async () => {
Expand All @@ -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 () => {
Expand All @@ -38,10 +41,13 @@ describe('Libs tests', () => {
describe('getTransactionHash', () => {
it('should return the correct transaction hash', async () => {
const tx = {
verifyingContractAddress: exchangeAddress,
salt: new BigNumber(0),
signerAddress: constants.NULL_ADDRESS,
data: '0x1234',
domain: {
verifyingContractAddress: exchangeAddress,
chainId,
},
};
const expectedTxHash = transactionHashUtils.getTransactionHashHex(tx);
const txHash = await coordinatorContract.getTransactionHash.callAsync(tx);
Expand All @@ -52,11 +58,14 @@ describe('Libs tests', () => {
describe('getApprovalHash', () => {
it('should return the correct approval hash', async () => {
const signedTx = {
verifyingContractAddress: exchangeAddress,
salt: new BigNumber(0),
signerAddress: constants.NULL_ADDRESS,
data: '0x1234',
signature: '0x5678',
domain: {
verifyingContractAddress: exchangeAddress,
chainId,
},
};
const approvalExpirationTimeSeconds = new BigNumber(0);
const txOrigin = constants.NULL_ADDRESS;
Expand Down
Loading