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:
@@ -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(
|
||||
|
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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))
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user