aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts/src/utils
diff options
context:
space:
mode:
authorJacob Evans <jacob@dekz.net>2018-05-30 08:11:33 +0800
committerJacob Evans <jacob@dekz.net>2018-06-05 08:41:00 +0800
commit4670cc1a5f04d61045a82b4a3bbcf56e009afd56 (patch)
treec66321deb69c78a85f7a5c907fac62cc95eae14d /packages/contracts/src/utils
parent70858603ed37de24ae47978a191b3f188f450182 (diff)
downloaddexon-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.ts63
-rw-r--r--packages/contracts/src/utils/order_factory.ts6
-rw-r--r--packages/contracts/src/utils/order_utils.ts56
-rw-r--r--packages/contracts/src/utils/transaction_factory.ts30
-rw-r--r--packages/contracts/src/utils/types.ts10
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[];
+}