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
This commit is contained in:
Jacob Evans
2018-06-18 20:59:23 +10:00
parent a8d328bfc9
commit d4ee0e8622
8 changed files with 111 additions and 111 deletions

View File

@@ -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(

View File

@@ -19,44 +19,37 @@
pragma solidity ^0.4.24;
contract LibEIP712 {
string public constant EIP191_HEADER = "\x19\x01";
// EIP191 header for EIP712 prefix
string constant EIP191_HEADER = "\x19\x01";
bytes32 public constant EIP712_DOMAIN_SEPARATOR_NAME_HASH = keccak256("0x Protocol");
// 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",
")"
));
bytes32 public constant EIP712_DOMAIN_SEPARATOR_VERSION_HASH = keccak256("2");
// Hash of the EIP712 Domain Separator data
bytes32 public EIP712_DOMAIN_HASH;
bytes32 public constant EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256(
abi.encodePacked(
"DomainSeparator(",
"string name,",
"string version,",
"address contract",
")"
)
);
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));
}
}
}

View File

@@ -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))
));
}
}

View File

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