diff options
author | Jacob Evans <jacob@dekz.net> | 2018-05-30 08:11:33 +0800 |
---|---|---|
committer | Jacob Evans <jacob@dekz.net> | 2018-06-05 08:41:00 +0800 |
commit | 4670cc1a5f04d61045a82b4a3bbcf56e009afd56 (patch) | |
tree | c66321deb69c78a85f7a5c907fac62cc95eae14d /packages/contracts/src/utils | |
parent | 70858603ed37de24ae47978a191b3f188f450182 (diff) | |
download | dexon-sol-tools-4670cc1a5f04d61045a82b4a3bbcf56e009afd56.tar.gz dexon-sol-tools-4670cc1a5f04d61045a82b4a3bbcf56e009afd56.tar.zst dexon-sol-tools-4670cc1a5f04d61045a82b4a3bbcf56e009afd56.zip |
Add missing EIP191 prefix for EIP712
Diffstat (limited to 'packages/contracts/src/utils')
-rw-r--r-- | packages/contracts/src/utils/eip712_utils.ts | 63 | ||||
-rw-r--r-- | packages/contracts/src/utils/order_factory.ts | 6 | ||||
-rw-r--r-- | packages/contracts/src/utils/order_utils.ts | 56 | ||||
-rw-r--r-- | packages/contracts/src/utils/transaction_factory.ts | 30 | ||||
-rw-r--r-- | packages/contracts/src/utils/types.ts | 10 |
5 files changed, 158 insertions, 7 deletions
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[]; +} |