Add expirationTimeSeconds to ZeroExTransaction schema throughout codebase

This commit is contained in:
Amir Bandeali 2019-05-23 18:18:53 -05:00
parent 238877b627
commit 6ddaa6f52a
8 changed files with 52 additions and 13 deletions

View File

@ -29,14 +29,16 @@ contract LibZeroExTransaction is
// keccak256(abi.encodePacked( // keccak256(abi.encodePacked(
// "ZeroExTransaction(", // "ZeroExTransaction(",
// "uint256 salt,", // "uint256 salt,",
// "uint256 expirationTimeSeconds,"
// "address signerAddress,", // "address signerAddress,",
// "bytes data", // "bytes data",
// ")" // ")"
// )); // ));
bytes32 constant internal EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH = 0x213c6f636f3ea94e701c0adf9b2624aa45a6c694f9a292c094f9a81c24b5df4c; bytes32 constant public EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH = 0x6b4c70d217b44d0ff0d3bf7aeb18eb8604c5cd06f615a4b497aeefa4f01d2775;
struct ZeroExTransaction { struct ZeroExTransaction {
uint256 salt; // Arbitrary number to ensure uniqueness of transaction hash. uint256 salt; // Arbitrary number to ensure uniqueness of transaction hash.
uint256 expirationTimeSeconds; // Timestamp in seconds at which transaction expires.
address signerAddress; // Address of transaction signer. address signerAddress; // Address of transaction signer.
bytes data; // AbiV2 encoded calldata. bytes data; // AbiV2 encoded calldata.
} }
@ -65,12 +67,14 @@ contract LibZeroExTransaction is
bytes32 schemaHash = EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH; bytes32 schemaHash = EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH;
bytes memory data = transaction.data; bytes memory data = transaction.data;
uint256 salt = transaction.salt; uint256 salt = transaction.salt;
uint256 expirationTimeSeconds = transaction.expirationTimeSeconds;
address signerAddress = transaction.signerAddress; address signerAddress = transaction.signerAddress;
// Assembly for more efficiently computing: // Assembly for more efficiently computing:
// keccak256(abi.encodePacked( // keccak256(abi.encodePacked(
// EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH, // EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH,
// transaction.salt, // transaction.salt,
// transaction.expirationTimeSeconds,
// uint256(transaction.signerAddress), // uint256(transaction.signerAddress),
// keccak256(transaction.data) // keccak256(transaction.data)
// )); // ));
@ -84,11 +88,12 @@ contract LibZeroExTransaction is
mstore(memPtr, schemaHash) // hash of schema mstore(memPtr, schemaHash) // hash of schema
mstore(add(memPtr, 32), salt) // salt mstore(add(memPtr, 32), salt) // salt
mstore(add(memPtr, 64), and(signerAddress, 0xffffffffffffffffffffffffffffffffffffffff)) // signerAddress mstore(add(memPtr, 64), expirationTimeSeconds) // expirationTimeSeconds
mstore(add(memPtr, 96), dataHash) // hash of data mstore(add(memPtr, 96), and(signerAddress, 0xffffffffffffffffffffffffffffffffffffffff)) // signerAddress
mstore(add(memPtr, 128), dataHash) // hash of data
// Compute hash // Compute hash
result := keccak256(memPtr, 128) result := keccak256(memPtr, 160)
} }
return result; return result;
} }

View File

