aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmir Bandeali <abandeali1@gmail.com>2018-03-08 08:05:43 +0800
committerAmir Bandeali <abandeali1@gmail.com>2018-04-21 04:56:16 +0800
commit3ff8a319c5460caaf9edc1bea68e807fe0611aaa (patch)
tree77c255e42d1dfcedad7f1692c9467e28cd9a3802
parentcd8f8e1e4acc00e9e31265050456a4c98d79a7d4 (diff)
downloaddexon-0x-contracts-3ff8a319c5460caaf9edc1bea68e807fe0611aaa.tar.gz
dexon-0x-contracts-3ff8a319c5460caaf9edc1bea68e807fe0611aaa.tar.zst
dexon-0x-contracts-3ff8a319c5460caaf9edc1bea68e807fe0611aaa.zip
Add utils for hashing and signing orders, update wrappers
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol2
-rw-r--r--packages/contracts/src/utils/exchange_wrapper.ts16
-rw-r--r--packages/contracts/src/utils/order_factory.ts36
-rw-r--r--packages/contracts/src/utils/order_utils.ts (renamed from packages/contracts/src/utils/signed_order_utils.ts)50
-rw-r--r--packages/contracts/src/utils/signing_utils.ts30
-rw-r--r--packages/contracts/src/utils/types.ts15
6 files changed, 96 insertions, 53 deletions
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
index 232765848..8e51404a7 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
@@ -19,7 +19,7 @@
pragma solidity ^0.4.19;
pragma experimental ABIEncoderV2;
-import './mixins/MExchangeCore.sol';
+import "./mixins/MExchangeCore.sol";
import "../../utils/SafeMath/SafeMath.sol";
/// @dev Consumes MExchangeCore
diff --git a/packages/contracts/src/utils/exchange_wrapper.ts b/packages/contracts/src/utils/exchange_wrapper.ts
index 7383f6b5d..04e6c2feb 100644
--- a/packages/contracts/src/utils/exchange_wrapper.ts
+++ b/packages/contracts/src/utils/exchange_wrapper.ts
@@ -8,7 +8,7 @@ import { ExchangeContract } from '../contract_wrappers/generated/exchange';
import { constants } from './constants';
import { formatters } from './formatters';
import { LogDecoder } from './log_decoder';
-import { signedOrderUtils } from './signed_order_utils';
+import { orderUtils } from './order_utils';
import { SignedOrder } from './types';
export class ExchangeWrapper {
@@ -24,7 +24,7 @@ export class ExchangeWrapper {
from: string,
opts: { takerTokenFillAmount?: BigNumber } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
- const params = signedOrderUtils.createFill(signedOrder, opts.takerTokenFillAmount);
+ const params = orderUtils.createFill(signedOrder, opts.takerTokenFillAmount);
const txHash = await this._exchange.fillOrder.sendTransactionAsync(
params.order,
params.takerTokenFillAmount,
@@ -45,7 +45,7 @@ export class ExchangeWrapper {
from: string,
opts: { takerTokenCancelAmount?: BigNumber } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
- const params = signedOrderUtils.createCancel(signedOrder, opts.takerTokenCancelAmount);
+ const params = orderUtils.createCancel(signedOrder, opts.takerTokenCancelAmount);
const txHash = await this._exchange.cancelOrder.sendTransactionAsync(
params.order,
params.takerTokenCancelAmount,
@@ -65,7 +65,7 @@ export class ExchangeWrapper {
from: string,
opts: { takerTokenFillAmount?: BigNumber } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
- const params = signedOrderUtils.createFill(signedOrder, opts.takerTokenFillAmount);
+ const params = orderUtils.createFill(signedOrder, opts.takerTokenFillAmount);
const txHash = await this._exchange.fillOrKillOrder.sendTransactionAsync(
params.order,
params.takerTokenFillAmount,
@@ -165,14 +165,14 @@ export class ExchangeWrapper {
return tx;
}
public async getOrderHashAsync(signedOrder: SignedOrder): Promise<string> {
- const order = signedOrderUtils.getOrderStruct(signedOrder);
+ const order = orderUtils.getOrderStruct(signedOrder);
const orderHash = await this._exchange.getOrderHash.callAsync(order);
return orderHash;
}
public async isValidSignatureAsync(signedOrder: SignedOrder): Promise<boolean> {
const isValidSignature = await this._exchange.isValidSignature.callAsync(
+ orderUtils.getOrderHashHex(signedOrder),
signedOrder.makerAddress,
- signedOrderUtils.getOrderHashHex(signedOrder),
signedOrder.signature,
);
return isValidSignature;
@@ -195,6 +195,10 @@ export class ExchangeWrapper {
);
return partialAmount;
}
+ public async getFilledTakerTokenAmountAsync(orderHashHex: string): Promise<BigNumber> {
+ const filledAmount = new BigNumber(await this._exchange.filled.callAsync(orderHashHex));
+ return filledAmount;
+ }
}
function wrapLogBigNumbers(log: any): any {
diff --git a/packages/contracts/src/utils/order_factory.ts b/packages/contracts/src/utils/order_factory.ts
index d5c3a9544..3f09cedf3 100644
--- a/packages/contracts/src/utils/order_factory.ts
+++ b/packages/contracts/src/utils/order_factory.ts
@@ -1,37 +1,35 @@
-import { Order, ZeroEx } from '0x.js';
+import { ZeroEx } from '0x.js';
import { BigNumber } from '@0xproject/utils';
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
-import { signedOrderUtils } from './signed_order_utils';
-import { DefaultOrderParams, SignedOrder } from './types';
+import { orderUtils } from './order_utils';
+import { signingUtils } from './signing_utils';
+import { DefaultOrderParams, SignatureType, SignedOrder, UnsignedOrder } from './types';
export class OrderFactory {
- private _defaultOrderParams: Partial<Order>;
- private _zeroEx: ZeroEx;
- constructor(zeroEx: ZeroEx, defaultOrderParams: Partial<Order>) {
+ private _defaultOrderParams: Partial<UnsignedOrder>;
+ private _secretKey: Buffer;
+ constructor(secretKey: Buffer, defaultOrderParams: Partial<UnsignedOrder>) {
this._defaultOrderParams = defaultOrderParams;
- this._zeroEx = zeroEx;
+ this._secretKey = secretKey;
}
- public async newSignedOrderAsync(customOrderParams: Partial<Order> = {}): Promise<SignedOrder> {
+ public newSignedOrder(
+ customOrderParams: Partial<UnsignedOrder> = {},
+ signatureType: SignatureType = SignatureType.Ecrecover,
+ ): SignedOrder {
const randomExpiration = new BigNumber(Math.floor((Date.now() + Math.random() * 100000000000) / 1000));
const order = ({
- expirationTimestampSeconds: randomExpiration,
+ expirationTimeSeconds: randomExpiration,
salt: ZeroEx.generatePseudoRandomSalt(),
takerAddress: ZeroEx.NULL_ADDRESS,
...this._defaultOrderParams,
...customOrderParams,
- } as any) as SignedOrder;
- const orderHashHex = signedOrderUtils.getOrderHashHex(order);
- const shouldAddPersonalMessagePrefix = false;
- const ecSignature = await this._zeroEx.signOrderHashAsync(
- orderHashHex,
- order.makerAddress,
- shouldAddPersonalMessagePrefix,
- );
+ } as any) as UnsignedOrder;
+ const orderHashBuff = orderUtils.getOrderHashBuff(order);
+ const signature = signingUtils.signMessage(orderHashBuff, this._secretKey, signatureType);
const signedOrder = {
...order,
- ecSignature,
+ signature: `0x${signature.toString('hex')}`,
};
return signedOrder;
}
diff --git a/packages/contracts/src/utils/signed_order_utils.ts b/packages/contracts/src/utils/order_utils.ts
index 1d9096ee4..513d0087e 100644
--- a/packages/contracts/src/utils/signed_order_utils.ts
+++ b/packages/contracts/src/utils/order_utils.ts
@@ -4,12 +4,12 @@ import ethUtil = require('ethereumjs-util');
import * as _ from 'lodash';
import { crypto } from './crypto';
-import { OrderStruct, SignatureType, SignedOrder } from './types';
+import { OrderStruct, SignatureType, SignedOrder, UnsignedOrder } from './types';
-export const signedOrderUtils = {
+export const orderUtils = {
createFill: (signedOrder: SignedOrder, takerTokenFillAmount?: BigNumber) => {
const fill = {
- order: signedOrderUtils.getOrderStruct(signedOrder),
+ order: orderUtils.getOrderStruct(signedOrder),
takerTokenFillAmount: takerTokenFillAmount || signedOrder.takerTokenAmount,
signature: signedOrder.signature,
};
@@ -17,7 +17,7 @@ export const signedOrderUtils = {
},
createCancel(signedOrder: SignedOrder, takerTokenCancelAmount?: BigNumber) {
const cancel = {
- order: signedOrderUtils.getOrderStruct(signedOrder),
+ order: orderUtils.getOrderStruct(signedOrder),
takerTokenCancelAmount: takerTokenCancelAmount || signedOrder.takerTokenAmount,
};
return cancel;
@@ -38,7 +38,7 @@ export const signedOrderUtils = {
};
return orderStruct;
},
- getOrderHashHex(signedOrder: SignedOrder): string {
+ getOrderHashBuff(order: SignedOrder | UnsignedOrder): Buffer {
const orderSchemaHashBuff = crypto.solSHA3([
'address exchangeAddress',
'address makerAddress',
@@ -50,35 +50,31 @@ export const signedOrderUtils = {
'uint256 takerTokenAmount',
'uint256 makerFeeAmount',
'uint256 takerFeeAmount',
- 'uint256 expirationTimestampSeconds',
+ 'uint256 expirationTimeSeconds',
'uint256 salt',
]);
const orderSchemaHashHex = `0x${orderSchemaHashBuff.toString('hex')}`;
const orderHashBuff = crypto.solSHA3([
- signedOrder.exchangeAddress,
- signedOrder.makerAddress,
- signedOrder.takerAddress,
- signedOrder.makerTokenAddress,
- signedOrder.takerTokenAddress,
- signedOrder.feeRecipientAddress,
- signedOrder.makerTokenAmount,
- signedOrder.takerTokenAmount,
- signedOrder.makerFeeAmount,
- signedOrder.takerFeeAmount,
- signedOrder.expirationTimeSeconds,
- signedOrder.salt,
+ order.exchangeAddress,
+ order.makerAddress,
+ order.takerAddress,
+ order.makerTokenAddress,
+ order.takerTokenAddress,
+ order.feeRecipientAddress,
+ order.makerTokenAmount,
+ order.takerTokenAmount,
+ order.makerFeeAmount,
+ order.takerFeeAmount,
+ order.expirationTimeSeconds,
+ order.salt,
]);
const orderHashHex = `0x${orderHashBuff.toString('hex')}`;
const prefixedOrderHashBuff = crypto.solSHA3([new BigNumber(orderSchemaHashHex), new BigNumber(orderHashHex)]);
- const prefixedOrderHashHex = `0x${prefixedOrderHashBuff.toString('hex')}`;
- return prefixedOrderHashHex;
+ return prefixedOrderHashBuff;
},
- getSignatureType(signature: string): SignatureType {
- const signatureBuff = new Buffer(signature);
- const signatureType = signatureBuff[0];
- if (!_.has(SignatureType, signatureType)) {
- throw new Error(`${signatureType} is not a valid signature type`);
- }
- return signatureType;
+ getOrderHashHex(order: SignedOrder | UnsignedOrder): string {
+ const orderHashBuff = orderUtils.getOrderHashBuff(order);
+ const orderHashHex = `0x${orderHashBuff.toString('hex')}`;
+ return orderHashHex;
},
};
diff --git a/packages/contracts/src/utils/signing_utils.ts b/packages/contracts/src/utils/signing_utils.ts
new file mode 100644
index 000000000..21b69619c
--- /dev/null
+++ b/packages/contracts/src/utils/signing_utils.ts
@@ -0,0 +1,30 @@
+import * as ethUtil from 'ethereumjs-util';
+
+import { SignatureType } from './types';
+
+export const signingUtils = {
+ signMessage(message: Buffer, secretKey: Buffer, signatureType: SignatureType): Buffer {
+ if (signatureType === SignatureType.Ecrecover) {
+ const prefixedMessage = ethUtil.hashPersonalMessage(message);
+ const ecSignature = ethUtil.ecsign(prefixedMessage, secretKey);
+ const signature = Buffer.concat([
+ ethUtil.toBuffer(signatureType),
+ ethUtil.toBuffer(ecSignature.v),
+ ecSignature.r,
+ ecSignature.s,
+ ]);
+ return signature;
+ } else if (signatureType === SignatureType.EIP712) {
+ const ecSignature = ethUtil.ecsign(message, secretKey);
+ const signature = Buffer.concat([
+ ethUtil.toBuffer(signatureType),
+ ethUtil.toBuffer(ecSignature.v),
+ ecSignature.r,
+ ecSignature.s,
+ ]);
+ return signature;
+ } else {
+ throw new Error(`${signatureType} is not a valid signature type`);
+ }
+ },
+};
diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts
index 5075c7bf5..b16925825 100644
--- a/packages/contracts/src/utils/types.ts
+++ b/packages/contracts/src/utils/types.ts
@@ -138,6 +138,21 @@ export interface OrderStruct {
salt: BigNumber;
}
+export interface UnsignedOrder {
+ exchangeAddress: string;
+ makerAddress: string;
+ takerAddress: string;
+ makerTokenAddress: string;
+ takerTokenAddress: string;
+ feeRecipientAddress: string;
+ makerTokenAmount: BigNumber;
+ takerTokenAmount: BigNumber;
+ makerFeeAmount: BigNumber;
+ takerFeeAmount: BigNumber;
+ expirationTimeSeconds: BigNumber;
+ salt: BigNumber;
+}
+
export enum SignatureType {
Illegal,
Invalid,