From 4670cc1a5f04d61045a82b4a3bbcf56e009afd56 Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Tue, 29 May 2018 17:11:33 -0700 Subject: Add missing EIP191 prefix for EIP712 --- .../protocol/Exchange/MixinTransactions.sol | 35 +++++++++--- .../current/protocol/Exchange/libs/LibEIP712.sol | 55 +++++++++++++++++++ .../current/protocol/Exchange/libs/LibOrder.sol | 61 ++++++++++----------- .../contracts/current/test/TestLibs/TestLibs.sol | 4 +- packages/contracts/src/utils/eip712_utils.ts | 63 ++++++++++++++++++++++ packages/contracts/src/utils/order_factory.ts | 6 +-- packages/contracts/src/utils/order_utils.ts | 56 ++++++++++++++++++- .../contracts/src/utils/transaction_factory.ts | 30 ++++++++++- packages/contracts/src/utils/types.ts | 10 ++++ 9 files changed, 272 insertions(+), 48 deletions(-) create mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol create mode 100644 packages/contracts/src/utils/eip712_utils.ts (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol index 30b0102fd..e3f6b2b2b 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol @@ -20,8 +20,11 @@ pragma solidity ^0.4.24; import "./libs/LibExchangeErrors.sol"; import "./mixins/MSignatureValidator.sol"; import "./mixins/MTransactions.sol"; +import "./libs/LibExchangeErrors.sol"; +import "./libs/LibEIP712.sol"; contract MixinTransactions is + LibEIP712, LibExchangeErrors, MSignatureValidator, MTransactions @@ -34,6 +37,30 @@ contract MixinTransactions is // Address of current transaction signer address public currentContextAddress; + bytes32 constant EXECUTE_TRANSACTION_SCHEMA_HASH = keccak256( + "ExecuteTransaction(", + "uint256 salt,", + "address signer,", + "bytes data", + ")" + ); + + function getExecuteTransactionHash(uint256 salt, address signer, bytes data) + internal + view + returns (bytes32 executeTransactionHash) + { + executeTransactionHash = createEIP712Message( + keccak256( + EXECUTE_TRANSACTION_SCHEMA_HASH, + salt, + bytes32(signer), + keccak256(data) + ) + ); + return executeTransactionHash; + } + /// @dev Executes an exchange method call in the context of signer. /// @param salt Arbitrary number to ensure uniqueness of transaction hash. /// @param signer Address of transaction signer. @@ -53,13 +80,7 @@ contract MixinTransactions is REENTRANCY_ILLEGAL ); - // Calculate transaction hash - bytes32 transactionHash = keccak256(abi.encodePacked( - address(this), - signer, - salt, - data - )); + bytes32 transactionHash = getExecuteTransactionHash(salt, signer, data); // Validate transaction has not been executed require( diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol new file mode 100644 index 000000000..d28ef876f --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol @@ -0,0 +1,55 @@ +/* + + Copyright 2018 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.4.24; + +contract LibEIP712 { + string public constant EIP191_HEADER = "\x19\x01"; + bytes32 public constant EIP712_DOMAIN_SEPARATOR_NAME_HASH = keccak256("0x Protocol"); + + bytes32 public constant EIP712_DOMAIN_SEPARATOR_VERSION_HASH = keccak256("1"); + + bytes32 public constant EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256( + "DomainSeparator(", + "string name,", + "string version,", + "address contract", + ")" + ); + + function createEIP712Message(bytes32 hashStruct) + internal + view + returns (bytes32 message) + { + // TODO: EIP712 is not finalized yet + // Source: https://github.com/ethereum/EIPs/pull/712 + // TODO: Cache the Domain Separator + message = keccak256( + EIP191_HEADER, + keccak256( + EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH, + EIP712_DOMAIN_SEPARATOR_NAME_HASH, + EIP712_DOMAIN_SEPARATOR_VERSION_HASH, + bytes32(address(this)) + ), + hashStruct + ); + return message; + } +} \ No newline at end of file diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol index 05ea27ffc..6888918e2 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol @@ -18,27 +18,28 @@ pragma solidity ^0.4.24; -contract LibOrder { +import "./LibEIP712.sol"; - bytes32 constant DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256(abi.encodePacked( - "DomainSeparator(address contract)" - )); +contract LibOrder is + LibEIP712 +{ - bytes32 constant ORDER_SCHEMA_HASH = keccak256(abi.encodePacked( - "Order(", - "address makerAddress,", - "address takerAddress,", - "address feeRecipientAddress,", - "address senderAddress,", - "uint256 makerAssetAmount,", - "uint256 takerAssetAmount,", - "uint256 makerFee,", - "uint256 takerFee,", - "uint256 expirationTimeSeconds,", - "uint256 salt,", - "bytes makerAssetData,", - "bytes takerAssetData,", - ")" + bytes32 constant EIP712_ORDER_SCHEMA_HASH = keccak256( + abi.encodePacked( + "Order(", + "address makerAddress,", + "address takerAddress,", + "address feeRecipientAddress,", + "address senderAddress,", + "uint256 makerAssetAmount,", + "uint256 takerAssetAmount,", + "uint256 makerFee,", + "uint256 takerFee,", + "uint256 expirationTimeSeconds,", + "uint256 salt,", + "bytes makerAssetData,", + "bytes takerAssetData", + ")" )); // A valid order remains fillable until it is expired, fully filled, or cancelled. @@ -85,17 +86,14 @@ contract LibOrder { view returns (bytes32 orderHash) { - // TODO: EIP712 is not finalized yet - // Source: https://github.com/ethereum/EIPs/pull/712 - orderHash = keccak256(abi.encodePacked( - DOMAIN_SEPARATOR_SCHEMA_HASH, - keccak256(abi.encodePacked(address(this))), - ORDER_SCHEMA_HASH, - keccak256(abi.encodePacked( - order.makerAddress, - order.takerAddress, - order.feeRecipientAddress, - order.senderAddress, + orderHash = createEIP712Message( + keccak256( + abi.encodePacked( + EIP712_ORDER_SCHEMA_HASH, + bytes32(order.makerAddress), + bytes32(order.takerAddress), + bytes32(order.feeRecipientAddress), + bytes32(order.senderAddress), order.makerAssetAmount, order.takerAssetAmount, order.makerFee, @@ -104,8 +102,7 @@ contract LibOrder { order.salt, keccak256(abi.encodePacked(order.makerAssetData)), keccak256(abi.encodePacked(order.takerAssetData)) - )) - )); + ))); return orderHash; } } diff --git a/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol b/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol index 47ce0dcf3..010080703 100644 --- a/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol +++ b/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol @@ -74,7 +74,7 @@ contract TestLibs is pure returns (bytes32) { - return ORDER_SCHEMA_HASH; + return EIP712_ORDER_SCHEMA_HASH; } function getDomainSeparatorSchemaHash() @@ -82,7 +82,7 @@ contract TestLibs is pure returns (bytes32) { - return DOMAIN_SEPARATOR_SCHEMA_HASH; + return EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH; } function publicAddFillResults(FillResults memory totalFillResults, FillResults memory singleFillResults) diff --git a/packages/contracts/src/utils/eip712_utils.ts b/packages/contracts/src/utils/eip712_utils.ts new file mode 100644 index 000000000..07b45c8af --- /dev/null +++ b/packages/contracts/src/utils/eip712_utils.ts @@ -0,0 +1,63 @@ +import { BigNumber } from '@0xproject/utils'; +import ethUtil = require('ethereumjs-util'); +import * as _ from 'lodash'; + +import { crypto } from './crypto'; +import { EIP712Schema } from './types'; + +const EIP191_PREFIX = '\x19\x01'; +const EIP712_DOMAIN_NAME = '0x Protocol'; +const EIP712_DOMAIN_VERSION = '1'; + +const EIP712_DOMAIN_SCHEMA: EIP712Schema = { + name: 'DomainSeparator', + parameters: [ + { name: 'name', type: 'string' }, + { name: 'version', type: 'string' }, + { name: 'contract', type: 'address' }, + ], +}; + +export const EIP712Utils = { + compileSchema(schema: EIP712Schema): Buffer { + const namedTypes = _.map(schema.parameters, parameter => `${parameter.type} ${parameter.name}`); + const namedTypesJoined = namedTypes.join(','); + const eip712Schema = `${schema.name}(${namedTypesJoined})`; + const eip712SchemaHashBuffer = crypto.solSHA3([eip712Schema]); + return eip712SchemaHashBuffer; + }, + createEIP712Message(hashStruct: string, contractAddress: string): Buffer { + const domainSeparatorHashHex = EIP712Utils.getDomainSeparatorHashHex(contractAddress); + const messageBuff = crypto.solSHA3([ + EIP191_PREFIX, + new BigNumber(domainSeparatorHashHex), + new BigNumber(hashStruct), + ]); + return messageBuff; + }, + getDomainSeparatorSchemaBuffer(): Buffer { + return EIP712Utils.compileSchema(EIP712_DOMAIN_SCHEMA); + }, + getDomainSeparatorHashHex(exchangeAddress: string): string { + const domainSeparatorSchemaBuffer = EIP712Utils.getDomainSeparatorSchemaBuffer(); + const nameHash = crypto.solSHA3([EIP712_DOMAIN_NAME]); + const versionHash = crypto.solSHA3([EIP712_DOMAIN_VERSION]); + const domainSeparatorHashBuff = crypto.solSHA3([ + domainSeparatorSchemaBuffer, + nameHash, + versionHash, + EIP712Utils.pad32Address(exchangeAddress), + ]); + const domainSeparatorHashHex = `0x${domainSeparatorHashBuff.toString('hex')}`; + return domainSeparatorHashHex; + }, + pad32Address(address: string): Buffer { + const addressBuffer = ethUtil.toBuffer(address); + const addressPadded = EIP712Utils.pad32Buffer(addressBuffer); + return addressPadded; + }, + pad32Buffer(buffer: Buffer): Buffer { + const bufferPadded = ethUtil.setLengthLeft(buffer, 32); + return bufferPadded; + }, +}; diff --git a/packages/contracts/src/utils/order_factory.ts b/packages/contracts/src/utils/order_factory.ts index af411c01f..bfe5013e8 100644 --- a/packages/contracts/src/utils/order_factory.ts +++ b/packages/contracts/src/utils/order_factory.ts @@ -1,5 +1,5 @@ import { generatePseudoRandomSalt, orderHashUtils } from '@0xproject/order-utils'; -import { Order, SignatureType, SignedOrder } from '@0xproject/types'; +import { Order, SignatureType, SignedOrder, UnsignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; @@ -26,8 +26,8 @@ export class OrderFactory { takerAddress: constants.NULL_ADDRESS, ...this._defaultOrderParams, ...customOrderParams, - } as any) as Order; - const orderHashBuff = orderHashUtils.getOrderHashBuff(order); + } as any) as UnsignedOrder; + const orderHashBuff = orderHashUtils.getOrderHashBuffer(order); const signature = signingUtils.signMessage(orderHashBuff, this._privateKey, signatureType); const signedOrder = { ...order, diff --git a/packages/contracts/src/utils/order_utils.ts b/packages/contracts/src/utils/order_utils.ts index 0d0329aa1..316350ffb 100644 --- a/packages/contracts/src/utils/order_utils.ts +++ b/packages/contracts/src/utils/order_utils.ts @@ -1,8 +1,29 @@ -import { Order, OrderWithoutExchangeAddress, SignedOrder } from '@0xproject/types'; +import { Order, OrderWithoutExchangeAddress, SignedOrder, UnsignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import ethUtil = require('ethereumjs-util'); +import * as _ from 'lodash'; -import { CancelOrder, MatchOrder } from './types'; +import { crypto } from './crypto'; +import { EIP712Utils } from './eip712_utils'; +import { CancelOrder, EIP712Schema, MatchOrder } from './types'; + +const EIP712_ORDER_SCHEMA: EIP712Schema = { + name: 'Order', + parameters: [ + { name: 'makerAddress', type: 'address' }, + { name: 'takerAddress', type: 'address' }, + { name: 'feeRecipientAddress', type: 'address' }, + { name: 'senderAddress', type: 'address' }, + { name: 'makerAssetAmount', type: 'uint256' }, + { name: 'takerAssetAmount', type: 'uint256' }, + { name: 'makerFee', type: 'uint256' }, + { name: 'takerFee', type: 'uint256' }, + { name: 'expirationTimeSeconds', type: 'uint256' }, + { name: 'salt', type: 'uint256' }, + { name: 'makerAssetData', type: 'bytes' }, + { name: 'takerAssetData', type: 'bytes' }, + ], +}; export const orderUtils = { createFill: (signedOrder: SignedOrder, takerAssetFillAmount?: BigNumber) => { @@ -37,6 +58,37 @@ export const orderUtils = { }; return orderStruct; }, + getOrderSchemaBuffer(): Buffer { + return EIP712Utils.compileSchema(EIP712_ORDER_SCHEMA); + }, + getOrderHashBuffer(order: SignedOrder | UnsignedOrder): Buffer { + const makerAssetDataHash = crypto.solSHA3([ethUtil.toBuffer(order.makerAssetData)]); + const takerAssetDataHash = crypto.solSHA3([ethUtil.toBuffer(order.takerAssetData)]); + + const orderParamsHashBuff = crypto.solSHA3([ + orderUtils.getOrderSchemaBuffer(), + EIP712Utils.pad32Address(order.makerAddress), + EIP712Utils.pad32Address(order.takerAddress), + EIP712Utils.pad32Address(order.feeRecipientAddress), + EIP712Utils.pad32Address(order.senderAddress), + order.makerAssetAmount, + order.takerAssetAmount, + order.makerFee, + order.takerFee, + order.expirationTimeSeconds, + order.salt, + makerAssetDataHash, + takerAssetDataHash, + ]); + const orderParamsHashHex = `0x${orderParamsHashBuff.toString('hex')}`; + const orderHashBuff = EIP712Utils.createEIP712Message(orderParamsHashHex, order.exchangeAddress); + return orderHashBuff; + }, + getOrderHashHex(order: SignedOrder | UnsignedOrder): string { + const orderHashBuff = orderUtils.getOrderHashBuffer(order); + const orderHashHex = `0x${orderHashBuff.toString('hex')}`; + return orderHashHex; + }, createMatchOrders(signedOrderLeft: SignedOrder, signedOrderRight: SignedOrder): MatchOrder { const fill = { left: orderUtils.getOrderWithoutExchangeAddress(signedOrderLeft), diff --git a/packages/contracts/src/utils/transaction_factory.ts b/packages/contracts/src/utils/transaction_factory.ts index 434611908..1c1029d62 100644 --- a/packages/contracts/src/utils/transaction_factory.ts +++ b/packages/contracts/src/utils/transaction_factory.ts @@ -2,9 +2,22 @@ import { crypto, generatePseudoRandomSalt } from '@0xproject/order-utils'; import { SignatureType } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as ethUtil from 'ethereumjs-util'; +import * as _ from 'lodash'; +import { crypto } from './crypto'; +import { EIP712Utils } from './eip712_utils'; +import { orderUtils } from './order_utils'; import { signingUtils } from './signing_utils'; -import { SignedTransaction } from './types'; +import { EIP712Schema, SignatureType, SignedTransaction } from './types'; + +const EIP712_EXECUTE_TRANSACTION_SCHEMA: EIP712Schema = { + name: 'ExecuteTransaction', + parameters: [ + { name: 'salt', type: 'uint256' }, + { name: 'signer', type: 'address' }, + { name: 'data', type: 'bytes' }, + ], +}; export class TransactionFactory { private _signerBuff: Buffer; @@ -16,8 +29,21 @@ export class TransactionFactory { this._signerBuff = ethUtil.privateToAddress(this._privateKey); } public newSignedTransaction(data: string, signatureType: SignatureType = SignatureType.EthSign): SignedTransaction { + const executeTransactionSchemaHashBuff = EIP712Utils.compileSchema(EIP712_EXECUTE_TRANSACTION_SCHEMA); + const salt = generatePseudoRandomSalt(); - const txHash = crypto.solSHA3([this._exchangeAddress, this._signerBuff, salt, ethUtil.toBuffer(data)]); + const dataHash = crypto.solSHA3([ethUtil.toBuffer(data)]); + + const executeTransactionDataHash = crypto.solSHA3([ + executeTransactionSchemaHashBuff, + salt, + EIP712Utils.pad32Buffer(this._signerBuff), + dataHash, + ]); + + const executeTransactionMessageHex = `0x${executeTransactionDataHash.toString('hex')}`; + + const txHash = EIP712Utils.createEIP712Message(executeTransactionMessageHex, this._exchangeAddress); const signature = signingUtils.signMessage(txHash, this._privateKey, signatureType); const signedTx = { exchangeAddress: this._exchangeAddress, diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts index 360e1fdbc..5b7f1bcee 100644 --- a/packages/contracts/src/utils/types.ts +++ b/packages/contracts/src/utils/types.ts @@ -147,3 +147,13 @@ export interface MatchOrder { leftSignature: string; rightSignature: string; } + +export interface EIP712Parameter { + name: string; + type: string; +} + +export interface EIP712Schema { + name: string; + parameters: EIP712Parameter[]; +} -- cgit From a59e9f024e76122c76600d938b565ea47938b287 Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Mon, 4 Jun 2018 18:40:07 -0700 Subject: Update Order utils to use eip712 --- .../current/protocol/Exchange/libs/LibEIP712.sol | 35 +++++++----- .../current/protocol/Exchange/libs/LibOrder.sol | 30 ++++++----- packages/contracts/src/utils/eip712_utils.ts | 63 ---------------------- packages/contracts/src/utils/order_factory.ts | 4 +- packages/contracts/src/utils/order_utils.ts | 56 +------------------ .../contracts/src/utils/transaction_factory.ts | 16 ++---- packages/contracts/src/utils/types.ts | 10 ---- 7 files changed, 44 insertions(+), 170 deletions(-) delete mode 100644 packages/contracts/src/utils/eip712_utils.ts (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol index d28ef876f..7704e3db4 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol @@ -20,16 +20,19 @@ pragma solidity ^0.4.24; contract LibEIP712 { string public constant EIP191_HEADER = "\x19\x01"; + bytes32 public constant EIP712_DOMAIN_SEPARATOR_NAME_HASH = keccak256("0x Protocol"); - bytes32 public constant EIP712_DOMAIN_SEPARATOR_VERSION_HASH = keccak256("1"); + bytes32 public constant EIP712_DOMAIN_SEPARATOR_VERSION_HASH = keccak256("2"); bytes32 public constant EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256( - "DomainSeparator(", - "string name,", - "string version,", - "address contract", - ")" + abi.encodePacked( + "DomainSeparator(", + "string name,", + "string version,", + "address contract", + ")" + ) ); function createEIP712Message(bytes32 hashStruct) @@ -41,14 +44,18 @@ contract LibEIP712 { // Source: https://github.com/ethereum/EIPs/pull/712 // TODO: Cache the Domain Separator message = keccak256( - EIP191_HEADER, - keccak256( - EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH, - EIP712_DOMAIN_SEPARATOR_NAME_HASH, - EIP712_DOMAIN_SEPARATOR_VERSION_HASH, - bytes32(address(this)) - ), - hashStruct + abi.encodePacked( + EIP191_HEADER, + keccak256( + abi.encodePacked( + EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH, + EIP712_DOMAIN_SEPARATOR_NAME_HASH, + EIP712_DOMAIN_SEPARATOR_VERSION_HASH, + bytes32(address(this)) + ) + ), + hashStruct + ) ); return message; } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol index 6888918e2..ed532fd59 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol @@ -89,20 +89,22 @@ contract LibOrder is orderHash = createEIP712Message( keccak256( abi.encodePacked( - EIP712_ORDER_SCHEMA_HASH, - bytes32(order.makerAddress), - bytes32(order.takerAddress), - bytes32(order.feeRecipientAddress), - bytes32(order.senderAddress), - order.makerAssetAmount, - order.takerAssetAmount, - order.makerFee, - order.takerFee, - order.expirationTimeSeconds, - order.salt, - keccak256(abi.encodePacked(order.makerAssetData)), - keccak256(abi.encodePacked(order.takerAssetData)) - ))); + EIP712_ORDER_SCHEMA_HASH, + bytes32(order.makerAddress), + bytes32(order.takerAddress), + bytes32(order.feeRecipientAddress), + bytes32(order.senderAddress), + order.makerAssetAmount, + order.takerAssetAmount, + order.makerFee, + order.takerFee, + order.expirationTimeSeconds, + order.salt, + keccak256(abi.encodePacked(order.makerAssetData)), + keccak256(abi.encodePacked(order.takerAssetData)) + ) + ) + ); return orderHash; } } diff --git a/packages/contracts/src/utils/eip712_utils.ts b/packages/contracts/src/utils/eip712_utils.ts deleted file mode 100644 index 07b45c8af..000000000 --- a/packages/contracts/src/utils/eip712_utils.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { BigNumber } from '@0xproject/utils'; -import ethUtil = require('ethereumjs-util'); -import * as _ from 'lodash'; - -import { crypto } from './crypto'; -import { EIP712Schema } from './types'; - -const EIP191_PREFIX = '\x19\x01'; -const EIP712_DOMAIN_NAME = '0x Protocol'; -const EIP712_DOMAIN_VERSION = '1'; - -const EIP712_DOMAIN_SCHEMA: EIP712Schema = { - name: 'DomainSeparator', - parameters: [ - { name: 'name', type: 'string' }, - { name: 'version', type: 'string' }, - { name: 'contract', type: 'address' }, - ], -}; - -export const EIP712Utils = { - compileSchema(schema: EIP712Schema): Buffer { - const namedTypes = _.map(schema.parameters, parameter => `${parameter.type} ${parameter.name}`); - const namedTypesJoined = namedTypes.join(','); - const eip712Schema = `${schema.name}(${namedTypesJoined})`; - const eip712SchemaHashBuffer = crypto.solSHA3([eip712Schema]); - return eip712SchemaHashBuffer; - }, - createEIP712Message(hashStruct: string, contractAddress: string): Buffer { - const domainSeparatorHashHex = EIP712Utils.getDomainSeparatorHashHex(contractAddress); - const messageBuff = crypto.solSHA3([ - EIP191_PREFIX, - new BigNumber(domainSeparatorHashHex), - new BigNumber(hashStruct), - ]); - return messageBuff; - }, - getDomainSeparatorSchemaBuffer(): Buffer { - return EIP712Utils.compileSchema(EIP712_DOMAIN_SCHEMA); - }, - getDomainSeparatorHashHex(exchangeAddress: string): string { - const domainSeparatorSchemaBuffer = EIP712Utils.getDomainSeparatorSchemaBuffer(); - const nameHash = crypto.solSHA3([EIP712_DOMAIN_NAME]); - const versionHash = crypto.solSHA3([EIP712_DOMAIN_VERSION]); - const domainSeparatorHashBuff = crypto.solSHA3([ - domainSeparatorSchemaBuffer, - nameHash, - versionHash, - EIP712Utils.pad32Address(exchangeAddress), - ]); - const domainSeparatorHashHex = `0x${domainSeparatorHashBuff.toString('hex')}`; - return domainSeparatorHashHex; - }, - pad32Address(address: string): Buffer { - const addressBuffer = ethUtil.toBuffer(address); - const addressPadded = EIP712Utils.pad32Buffer(addressBuffer); - return addressPadded; - }, - pad32Buffer(buffer: Buffer): Buffer { - const bufferPadded = ethUtil.setLengthLeft(buffer, 32); - return bufferPadded; - }, -}; diff --git a/packages/contracts/src/utils/order_factory.ts b/packages/contracts/src/utils/order_factory.ts index bfe5013e8..dd02e1f5c 100644 --- a/packages/contracts/src/utils/order_factory.ts +++ b/packages/contracts/src/utils/order_factory.ts @@ -1,5 +1,5 @@ import { generatePseudoRandomSalt, orderHashUtils } from '@0xproject/order-utils'; -import { Order, SignatureType, SignedOrder, UnsignedOrder } from '@0xproject/types'; +import { Order, SignatureType, SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; @@ -26,7 +26,7 @@ export class OrderFactory { takerAddress: constants.NULL_ADDRESS, ...this._defaultOrderParams, ...customOrderParams, - } as any) as UnsignedOrder; + } as any) as Order; const orderHashBuff = orderHashUtils.getOrderHashBuffer(order); const signature = signingUtils.signMessage(orderHashBuff, this._privateKey, signatureType); const signedOrder = { diff --git a/packages/contracts/src/utils/order_utils.ts b/packages/contracts/src/utils/order_utils.ts index 316350ffb..180761f2c 100644 --- a/packages/contracts/src/utils/order_utils.ts +++ b/packages/contracts/src/utils/order_utils.ts @@ -1,29 +1,8 @@ -import { Order, OrderWithoutExchangeAddress, SignedOrder, UnsignedOrder } from '@0xproject/types'; +import { OrderWithoutExchangeAddress, SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import ethUtil = require('ethereumjs-util'); -import * as _ from 'lodash'; -import { crypto } from './crypto'; -import { EIP712Utils } from './eip712_utils'; -import { CancelOrder, EIP712Schema, MatchOrder } from './types'; - -const EIP712_ORDER_SCHEMA: EIP712Schema = { - name: 'Order', - parameters: [ - { name: 'makerAddress', type: 'address' }, - { name: 'takerAddress', type: 'address' }, - { name: 'feeRecipientAddress', type: 'address' }, - { name: 'senderAddress', type: 'address' }, - { name: 'makerAssetAmount', type: 'uint256' }, - { name: 'takerAssetAmount', type: 'uint256' }, - { name: 'makerFee', type: 'uint256' }, - { name: 'takerFee', type: 'uint256' }, - { name: 'expirationTimeSeconds', type: 'uint256' }, - { name: 'salt', type: 'uint256' }, - { name: 'makerAssetData', type: 'bytes' }, - { name: 'takerAssetData', type: 'bytes' }, - ], -}; +import { CancelOrder, MatchOrder } from './types'; export const orderUtils = { createFill: (signedOrder: SignedOrder, takerAssetFillAmount?: BigNumber) => { @@ -58,37 +37,6 @@ export const orderUtils = { }; return orderStruct; }, - getOrderSchemaBuffer(): Buffer { - return EIP712Utils.compileSchema(EIP712_ORDER_SCHEMA); - }, - getOrderHashBuffer(order: SignedOrder | UnsignedOrder): Buffer { - const makerAssetDataHash = crypto.solSHA3([ethUtil.toBuffer(order.makerAssetData)]); - const takerAssetDataHash = crypto.solSHA3([ethUtil.toBuffer(order.takerAssetData)]); - - const orderParamsHashBuff = crypto.solSHA3([ - orderUtils.getOrderSchemaBuffer(), - EIP712Utils.pad32Address(order.makerAddress), - EIP712Utils.pad32Address(order.takerAddress), - EIP712Utils.pad32Address(order.feeRecipientAddress), - EIP712Utils.pad32Address(order.senderAddress), - order.makerAssetAmount, - order.takerAssetAmount, - order.makerFee, - order.takerFee, - order.expirationTimeSeconds, - order.salt, - makerAssetDataHash, - takerAssetDataHash, - ]); - const orderParamsHashHex = `0x${orderParamsHashBuff.toString('hex')}`; - const orderHashBuff = EIP712Utils.createEIP712Message(orderParamsHashHex, order.exchangeAddress); - return orderHashBuff; - }, - getOrderHashHex(order: SignedOrder | UnsignedOrder): string { - const orderHashBuff = orderUtils.getOrderHashBuffer(order); - const orderHashHex = `0x${orderHashBuff.toString('hex')}`; - return orderHashHex; - }, createMatchOrders(signedOrderLeft: SignedOrder, signedOrderRight: SignedOrder): MatchOrder { const fill = { left: orderUtils.getOrderWithoutExchangeAddress(signedOrderLeft), diff --git a/packages/contracts/src/utils/transaction_factory.ts b/packages/contracts/src/utils/transaction_factory.ts index 1c1029d62..7aaf3691c 100644 --- a/packages/contracts/src/utils/transaction_factory.ts +++ b/packages/contracts/src/utils/transaction_factory.ts @@ -1,14 +1,9 @@ -import { crypto, generatePseudoRandomSalt } from '@0xproject/order-utils'; +import { crypto, EIP712Schema, EIP712Utils, generatePseudoRandomSalt } from '@0xproject/order-utils'; import { SignatureType } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; -import { crypto } from './crypto'; -import { EIP712Utils } from './eip712_utils'; -import { orderUtils } from './order_utils'; import { signingUtils } from './signing_utils'; -import { EIP712Schema, SignatureType, SignedTransaction } from './types'; +import { SignedTransaction } from './types'; const EIP712_EXECUTE_TRANSACTION_SCHEMA: EIP712Schema = { name: 'ExecuteTransaction', @@ -30,20 +25,15 @@ export class TransactionFactory { } public newSignedTransaction(data: string, signatureType: SignatureType = SignatureType.EthSign): SignedTransaction { const executeTransactionSchemaHashBuff = EIP712Utils.compileSchema(EIP712_EXECUTE_TRANSACTION_SCHEMA); - const salt = generatePseudoRandomSalt(); const dataHash = crypto.solSHA3([ethUtil.toBuffer(data)]); - const executeTransactionDataHash = crypto.solSHA3([ executeTransactionSchemaHashBuff, salt, EIP712Utils.pad32Buffer(this._signerBuff), dataHash, ]); - - const executeTransactionMessageHex = `0x${executeTransactionDataHash.toString('hex')}`; - - const txHash = EIP712Utils.createEIP712Message(executeTransactionMessageHex, this._exchangeAddress); + const txHash = EIP712Utils.createEIP712Message(executeTransactionDataHash, this._exchangeAddress); const signature = signingUtils.signMessage(txHash, this._privateKey, signatureType); const signedTx = { exchangeAddress: this._exchangeAddress, diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts index 5b7f1bcee..360e1fdbc 100644 --- a/packages/contracts/src/utils/types.ts +++ b/packages/contracts/src/utils/types.ts @@ -147,13 +147,3 @@ export interface MatchOrder { leftSignature: string; rightSignature: string; } - -export interface EIP712Parameter { - name: string; - type: string; -} - -export interface EIP712Schema { - name: string; - parameters: EIP712Parameter[]; -} -- cgit From a8d328bfc926a62d61830334fadc43fc5d013e0e Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Thu, 7 Jun 2018 16:03:14 -0700 Subject: Basic EIP712 encoder --- packages/contracts/src/utils/transaction_factory.ts | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/utils/transaction_factory.ts b/packages/contracts/src/utils/transaction_factory.ts index 7aaf3691c..bb15a0309 100644 --- a/packages/contracts/src/utils/transaction_factory.ts +++ b/packages/contracts/src/utils/transaction_factory.ts @@ -26,21 +26,22 @@ export class TransactionFactory { public newSignedTransaction(data: string, signatureType: SignatureType = SignatureType.EthSign): SignedTransaction { const executeTransactionSchemaHashBuff = EIP712Utils.compileSchema(EIP712_EXECUTE_TRANSACTION_SCHEMA); const salt = generatePseudoRandomSalt(); - const dataHash = crypto.solSHA3([ethUtil.toBuffer(data)]); - const executeTransactionDataHash = crypto.solSHA3([ - executeTransactionSchemaHashBuff, + const signer = `0x${this._signerBuff.toString('hex')}`; + const executeTransactionData = { salt, - EIP712Utils.pad32Buffer(this._signerBuff), - dataHash, - ]); - const txHash = EIP712Utils.createEIP712Message(executeTransactionDataHash, this._exchangeAddress); + signer, + data, + }; + const executeTransactionHashBuff = EIP712Utils.structHash( + EIP712_EXECUTE_TRANSACTION_SCHEMA, + executeTransactionData, + ); + const txHash = EIP712Utils.createEIP712Message(executeTransactionHashBuff, this._exchangeAddress); const signature = signingUtils.signMessage(txHash, this._privateKey, signatureType); const signedTx = { exchangeAddress: this._exchangeAddress, - salt, - signer: `0x${this._signerBuff.toString('hex')}`, - data, signature: `0x${signature.toString('hex')}`, + ...executeTransactionData, }; return signedTx; } -- cgit From 82d1412d456ee28d80597208a241a2b62f561837 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Mon, 11 Jun 2018 09:19:52 +0200 Subject: Simplified handling of source < 32 edge case --- .../src/contracts/current/utils/LibMem/LibMem.sol | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol index 6afb9973a..97fb5fb0f 100644 --- a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol +++ b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol @@ -80,9 +80,6 @@ contract LibMem // if (source > dest) { assembly { - // Record the total number of full words to copy - let nWords := div(length, 32) - // We subtract 32 from `sEnd` and `dEnd` because it // is easier to compare with in the loop, and these // are also the addresses we need for copying the @@ -98,20 +95,19 @@ contract LibMem let last := mload(sEnd) // Copy whole words front to back - for {let i := 0} lt(i, nWords) {i := add(i, 1)} { + // Note: the first check is always true, + // this could have been a do-while loop. + for {} lt(source, sEnd) {} { mstore(dest, mload(source)) source := add(source, 32) dest := add(dest, 32) } - + // Write the last 32 bytes mstore(dEnd, last) } } else { assembly { - // Record the total number of full words to copy - let nWords := div(length, 32) - // We subtract 32 from `sEnd` and `dEnd` because those // are the starting points when copying a word at the end. length := sub(length, 32) @@ -125,12 +121,18 @@ contract LibMem let first := mload(source) // Copy whole words back to front - for {let i := 0} lt(i, nWords) {i := add(i, 1)} { + // We use a signed comparisson here to allow dEnd to become + // negative (happens when source and dest < 32). Valid + // addresses in local memory will never be larger than + // 2**255, so they can be safely re-interpreted as signed. + // Note: the first check is always true, + // this could have been a do-while loop. + for {} slt(dest, dEnd) {} { mstore(dEnd, mload(sEnd)) sEnd := sub(sEnd, 32) dEnd := sub(dEnd, 32) } - + // Write the first 32 bytes mstore(dest, first) } -- cgit From d4ee0e862297c16f8ee62efccd31f1193052c64e Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Mon, 18 Jun 2018 20:59:23 +1000 Subject: Rebase and update feedback Cache the domain separator data with address this Use the EIP712Types enum for types everywhere Rename EIP712 struct ExecuteTransaction to ZeroExTransaction --- .../protocol/Exchange/MixinTransactions.sol | 33 ++++++----- .../current/protocol/Exchange/libs/LibEIP712.sol | 65 ++++++++++------------ .../current/protocol/Exchange/libs/LibOrder.sol | 52 +++++++++-------- .../contracts/src/utils/transaction_factory.ts | 16 +++--- 4 files changed, 85 insertions(+), 81 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol index e3f6b2b2b..9bdaa0f8f 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol @@ -37,28 +37,31 @@ contract MixinTransactions is // Address of current transaction signer address public currentContextAddress; - bytes32 constant EXECUTE_TRANSACTION_SCHEMA_HASH = keccak256( - "ExecuteTransaction(", + // Hash for the EIP712 ZeroEx Transaction Schema + bytes32 constant EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH = keccak256(abi.encodePacked( + "ZeroExTransaction(", "uint256 salt,", "address signer,", "bytes data", ")" - ); + )); - function getExecuteTransactionHash(uint256 salt, address signer, bytes data) + /// @dev Calculates EIP712 hash of the Transaction. + /// @param salt Arbitrary number to ensure uniqueness of transaction hash. + /// @param signer Address of transaction signer. + /// @param data AbiV2 encoded calldata. + /// @return EIP712 hash of the Transaction. + function hashZeroExTransaction(uint256 salt, address signer, bytes data) internal view - returns (bytes32 executeTransactionHash) + returns (bytes32) { - executeTransactionHash = createEIP712Message( - keccak256( - EXECUTE_TRANSACTION_SCHEMA_HASH, - salt, - bytes32(signer), - keccak256(data) - ) - ); - return executeTransactionHash; + return keccak256(abi.encodePacked( + EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH, + salt, + bytes32(signer), + keccak256(abi.encodePacked(data)) + )); } /// @dev Executes an exchange method call in the context of signer. @@ -80,7 +83,7 @@ contract MixinTransactions is REENTRANCY_ILLEGAL ); - bytes32 transactionHash = getExecuteTransactionHash(salt, signer, data); + bytes32 transactionHash = hashEIP712Message(hashZeroExTransaction(salt, signer, data)); // Validate transaction has not been executed require( diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol index 7704e3db4..991137f32 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol @@ -19,44 +19,37 @@ pragma solidity ^0.4.24; contract LibEIP712 { - string public constant EIP191_HEADER = "\x19\x01"; - - bytes32 public constant EIP712_DOMAIN_SEPARATOR_NAME_HASH = keccak256("0x Protocol"); - - bytes32 public constant EIP712_DOMAIN_SEPARATOR_VERSION_HASH = keccak256("2"); - - bytes32 public constant EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256( - abi.encodePacked( - "DomainSeparator(", - "string name,", - "string version,", - "address contract", - ")" - ) - ); + // EIP191 header for EIP712 prefix + string constant EIP191_HEADER = "\x19\x01"; + + // Hash of the EIP712 Domain Separator Schema + bytes32 public constant EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256(abi.encodePacked( + "EIP712Domain(", + "string name,", + "string version,", + "address verifyingContract", + ")" + )); + + // Hash of the EIP712 Domain Separator data + bytes32 public EIP712_DOMAIN_HASH; + + constructor () + public + { + EIP712_DOMAIN_HASH = keccak256(abi.encodePacked( + EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH, + keccak256(abi.encodePacked("0x Protocol")), + keccak256(abi.encodePacked("2")), + bytes32(address(this)) + )); + } - function createEIP712Message(bytes32 hashStruct) + function hashEIP712Message(bytes32 hashStruct) internal view - returns (bytes32 message) + returns (bytes32) { - // TODO: EIP712 is not finalized yet - // Source: https://github.com/ethereum/EIPs/pull/712 - // TODO: Cache the Domain Separator - message = keccak256( - abi.encodePacked( - EIP191_HEADER, - keccak256( - abi.encodePacked( - EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH, - EIP712_DOMAIN_SEPARATOR_NAME_HASH, - EIP712_DOMAIN_SEPARATOR_VERSION_HASH, - bytes32(address(this)) - ) - ), - hashStruct - ) - ); - return message; + return keccak256(abi.encodePacked(EIP191_HEADER, EIP712_DOMAIN_HASH, hashStruct)); } -} \ No newline at end of file +} diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol index ed532fd59..04374f1d0 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol @@ -24,8 +24,8 @@ contract LibOrder is LibEIP712 { - bytes32 constant EIP712_ORDER_SCHEMA_HASH = keccak256( - abi.encodePacked( + // Hash for the EIP712 Order Schema + bytes32 constant EIP712_ORDER_SCHEMA_HASH = keccak256(abi.encodePacked( "Order(", "address makerAddress,", "address takerAddress,", @@ -40,7 +40,8 @@ contract LibOrder is "bytes makerAssetData,", "bytes takerAssetData", ")" - )); + ) + ); // A valid order remains fillable until it is expired, fully filled, or cancelled. // An order's state is unaffected by external factors, like account balances. @@ -86,25 +87,32 @@ contract LibOrder is view returns (bytes32 orderHash) { - orderHash = createEIP712Message( - keccak256( - abi.encodePacked( - EIP712_ORDER_SCHEMA_HASH, - bytes32(order.makerAddress), - bytes32(order.takerAddress), - bytes32(order.feeRecipientAddress), - bytes32(order.senderAddress), - order.makerAssetAmount, - order.takerAssetAmount, - order.makerFee, - order.takerFee, - order.expirationTimeSeconds, - order.salt, - keccak256(abi.encodePacked(order.makerAssetData)), - keccak256(abi.encodePacked(order.takerAssetData)) - ) - ) - ); + orderHash = hashEIP712Message(hashOrder(order)); return orderHash; } + + /// @dev Calculates EIP712 hash of the order. + /// @param order The order structure. + /// @return EIP712 hash of the order. + function hashOrder(Order memory order) + internal + pure + returns (bytes32) + { + return keccak256(abi.encodePacked( + EIP712_ORDER_SCHEMA_HASH, + bytes32(order.makerAddress), + bytes32(order.takerAddress), + bytes32(order.feeRecipientAddress), + bytes32(order.senderAddress), + order.makerAssetAmount, + order.takerAssetAmount, + order.makerFee, + order.takerFee, + order.expirationTimeSeconds, + order.salt, + keccak256(abi.encodePacked(order.makerAssetData)), + keccak256(abi.encodePacked(order.takerAssetData)) + )); + } } diff --git a/packages/contracts/src/utils/transaction_factory.ts b/packages/contracts/src/utils/transaction_factory.ts index bb15a0309..c0a32b83a 100644 --- a/packages/contracts/src/utils/transaction_factory.ts +++ b/packages/contracts/src/utils/transaction_factory.ts @@ -1,16 +1,16 @@ -import { crypto, EIP712Schema, EIP712Utils, generatePseudoRandomSalt } from '@0xproject/order-utils'; +import { crypto, EIP712Schema, EIP712Types, EIP712Utils, generatePseudoRandomSalt } from '@0xproject/order-utils'; import { SignatureType } from '@0xproject/types'; import * as ethUtil from 'ethereumjs-util'; import { signingUtils } from './signing_utils'; import { SignedTransaction } from './types'; -const EIP712_EXECUTE_TRANSACTION_SCHEMA: EIP712Schema = { - name: 'ExecuteTransaction', +const EIP712_ZEROEX_TRANSACTION_SCHEMA: EIP712Schema = { + name: 'ZeroExTransaction', parameters: [ - { name: 'salt', type: 'uint256' }, - { name: 'signer', type: 'address' }, - { name: 'data', type: 'bytes' }, + { name: 'salt', type: EIP712Types.Uint256 }, + { name: 'signer', type: EIP712Types.Address }, + { name: 'data', type: EIP712Types.Bytes }, ], }; @@ -24,7 +24,7 @@ export class TransactionFactory { this._signerBuff = ethUtil.privateToAddress(this._privateKey); } public newSignedTransaction(data: string, signatureType: SignatureType = SignatureType.EthSign): SignedTransaction { - const executeTransactionSchemaHashBuff = EIP712Utils.compileSchema(EIP712_EXECUTE_TRANSACTION_SCHEMA); + const executeTransactionSchemaHashBuff = EIP712Utils.compileSchema(EIP712_ZEROEX_TRANSACTION_SCHEMA); const salt = generatePseudoRandomSalt(); const signer = `0x${this._signerBuff.toString('hex')}`; const executeTransactionData = { @@ -33,7 +33,7 @@ export class TransactionFactory { data, }; const executeTransactionHashBuff = EIP712Utils.structHash( - EIP712_EXECUTE_TRANSACTION_SCHEMA, + EIP712_ZEROEX_TRANSACTION_SCHEMA, executeTransactionData, ); const txHash = EIP712Utils.createEIP712Message(executeTransactionHashBuff, this._exchangeAddress); -- cgit From 560a55bfd1a05bda0d4fb4b97d76e9ea0d9301a7 Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Tue, 19 Jun 2018 13:30:13 +1000 Subject: Optimize and remove redundant encodePacked --- .../current/protocol/Exchange/MixinTransactions.sol | 8 ++++---- .../current/protocol/Exchange/libs/LibEIP712.sol | 19 ++++++++++++++----- .../current/protocol/Exchange/libs/LibOrder.sol | 6 ++++-- packages/contracts/src/utils/transaction_factory.ts | 3 +-- 4 files changed, 23 insertions(+), 13 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol index 9bdaa0f8f..f1332363c 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol @@ -53,14 +53,14 @@ contract MixinTransactions is /// @return EIP712 hash of the Transaction. function hashZeroExTransaction(uint256 salt, address signer, bytes data) internal - view + pure returns (bytes32) { - return keccak256(abi.encodePacked( + return keccak256(abi.encode( EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH, salt, - bytes32(signer), - keccak256(abi.encodePacked(data)) + signer, + keccak256(data) )); } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol index 991137f32..b983347a4 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol @@ -22,6 +22,12 @@ contract LibEIP712 { // EIP191 header for EIP712 prefix string constant EIP191_HEADER = "\x19\x01"; + // EIP712 Domain Name value + string constant EIP712_DOMAIN_NAME = "0x Protocol"; + + // EIP712 Domain Version value + string constant EIP712_DOMAIN_VERSION = "2"; + // Hash of the EIP712 Domain Separator Schema bytes32 public constant EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256(abi.encodePacked( "EIP712Domain(", @@ -35,16 +41,19 @@ contract LibEIP712 { bytes32 public EIP712_DOMAIN_HASH; constructor () - public + public { - EIP712_DOMAIN_HASH = keccak256(abi.encodePacked( + EIP712_DOMAIN_HASH = keccak256(abi.encode( EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH, - keccak256(abi.encodePacked("0x Protocol")), - keccak256(abi.encodePacked("2")), - bytes32(address(this)) + keccak256(bytes(EIP712_DOMAIN_NAME)), + keccak256(bytes(EIP712_DOMAIN_VERSION)), + address(this) )); } + /// @dev Calculates EIP712 encoding for a hash struct in this EIP712 Domain. + /// @param hashStruct The EIP712 hash struct. + /// @return EIP712 hash applied to this EIP712 Domain. function hashEIP712Message(bytes32 hashStruct) internal view diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol index 04374f1d0..b21de6927 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol @@ -99,6 +99,8 @@ contract LibOrder is pure returns (bytes32) { + // Note: changing this to abi.encode results in an error on 0.4.24 + // UnimplementedFeatureError: Variable inaccessible, too deep inside stack (17) return keccak256(abi.encodePacked( EIP712_ORDER_SCHEMA_HASH, bytes32(order.makerAddress), @@ -111,8 +113,8 @@ contract LibOrder is order.takerFee, order.expirationTimeSeconds, order.salt, - keccak256(abi.encodePacked(order.makerAssetData)), - keccak256(abi.encodePacked(order.takerAssetData)) + keccak256(order.makerAssetData), + keccak256(order.takerAssetData) )); } } diff --git a/packages/contracts/src/utils/transaction_factory.ts b/packages/contracts/src/utils/transaction_factory.ts index c0a32b83a..19ef4e1bf 100644 --- a/packages/contracts/src/utils/transaction_factory.ts +++ b/packages/contracts/src/utils/transaction_factory.ts @@ -1,4 +1,4 @@ -import { crypto, EIP712Schema, EIP712Types, EIP712Utils, generatePseudoRandomSalt } from '@0xproject/order-utils'; +import { EIP712Schema, EIP712Types, EIP712Utils, generatePseudoRandomSalt } from '@0xproject/order-utils'; import { SignatureType } from '@0xproject/types'; import * as ethUtil from 'ethereumjs-util'; @@ -24,7 +24,6 @@ export class TransactionFactory { this._signerBuff = ethUtil.privateToAddress(this._privateKey); } public newSignedTransaction(data: string, signatureType: SignatureType = SignatureType.EthSign): SignedTransaction { - const executeTransactionSchemaHashBuff = EIP712Utils.compileSchema(EIP712_ZEROEX_TRANSACTION_SCHEMA); const salt = generatePseudoRandomSalt(); const signer = `0x${this._signerBuff.toString('hex')}`; const executeTransactionData = { -- cgit From 9a2e023a514e9204a1c91ee7d9032b61fbd157de Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Tue, 19 Jun 2018 12:55:04 +0200 Subject: Assembler orderHash function --- .../current/protocol/Exchange/libs/LibOrder.sol | 40 ++++++++++++---------- 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol index b21de6927..cf9df2c3d 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol @@ -97,24 +97,28 @@ contract LibOrder is function hashOrder(Order memory order) internal pure - returns (bytes32) + returns (bytes32 result) { - // Note: changing this to abi.encode results in an error on 0.4.24 - // UnimplementedFeatureError: Variable inaccessible, too deep inside stack (17) - return keccak256(abi.encodePacked( - EIP712_ORDER_SCHEMA_HASH, - bytes32(order.makerAddress), - bytes32(order.takerAddress), - bytes32(order.feeRecipientAddress), - bytes32(order.senderAddress), - order.makerAssetAmount, - order.takerAssetAmount, - order.makerFee, - order.takerFee, - order.expirationTimeSeconds, - order.salt, - keccak256(order.makerAssetData), - keccak256(order.takerAssetData) - )); + bytes32 schemaHash = EIP712_ORDER_SCHEMA_HASH; + bytes32 makerAssetDataHash = keccak256(order.makerAssetData); + bytes32 takerAssetDataHash = keccak256(order.takerAssetData); + assembly { + // Backup + let temp1 := mload(sub(order, 32)) + let temp2 := mload(add(order, 320)) + let temp3 := mload(add(order, 352)) + + // Hash in place + mstore(sub(order, 32), schemaHash) + mstore(add(order, 320), makerAssetDataHash) + mstore(add(order, 352), takerAssetDataHash) + result := keccak256(sub(order, 32), 416) + + // Restore + mstore(sub(order, 32), temp1) + mstore(add(order, 320), temp2) + mstore(add(order, 352), temp3) + } + return result; } } -- cgit From e92926e8814257d71f45ded8011cb17b08fc37de Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sat, 16 Jun 2018 21:45:12 -0700 Subject: Make cancelOrdersUpTo compatible with sender abstraction --- .../protocol/Exchange/MixinExchangeCore.sol | 15 ++-- .../protocol/Exchange/mixins/MExchangeCore.sol | 1 + .../test/ExchangeWrapper/ExchangeWrapper.sol | 97 ++++++++++++++++++++++ .../contracts/current/test/Whitelist/Whitelist.sol | 2 +- packages/contracts/src/utils/artifacts.ts | 2 + 5 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 packages/contracts/src/contracts/current/test/ExchangeWrapper/ExchangeWrapper.sol (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol index 0a0f0209a..2ebbfdabf 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol @@ -44,9 +44,9 @@ contract MixinExchangeCore is // Mapping of orderHash => cancelled mapping (bytes32 => bool) public cancelled; - // Mapping of makerAddress => lowest salt an order can have in order to be fillable + // Mapping of makerAddress => senderAddress => lowest salt an order can have in order to be fillable // Orders with a salt less than their maker's epoch are considered cancelled - mapping (address => uint256) public makerEpoch; + mapping (address => mapping (address => uint256)) public makerEpoch; ////// Core exchange functions ////// @@ -56,10 +56,13 @@ contract MixinExchangeCore is external { address makerAddress = getCurrentContextAddress(); + // If this function is called via `executeTransaction`, we only update the makerEpoch for the makerAddress/msg.sender combination. + // This allows external filter contracts to add rules to how orders are cancelled via this function. + address senderAddress = makerAddress == msg.sender ? address(0) : msg.sender; // makerEpoch is initialized to 0, so to cancelUpTo we need salt + 1 uint256 newMakerEpoch = salt + 1; - uint256 oldMakerEpoch = makerEpoch[makerAddress]; + uint256 oldMakerEpoch = makerEpoch[makerAddress][senderAddress]; // Ensure makerEpoch is monotonically increasing require( @@ -68,8 +71,8 @@ contract MixinExchangeCore is ); // Update makerEpoch - makerEpoch[makerAddress] = newMakerEpoch; - emit CancelUpTo(makerAddress, newMakerEpoch); + makerEpoch[makerAddress][senderAddress] = newMakerEpoch; + emit CancelUpTo(makerAddress, senderAddress, newMakerEpoch); } /// @dev Fills the input order. @@ -180,7 +183,7 @@ contract MixinExchangeCore is orderInfo.orderStatus = uint8(OrderStatus.CANCELLED); return orderInfo; } - if (makerEpoch[order.makerAddress] > order.salt) { + if (makerEpoch[order.makerAddress][order.senderAddress] > order.salt) { orderInfo.orderStatus = uint8(OrderStatus.CANCELLED); return orderInfo; } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol index de7c4d3af..b4552b7bf 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol @@ -52,6 +52,7 @@ contract MExchangeCore is // CancelUpTo event is emitted whenever `cancelOrdersUpTo` is executed succesfully. event CancelUpTo( address indexed makerAddress, + address indexed senderAddress, uint256 makerEpoch ); diff --git a/packages/contracts/src/contracts/current/test/ExchangeWrapper/ExchangeWrapper.sol b/packages/contracts/src/contracts/current/test/ExchangeWrapper/ExchangeWrapper.sol new file mode 100644 index 000000000..629a846d9 --- /dev/null +++ b/packages/contracts/src/contracts/current/test/ExchangeWrapper/ExchangeWrapper.sol @@ -0,0 +1,97 @@ +/* + + Copyright 2018 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.4.24; +pragma experimental ABIEncoderV2; + +import "../../protocol/Exchange/interfaces/IExchange.sol"; +import "../../protocol/Exchange/libs/LibOrder.sol"; + +contract ExchangeWrapper { + + // Exchange contract. + IExchange EXCHANGE; + + constructor (address _exchange) + public + { + EXCHANGE = IExchange(_exchange); + } + + /// @dev Fills an order using `msg.sender` as the taker. + /// @param order Order struct containing order specifications. + /// @param takerAssetFillAmount Desired amount of takerAsset to sell. + /// @param salt Arbitrary value to gaurantee uniqueness of 0x transaction hash. + /// @param orderSignature Proof that order has been created by maker. + /// @param takerSignature Proof that taker wishes to call this function with given params. + function fillOrder( + LibOrder.Order memory order, + uint256 takerAssetFillAmount, + uint256 salt, + bytes memory orderSignature, + bytes memory takerSignature + ) + public + { + address takerAddress = msg.sender; + + // Encode arguments into byte array. + bytes memory data = abi.encodeWithSelector( + EXCHANGE.fillOrder.selector, + order, + takerAssetFillAmount, + orderSignature + ); + + // Call `fillOrder` via `executeTransaction`. + EXCHANGE.executeTransaction( + salt, + takerAddress, + data, + takerSignature + ); + } + + /// @dev Cancels all orders created by sender with a salt less than or equal to the specified salt value. + /// @param cancelSalt Orders created with a salt less or equal to this value will be cancelled. + /// @param salt Arbitrary value to gaurantee uniqueness of 0x transaction hash. + /// @param makerSignature Proof that maker wishes to call this function with given params. + function cancelOrdersUpTo( + uint256 cancelSalt, + uint256 salt, + bytes makerSignature + ) + external + { + address makerAddress = msg.sender; + + // Encode arguments into byte array. + bytes memory data = abi.encodeWithSelector( + EXCHANGE.cancelOrdersUpTo.selector, + cancelSalt + ); + + // Call `cancelOrdersUpTo` via `executeTransaction`. + EXCHANGE.executeTransaction( + salt, + makerAddress, + data, + makerSignature + ); + } +} diff --git a/packages/contracts/src/contracts/current/test/Whitelist/Whitelist.sol b/packages/contracts/src/contracts/current/test/Whitelist/Whitelist.sol index 0594e2767..460c9ea42 100644 --- a/packages/contracts/src/contracts/current/test/Whitelist/Whitelist.sol +++ b/packages/contracts/src/contracts/current/test/Whitelist/Whitelist.sol @@ -16,7 +16,7 @@ */ -pragma solidity ^0.4.23; +pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; import "../../protocol/Exchange/interfaces/IExchange.sol"; diff --git a/packages/contracts/src/utils/artifacts.ts b/packages/contracts/src/utils/artifacts.ts index bf7221d6d..7ba467708 100644 --- a/packages/contracts/src/utils/artifacts.ts +++ b/packages/contracts/src/utils/artifacts.ts @@ -7,6 +7,7 @@ import * as DummyERC721Token from '../artifacts/DummyERC721Token.json'; import * as ERC20Proxy from '../artifacts/ERC20Proxy.json'; import * as ERC721Proxy from '../artifacts/ERC721Proxy.json'; import * as Exchange from '../artifacts/Exchange.json'; +import * as ExchangeWrapper from '../artifacts/ExchangeWrapper.json'; import * as MixinAuthorizable from '../artifacts/MixinAuthorizable.json'; import * as MultiSigWallet from '../artifacts/MultiSigWallet.json'; import * as MultiSigWalletWithTimeLock from '../artifacts/MultiSigWalletWithTimeLock.json'; @@ -29,6 +30,7 @@ export const artifacts = { ERC20Proxy: (ERC20Proxy as any) as ContractArtifact, ERC721Proxy: (ERC721Proxy as any) as ContractArtifact, Exchange: (Exchange as any) as ContractArtifact, + ExchangeWrapper: (ExchangeWrapper as any) as ContractArtifact, EtherToken: (EtherToken as any) as ContractArtifact, MixinAuthorizable: (MixinAuthorizable as any) as ContractArtifact, MultiSigWallet: (MultiSigWallet as any) as ContractArtifact, -- cgit From 6b08e6b80996d9553f280c6d7ade293ae7333711 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Mon, 18 Jun 2018 08:07:04 -0700 Subject: Rename makerEpoch => orderEpoch --- .../protocol/Exchange/MixinExchangeCore.sol | 33 +++++++++++----------- .../protocol/Exchange/interfaces/IExchangeCore.sol | 7 +++-- .../protocol/Exchange/libs/LibExchangeErrors.sol | 4 +-- .../protocol/Exchange/mixins/MExchangeCore.sol | 2 +- .../test/ExchangeWrapper/ExchangeWrapper.sol | 9 +++--- 5 files changed, 29 insertions(+), 26 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol index 2ebbfdabf..c406354a7 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol @@ -45,34 +45,35 @@ contract MixinExchangeCore is mapping (bytes32 => bool) public cancelled; // Mapping of makerAddress => senderAddress => lowest salt an order can have in order to be fillable - // Orders with a salt less than their maker's epoch are considered cancelled - mapping (address => mapping (address => uint256)) public makerEpoch; + // Orders with specified senderAddress and with a salt less than their epoch to are considered cancelled + mapping (address => mapping (address => uint256)) public orderEpoch; ////// Core exchange functions ////// - /// @dev Cancels all orders created by sender with a salt less than or equal to the specified salt value. - /// @param salt Orders created with a salt less or equal to this value will be cancelled. - function cancelOrdersUpTo(uint256 salt) + /// @dev Cancels all orders created by makerAddress with a salt less than or equal to the targetOrderEpoch + /// and senderAddress equal to msg.sender (or null address if msg.sender == makerAddress). + /// @param targetOrderEpoch Orders created with a salt less or equal to this value will be cancelled. + function cancelOrdersUpTo(uint256 targetOrderEpoch) external { address makerAddress = getCurrentContextAddress(); - // If this function is called via `executeTransaction`, we only update the makerEpoch for the makerAddress/msg.sender combination. + // If this function is called via `executeTransaction`, we only update the orderEpoch for the makerAddress/msg.sender combination. // This allows external filter contracts to add rules to how orders are cancelled via this function. address senderAddress = makerAddress == msg.sender ? address(0) : msg.sender; - // makerEpoch is initialized to 0, so to cancelUpTo we need salt + 1 - uint256 newMakerEpoch = salt + 1; - uint256 oldMakerEpoch = makerEpoch[makerAddress][senderAddress]; + // orderEpoch is initialized to 0, so to cancelUpTo we need salt + 1 + uint256 newOrderEpoch = targetOrderEpoch + 1; + uint256 oldOrderEpoch = orderEpoch[makerAddress][senderAddress]; - // Ensure makerEpoch is monotonically increasing + // Ensure orderEpoch is monotonically increasing require( - newMakerEpoch > oldMakerEpoch, - INVALID_NEW_MAKER_EPOCH + newOrderEpoch > oldOrderEpoch, + INVALID_NEW_ORDER_EPOCH ); - // Update makerEpoch - makerEpoch[makerAddress][senderAddress] = newMakerEpoch; - emit CancelUpTo(makerAddress, senderAddress, newMakerEpoch); + // Update orderEpoch + orderEpoch[makerAddress][senderAddress] = newOrderEpoch; + emit CancelUpTo(makerAddress, senderAddress, newOrderEpoch); } /// @dev Fills the input order. @@ -183,7 +184,7 @@ contract MixinExchangeCore is orderInfo.orderStatus = uint8(OrderStatus.CANCELLED); return orderInfo; } - if (makerEpoch[order.makerAddress][order.senderAddress] > order.salt) { + if (orderEpoch[order.makerAddress][order.senderAddress] > order.salt) { orderInfo.orderStatus = uint8(OrderStatus.CANCELLED); return orderInfo; } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol index 7ca2dd052..98222f33f 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol @@ -24,9 +24,10 @@ import "../libs/LibFillResults.sol"; contract IExchangeCore { - /// @dev Cancels all orders reated by sender with a salt less than or equal to the specified salt value. - /// @param salt Orders created with a salt less or equal to this value will be cancelled. - function cancelOrdersUpTo(uint256 salt) + /// @dev Cancels all orders created by makerAddress with a salt less than or equal to the targetOrderEpoch + /// and senderAddress equal to msg.sender (or null address if msg.sender == makerAddress). + /// @param targetOrderEpoch Orders created with a salt less or equal to this value will be cancelled. + function cancelOrdersUpTo(uint256 targetOrderEpoch) external; /// @dev Fills the input order. diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol index 48dd0f8be..adf27bec3 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol @@ -36,7 +36,7 @@ contract LibExchangeErrors { string constant SIGNATURE_UNSUPPORTED = "SIGNATURE_UNSUPPORTED"; // Signature type unsupported. /// cancelOrdersUptTo errors /// - string constant INVALID_NEW_MAKER_EPOCH = "INVALID_NEW_MAKER_EPOCH"; // Specified salt must be greater than or equal to existing makerEpoch. + string constant INVALID_NEW_ORDER_EPOCH = "INVALID_NEW_ORDER_EPOCH"; // Specified salt must be greater than or equal to existing orderEpoch. /// fillOrKillOrder errors /// string constant COMPLETE_FILL_FAILED = "COMPLETE_FILL_FAILED"; // Desired takerAssetFillAmount could not be completely filled. @@ -55,7 +55,7 @@ contract LibExchangeErrors { string constant ASSET_PROXY_ID_MISMATCH = "ASSET_PROXY_ID_MISMATCH"; // newAssetProxyId does not match given assetProxyId. /// Length validation errors /// - string constant LENGTH_GREATER_THAN_0_REQUIRED = "LENGTH_GREATER_THAN_0_REQUIRED"; // Byte array must have a length greater than 0. + string constant LENGTH_GREATER_THAN_0_REQUIRED = "LENGTH_GREATER_THAN_0_REQUIRED"; // Byte array must have a length greater than 0. string constant LENGTH_0_REQUIRED = "LENGTH_1_REQUIRED"; // Byte array must have a length of 1. string constant LENGTH_65_REQUIRED = "LENGTH_66_REQUIRED"; // Byte array must have a length of 66. } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol index b4552b7bf..fb345294c 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol @@ -53,7 +53,7 @@ contract MExchangeCore is event CancelUpTo( address indexed makerAddress, address indexed senderAddress, - uint256 makerEpoch + uint256 orderEpoch ); /// @dev Updates state with results of a fill order. diff --git a/packages/contracts/src/contracts/current/test/ExchangeWrapper/ExchangeWrapper.sol b/packages/contracts/src/contracts/current/test/ExchangeWrapper/ExchangeWrapper.sol index 629a846d9..5baaf6e5a 100644 --- a/packages/contracts/src/contracts/current/test/ExchangeWrapper/ExchangeWrapper.sol +++ b/packages/contracts/src/contracts/current/test/ExchangeWrapper/ExchangeWrapper.sol @@ -67,12 +67,13 @@ contract ExchangeWrapper { ); } - /// @dev Cancels all orders created by sender with a salt less than or equal to the specified salt value. - /// @param cancelSalt Orders created with a salt less or equal to this value will be cancelled. + /// @dev Cancels all orders created by sender with a salt less than or equal to the targetOrderEpoch + /// and senderAddress equal to this contract. + /// @param targetOrderEpoch Orders created with a salt less or equal to this value will be cancelled. /// @param salt Arbitrary value to gaurantee uniqueness of 0x transaction hash. /// @param makerSignature Proof that maker wishes to call this function with given params. function cancelOrdersUpTo( - uint256 cancelSalt, + uint256 targetOrderEpoch, uint256 salt, bytes makerSignature ) @@ -83,7 +84,7 @@ contract ExchangeWrapper { // Encode arguments into byte array. bytes memory data = abi.encodeWithSelector( EXCHANGE.cancelOrdersUpTo.selector, - cancelSalt + targetOrderEpoch ); // Call `cancelOrdersUpTo` via `executeTransaction`. -- cgit From 25fa29e6e14e3e2d5551b868ee4c433ae9708e60 Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Wed, 20 Jun 2018 10:01:41 +1000 Subject: Update after rebase --- .../contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol index d09aba599..9dc9e6525 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol @@ -53,13 +53,7 @@ contract MixinERC721Transfer is bytes memory receiverData ) = decodeERC721AssetData(assetData); - // Transfer token. Saves gas by calling safeTransferFrom only - // when there is receiverData present. Either succeeds or throws. - if (receiverData.length > 0) { - ERC721Token(token).safeTransferFrom(from, to, tokenId, receiverData); - } else { - ERC721Token(token).transferFrom(from, to, tokenId); - } + ERC721Token(token).safeTransferFrom(from, to, tokenId, receiverData); } /// @dev Decodes ERC721 Asset data. -- cgit From 512bd84cc2478267eb359f340cdde8a110c61572 Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Wed, 20 Jun 2018 10:27:45 +1000 Subject: Fix closing parens in liborder --- .../current/protocol/Exchange/libs/LibOrder.sol | 31 +++++++++++----------- 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol index cf9df2c3d..bfc7aaae0 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol @@ -26,22 +26,21 @@ contract LibOrder is // Hash for the EIP712 Order Schema bytes32 constant EIP712_ORDER_SCHEMA_HASH = keccak256(abi.encodePacked( - "Order(", - "address makerAddress,", - "address takerAddress,", - "address feeRecipientAddress,", - "address senderAddress,", - "uint256 makerAssetAmount,", - "uint256 takerAssetAmount,", - "uint256 makerFee,", - "uint256 takerFee,", - "uint256 expirationTimeSeconds,", - "uint256 salt,", - "bytes makerAssetData,", - "bytes takerAssetData", - ")" - ) - ); + "Order(", + "address makerAddress,", + "address takerAddress,", + "address feeRecipientAddress,", + "address senderAddress,", + "uint256 makerAssetAmount,", + "uint256 takerAssetAmount,", + "uint256 makerFee,", + "uint256 takerFee,", + "uint256 expirationTimeSeconds,", + "uint256 salt,", + "bytes makerAssetData,", + "bytes takerAssetData", + ")" + )); // A valid order remains fillable until it is expired, fully filled, or cancelled. // An order's state is unaffected by external factors, like account balances. -- cgit