@ -22,6 +22,7 @@ pragma experimental ABIEncoderV2;
import "../src/LibEIP712ExchangeDomain.sol"; import "../src/LibEIP712ExchangeDomain.sol";
import "../src/LibMath.sol"; import "../src/LibMath.sol";
import "../src/LibOrder.sol"; import "../src/LibOrder.sol";
import "../src/LibZeroExTransaction.sol";
import "../src/LibFillResults.sol"; import "../src/LibFillResults.sol";
@ -30,6 +31,7 @@ contract TestLibs is
LibEIP712ExchangeDomain, LibEIP712ExchangeDomain,
LibMath, LibMath,
LibOrder, LibOrder,
LibZeroExTransaction,
LibFillResults LibFillResults
{ {
constructor (uint256 chainId) constructor (uint256 chainId)

View File

@ -8,14 +8,14 @@ import {
web3Wrapper, web3Wrapper,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; import { assetDataUtils, orderHashUtils, transactionHashUtils } from '@0x/order-utils';
import { constants as orderConstants } from '@0x/order-utils/lib/src/constants'; import { constants as orderConstants } from '@0x/order-utils/lib/src/constants';
import { SignedOrder } from '@0x/types'; import { SignedOrder } from '@0x/types';
import { BigNumber, providerUtils } 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';
import { TestLibsContract } from '../generated-wrappers/test_libs'; import { TestLibsContract } from '../src';
import { artifacts } from '../src/artifacts'; import { artifacts } from '../src/artifacts';
import { stringifySchema } from './utils'; import { stringifySchema } from './utils';
@ -56,7 +56,6 @@ describe('Exchange libs', () => {
txDefaults, txDefaults,
new BigNumber(alternateChainId), new BigNumber(alternateChainId),
); );
const defaultOrderParams = { const defaultOrderParams = {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
makerAddress, makerAddress,
@ -154,6 +153,33 @@ describe('Exchange libs', () => {
}); });
}); });
describe('LibZeroExTransaction', () => {
describe('EIP712ZeroExTransactionSchemaHash', () => {
it('should return the correct schema hash', async () => {
const schemaHash = await libs.EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH.callAsync();
const schemaString =
'ZeroExTransaction(uint256 salt,uint256 expirationTimeSeconds,address signerAddress,bytes data)';
const expectedSchemaHash = ethUtil.addHexPrefix(ethUtil.bufferToHex(ethUtil.sha3(schemaString)));
expect(schemaHash).to.equal(expectedSchemaHash);
});
it('should return the correct transactionHash', async () => {
const transaction = {
salt: new BigNumber(0),
expirationTimeSeconds: new BigNumber(0),
signerAddress: constants.NULL_ADDRESS,
data: constants.NULL_BYTES,
domain: {
verifyingContractAddress: libs.address,
chainId,
},
};
const transactionHash = await libs.getTransactionHash.callAsync(transaction);
const expectedTransactionHash = transactionHashUtils.getTransactionHashHex(transaction);
expect(transactionHash).to.equal(expectedTransactionHash);
});
});
});
describe('LibEIP712', () => { describe('LibEIP712', () => {
it('should return the correct domain separator schema hash', async () => { it('should return the correct domain separator schema hash', async () => {
const schema = stringifySchema(orderConstants.DEFAULT_DOMAIN_SCHEMA); const schema = stringifySchema(orderConstants.DEFAULT_DOMAIN_SCHEMA);

View File

@ -4,8 +4,9 @@
"data": { "$ref": "/hexSchema" }, "data": { "$ref": "/hexSchema" },
"signerAddress": { "$ref": "/addressSchema" }, "signerAddress": { "$ref": "/addressSchema" },
"salt": { "$ref": "/wholeNumberSchema" }, "salt": { "$ref": "/wholeNumberSchema" },
"expirationTimeSeconds": { "$ref": "/wholeNumberSchema" },
"domain": { "$ref": "/eip712DomainSchema" } "domain": { "$ref": "/eip712DomainSchema" }
}, },
"required": ["data", "salt", "signerAddress", "domain"], "required": ["data", "salt", "expirationTimeSeconds", "signerAddress", "domain"],
"type": "object" "type": "object"
} }

View File

@ -133,6 +133,7 @@ export const constants = {
name: 'ZeroExTransaction', name: 'ZeroExTransaction',
parameters: [ parameters: [
{ name: 'salt', type: 'uint256' }, { name: 'salt', type: 'uint256' },
{ name: 'expirationTimeSeconds', type: 'uint256' },
{ name: 'signerAddress', type: 'address' }, { name: 'signerAddress', type: 'address' },
{ name: 'data', type: 'bytes' }, { name: 'data', type: 'bytes' },
], ],

View File

@ -57,7 +57,8 @@ describe('EIP712 Utils', () => {
describe('createZeroExTransactionTypedData', () => { describe('createZeroExTransactionTypedData', () => {
it('adds in the EIP712DomainSeparator', () => { it('adds in the EIP712DomainSeparator', () => {
const typedData = eip712Utils.createZeroExTransactionTypedData({ const typedData = eip712Utils.createZeroExTransactionTypedData({
salt: new BigNumber('0'), salt: new BigNumber(0),
expirationTimeSeconds: new BigNumber(0),
data: constants.NULL_BYTES, data: constants.NULL_BYTES,
signerAddress: constants.NULL_ADDRESS, signerAddress: constants.NULL_ADDRESS,
domain: { domain: {

View File

@ -14,12 +14,13 @@ const expect = chai.expect;
describe('0x transaction hashing', () => { describe('0x transaction hashing', () => {
describe('#getTransactionHashHex', () => { describe('#getTransactionHashHex', () => {
const expectedTransactionHash = '0x834125acbd69d6e2e706df216865728e9b63bfd7c8bcecb5987d9d02ea62ecd5'; const expectedTransactionHash = '0x9779e4ca195f8c9c6f137f495599e9a1944806310b64748479bfa6c6b1ae7eb4';
const fakeVerifyingContractAddress = '0x5e72914535f202659083db3a02c984188fa26e9f'; const fakeVerifyingContractAddress = '0x5e72914535f202659083db3a02c984188fa26e9f';
const fakeChainId = 1337; const fakeChainId = 1337;
const transaction: ZeroExTransaction = { const transaction: ZeroExTransaction = {
signerAddress: constants.NULL_ADDRESS, signerAddress: constants.NULL_ADDRESS,
salt: new BigNumber(0), salt: new BigNumber(0),
expirationTimeSeconds: new BigNumber(0),
data: constants.NULL_BYTES, data: constants.NULL_BYTES,
domain: { domain: {
verifyingContractAddress: fakeVerifyingContractAddress, verifyingContractAddress: fakeVerifyingContractAddress,
@ -38,6 +39,7 @@ describe('0x transaction hashing', () => {
const transactionHash = transactionHashUtils.getTransactionHashHex({ const transactionHash = transactionHashUtils.getTransactionHashHex({
...transaction, ...transaction,
salt: '0', salt: '0',
expirationTimeSeconds: '0',
} as any); } as any);
expect(transactionHash).to.be.equal(expectedTransactionHash); expect(transactionHash).to.be.equal(expectedTransactionHash);
}); });

View File

@ -55,6 +55,7 @@ export enum MarketOperation {
*/ */
export interface ZeroExTransaction { export interface ZeroExTransaction {
salt: BigNumber; salt: BigNumber;
expirationTimeSeconds: BigNumber;
signerAddress: string; signerAddress: string;
data: string; data: string;
domain: EIP712DomainWithDefaultSchema; domain: EIP712DomainWithDefaultSchema;