aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/contracts')
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol1
-rw-r--r--packages/contracts/src/utils/crypto.ts2
-rw-r--r--packages/contracts/src/utils/exchange_wrapper.ts56
-rw-r--r--packages/contracts/src/utils/formatters.ts116
-rw-r--r--packages/contracts/src/utils/order_factory.ts15
-rw-r--r--packages/contracts/src/utils/signed_order_utils.ts82
-rw-r--r--packages/contracts/src/utils/types.ts67
7 files changed, 189 insertions, 150 deletions
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol b/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol
index 3cb76741a..55246eaea 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol
@@ -36,7 +36,6 @@ contract LibOrder {
"uint256 salt"
);
- // TODO: Append `Address` to all address fields and `Amount` to all value fields?
struct Order {
address makerAddress;
address takerAddress;
diff --git a/packages/contracts/src/utils/crypto.ts b/packages/contracts/src/utils/crypto.ts
index 810072d2f..4126b8ff4 100644
--- a/packages/contracts/src/utils/crypto.ts
+++ b/packages/contracts/src/utils/crypto.ts
@@ -3,6 +3,8 @@ import ABI = require('ethereumjs-abi');
import ethUtil = require('ethereumjs-util');
import * as _ from 'lodash';
+import { SignedOrder } from './types';
+
export const crypto = {
/**
* We convert types from JS to Solidity as follows:
diff --git a/packages/contracts/src/utils/exchange_wrapper.ts b/packages/contracts/src/utils/exchange_wrapper.ts
index 788bf07f4..7383f6b5d 100644
--- a/packages/contracts/src/utils/exchange_wrapper.ts
+++ b/packages/contracts/src/utils/exchange_wrapper.ts
@@ -1,4 +1,4 @@
-import { SignedOrder, TransactionReceiptWithDecodedLogs, ZeroEx } from '0x.js';
+import { TransactionReceiptWithDecodedLogs, ZeroEx } from '0x.js';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import * as Web3 from 'web3';
@@ -9,6 +9,7 @@ import { constants } from './constants';
import { formatters } from './formatters';
import { LogDecoder } from './log_decoder';
import { signedOrderUtils } from './signed_order_utils';
+import { SignedOrder } from './types';
export class ExchangeWrapper {
private _exchange: ExchangeContract;
@@ -25,12 +26,9 @@ export class ExchangeWrapper {
): Promise<TransactionReceiptWithDecodedLogs> {
const params = signedOrderUtils.createFill(signedOrder, opts.takerTokenFillAmount);
const txHash = await this._exchange.fillOrder.sendTransactionAsync(
- params.orderAddresses,
- params.orderValues,
+ params.order,
params.takerTokenFillAmount,
- params.v,
- params.r,
- params.s,
+ params.signature,
{ from },
);
const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
@@ -49,8 +47,7 @@ export class ExchangeWrapper {
): Promise<TransactionReceiptWithDecodedLogs> {
const params = signedOrderUtils.createCancel(signedOrder, opts.takerTokenCancelAmount);
const txHash = await this._exchange.cancelOrder.sendTransactionAsync(
- params.orderAddresses,
- params.orderValues,
+ params.order,
params.takerTokenCancelAmount,
{ from },
);
@@ -70,12 +67,9 @@ export class ExchangeWrapper {
): Promise<TransactionReceiptWithDecodedLogs> {
const params = signedOrderUtils.createFill(signedOrder, opts.takerTokenFillAmount);
const txHash = await this._exchange.fillOrKillOrder.sendTransactionAsync(
- params.orderAddresses,
- params.orderValues,
+ params.order,
params.takerTokenFillAmount,
- params.v,
- params.r,
- params.s,
+ params.signature,
{ from },
);
const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
@@ -94,12 +88,9 @@ export class ExchangeWrapper {
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createBatchFill(orders, opts.takerTokenFillAmounts);
const txHash = await this._exchange.batchFillOrders.sendTransactionAsync(
- params.orderAddresses,
- params.orderValues,
+ params.orders,
params.takerTokenFillAmounts,
- params.v,
- params.r,
- params.s,
+ params.signatures,
{ from },
);
const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
@@ -118,12 +109,9 @@ export class ExchangeWrapper {
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createBatchFill(orders, opts.takerTokenFillAmounts);
const txHash = await this._exchange.batchFillOrKillOrders.sendTransactionAsync(
- params.orderAddresses,
- params.orderValues,
+ params.orders,
params.takerTokenFillAmounts,
- params.v,
- params.r,
- params.s,
+ params.signatures,
{ from },
);
const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
@@ -142,12 +130,9 @@ export class ExchangeWrapper {
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createMarketFillOrders(orders, opts.takerTokenFillAmount);
const txHash = await this._exchange.marketFillOrders.sendTransactionAsync(
- params.orderAddresses,
- params.orderValues,
+ params.orders,
params.takerTokenFillAmount,
- params.v,
- params.r,
- params.s,
+ params.signatures,
{ from },
);
const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
@@ -166,8 +151,7 @@ export class ExchangeWrapper {
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createBatchCancel(orders, opts.takerTokenCancelAmounts);
const txHash = await this._exchange.batchCancelOrders.sendTransactionAsync(
- params.orderAddresses,
- params.orderValues,
+ params.orders,
params.takerTokenCancelAmounts,
{ from },
);
@@ -181,17 +165,15 @@ export class ExchangeWrapper {
return tx;
}
public async getOrderHashAsync(signedOrder: SignedOrder): Promise<string> {
- const params = signedOrderUtils.getOrderAddressesAndValues(signedOrder);
- const orderHash = await this._exchange.getOrderHash.callAsync(params.orderAddresses, params.orderValues);
+ const order = signedOrderUtils.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(
- signedOrder.maker,
- ZeroEx.getOrderHashHex(signedOrder),
- signedOrder.ecSignature.v,
- signedOrder.ecSignature.r,
- signedOrder.ecSignature.s,
+ signedOrder.makerAddress,
+ signedOrderUtils.getOrderHashHex(signedOrder),
+ signedOrder.signature,
);
return isValidSignature;
}
diff --git a/packages/contracts/src/utils/formatters.ts b/packages/contracts/src/utils/formatters.ts
index 48c77fea1..4f6116f06 100644
--- a/packages/contracts/src/utils/formatters.ts
+++ b/packages/contracts/src/utils/formatters.ts
@@ -1,38 +1,30 @@
-import { SignedOrder } from '0x.js';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
-import { BatchCancelOrders, BatchFillOrders, MarketFillOrders } from './types';
+import { BatchCancelOrders, BatchFillOrders, MarketFillOrders, SignedOrder } from './types';
export const formatters = {
createBatchFill(signedOrders: SignedOrder[], takerTokenFillAmounts: BigNumber[] = []) {
const batchFill: BatchFillOrders = {
- orderAddresses: [],
- orderValues: [],
+ orders: [],
+ signatures: [],
takerTokenFillAmounts,
- v: [],
- r: [],
- s: [],
};
_.forEach(signedOrders, signedOrder => {
- batchFill.orderAddresses.push([
- signedOrder.maker,
- signedOrder.taker,
- signedOrder.makerTokenAddress,
- signedOrder.takerTokenAddress,
- signedOrder.feeRecipient,
- ]);
- batchFill.orderValues.push([
- signedOrder.makerTokenAmount,
- signedOrder.takerTokenAmount,
- signedOrder.makerFee,
- signedOrder.takerFee,
- signedOrder.expirationUnixTimestampSec,
- signedOrder.salt,
- ]);
- batchFill.v.push(signedOrder.ecSignature.v);
- batchFill.r.push(signedOrder.ecSignature.r);
- batchFill.s.push(signedOrder.ecSignature.s);
+ batchFill.orders.push({
+ makerAddress: signedOrder.makerAddress,
+ takerAddress: signedOrder.takerAddress,
+ makerTokenAddress: signedOrder.makerTokenAddress,
+ takerTokenAddress: signedOrder.takerTokenAddress,
+ feeRecipientAddress: signedOrder.feeRecipientAddress,
+ makerTokenAmount: signedOrder.makerTokenAmount,
+ takerTokenAmount: signedOrder.takerTokenAmount,
+ makerFeeAmount: signedOrder.makerFeeAmount,
+ takerFeeAmount: signedOrder.takerFeeAmount,
+ expirationTimeSeconds: signedOrder.expirationTimeSeconds,
+ salt: signedOrder.salt,
+ });
+ batchFill.signatures.push(signedOrder.signature);
if (takerTokenFillAmounts.length < signedOrders.length) {
batchFill.takerTokenFillAmounts.push(signedOrder.takerTokenAmount);
}
@@ -41,57 +33,47 @@ export const formatters = {
},
createMarketFillOrders(signedOrders: SignedOrder[], takerTokenFillAmount: BigNumber) {
const marketFillOrders: MarketFillOrders = {
- orderAddresses: [],
- orderValues: [],
+ orders: [],
+ signatures: [],
takerTokenFillAmount,
- v: [],
- r: [],
- s: [],
};
- signedOrders.forEach(signedOrder => {
- marketFillOrders.orderAddresses.push([
- signedOrder.maker,
- signedOrder.taker,
- signedOrder.makerTokenAddress,
- signedOrder.takerTokenAddress,
- signedOrder.feeRecipient,
- ]);
- marketFillOrders.orderValues.push([
- signedOrder.makerTokenAmount,
- signedOrder.takerTokenAmount,
- signedOrder.makerFee,
- signedOrder.takerFee,
- signedOrder.expirationUnixTimestampSec,
- signedOrder.salt,
- ]);
- marketFillOrders.v.push(signedOrder.ecSignature.v);
- marketFillOrders.r.push(signedOrder.ecSignature.r);
- marketFillOrders.s.push(signedOrder.ecSignature.s);
+ _.forEach(signedOrders, signedOrder => {
+ marketFillOrders.orders.push({
+ makerAddress: signedOrder.makerAddress,
+ takerAddress: signedOrder.takerAddress,
+ makerTokenAddress: signedOrder.makerTokenAddress,
+ takerTokenAddress: signedOrder.takerTokenAddress,
+ feeRecipientAddress: signedOrder.feeRecipientAddress,
+ makerTokenAmount: signedOrder.makerTokenAmount,
+ takerTokenAmount: signedOrder.takerTokenAmount,
+ makerFeeAmount: signedOrder.makerFeeAmount,
+ takerFeeAmount: signedOrder.takerFeeAmount,
+ expirationTimeSeconds: signedOrder.expirationTimeSeconds,
+ salt: signedOrder.salt,
+ });
+ marketFillOrders.signatures.push(signedOrder.signature);
});
return marketFillOrders;
},
createBatchCancel(signedOrders: SignedOrder[], takerTokenCancelAmounts: BigNumber[] = []) {
const batchCancel: BatchCancelOrders = {
- orderAddresses: [],
- orderValues: [],
+ orders: [],
takerTokenCancelAmounts,
};
- signedOrders.forEach(signedOrder => {
- batchCancel.orderAddresses.push([
- signedOrder.maker,
- signedOrder.taker,
- signedOrder.makerTokenAddress,
- signedOrder.takerTokenAddress,
- signedOrder.feeRecipient,
- ]);
- batchCancel.orderValues.push([
- signedOrder.makerTokenAmount,
- signedOrder.takerTokenAmount,
- signedOrder.makerFee,
- signedOrder.takerFee,
- signedOrder.expirationUnixTimestampSec,
- signedOrder.salt,
- ]);
+ _.forEach(signedOrders, signedOrder => {
+ batchCancel.orders.push({
+ makerAddress: signedOrder.makerAddress,
+ takerAddress: signedOrder.takerAddress,
+ makerTokenAddress: signedOrder.makerTokenAddress,
+ takerTokenAddress: signedOrder.takerTokenAddress,
+ feeRecipientAddress: signedOrder.feeRecipientAddress,
+ makerTokenAmount: signedOrder.makerTokenAmount,
+ takerTokenAmount: signedOrder.takerTokenAmount,
+ makerFeeAmount: signedOrder.makerFeeAmount,
+ takerFeeAmount: signedOrder.takerFeeAmount,
+ expirationTimeSeconds: signedOrder.expirationTimeSeconds,
+ salt: signedOrder.salt,
+ });
if (takerTokenCancelAmounts.length < signedOrders.length) {
batchCancel.takerTokenCancelAmounts.push(signedOrder.takerTokenAmount);
}
diff --git a/packages/contracts/src/utils/order_factory.ts b/packages/contracts/src/utils/order_factory.ts
index 8ba5df24a..d5c3a9544 100644
--- a/packages/contracts/src/utils/order_factory.ts
+++ b/packages/contracts/src/utils/order_factory.ts
@@ -1,9 +1,10 @@
-import { Order, SignedOrder, ZeroEx } from '0x.js';
+import { Order, ZeroEx } from '0x.js';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
-import { DefaultOrderParams } from './types';
+import { signedOrderUtils } from './signed_order_utils';
+import { DefaultOrderParams, SignedOrder } from './types';
export class OrderFactory {
private _defaultOrderParams: Partial<Order>;
@@ -15,17 +16,17 @@ export class OrderFactory {
public async newSignedOrderAsync(customOrderParams: Partial<Order> = {}): Promise<SignedOrder> {
const randomExpiration = new BigNumber(Math.floor((Date.now() + Math.random() * 100000000000) / 1000));
const order = ({
- expirationUnixTimestampSec: randomExpiration,
+ expirationTimestampSeconds: randomExpiration,
salt: ZeroEx.generatePseudoRandomSalt(),
- taker: ZeroEx.NULL_ADDRESS,
+ takerAddress: ZeroEx.NULL_ADDRESS,
...this._defaultOrderParams,
...customOrderParams,
- } as any) as Order;
- const orderHashHex = ZeroEx.getOrderHashHex(order);
+ } as any) as SignedOrder;
+ const orderHashHex = signedOrderUtils.getOrderHashHex(order);
const shouldAddPersonalMessagePrefix = false;
const ecSignature = await this._zeroEx.signOrderHashAsync(
orderHashHex,
- order.maker,
+ order.makerAddress,
shouldAddPersonalMessagePrefix,
);
const signedOrder = {
diff --git a/packages/contracts/src/utils/signed_order_utils.ts b/packages/contracts/src/utils/signed_order_utils.ts
index 6122748b4..1d9096ee4 100644
--- a/packages/contracts/src/utils/signed_order_utils.ts
+++ b/packages/contracts/src/utils/signed_order_utils.ts
@@ -1,44 +1,84 @@
-import { SignedOrder } from '0x.js';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import ethUtil = require('ethereumjs-util');
import * as _ from 'lodash';
import { crypto } from './crypto';
+import { OrderStruct, SignatureType, SignedOrder } from './types';
export const signedOrderUtils = {
createFill: (signedOrder: SignedOrder, takerTokenFillAmount?: BigNumber) => {
const fill = {
- ...signedOrderUtils.getOrderAddressesAndValues(signedOrder),
+ order: signedOrderUtils.getOrderStruct(signedOrder),
takerTokenFillAmount: takerTokenFillAmount || signedOrder.takerTokenAmount,
- ...signedOrder.ecSignature,
+ signature: signedOrder.signature,
};
return fill;
},
createCancel(signedOrder: SignedOrder, takerTokenCancelAmount?: BigNumber) {
const cancel = {
- ...signedOrderUtils.getOrderAddressesAndValues(signedOrder),
+ order: signedOrderUtils.getOrderStruct(signedOrder),
takerTokenCancelAmount: takerTokenCancelAmount || signedOrder.takerTokenAmount,
};
return cancel;
},
- getOrderAddressesAndValues(signedOrder: SignedOrder) {
- return {
- orderAddresses: [
- signedOrder.maker,
- signedOrder.taker,
- signedOrder.makerTokenAddress,
- signedOrder.takerTokenAddress,
- signedOrder.feeRecipient,
- ],
- orderValues: [
- signedOrder.makerTokenAmount,
- signedOrder.takerTokenAmount,
- signedOrder.makerFee,
- signedOrder.takerFee,
- signedOrder.expirationUnixTimestampSec,
- signedOrder.salt,
- ],
+ getOrderStruct(signedOrder: SignedOrder): OrderStruct {
+ const orderStruct = {
+ makerAddress: signedOrder.makerAddress,
+ takerAddress: signedOrder.takerAddress,
+ makerTokenAddress: signedOrder.makerTokenAddress,
+ takerTokenAddress: signedOrder.takerTokenAddress,
+ feeRecipientAddress: signedOrder.feeRecipientAddress,
+ makerTokenAmount: signedOrder.makerTokenAmount,
+ takerTokenAmount: signedOrder.takerTokenAmount,
+ makerFeeAmount: signedOrder.makerFeeAmount,
+ takerFeeAmount: signedOrder.takerFeeAmount,
+ expirationTimeSeconds: signedOrder.expirationTimeSeconds,
+ salt: signedOrder.salt,
};
+ return orderStruct;
+ },
+ getOrderHashHex(signedOrder: SignedOrder): string {
+ const orderSchemaHashBuff = crypto.solSHA3([
+ 'address exchangeAddress',
+ 'address makerAddress',
+ 'address takerAddress',
+ 'address makerTokenAddress',
+ 'address takerTokenAddress',
+ 'address feeRecipientAddress',
+ 'uint256 makerTokenAmount',
+ 'uint256 takerTokenAmount',
+ 'uint256 makerFeeAmount',
+ 'uint256 takerFeeAmount',
+ 'uint256 expirationTimestampSeconds',
+ '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,
+ ]);
+ const orderHashHex = `0x${orderHashBuff.toString('hex')}`;
+ const prefixedOrderHashBuff = crypto.solSHA3([new BigNumber(orderSchemaHashHex), new BigNumber(orderHashHex)]);
+ const prefixedOrderHashHex = `0x${prefixedOrderHashBuff.toString('hex')}`;
+ return prefixedOrderHashHex;
+ },
+ 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;
},
};
diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts
index 2ffc84f04..5075c7bf5 100644
--- a/packages/contracts/src/utils/types.ts
+++ b/packages/contracts/src/utils/types.ts
@@ -12,39 +12,32 @@ export interface SubmissionContractEventArgs {
}
export interface BatchFillOrders {
- orderAddresses: string[][];
- orderValues: BigNumber[][];
+ orders: OrderStruct[];
+ signatures: string[];
takerTokenFillAmounts: BigNumber[];
- v: number[];
- r: string[];
- s: string[];
}
export interface MarketFillOrders {
- orderAddresses: string[][];
- orderValues: BigNumber[][];
+ orders: OrderStruct[];
+ signatures: string[];
takerTokenFillAmount: BigNumber;
- v: number[];
- r: string[];
- s: string[];
}
export interface BatchCancelOrders {
- orderAddresses: string[][];
- orderValues: BigNumber[][];
+ orders: OrderStruct[];
takerTokenCancelAmounts: BigNumber[];
}
export interface DefaultOrderParams {
- exchangeContractAddress: string;
- maker: string;
- feeRecipient: string;
+ exchangeAddress: string;
+ makerAddress: string;
+ feeRecipientAddress: string;
makerTokenAddress: string;
takerTokenAddress: string;
makerTokenAmount: BigNumber;
takerTokenAmount: BigNumber;
- makerFee: BigNumber;
- takerFee: BigNumber;
+ makerFeeAmount: BigNumber;
+ takerFeeAmount: BigNumber;
}
export interface TransactionDataParams {
@@ -114,3 +107,43 @@ export interface Artifact {
};
};
}
+
+export interface SignedOrder {
+ exchangeAddress: string;
+ makerAddress: string;
+ takerAddress: string;
+ makerTokenAddress: string;
+ takerTokenAddress: string;
+ feeRecipientAddress: string;
+ makerTokenAmount: BigNumber;
+ takerTokenAmount: BigNumber;
+ makerFeeAmount: BigNumber;
+ takerFeeAmount: BigNumber;
+ expirationTimeSeconds: BigNumber;
+ salt: BigNumber;
+ signature: string;
+}
+
+export interface OrderStruct {
+ 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,
+ Caller,
+ Ecrecover,
+ EIP712,
+ Trezor,
+ Contract,
+}