aboutsummaryrefslogtreecommitdiffstats
path: root/packages/order-utils/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/order-utils/src')
-rw-r--r--packages/order-utils/src/eip712_utils.ts70
-rw-r--r--packages/order-utils/src/index.ts3
-rw-r--r--packages/order-utils/src/order_hash.ts75
-rw-r--r--packages/order-utils/src/types.ts10
4 files changed, 112 insertions, 46 deletions
diff --git a/packages/order-utils/src/eip712_utils.ts b/packages/order-utils/src/eip712_utils.ts
new file mode 100644
index 000000000..f7583f8d5
--- /dev/null
+++ b/packages/order-utils/src/eip712_utils.ts
@@ -0,0 +1,70 @@
+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 = '2';
+const EIP712_VALUE_LENGTH = 32;
+
+const EIP712_DOMAIN_SCHEMA: EIP712Schema = {
+ name: 'DomainSeparator',
+ parameters: [
+ { name: 'name', type: 'string' },
+ { name: 'version', type: 'string' },
+ { name: 'contract', type: 'address' },
+ ],
+};
+
+export const EIP712Utils = {
+ /**
+ * Compiles the EIP712Schema and returns the hash of the schema.
+ * @param schema The EIP712 schema.
+ * @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 eip712SchemaHashBuffer = crypto.solSHA3([eip712Schema]);
+ return eip712SchemaHashBuffer;
+ },
+ /**
+ * Merges the EIP712 hash of a struct with the DomainSeparator for 0x v2.
+ * @param hashStruct the EIP712 hash of a struct
+ * @param contractAddress the exchange contract address
+ * @return The hash of an EIP712 message with domain separator prefixed
+ */
+ createEIP712Message(hashStruct: Buffer, contractAddress: string): Buffer {
+ const domainSeparatorHashBuffer = EIP712Utils._getDomainSeparatorHashBuffer(contractAddress);
+ const messageBuff = crypto.solSHA3([EIP191_PREFIX, domainSeparatorHashBuffer, hashStruct]);
+ return messageBuff;
+ },
+ 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, EIP712_VALUE_LENGTH);
+ return bufferPadded;
+ },
+ _getDomainSeparatorSchemaBuffer(): Buffer {
+ return EIP712Utils.compileSchema(EIP712_DOMAIN_SCHEMA);
+ },
+ _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;
+ },
+};
diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts
index b844fbfcb..caa996621 100644
--- a/packages/order-utils/src/index.ts
+++ b/packages/order-utils/src/index.ts
@@ -4,9 +4,10 @@ export { orderFactory } from './order_factory';
export { constants } from './constants';
export { crypto } from './crypto';
export { generatePseudoRandomSalt } from './salt';
-export { OrderError, MessagePrefixType, MessagePrefixOpts } from './types';
+export { OrderError, MessagePrefixType, MessagePrefixOpts, EIP712Parameter, EIP712Schema } from './types';
export { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher';
export { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher';
export { RemainingFillableCalculator } from './remaining_fillable_calculator';
export { OrderStateUtils } from './order_state_utils';
export { assetProxyUtils } from './asset_proxy_utils';
+export { EIP712Utils } from './eip712_utils';
diff --git a/packages/order-utils/src/order_hash.ts b/packages/order-utils/src/order_hash.ts
index 2ef746ef8..b2414febc 100644
--- a/packages/order-utils/src/order_hash.ts
+++ b/packages/order-utils/src/order_hash.ts
@@ -9,9 +9,29 @@ import * as _ from 'lodash';
import { assert } from './assert';
import { crypto } from './crypto';
+import { EIP712Utils } from './eip712_utils';
+import { EIP712Schema } from './types';
const INVALID_TAKER_FORMAT = 'instance.takerAddress is not of a type(s) string';
+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 orderHashUtils = {
/**
* Checks if the supplied hex encoded order hash is valid.
@@ -45,7 +65,7 @@ export const orderHashUtils = {
throw error;
}
- const orderHashBuff = this.getOrderHashBuff(order);
+ const orderHashBuff = orderHashUtils.getOrderHashBuffer(order);
const orderHashHex = `0x${orderHashBuff.toString('hex')}`;
return orderHashHex;
},
@@ -54,15 +74,16 @@ export const orderHashUtils = {
* @param order An object that conforms to the Order or SignedOrder interface definitions.
* @return The resulting orderHash from hashing the supplied order as a Buffer
*/
- getOrderHashBuff(order: SignedOrder | Order): 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([
- order.makerAddress,
- order.takerAddress,
- order.feeRecipientAddress,
- order.senderAddress,
+ orderHashUtils._getOrderSchemaBuffer(),
+ EIP712Utils.pad32Address(order.makerAddress),
+ EIP712Utils.pad32Address(order.takerAddress),
+ EIP712Utils.pad32Address(order.feeRecipientAddress),
+ EIP712Utils.pad32Address(order.senderAddress),
order.makerAssetAmount,
order.takerAssetAmount,
order.makerFee,
@@ -72,46 +93,10 @@ export const orderHashUtils = {
makerAssetDataHash,
takerAssetDataHash,
]);
- const orderParamsHashHex = `0x${orderParamsHashBuff.toString('hex')}`;
- const orderSchemaHashHex = this._getOrderSchemaHex();
- const domainSeparatorHashHex = this._getDomainSeparatorHashHex(order.exchangeAddress);
- const domainSeparatorSchemaHex = this._getDomainSeparatorSchemaHex();
- const orderHashBuff = crypto.solSHA3([
- new BigNumber(domainSeparatorSchemaHex),
- new BigNumber(domainSeparatorHashHex),
- new BigNumber(orderSchemaHashHex),
- new BigNumber(orderParamsHashHex),
- ]);
+ const orderHashBuff = EIP712Utils.createEIP712Message(orderParamsHashBuff, order.exchangeAddress);
return orderHashBuff;
},
- _getOrderSchemaHex(): string {
- const orderSchemaHashBuff = crypto.solSHA3([
- 'Order(',
- 'address makerAddress,',
- 'address takerAddress,',
- 'address feeRecipientAddress,',
- 'address senderAddress,',
- 'uint256 makerAssetAmount,',
- 'uint256 takerAssetAmount,',
- 'uint256 makerFee,',
- 'uint256 takerFee,',
- 'uint256 expirationTimeSeconds,',
- 'uint256 salt,',
- 'bytes makerAssetData,',
- 'bytes takerAssetData,',
- ')',
- ]);
- const schemaHashHex = `0x${orderSchemaHashBuff.toString('hex')}`;
- return schemaHashHex;
- },
- _getDomainSeparatorSchemaHex(): string {
- const domainSeparatorSchemaHashBuff = crypto.solSHA3(['DomainSeparator(address contract)']);
- const schemaHashHex = `0x${domainSeparatorSchemaHashBuff.toString('hex')}`;
- return schemaHashHex;
- },
- _getDomainSeparatorHashHex(exchangeAddress: string): string {
- const domainSeparatorHashBuff = crypto.solSHA3([exchangeAddress]);
- const domainSeparatorHashHex = `0x${domainSeparatorHashBuff.toString('hex')}`;
- return domainSeparatorHashHex;
+ _getOrderSchemaBuffer(): Buffer {
+ return EIP712Utils.compileSchema(EIP712_ORDER_SCHEMA);
},
};
diff --git a/packages/order-utils/src/types.ts b/packages/order-utils/src/types.ts
index db0bfb249..858c0e18b 100644
--- a/packages/order-utils/src/types.ts
+++ b/packages/order-utils/src/types.ts
@@ -23,3 +23,13 @@ export interface MessagePrefixOpts {
prefixType: MessagePrefixType;
shouldAddPrefixBeforeCallingEthSign: boolean;
}
+
+export interface EIP712Parameter {
+ name: string;
+ type: string;
+}
+
+export interface EIP712Schema {
+ name: string;
+ parameters: EIP712Parameter[];
+}