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 --- .../contracts/src/utils/transaction_factory.ts | 21 ++++---- packages/order-utils/src/eip712_utils.ts | 61 +++++++++++++++++----- packages/order-utils/src/order_hash.ts | 19 +------ 3 files changed, 61 insertions(+), 40 deletions(-) (limited to 'packages') 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; } diff --git a/packages/order-utils/src/eip712_utils.ts b/packages/order-utils/src/eip712_utils.ts index f7583f8d5..e54ca0e83 100644 --- a/packages/order-utils/src/eip712_utils.ts +++ b/packages/order-utils/src/eip712_utils.ts @@ -2,6 +2,7 @@ import { BigNumber } from '@0xproject/utils'; import ethUtil = require('ethereumjs-util'); import * as _ from 'lodash'; +import { assetProxyUtils } from './asset_proxy_utils'; import { crypto } from './crypto'; import { EIP712Schema } from './types'; @@ -19,6 +20,14 @@ const EIP712_DOMAIN_SCHEMA: EIP712Schema = { ], }; +enum EIP712Types { + String = 'string', + Bytes = 'bytes', + Address = 'address', + Bytes32 = 'bytes32', + Uint256 = 'uint256', +} + export const EIP712Utils = { /** * Compiles the EIP712Schema and returns the hash of the schema. @@ -26,9 +35,7 @@ export const EIP712Utils = { * @return The hash of the compiled schema */ compileSchema(schema: EIP712Schema): Buffer { - const namedTypes = _.map(schema.parameters, parameter => `${parameter.type} ${parameter.name}`); - const namedTypesJoined = namedTypes.join(','); - const eip712Schema = `${schema.name}(${namedTypesJoined})`; + const eip712Schema = EIP712Utils._encodeType(schema); const eip712SchemaHashBuffer = crypto.solSHA3([eip712Schema]); return eip712SchemaHashBuffer; }, @@ -57,14 +64,44 @@ export const EIP712Utils = { }, _getDomainSeparatorHashBuffer(exchangeAddress: string): Buffer { 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), - ]); - return domainSeparatorHashBuff; + const encodedData = EIP712Utils._encodeData(EIP712_DOMAIN_SCHEMA, { + name: EIP712_DOMAIN_NAME, + version: EIP712_DOMAIN_VERSION, + contract: exchangeAddress, + }); + const domainSeparatorHashBuff2 = crypto.solSHA3([domainSeparatorSchemaBuffer, ...encodedData]); + return domainSeparatorHashBuff2; + }, + _encodeType(schema: EIP712Schema): string { + const namedTypes = _.map(schema.parameters, ({ name, type }) => `${type} ${name}`); + const namedTypesJoined = namedTypes.join(','); + const encodedType = `${schema.name}(${namedTypesJoined})`; + return encodedType; + }, + _encodeData(schema: EIP712Schema, data: { [key: string]: any }): any { + const encodedTypes = []; + const encodedValues = []; + for (const parameter of schema.parameters) { + const value = data[parameter.name]; + if (parameter.type === EIP712Types.String || parameter.type === EIP712Types.Bytes) { + encodedTypes.push(EIP712Types.Bytes32); + encodedValues.push(crypto.solSHA3([ethUtil.toBuffer(value)])); + } else if (parameter.type === EIP712Types.Uint256) { + encodedTypes.push(EIP712Types.Uint256); + encodedValues.push(value); + } else if (parameter.type === EIP712Types.Address) { + encodedTypes.push(EIP712Types.Address); + encodedValues.push(EIP712Utils.pad32Address(value)); + } else { + throw new Error(`Unable to encode ${parameter.type}`); + } + } + return encodedValues; + }, + structHash(schema: EIP712Schema, data: { [key: string]: any }): Buffer { + const encodedData = EIP712Utils._encodeData(schema, data); + const schemaHash = EIP712Utils.compileSchema(schema); + const hashBuffer = crypto.solSHA3([schemaHash, ...encodedData]); + return hashBuffer; }, }; diff --git a/packages/order-utils/src/order_hash.ts b/packages/order-utils/src/order_hash.ts index b2414febc..46cce4b3b 100644 --- a/packages/order-utils/src/order_hash.ts +++ b/packages/order-utils/src/order_hash.ts @@ -75,24 +75,7 @@ export const orderHashUtils = { * @return The resulting orderHash from hashing the supplied order as a Buffer */ getOrderHashBuffer(order: SignedOrder | Order): Buffer { - const makerAssetDataHash = crypto.solSHA3([ethUtil.toBuffer(order.makerAssetData)]); - const takerAssetDataHash = crypto.solSHA3([ethUtil.toBuffer(order.takerAssetData)]); - - const orderParamsHashBuff = crypto.solSHA3([ - orderHashUtils._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 orderParamsHashBuff = EIP712Utils.structHash(EIP712_ORDER_SCHEMA, order); const orderHashBuff = EIP712Utils.createEIP712Message(orderParamsHashBuff, order.exchangeAddress); return orderHashBuff; }, -- cgit v1.2.3