aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol2
-rw-r--r--packages/contracts/src/utils/address_utils.ts4
-rw-r--r--packages/contracts/src/utils/exchange_wrapper.ts4
-rw-r--r--packages/contracts/src/utils/match_order_tester.ts15
-rw-r--r--packages/contracts/src/utils/order_factory.ts15
-rw-r--r--packages/contracts/src/utils/order_utils.ts72
-rw-r--r--packages/contracts/src/utils/signing_utils.ts3
-rw-r--r--packages/contracts/src/utils/transaction_factory.ts6
-rw-r--r--packages/contracts/src/utils/types.ts33
-rw-r--r--packages/contracts/test/asset_proxy/proxies.ts4
-rw-r--r--packages/contracts/test/exchange/core.ts47
-rw-r--r--packages/contracts/test/exchange/dispatcher.ts4
-rw-r--r--packages/contracts/test/exchange/libs.ts9
-rw-r--r--packages/contracts/test/exchange/match_orders.ts10
-rw-r--r--packages/contracts/test/exchange/signature_validator.ts8
-rw-r--r--packages/contracts/test/exchange/transactions.ts12
-rw-r--r--packages/contracts/test/exchange/wrapper.ts6
-rw-r--r--packages/contracts/test/libraries/lib_bytes.ts3
-rw-r--r--packages/json-schemas/schemas/order_schemas.ts2
-rw-r--r--packages/json-schemas/test/schema_test.ts1
-rw-r--r--packages/migrations/compiler.json5
-rw-r--r--packages/migrations/package.json2
-rw-r--r--packages/order-utils/package.json15
-rw-r--r--packages/order-utils/src/artifacts.ts8
-rw-r--r--packages/order-utils/src/assert.ts2
-rw-r--r--packages/order-utils/src/asset_proxy_utils.ts (renamed from packages/contracts/src/utils/asset_proxy_utils.ts)19
-rw-r--r--packages/order-utils/src/crypto.ts (renamed from packages/contracts/src/utils/crypto.ts)3
-rw-r--r--packages/order-utils/src/formatters.ts23
-rw-r--r--packages/order-utils/src/index.ts7
-rw-r--r--packages/order-utils/src/order_factory.ts58
-rw-r--r--packages/order-utils/src/order_hash.ts180
-rw-r--r--packages/order-utils/src/order_state_utils.ts32
-rw-r--r--packages/order-utils/src/remaining_fillable_calculator.ts12
-rw-r--r--packages/order-utils/src/signature_utils.ts121
-rw-r--r--packages/order-utils/test/order_hash_test.ts30
-rw-r--r--packages/order-utils/test/signature_utils_test.ts83
-rw-r--r--packages/types/src/index.ts50
38 files changed, 510 insertions, 401 deletions
diff --git a/.gitignore b/.gitignore
index 96f562b1e..73b18e3f4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -86,6 +86,7 @@ packages/contract-wrappers/src/contract_wrappers/generated/
packages/metacoin/src/contract_wrappers
packages/fill-scenarios/src/generated_contract_wrappers/
packages/order-watcher/src/generated_contract_wrappers/
+packages/order-utils/src/generated_contract_wrappers/
packages/migrations/src/v1/contract_wrappers
packages/migrations/src/v2/contract_wrappers
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol
index f7fcd36b6..af1199f66 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol
@@ -30,7 +30,7 @@ contract MixinSignatureValidator is
{
// Mapping of hash => signer => signed
- mapping(bytes32 => mapping(address => bool)) preSigned;
+ mapping(bytes32 => mapping(address => bool)) public preSigned;
/// @dev Approves a hash on-chain using any valid signature type.
/// After presigning a hash, the preSign signature type will become valid for that hash and signer.
diff --git a/packages/contracts/src/utils/address_utils.ts b/packages/contracts/src/utils/address_utils.ts
index dc63459f9..a9fb6921a 100644
--- a/packages/contracts/src/utils/address_utils.ts
+++ b/packages/contracts/src/utils/address_utils.ts
@@ -1,6 +1,4 @@
-import { generatePseudoRandomSalt } from '@0xproject/order-utils';
-
-import { crypto } from './crypto';
+import { crypto, generatePseudoRandomSalt } from '@0xproject/order-utils';
export const addressUtils = {
generatePseudoRandomAddress(): string {
diff --git a/packages/contracts/src/utils/exchange_wrapper.ts b/packages/contracts/src/utils/exchange_wrapper.ts
index 0446f35d1..f7bd207a4 100644
--- a/packages/contracts/src/utils/exchange_wrapper.ts
+++ b/packages/contracts/src/utils/exchange_wrapper.ts
@@ -1,4 +1,4 @@
-import { Provider, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
+import { AssetProxyId, Provider, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
@@ -9,7 +9,7 @@ import { constants } from './constants';
import { formatters } from './formatters';
import { logDecoder } from './log_decoder';
import { orderUtils } from './order_utils';
-import { AssetProxyId, OrderInfo, SignedTransaction } from './types';
+import { OrderInfo, SignedTransaction } from './types';
export class ExchangeWrapper {
private _exchange: ExchangeContract;
diff --git a/packages/contracts/src/utils/match_order_tester.ts b/packages/contracts/src/utils/match_order_tester.ts
index 87399b9f6..85348b14d 100644
--- a/packages/contracts/src/utils/match_order_tester.ts
+++ b/packages/contracts/src/utils/match_order_tester.ts
@@ -1,5 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
-import { LogWithDecodedArgs, SignedOrder } from '@0xproject/types';
+import { assetProxyUtils, crypto, orderHashUtils } from '@0xproject/order-utils';
+import { AssetProxyId, LogWithDecodedArgs, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import ethUtil = require('ethereumjs-util');
@@ -14,17 +15,13 @@ import {
ExchangeContract,
FillContractEventArgs,
} from '../contract_wrappers/generated/exchange';
-import { assetProxyUtils } from '../utils/asset_proxy_utils';
import { chaiSetup } from '../utils/chai_setup';
import { constants } from '../utils/constants';
-import { crypto } from '../utils/crypto';
import { ERC20Wrapper } from '../utils/erc20_wrapper';
import { ERC721Wrapper } from '../utils/erc721_wrapper';
import { ExchangeWrapper } from '../utils/exchange_wrapper';
import { OrderFactory } from '../utils/order_factory';
-import { orderUtils } from '../utils/order_utils';
import {
- AssetProxyId,
ContractName,
ERC20BalancesByOwner,
ERC721TokenIdsByOwner,
@@ -122,7 +119,7 @@ export class MatchOrderTester {
const feeRecipientAddressRight = signedOrderRight.feeRecipientAddress;
// Verify Left order preconditions
const orderTakerAssetFilledAmountLeft = await this._exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderUtils.getOrderHashHex(signedOrderLeft),
+ orderHashUtils.getOrderHashHex(signedOrderLeft),
);
const expectedOrderFilledAmountLeft = initialTakerAssetFilledAmountLeft
? initialTakerAssetFilledAmountLeft
@@ -130,7 +127,7 @@ export class MatchOrderTester {
expect(expectedOrderFilledAmountLeft).to.be.bignumber.equal(orderTakerAssetFilledAmountLeft);
// Verify Right order preconditions
const orderTakerAssetFilledAmountRight = await this._exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderUtils.getOrderHashHex(signedOrderRight),
+ orderHashUtils.getOrderHashHex(signedOrderRight),
);
const expectedOrderFilledAmountRight = initialTakerAssetFilledAmountRight
? initialTakerAssetFilledAmountRight
@@ -181,7 +178,7 @@ export class MatchOrderTester {
orderTakerAssetFilledAmountRight: BigNumber,
): Promise<TransferAmounts> {
let amountBoughtByLeftMaker = await this._exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderUtils.getOrderHashHex(signedOrderLeft),
+ orderHashUtils.getOrderHashHex(signedOrderLeft),
);
amountBoughtByLeftMaker = amountBoughtByLeftMaker.minus(orderTakerAssetFilledAmountLeft);
const amountSoldByLeftMaker = amountBoughtByLeftMaker
@@ -192,7 +189,7 @@ export class MatchOrderTester {
.dividedToIntegerBy(signedOrderRight.makerAssetAmount);
const amountReceivedByTaker = amountSoldByLeftMaker.minus(amountReceivedByRightMaker);
let amountBoughtByRightMaker = await this._exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderUtils.getOrderHashHex(signedOrderRight),
+ orderHashUtils.getOrderHashHex(signedOrderRight),
);
amountBoughtByRightMaker = amountBoughtByRightMaker.minus(orderTakerAssetFilledAmountRight);
const amountSoldByRightMaker = amountBoughtByRightMaker
diff --git a/packages/contracts/src/utils/order_factory.ts b/packages/contracts/src/utils/order_factory.ts
index f704c26ec..59fc663f4 100644
--- a/packages/contracts/src/utils/order_factory.ts
+++ b/packages/contracts/src/utils/order_factory.ts
@@ -1,22 +1,21 @@
import { generatePseudoRandomSalt } from '@0xproject/order-utils';
-import { SignedOrder, UnsignedOrder } from '@0xproject/types';
+import { orderHashUtils } from '@0xproject/order-utils';
+import { Order, SignatureType, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { constants } from './constants';
-import { orderUtils } from './order_utils';
import { signingUtils } from './signing_utils';
-import { SignatureType } from './types';
export class OrderFactory {
- private _defaultOrderParams: Partial<UnsignedOrder>;
+ private _defaultOrderParams: Partial<Order>;
private _privateKey: Buffer;
- constructor(privateKey: Buffer, defaultOrderParams: Partial<UnsignedOrder>) {
+ constructor(privateKey: Buffer, defaultOrderParams: Partial<Order>) {
this._defaultOrderParams = defaultOrderParams;
this._privateKey = privateKey;
}
public newSignedOrder(
- customOrderParams: Partial<UnsignedOrder> = {},
+ customOrderParams: Partial<Order> = {},
signatureType: SignatureType = SignatureType.Ecrecover,
): SignedOrder {
const randomExpiration = new BigNumber(Math.floor((Date.now() + Math.random() * 100000000000) / 1000));
@@ -27,8 +26,8 @@ export class OrderFactory {
takerAddress: constants.NULL_ADDRESS,
...this._defaultOrderParams,
...customOrderParams,
- } as any) as UnsignedOrder;
- const orderHashBuff = orderUtils.getOrderHashBuff(order);
+ } as any) as Order;
+ const orderHashBuff = orderHashUtils.getOrderHashBuff(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 6d1aaa06b..dd7a04cb6 100644
--- a/packages/contracts/src/utils/order_utils.ts
+++ b/packages/contracts/src/utils/order_utils.ts
@@ -1,8 +1,7 @@
-import { Order, SignedOrder, UnsignedOrder } from '@0xproject/types';
+import { Order, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import ethUtil = require('ethereumjs-util');
-import { crypto } from './crypto';
import { CancelOrder, MatchOrder } from './types';
export const orderUtils = {
@@ -21,6 +20,9 @@ export const orderUtils = {
};
return cancel;
},
+ // TODO: This seems redundant... it currently returns a deep copy w/o signature.
+ // Question: Should we still have a separate OrderStruct type that simply doesn't
+ // include the exchangeAddress? Seems like we need to for batch ops...
getOrderStruct(signedOrder: SignedOrder): Order {
const orderStruct = {
senderAddress: signedOrder.senderAddress,
@@ -35,74 +37,10 @@ export const orderUtils = {
salt: signedOrder.salt,
makerAssetData: signedOrder.makerAssetData,
takerAssetData: signedOrder.takerAssetData,
+ exchangeAddress: signedOrder.exchangeAddress,
};
return orderStruct;
},
- 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;
- },
- 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;
- },
- getOrderHashBuff(order: SignedOrder | UnsignedOrder): 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,
- order.makerAssetAmount,
- order.takerAssetAmount,
- order.makerFee,
- order.takerFee,
- order.expirationTimeSeconds,
- order.salt,
- makerAssetDataHash,
- takerAssetDataHash,
- ]);
- const orderParamsHashHex = `0x${orderParamsHashBuff.toString('hex')}`;
- const orderSchemaHashHex = orderUtils.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),
- ]);
- return orderHashBuff;
- },
- getOrderHashHex(order: SignedOrder | UnsignedOrder): string {
- const orderHashBuff = orderUtils.getOrderHashBuff(order);
- const orderHashHex = `0x${orderHashBuff.toString('hex')}`;
- return orderHashHex;
- },
createMatchOrders(signedOrderLeft: SignedOrder, signedOrderRight: SignedOrder): MatchOrder {
const fill = {
left: orderUtils.getOrderStruct(signedOrderLeft),
diff --git a/packages/contracts/src/utils/signing_utils.ts b/packages/contracts/src/utils/signing_utils.ts
index 61ab1f138..41d63832e 100644
--- a/packages/contracts/src/utils/signing_utils.ts
+++ b/packages/contracts/src/utils/signing_utils.ts
@@ -1,7 +1,6 @@
+import { SignatureType } from '@0xproject/types';
import * as ethUtil from 'ethereumjs-util';
-import { SignatureType } from './types';
-
export const signingUtils = {
signMessage(message: Buffer, privateKey: Buffer, signatureType: SignatureType): Buffer {
if (signatureType === SignatureType.Ecrecover) {
diff --git a/packages/contracts/src/utils/transaction_factory.ts b/packages/contracts/src/utils/transaction_factory.ts
index 941bff96d..41907132a 100644
--- a/packages/contracts/src/utils/transaction_factory.ts
+++ b/packages/contracts/src/utils/transaction_factory.ts
@@ -1,10 +1,10 @@
-import { generatePseudoRandomSalt } from '@0xproject/order-utils';
+import { crypto, generatePseudoRandomSalt } from '@0xproject/order-utils';
+import { SignatureType } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as ethUtil from 'ethereumjs-util';
-import { crypto } from './crypto';
import { signingUtils } from './signing_utils';
-import { SignatureType, SignedTransaction } from './types';
+import { SignedTransaction } from './types';
export class TransactionFactory {
private _signer: string;
diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts
index 90f90ec27..e4401bd92 100644
--- a/packages/contracts/src/utils/types.ts
+++ b/packages/contracts/src/utils/types.ts
@@ -43,12 +43,6 @@ export interface CancelOrdersBefore {
salt: BigNumber;
}
-export enum AssetProxyId {
- INVALID,
- ERC20,
- ERC721,
-}
-
export interface TransactionDataParams {
name: string;
abi: AbiDefinition[];
@@ -113,16 +107,6 @@ export enum ContractName {
Authorizable = 'Authorizable',
}
-export enum SignatureType {
- Illegal,
- Invalid,
- Caller,
- Ecrecover,
- EIP712,
- Trezor,
- Contract,
-}
-
export interface SignedTransaction {
exchangeAddress: string;
salt: BigNumber;
@@ -158,23 +142,6 @@ export interface OrderInfo {
orderTakerAssetFilledAmount: BigNumber;
}
-export interface ERC20ProxyData {
- assetProxyId: AssetProxyId;
- tokenAddress: string;
-}
-
-export interface ERC721ProxyData {
- assetProxyId: AssetProxyId;
- tokenAddress: string;
- tokenId: BigNumber;
-}
-
-export interface ProxyData {
- assetProxyId: AssetProxyId;
- tokenAddress?: string;
- data?: any;
-}
-
export interface CancelOrder {
order: Order;
takerAssetCancelAmount: BigNumber;
diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts
index 9bcdfa2b8..faab39759 100644
--- a/packages/contracts/test/asset_proxy/proxies.ts
+++ b/packages/contracts/test/asset_proxy/proxies.ts
@@ -1,4 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
+import { assetProxyUtils } from '@0xproject/order-utils';
+import { AssetProxyId } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import * as _ from 'lodash';
@@ -8,12 +10,10 @@ import { DummyERC20TokenContract } from '../../src/contract_wrappers/generated/d
import { DummyERC721TokenContract } from '../../src/contract_wrappers/generated/dummy_e_r_c721_token';
import { ERC20ProxyContract } from '../../src/contract_wrappers/generated/e_r_c20_proxy';
import { ERC721ProxyContract } from '../../src/contract_wrappers/generated/e_r_c721_proxy';
-import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
import { ERC721Wrapper } from '../../src/utils/erc721_wrapper';
-import { AssetProxyId } from '../../src/utils/types';
import { provider, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();
diff --git a/packages/contracts/test/exchange/core.ts b/packages/contracts/test/exchange/core.ts
index be8d14cb0..e8397f8a2 100644
--- a/packages/contracts/test/exchange/core.ts
+++ b/packages/contracts/test/exchange/core.ts
@@ -1,5 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
-import { LogWithDecodedArgs, SignedOrder } from '@0xproject/types';
+import { assetProxyUtils, crypto, orderHashUtils } from '@0xproject/order-utils';
+import { AssetProxyId, LogWithDecodedArgs, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
@@ -17,16 +18,13 @@ import {
FillContractEventArgs,
} from '../../src/contract_wrappers/generated/exchange';
import { artifacts } from '../../src/utils/artifacts';
-import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
-import { crypto } from '../../src/utils/crypto';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
import { ERC721Wrapper } from '../../src/utils/erc721_wrapper';
import { ExchangeWrapper } from '../../src/utils/exchange_wrapper';
import { OrderFactory } from '../../src/utils/order_factory';
-import { orderUtils } from '../../src/utils/order_utils';
-import { AssetProxyId, ContractName, ERC20BalancesByOwner, ExchangeStatus } from '../../src/utils/types';
+import { ContractName, ERC20BalancesByOwner, ExchangeStatus } from '../../src/utils/types';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();
@@ -127,7 +125,6 @@ describe('Exchange core', () => {
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
-
describe('fillOrder', () => {
beforeEach(async () => {
erc20Balances = await erc20Wrapper.getBalancesAsync();
@@ -141,7 +138,7 @@ describe('Exchange core', () => {
});
const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderUtils.getOrderHashHex(signedOrder),
+ orderHashUtils.getOrderHashHex(signedOrder),
);
expect(takerAssetFilledAmountBefore).to.be.bignumber.equal(0);
@@ -151,7 +148,7 @@ describe('Exchange core', () => {
});
const takerAssetFilledAmountAfter1 = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderUtils.getOrderHashHex(signedOrder),
+ orderHashUtils.getOrderHashHex(signedOrder),
);
expect(takerAssetFilledAmountAfter1).to.be.bignumber.equal(fillTakerAssetAmount1);
@@ -161,7 +158,7 @@ describe('Exchange core', () => {
});
const takerAssetFilledAmountAfter2 = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderUtils.getOrderHashHex(signedOrder),
+ orderHashUtils.getOrderHashHex(signedOrder),
);
expect(takerAssetFilledAmountAfter2).to.be.bignumber.equal(takerAssetFilledAmountAfter1);
});
@@ -173,7 +170,7 @@ describe('Exchange core', () => {
});
const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderUtils.getOrderHashHex(signedOrder),
+ orderHashUtils.getOrderHashHex(signedOrder),
);
expect(takerAssetFilledAmountBefore).to.be.bignumber.equal(0);
@@ -181,7 +178,7 @@ describe('Exchange core', () => {
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
const makerAmountBoughtAfter = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderUtils.getOrderHashHex(signedOrder),
+ orderHashUtils.getOrderHashHex(signedOrder),
);
expect(makerAmountBoughtAfter).to.be.bignumber.equal(takerAssetFillAmount);
@@ -226,7 +223,7 @@ describe('Exchange core', () => {
});
const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderUtils.getOrderHashHex(signedOrder),
+ orderHashUtils.getOrderHashHex(signedOrder),
);
expect(takerAssetFilledAmountBefore).to.be.bignumber.equal(0);
@@ -234,7 +231,7 @@ describe('Exchange core', () => {
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
const makerAmountBoughtAfter = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderUtils.getOrderHashHex(signedOrder),
+ orderHashUtils.getOrderHashHex(signedOrder),
);
expect(makerAmountBoughtAfter).to.be.bignumber.equal(takerAssetFillAmount);
@@ -279,7 +276,7 @@ describe('Exchange core', () => {
});
const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderUtils.getOrderHashHex(signedOrder),
+ orderHashUtils.getOrderHashHex(signedOrder),
);
expect(takerAssetFilledAmountBefore).to.be.bignumber.equal(0);
@@ -287,7 +284,7 @@ describe('Exchange core', () => {
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
const makerAmountBoughtAfter = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderUtils.getOrderHashHex(signedOrder),
+ orderHashUtils.getOrderHashHex(signedOrder),
);
expect(makerAmountBoughtAfter).to.be.bignumber.equal(takerAssetFillAmount);
@@ -333,7 +330,7 @@ describe('Exchange core', () => {
});
const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderUtils.getOrderHashHex(signedOrder),
+ orderHashUtils.getOrderHashHex(signedOrder),
);
expect(takerAssetFilledAmountBefore).to.be.bignumber.equal(0);
@@ -341,7 +338,7 @@ describe('Exchange core', () => {
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
const makerAmountBoughtAfter = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderUtils.getOrderHashHex(signedOrder),
+ orderHashUtils.getOrderHashHex(signedOrder),
);
const expectedMakerAmountBoughtAfter = takerAssetFillAmount.add(takerAssetFilledAmountBefore);
expect(makerAmountBoughtAfter).to.be.bignumber.equal(expectedMakerAmountBoughtAfter);
@@ -441,7 +438,7 @@ describe('Exchange core', () => {
expect(expectedFilledTakerAssetAmount).to.be.bignumber.equal(logArgs.takerAssetFilledAmount);
expect(expectedFeeMPaid).to.be.bignumber.equal(logArgs.makerFeePaid);
expect(expectedFeeTPaid).to.be.bignumber.equal(logArgs.takerFeePaid);
- expect(orderUtils.getOrderHashHex(signedOrder)).to.be.equal(logArgs.orderHash);
+ expect(orderHashUtils.getOrderHashHex(signedOrder)).to.be.equal(logArgs.orderHash);
});
it('should throw when taker is specified and order is claimed by other', async () => {
@@ -534,12 +531,6 @@ describe('Exchange core', () => {
await expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(
constants.REVERT,
);
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20TokenA.approve.sendTransactionAsync(erc20Proxy.address, constants.INITIAL_ERC20_ALLOWANCE, {
- from: makerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
});
it('should throw if taker allowances are too low to fill order', async () => {
@@ -555,12 +546,6 @@ describe('Exchange core', () => {
await expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(
constants.REVERT,
);
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20TokenB.approve.sendTransactionAsync(erc20Proxy.address, constants.INITIAL_ERC20_ALLOWANCE, {
- from: takerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
});
it('should not change erc20Balances if an order is expired', async () => {
@@ -651,7 +636,7 @@ describe('Exchange core', () => {
expect(signedOrder.feeRecipientAddress).to.be.equal(logArgs.feeRecipientAddress);
expect(signedOrder.makerAssetData).to.be.equal(logArgs.makerAssetData);
expect(signedOrder.takerAssetData).to.be.equal(logArgs.takerAssetData);
- expect(orderUtils.getOrderHashHex(signedOrder)).to.be.equal(logArgs.orderHash);
+ expect(orderHashUtils.getOrderHashHex(signedOrder)).to.be.equal(logArgs.orderHash);
});
it('should log an error if already cancelled', async () => {
diff --git a/packages/contracts/test/exchange/dispatcher.ts b/packages/contracts/test/exchange/dispatcher.ts
index b9c7039bd..8bc66e3cf 100644
--- a/packages/contracts/test/exchange/dispatcher.ts
+++ b/packages/contracts/test/exchange/dispatcher.ts
@@ -1,4 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
+import { assetProxyUtils } from '@0xproject/order-utils';
+import { AssetProxyId } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import * as Web3 from 'web3';
@@ -8,12 +10,10 @@ import { ERC20ProxyContract } from '../../src/contract_wrappers/generated/e_r_c2
import { ERC721ProxyContract } from '../../src/contract_wrappers/generated/e_r_c721_proxy';
import { TestAssetProxyDispatcherContract } from '../../src/contract_wrappers/generated/test_asset_proxy_dispatcher';
import { artifacts } from '../../src/utils/artifacts';
-import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
import { ERC721Wrapper } from '../../src/utils/erc721_wrapper';
-import { AssetProxyId } from '../../src/utils/types';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();
diff --git a/packages/contracts/test/exchange/libs.ts b/packages/contracts/test/exchange/libs.ts
index bbca54274..5f2c24ac0 100644
--- a/packages/contracts/test/exchange/libs.ts
+++ b/packages/contracts/test/exchange/libs.ts
@@ -1,4 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
+import { assetProxyUtils, orderHashUtils } from '@0xproject/order-utils';
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
@@ -7,11 +8,9 @@ import ethUtil = require('ethereumjs-util');
import { TestLibsContract } from '../../src/contract_wrappers/generated/test_libs';
import { addressUtils } from '../../src/utils/address_utils';
import { artifacts } from '../../src/utils/artifacts';
-import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { OrderFactory } from '../../src/utils/order_factory';
-import { orderUtils } from '../../src/utils/order_utils';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();
@@ -59,19 +58,19 @@ describe('Exchange libs', () => {
describe('getOrderSchema', () => {
it('should output the correct order schema hash', async () => {
const orderSchema = await libs.getOrderSchemaHash.callAsync();
- expect(orderUtils.getOrderSchemaHex()).to.be.equal(orderSchema);
+ expect(orderHashUtils._getOrderSchemaHex()).to.be.equal(orderSchema);
});
});
describe('getDomainSeparatorSchema', () => {
it('should output the correct domain separator schema hash', async () => {
const domainSeparatorSchema = await libs.getDomainSeparatorSchemaHash.callAsync();
- expect(orderUtils.getDomainSeparatorSchemaHex()).to.be.equal(domainSeparatorSchema);
+ expect(orderHashUtils._getDomainSeparatorSchemaHex()).to.be.equal(domainSeparatorSchema);
});
});
describe('getOrderHash', () => {
it('should output the correct order hash', async () => {
const orderHashHex = await libs.publicGetOrderHash.callAsync(signedOrder);
- expect(orderUtils.getOrderHashHex(signedOrder)).to.be.equal(orderHashHex);
+ expect(orderHashUtils.getOrderHashHex(signedOrder)).to.be.equal(orderHashHex);
});
});
});
diff --git a/packages/contracts/test/exchange/match_orders.ts b/packages/contracts/test/exchange/match_orders.ts
index 0da0287bc..67281a915 100644
--- a/packages/contracts/test/exchange/match_orders.ts
+++ b/packages/contracts/test/exchange/match_orders.ts
@@ -1,5 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
-import { LogWithDecodedArgs, SignedOrder } from '@0xproject/types';
+import { assetProxyUtils, crypto } from '@0xproject/order-utils';
+import { AssetProxyId, LogWithDecodedArgs, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
@@ -17,17 +18,14 @@ import {
FillContractEventArgs,
} from '../../src/contract_wrappers/generated/exchange';
import { artifacts } from '../../src/utils/artifacts';
-import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
-import { crypto } from '../../src/utils/crypto';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
import { ERC721Wrapper } from '../../src/utils/erc721_wrapper';
import { ExchangeWrapper } from '../../src/utils/exchange_wrapper';
+import { MatchOrderTester } from '../../src/utils/match_order_tester';
import { OrderFactory } from '../../src/utils/order_factory';
-import { orderUtils } from '../../src/utils/order_utils';
import {
- AssetProxyId,
ContractName,
ERC20BalancesByOwner,
ERC721TokenIdsByOwner,
@@ -36,8 +34,6 @@ import {
} from '../../src/utils/types';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
-import { MatchOrderTester } from '../../src/utils/match_order_tester';
-
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
diff --git a/packages/contracts/test/exchange/signature_validator.ts b/packages/contracts/test/exchange/signature_validator.ts
index 376fff438..a41a19426 100644
--- a/packages/contracts/test/exchange/signature_validator.ts
+++ b/packages/contracts/test/exchange/signature_validator.ts
@@ -1,4 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
+import { orderHashUtils } from '@0xproject/order-utils';
+import { assetProxyUtils } from '@0xproject/order-utils';
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
@@ -7,11 +9,9 @@ import ethUtil = require('ethereumjs-util');
import { TestSignatureValidatorContract } from '../../src/contract_wrappers/generated/test_signature_validator';
import { addressUtils } from '../../src/utils/address_utils';
import { artifacts } from '../../src/utils/artifacts';
-import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { OrderFactory } from '../../src/utils/order_factory';
-import { orderUtils } from '../../src/utils/order_utils';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();
@@ -65,7 +65,7 @@ describe('MixinSignatureValidator', () => {
});
it('should return true with a valid signature', async () => {
- const orderHashHex = orderUtils.getOrderHashHex(signedOrder);
+ const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
const isValidSignature = await signatureValidator.publicIsValidSignature.callAsync(
orderHashHex,
signedOrder.makerAddress,
@@ -84,7 +84,7 @@ describe('MixinSignatureValidator', () => {
]);
const invalidSigHex = `0x${invalidSigBuff.toString('hex')}`;
signedOrder.signature = invalidSigHex;
- const orderHashHex = orderUtils.getOrderHashHex(signedOrder);
+ const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
const isValidSignature = await signatureValidator.publicIsValidSignature.callAsync(
orderHashHex,
signedOrder.makerAddress,
diff --git a/packages/contracts/test/exchange/transactions.ts b/packages/contracts/test/exchange/transactions.ts
index 33fe11bfa..3f884a6c3 100644
--- a/packages/contracts/test/exchange/transactions.ts
+++ b/packages/contracts/test/exchange/transactions.ts
@@ -1,5 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
-import { Order, SignedOrder } from '@0xproject/types';
+import { AssetProxyId, Order, SignatureType, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import * as ethUtil from 'ethereumjs-util';
@@ -9,7 +9,7 @@ import { DummyERC20TokenContract } from '../../src/contract_wrappers/generated/d
import { ERC20ProxyContract } from '../../src/contract_wrappers/generated/e_r_c20_proxy';
import { ExchangeContract } from '../../src/contract_wrappers/generated/exchange';
import { artifacts } from '../../src/utils/artifacts';
-import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
+import { assetProxyUtils } from '@0xproject/order-utils';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
@@ -17,13 +17,7 @@ import { ExchangeWrapper } from '../../src/utils/exchange_wrapper';
import { OrderFactory } from '../../src/utils/order_factory';
import { orderUtils } from '../../src/utils/order_utils';
import { TransactionFactory } from '../../src/utils/transaction_factory';
-import {
- AssetProxyId,
- ERC20BalancesByOwner,
- ExchangeStatus,
- SignatureType,
- SignedTransaction,
-} from '../../src/utils/types';
+import { ERC20BalancesByOwner, ExchangeStatus, SignedTransaction } from '../../src/utils/types';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();
diff --git a/packages/contracts/test/exchange/wrapper.ts b/packages/contracts/test/exchange/wrapper.ts
index 7e1818f4a..d8055908a 100644
--- a/packages/contracts/test/exchange/wrapper.ts
+++ b/packages/contracts/test/exchange/wrapper.ts
@@ -1,5 +1,5 @@
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
-import { SignedOrder } from '@0xproject/types';
+import { AssetProxyId, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
@@ -14,14 +14,14 @@ import { ERC721ProxyContract } from '../../src/contract_wrappers/generated/e_r_c
import { ExchangeContract } from '../../src/contract_wrappers/generated/exchange';
import { TokenRegistryContract } from '../../src/contract_wrappers/generated/token_registry';
import { artifacts } from '../../src/utils/artifacts';
-import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
+import { assetProxyUtils } from '@0xproject/order-utils';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
import { ERC721Wrapper } from '../../src/utils/erc721_wrapper';
import { ExchangeWrapper } from '../../src/utils/exchange_wrapper';
import { OrderFactory } from '../../src/utils/order_factory';
-import { AssetProxyId, ERC20BalancesByOwner } from '../../src/utils/types';
+import { ERC20BalancesByOwner } from '../../src/utils/types';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();
diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts
index 968bac300..de4011853 100644
--- a/packages/contracts/test/libraries/lib_bytes.ts
+++ b/packages/contracts/test/libraries/lib_bytes.ts
@@ -1,5 +1,5 @@
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
-import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
+import { AssetProxyId, LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import BN = require('bn.js');
@@ -11,7 +11,6 @@ import { TestLibBytesContract } from '../../src/contract_wrappers/generated/test
import { artifacts } from '../../src/utils/artifacts';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
-import { AssetProxyId } from '../../src/utils/types';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();
diff --git a/packages/json-schemas/schemas/order_schemas.ts b/packages/json-schemas/schemas/order_schemas.ts
index 4dc458d8d..dcbfde6e0 100644
--- a/packages/json-schemas/schemas/order_schemas.ts
+++ b/packages/json-schemas/schemas/order_schemas.ts
@@ -11,6 +11,7 @@ export const orderSchema = {
makerAssetData: { $ref: '/Hex' },
takerAssetData: { $ref: '/Hex' },
salt: { $ref: '/Number' },
+ exchangeAddress: { $ref: '/Address' },
feeRecipientAddress: { $ref: '/Address' },
expirationTimeSeconds: { $ref: '/Number' },
},
@@ -25,6 +26,7 @@ export const orderSchema = {
'makerAssetData',
'takerAssetData',
'salt',
+ 'exchangeAddress',
'feeRecipientAddress',
'expirationTimeSeconds',
],
diff --git a/packages/json-schemas/test/schema_test.ts b/packages/json-schemas/test/schema_test.ts
index 93e9624a9..3858c7fa7 100644
--- a/packages/json-schemas/test/schema_test.ts
+++ b/packages/json-schemas/test/schema_test.ts
@@ -180,6 +180,7 @@ describe('Schema', () => {
takerAssetData: NULL_ADDRESS,
salt: '67006738228878699843088602623665307406148487219438534730168799356281242528500',
feeRecipientAddress: NULL_ADDRESS,
+ exchangeAddress: NULL_ADDRESS,
expirationTimeSeconds: '42',
};
describe('#orderSchema', () => {
diff --git a/packages/migrations/compiler.json b/packages/migrations/compiler.json
index e1204b2d1..782b939dc 100644
--- a/packages/migrations/compiler.json
+++ b/packages/migrations/compiler.json
@@ -1,5 +1,5 @@
{
- "artifactsDir": "artifacts/1.0.0",
+ "artifactsDir": "artifacts/2.0.0",
"contractsDir": "../contracts/src/contracts",
"contracts": [
"Exchange_v1",
@@ -10,7 +10,8 @@
"MultiSigWallet",
"MultiSigWalletWithTimeLock",
"MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress",
- "TokenRegistry"
+ "TokenRegistry",
+ "ISigner"
],
"compilerSettings": {
"outputSelection": {
diff --git a/packages/migrations/package.json b/packages/migrations/package.json
index 54866110e..ebef2dfb4 100644
--- a/packages/migrations/package.json
+++ b/packages/migrations/package.json
@@ -30,7 +30,7 @@
"v1":
"artifacts/1.0.0/@(DummyERC20Token|TokenTransferProxy_v1|Exchange_v1|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|WETH9).json",
"v2":
- "artifacts/2.0.0/@(DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|ZRXToken|WETH9).json"
+ "artifacts/2.0.0/@(DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|ZRXToken|WETH9|ISigner).json"
}
},
"license": "Apache-2.0",
diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json
index c69d99c05..0b0686954 100644
--- a/packages/order-utils/package.json
+++ b/packages/order-utils/package.json
@@ -9,13 +9,16 @@
"types": "lib/src/index.d.ts",
"scripts": {
"watch": "tsc -w",
+ "prebuild": "run-s clean update_artifacts generate_contract_wrappers",
"build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
- "test": "run-s clean build run_mocha",
+ "generate_contract_wrappers": "abi-gen --abis 'lib/src/artifacts/@(Exchange|ISigner).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers && prettier --write 'src/generated_contract_wrappers/**.ts'",
+ "update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/2.0.0/$i.json lib/src/artifacts; done;",
+ "test": "run-s build run_mocha",
"test:circleci": "yarn test:coverage",
"run_mocha": "mocha lib/test/**/*_test.js --bail --exit",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
- "clean": "shx rm -rf lib scripts",
+ "clean": "shx rm -rf lib scripts lib/src/artifacts src/generated_contract_wrappers",
"lint": "tslint --project .",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js",
"docs:stage": "node scripts/stage_docs.js",
@@ -23,6 +26,7 @@
"upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json"
},
"config": {
+ "contracts": "ISigner Exchange",
"postpublish": {
"docPublishConfigs": {
"extraFileIncludes": [
@@ -63,8 +67,10 @@
},
"dependencies": {
"@0xproject/assert": "^0.2.10",
- "@0xproject/json-schemas": "0.7.22",
- "@0xproject/types": "0.7.0",
+ "@0xproject/base-contract": "^0.3.2",
+ "@0xproject/json-schemas": "0.7.24",
+ "@0xproject/sol-compiler": "^0.5.0",
+ "@0xproject/types": "^0.7.1",
"@0xproject/typescript-typings": "^0.3.2",
"@0xproject/utils": "^0.6.2",
"@0xproject/web3-wrapper": "^0.6.4",
@@ -72,6 +78,7 @@
"bn.js": "^4.11.8",
"ethereumjs-abi": "^0.6.4",
"ethereumjs-util": "^5.1.1",
+ "ethers": "^3.0.15",
"lodash": "^4.17.4"
},
"publishConfig": {
diff --git a/packages/order-utils/src/artifacts.ts b/packages/order-utils/src/artifacts.ts
new file mode 100644
index 000000000..6eb5ad0c0
--- /dev/null
+++ b/packages/order-utils/src/artifacts.ts
@@ -0,0 +1,8 @@
+import { Artifact } from '@0xproject/types';
+
+import * as Exchange from './artifacts/Exchange.json';
+import * as ISigner from './artifacts/ISigner.json';
+export const artifacts = {
+ Exchange: (Exchange as any) as Artifact,
+ ISigner: (ISigner as any) as Artifact,
+};
diff --git a/packages/order-utils/src/assert.ts b/packages/order-utils/src/assert.ts
index 5ac402e7e..07cde453a 100644
--- a/packages/order-utils/src/assert.ts
+++ b/packages/order-utils/src/assert.ts
@@ -8,8 +8,6 @@ import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
-import { isValidSignature } from './signature_utils';
-
export const assert = {
...sharedAssert,
async isSenderAddressAsync(
diff --git a/packages/contracts/src/utils/asset_proxy_utils.ts b/packages/order-utils/src/asset_proxy_utils.ts
index c042da5d0..11f81c656 100644
--- a/packages/contracts/src/utils/asset_proxy_utils.ts
+++ b/packages/order-utils/src/asset_proxy_utils.ts
@@ -1,8 +1,10 @@
+import { AssetProxyId, ERC20ProxyData, ERC721ProxyData, ProxyData } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import BN = require('bn.js');
import ethUtil = require('ethereumjs-util');
-import { AssetProxyId, ERC20ProxyData, ERC721ProxyData, ProxyData } from './types';
+const ERC20_PROXY_METADATA_BYTE_LENGTH = 21;
+const ERC721_PROXY_METADATA_BYTE_LENGTH = 53;
export const assetProxyUtils = {
encodeAssetProxyId(assetProxyId: AssetProxyId): Buffer {
@@ -26,8 +28,10 @@ export const assetProxyUtils = {
return address;
},
encodeUint256(value: BigNumber): Buffer {
- const formattedValue = new BN(value.toString(10));
+ const base = 10;
+ const formattedValue = new BN(value.toString(base));
const encodedValue = ethUtil.toBuffer(formattedValue);
+ // tslint:disable-next-line:custom-no-magic-numbers
const paddedValue = ethUtil.setLengthLeft(encodedValue, 32);
return paddedValue;
},
@@ -45,7 +49,7 @@ export const assetProxyUtils = {
},
decodeERC20ProxyData(proxyData: string): ERC20ProxyData {
const encodedProxyMetadata = ethUtil.toBuffer(proxyData);
- if (encodedProxyMetadata.byteLength !== 21) {
+ if (encodedProxyMetadata.byteLength !== ERC20_PROXY_METADATA_BYTE_LENGTH) {
throw new Error(
`Could not decode ERC20 Proxy Data. Expected length of encoded data to be 21. Got ${
encodedProxyMetadata.byteLength
@@ -61,7 +65,7 @@ export const assetProxyUtils = {
}), but got ${assetProxyId}`,
);
}
- const encodedTokenAddress = encodedProxyMetadata.slice(1, 21);
+ const encodedTokenAddress = encodedProxyMetadata.slice(1, ERC20_PROXY_METADATA_BYTE_LENGTH);
const tokenAddress = assetProxyUtils.decodeAddress(encodedTokenAddress);
const erc20ProxyData = {
assetProxyId,
@@ -79,7 +83,7 @@ export const assetProxyUtils = {
},
decodeERC721ProxyData(proxyData: string): ERC721ProxyData {
const encodedProxyMetadata = ethUtil.toBuffer(proxyData);
- if (encodedProxyMetadata.byteLength !== 53) {
+ if (encodedProxyMetadata.byteLength !== ERC721_PROXY_METADATA_BYTE_LENGTH) {
throw new Error(
`Could not decode ERC20 Proxy Data. Expected length of encoded data to be 53. Got ${
encodedProxyMetadata.byteLength
@@ -95,9 +99,10 @@ export const assetProxyUtils = {
}), but got ${assetProxyId}`,
);
}
- const encodedTokenAddress = encodedProxyMetadata.slice(1, 21);
+ const addressOffset = 21;
+ const encodedTokenAddress = encodedProxyMetadata.slice(1, addressOffset);
const tokenAddress = assetProxyUtils.decodeAddress(encodedTokenAddress);
- const encodedTokenId = encodedProxyMetadata.slice(21, 53);
+ const encodedTokenId = encodedProxyMetadata.slice(addressOffset, ERC721_PROXY_METADATA_BYTE_LENGTH);
const tokenId = assetProxyUtils.decodeUint256(encodedTokenId);
const erc721ProxyData = {
assetProxyId,
diff --git a/packages/contracts/src/utils/crypto.ts b/packages/order-utils/src/crypto.ts
index 80c5f30a5..517ca2840 100644
--- a/packages/contracts/src/utils/crypto.ts
+++ b/packages/order-utils/src/crypto.ts
@@ -26,7 +26,8 @@ export const crypto = {
argTypes.push('uint8');
} else if (arg.isBigNumber) {
argTypes.push('uint256');
- args[i] = new BN(arg.toString(10), 10);
+ const base = 10;
+ args[i] = new BN(arg.toString(base), base);
} else if (ethUtil.isValidAddress(arg)) {
argTypes.push('address');
} else if (_.isString(arg)) {
diff --git a/packages/order-utils/src/formatters.ts b/packages/order-utils/src/formatters.ts
deleted file mode 100644
index 2b6f4ddb7..000000000
--- a/packages/order-utils/src/formatters.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { Order, OrderAddresses, OrderValues } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-
-export const formatters = {
- getOrderAddressesAndValues(order: Order): [OrderAddresses, OrderValues] {
- const orderAddresses: OrderAddresses = [
- order.maker,
- order.taker,
- order.makerTokenAddress,
- order.takerTokenAddress,
- order.feeRecipient,
- ];
- const orderValues: OrderValues = [
- order.makerTokenAmount,
- order.takerTokenAmount,
- order.makerFee,
- order.takerFee,
- order.expirationUnixTimestampSec,
- order.salt,
- ];
- return [orderAddresses, orderValues];
- },
-};
diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts
index e9cea95ed..5b4e20119 100644
--- a/packages/order-utils/src/index.ts
+++ b/packages/order-utils/src/index.ts
@@ -1,11 +1,12 @@
-export { getOrderHashHex, isValidOrderHash } from './order_hash';
-export { isValidSignature, signOrderHashAsync } from './signature_utils';
+export { orderHashUtils } from './order_hash';
+export { isValidSignatureAsync, ecSignOrderHashAsync } from './signature_utils';
export { orderFactory } from './order_factory';
export { constants } from './constants';
+export { crypto } from './crypto';
export { generatePseudoRandomSalt } from './salt';
export { OrderError } from './types';
-export { formatters } from './formatters';
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';
diff --git a/packages/order-utils/src/order_factory.ts b/packages/order-utils/src/order_factory.ts
index 2759aac81..fe341b845 100644
--- a/packages/order-utils/src/order_factory.ts
+++ b/packages/order-utils/src/order_factory.ts
@@ -2,48 +2,56 @@ import { Provider, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
-import { getOrderHashHex } from './order_hash';
+import { orderHashUtils } from './order_hash';
import { generatePseudoRandomSalt } from './salt';
-import { signOrderHashAsync } from './signature_utils';
+import { ecSignOrderHashAsync, getVRSHexString } from './signature_utils';
const SHOULD_ADD_PERSONAL_MESSAGE_PREFIX = false;
export const orderFactory = {
async createSignedOrderAsync(
provider: Provider,
- maker: string,
- taker: string,
+ makerAddress: string,
+ takerAddress: string,
+ senderAddress: string,
makerFee: BigNumber,
takerFee: BigNumber,
- makerTokenAmount: BigNumber,
- makerTokenAddress: string,
- takerTokenAmount: BigNumber,
- takerTokenAddress: string,
- exchangeContractAddress: string,
- feeRecipient: string,
- expirationUnixTimestampSecIfExists?: BigNumber,
+ makerAssetAmount: BigNumber,
+ makerAssetData: string,
+ takerAssetAmount: BigNumber,
+ takerAssetData: string,
+ exchangeAddress: string,
+ feeRecipientAddress: string,
+ expirationTimeSecondsIfExists?: BigNumber,
): Promise<SignedOrder> {
const defaultExpirationUnixTimestampSec = new BigNumber(2524604400); // Close to infinite
- const expirationUnixTimestampSec = _.isUndefined(expirationUnixTimestampSecIfExists)
+ const expirationTimeSeconds = _.isUndefined(expirationTimeSecondsIfExists)
? defaultExpirationUnixTimestampSec
- : expirationUnixTimestampSecIfExists;
+ : expirationTimeSecondsIfExists;
const order = {
- maker,
- taker,
+ makerAddress,
+ takerAddress,
+ senderAddress,
makerFee,
takerFee,
- makerTokenAmount,
- takerTokenAmount,
- makerTokenAddress,
- takerTokenAddress,
+ makerAssetAmount,
+ takerAssetAmount,
+ makerAssetData,
+ takerAssetData,
salt: generatePseudoRandomSalt(),
- exchangeContractAddress,
- feeRecipient,
- expirationUnixTimestampSec,
+ exchangeAddress,
+ feeRecipientAddress,
+ expirationTimeSeconds,
};
- const orderHash = getOrderHashHex(order);
- const ecSignature = await signOrderHashAsync(provider, orderHash, maker, SHOULD_ADD_PERSONAL_MESSAGE_PREFIX);
- const signedOrder: SignedOrder = _.assign(order, { ecSignature });
+ const orderHash = orderHashUtils.getOrderHashHex(order);
+ const ecSignature = await ecSignOrderHashAsync(
+ provider,
+ orderHash,
+ makerAddress,
+ SHOULD_ADD_PERSONAL_MESSAGE_PREFIX,
+ );
+ const signature = getVRSHexString(ecSignature);
+ const signedOrder: SignedOrder = _.assign(order, { signature });
return signedOrder;
},
};
diff --git a/packages/order-utils/src/order_hash.ts b/packages/order-utils/src/order_hash.ts
index 108344a04..3d0db5b0c 100644
--- a/packages/order-utils/src/order_hash.ts
+++ b/packages/order-utils/src/order_hash.ts
@@ -1,5 +1,5 @@
import { schemas, SchemaValidator } from '@0xproject/json-schemas';
-import { Order, SignedOrder, SolidityTypes } from '@0xproject/types';
+import { Order, SignatureType, SignedOrder, SolidityTypes } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import BN = require('bn.js');
import * as ethABI from 'ethereumjs-abi';
@@ -7,84 +7,110 @@ import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash';
import { assert } from './assert';
+import { crypto } from './crypto';
const INVALID_TAKER_FORMAT = 'instance.taker is not of a type(s) string';
-/**
- * Converts BigNumber instance to BN
- * The only reason we convert to BN is to remain compatible with `ethABI.soliditySHA3` that
- * expects values of Solidity type `uint` to be passed as type `BN`.
- * We do not use BN anywhere else in the codebase.
- */
-function bigNumberToBN(value: BigNumber): BN {
- const base = 10;
- return new BN(value.toString(), base);
-}
-
-/**
- * Computes the orderHash for a supplied order.
- * @param order An object that conforms to the Order or SignedOrder interface definitions.
- * @return The resulting orderHash from hashing the supplied order.
- */
-export function getOrderHashHex(order: Order | SignedOrder): string {
- try {
- assert.doesConformToSchema('order', order, schemas.orderSchema);
- } catch (error) {
- if (_.includes(error.message, INVALID_TAKER_FORMAT)) {
- const errMsg =
- 'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
- throw new Error(errMsg);
+export const orderHashUtils = {
+ /**
+ * Checks if the supplied hex encoded order hash is valid.
+ * Note: Valid means it has the expected format, not that an order with the orderHash exists.
+ * Use this method when processing orderHashes submitted as user input.
+ * @param orderHash Hex encoded orderHash.
+ * @return Whether the supplied orderHash has the expected format.
+ */
+ isValidOrderHash(orderHash: string): boolean {
+ // Since this method can be called to check if any arbitrary string conforms to an orderHash's
+ // format, we only assert that we were indeed passed a string.
+ assert.isString('orderHash', orderHash);
+ const schemaValidator = new SchemaValidator();
+ const isValid = schemaValidator.validate(orderHash, schemas.orderHashSchema).valid;
+ return isValid;
+ },
+ /**
+ * Computes the orderHash for a supplied order.
+ * @param order An object that conforms to the Order or SignedOrder interface definitions.
+ * @return The resulting orderHash from hashing the supplied order.
+ */
+ getOrderHashHex(order: SignedOrder | Order): string {
+ try {
+ assert.doesConformToSchema('order', order, schemas.orderSchema);
+ } catch (error) {
+ if (_.includes(error.message, INVALID_TAKER_FORMAT)) {
+ const errMsg =
+ 'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
+ throw new Error(errMsg);
+ }
+ throw error;
}
- throw error;
- }
- const orderParts = [
- { value: order.exchangeContractAddress, type: SolidityTypes.Address },
- { value: order.maker, type: SolidityTypes.Address },
- { value: order.taker, type: SolidityTypes.Address },
- { value: order.makerTokenAddress, type: SolidityTypes.Address },
- { value: order.takerTokenAddress, type: SolidityTypes.Address },
- { value: order.feeRecipient, type: SolidityTypes.Address },
- {
- value: bigNumberToBN(order.makerTokenAmount),
- type: SolidityTypes.Uint256,
- },
- {
- value: bigNumberToBN(order.takerTokenAmount),
- type: SolidityTypes.Uint256,
- },
- {
- value: bigNumberToBN(order.makerFee),
- type: SolidityTypes.Uint256,
- },
- {
- value: bigNumberToBN(order.takerFee),
- type: SolidityTypes.Uint256,
- },
- {
- value: bigNumberToBN(order.expirationUnixTimestampSec),
- type: SolidityTypes.Uint256,
- },
- { value: bigNumberToBN(order.salt), type: SolidityTypes.Uint256 },
- ];
- const types = _.map(orderParts, o => o.type);
- const values = _.map(orderParts, o => o.value);
- const hashBuff = ethABI.soliditySHA3(types, values);
- const hashHex = ethUtil.bufferToHex(hashBuff);
- return hashHex;
-}
-/**
- * Checks if the supplied hex encoded order hash is valid.
- * Note: Valid means it has the expected format, not that an order with the orderHash exists.
- * Use this method when processing orderHashes submitted as user input.
- * @param orderHash Hex encoded orderHash.
- * @return Whether the supplied orderHash has the expected format.
- */
-export function isValidOrderHash(orderHash: string): boolean {
- // Since this method can be called to check if any arbitrary string conforms to an orderHash's
- // format, we only assert that we were indeed passed a string.
- assert.isString('orderHash', orderHash);
- const schemaValidator = new SchemaValidator();
- const isValid = schemaValidator.validate(orderHash, schemas.orderHashSchema).valid;
- return isValid;
-}
+ const orderHashBuff = this.getOrderHashBuff(order);
+ const orderHashHex = `0x${orderHashBuff.toString('hex')}`;
+ return orderHashHex;
+ },
+ /**
+ * Computes the orderHash for a supplied order and returns it as a Buffer
+ * @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 {
+ 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,
+ order.makerAssetAmount,
+ order.takerAssetAmount,
+ order.makerFee,
+ order.takerFee,
+ order.expirationTimeSeconds,
+ order.salt,
+ 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),
+ ]);
+ 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;
+ },
+};
diff --git a/packages/order-utils/src/order_state_utils.ts b/packages/order-utils/src/order_state_utils.ts
index 36171f526..61050c9d6 100644
--- a/packages/order-utils/src/order_state_utils.ts
+++ b/packages/order-utils/src/order_state_utils.ts
@@ -11,7 +11,8 @@ import * as _ from 'lodash';
import { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher';
import { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher';
-import { getOrderHashHex } from './order_hash';
+import { assetProxyUtils } from './asset_proxy_utils';
+import { orderHashUtils } from './order_hash';
import { RemainingFillableCalculator } from './remaining_fillable_calculator';
const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001;
@@ -23,7 +24,7 @@ export class OrderStateUtils {
const unavailableTakerTokenAmount = orderRelevantState.cancelledTakerTokenAmount.add(
orderRelevantState.filledTakerTokenAmount,
);
- const availableTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
+ const availableTakerTokenAmount = signedOrder.takerAssetAmount.minus(unavailableTakerTokenAmount);
if (availableTakerTokenAmount.eq(0)) {
throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero);
}
@@ -42,9 +43,9 @@ export class OrderStateUtils {
throw new Error(ExchangeContractErrs.InsufficientMakerFeeAllowance);
}
}
- const minFillableTakerTokenAmountWithinNoRoundingErrorRange = signedOrder.takerTokenAmount
+ const minFillableTakerTokenAmountWithinNoRoundingErrorRange = signedOrder.takerAssetAmount
.dividedBy(ACCEPTABLE_RELATIVE_ROUNDING_ERROR)
- .dividedBy(signedOrder.makerTokenAmount);
+ .dividedBy(signedOrder.makerAssetAmount);
if (
orderRelevantState.remainingFillableTakerTokenAmount.lessThan(
minFillableTakerTokenAmountWithinNoRoundingErrorRange,
@@ -62,7 +63,7 @@ export class OrderStateUtils {
}
public async getOrderStateAsync(signedOrder: SignedOrder): Promise<OrderState> {
const orderRelevantState = await this.getOrderRelevantStateAsync(signedOrder);
- const orderHash = getOrderHashHex(signedOrder);
+ const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
try {
OrderStateUtils._validateIfOrderIsValid(signedOrder, orderRelevantState);
const orderState: OrderStateValid = {
@@ -82,22 +83,22 @@ export class OrderStateUtils {
}
public async getOrderRelevantStateAsync(signedOrder: SignedOrder): Promise<OrderRelevantState> {
const zrxTokenAddress = this._orderFilledCancelledFetcher.getZRXTokenAddress();
- const orderHash = getOrderHashHex(signedOrder);
+ const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
const makerBalance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync(
- signedOrder.makerTokenAddress,
- signedOrder.maker,
+ signedOrder.makerAssetData,
+ signedOrder.makerAddress,
);
const makerProxyAllowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync(
- signedOrder.makerTokenAddress,
- signedOrder.maker,
+ signedOrder.makerAssetData,
+ signedOrder.makerAddress,
);
const makerFeeBalance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync(
zrxTokenAddress,
- signedOrder.maker,
+ signedOrder.makerAddress,
);
const makerFeeProxyAllowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync(
zrxTokenAddress,
- signedOrder.maker,
+ signedOrder.makerAddress,
);
const filledTakerTokenAmount = await this._orderFilledCancelledFetcher.getFilledTakerAmountAsync(orderHash);
const cancelledTakerTokenAmount = await this._orderFilledCancelledFetcher.getCancelledTakerAmountAsync(
@@ -106,8 +107,8 @@ export class OrderStateUtils {
const unavailableTakerTokenAmount = await this._orderFilledCancelledFetcher.getUnavailableTakerAmountAsync(
orderHash,
);
- const totalMakerTokenAmount = signedOrder.makerTokenAmount;
- const totalTakerTokenAmount = signedOrder.takerTokenAmount;
+ const totalMakerTokenAmount = signedOrder.makerAssetAmount;
+ const totalTakerTokenAmount = signedOrder.takerAssetAmount;
const remainingTakerTokenAmount = totalTakerTokenAmount.minus(unavailableTakerTokenAmount);
const remainingMakerTokenAmount = remainingTakerTokenAmount
.times(totalMakerTokenAmount)
@@ -115,7 +116,8 @@ export class OrderStateUtils {
const transferrableMakerTokenAmount = BigNumber.min([makerProxyAllowance, makerBalance]);
const transferrableFeeTokenAmount = BigNumber.min([makerFeeProxyAllowance, makerFeeBalance]);
- const isMakerTokenZRX = signedOrder.makerTokenAddress === zrxTokenAddress;
+ const zrxAssetData = assetProxyUtils.encodeERC20ProxyData(zrxTokenAddress);
+ const isMakerTokenZRX = signedOrder.makerAssetData === zrxAssetData;
const remainingFillableCalculator = new RemainingFillableCalculator(
signedOrder,
isMakerTokenZRX,
diff --git a/packages/order-utils/src/remaining_fillable_calculator.ts b/packages/order-utils/src/remaining_fillable_calculator.ts
index 184c13aa4..b291d8ea9 100644
--- a/packages/order-utils/src/remaining_fillable_calculator.ts
+++ b/packages/order-utils/src/remaining_fillable_calculator.ts
@@ -23,7 +23,7 @@ export class RemainingFillableCalculator {
this._remainingMakerTokenAmount = remainingMakerTokenAmount;
this._remainingMakerFeeAmount = remainingMakerTokenAmount
.times(signedOrder.makerFee)
- .dividedToIntegerBy(signedOrder.makerTokenAmount);
+ .dividedToIntegerBy(signedOrder.makerAssetAmount);
}
public computeRemainingMakerFillable(): BigNumber {
if (this._hasSufficientFundsForFeeAndTransferAmount()) {
@@ -36,8 +36,8 @@ export class RemainingFillableCalculator {
}
public computeRemainingTakerFillable(): BigNumber {
return this.computeRemainingMakerFillable()
- .times(this._signedOrder.takerTokenAmount)
- .dividedToIntegerBy(this._signedOrder.makerTokenAmount);
+ .times(this._signedOrder.takerAssetAmount)
+ .dividedToIntegerBy(this._signedOrder.makerAssetAmount);
}
private _hasSufficientFundsForFeeAndTransferAmount(): boolean {
if (this._isMakerTokenZRX) {
@@ -59,7 +59,7 @@ export class RemainingFillableCalculator {
}
private _calculatePartiallyFillableMakerTokenAmount(): BigNumber {
// Given an order for 200 wei for 2 ZRXwei fee, find 100 wei for 1 ZRXwei. Order ratio is then 100:1
- const orderToFeeRatio = this._signedOrder.makerTokenAmount.dividedBy(this._signedOrder.makerFee);
+ const orderToFeeRatio = this._signedOrder.makerAssetAmount.dividedBy(this._signedOrder.makerFee);
// The number of times the maker can fill the order, if each fill only required the transfer of a single
// baseUnit of fee tokens.
// Given 2 ZRXwei, the maximum amount of times Maker can fill this order, in terms of fees, is 2
@@ -81,10 +81,10 @@ export class RemainingFillableCalculator {
// When Ratio is not fully divisible there can be remainders which cannot be represented, so they are floored.
// This can result in a RoundingError being thrown by the Exchange Contract.
const partiallyFillableMakerTokenAmount = fillableTimesInMakerTokenUnits
- .times(this._signedOrder.makerTokenAmount)
+ .times(this._signedOrder.makerAssetAmount)
.dividedToIntegerBy(this._signedOrder.makerFee);
const partiallyFillableFeeTokenAmount = fillableTimesInFeeTokenBaseUnits
- .times(this._signedOrder.makerTokenAmount)
+ .times(this._signedOrder.makerAssetAmount)
.dividedToIntegerBy(this._signedOrder.makerFee);
const partiallyFillableAmount = BigNumber.min(
partiallyFillableMakerTokenAmount,
diff --git a/packages/order-utils/src/signature_utils.ts b/packages/order-utils/src/signature_utils.ts
index ebd636b20..106bbf4e8 100644
--- a/packages/order-utils/src/signature_utils.ts
+++ b/packages/order-utils/src/signature_utils.ts
@@ -1,28 +1,97 @@
import { schemas } from '@0xproject/json-schemas';
-import { ECSignature, Provider } from '@0xproject/types';
+import { ECSignature, Provider, SignatureType } from '@0xproject/types';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash';
+import { artifacts } from './artifacts';
import { assert } from './assert';
+import { ExchangeContract } from './generated_contract_wrappers/exchange';
+import { ISignerContract } from './generated_contract_wrappers/i_signer';
import { OrderError } from './types';
/**
- * Verifies that the elliptic curve signature `signature` was generated
- * by signing `data` with the private key corresponding to the `signerAddress` address.
+ * Verifies that the provided signature is valid according to the 0x Protocol smart contracts
* @param data The hex encoded data signed by the supplied signature.
* @param signature An object containing the elliptic curve signature parameters.
* @param signerAddress The hex encoded address that signed the data, producing the supplied signature.
* @return Whether the signature is valid for the supplied signerAddress and data.
*/
-export function isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
+export async function isValidSignatureAsync(
+ provider: Provider,
+ data: string,
+ signature: string,
+ signerAddress: string,
+): Promise<boolean> {
+ const signatureTypeIndexIfExists = getSignatureTypeIndexIfExists(signature);
+ if (_.isUndefined(signatureTypeIndexIfExists)) {
+ throw new Error(`Unrecognized signatureType in signature: ${signature}`);
+ }
+
+ switch (signatureTypeIndexIfExists) {
+ case SignatureType.Illegal:
+ case SignatureType.Invalid:
+ return false;
+
+ // Question: Does it make sense to handle this?
+ case SignatureType.Caller:
+ return true;
+
+ // TODO: Rename this type to `EthSign` b/c multiple of the signature
+ // types use ECRecover...
+ case SignatureType.Ecrecover: {
+ const ecSignature = parseECSignature(signature);
+ const dataBuff = ethUtil.toBuffer(data);
+ const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff);
+ const msgHash = ethUtil.bufferToHex(msgHashBuff);
+ return isValidECSignature(msgHash, ecSignature, signerAddress);
+ }
+
+ case SignatureType.EIP712: {
+ const ecSignature = parseECSignature(signature);
+ return isValidECSignature(data, ecSignature, signerAddress);
+ }
+
+ case SignatureType.Trezor: {
+ const dataBuff = ethUtil.toBuffer(data);
+ const msgHashBuff = hashTrezorPersonalMessage(dataBuff);
+ const msgHash = ethUtil.bufferToHex(msgHashBuff);
+ const ecSignature = parseECSignature(signature);
+ return isValidECSignature(msgHash, ecSignature, signerAddress);
+ }
+
+ // TODO: Rename Contract -> Wallet
+ case SignatureType.Contract: {
+ const signerContract = new ISignerContract(artifacts.ISigner.abi, signerAddress, provider);
+ const isValid = await signerContract.isValidSignature.callAsync(data, signature);
+ return isValid;
+ }
+
+ case SignatureType.PreSigned: {
+ const exchangeContract = new ExchangeContract(artifacts.Exchange.abi, signerAddress, provider);
+ const isValid = await exchangeContract.preSigned.callAsync(data, signerAddress);
+ return true;
+ }
+
+ default:
+ throw new Error(`Unhandled SignatureType: ${signatureTypeIndexIfExists}`);
+ }
+}
+
+export function getVRSHexString(ecSignature: ECSignature): string {
+ const vrs = `0x${intToHex(ecSignature.v)}${ethUtil.stripHexPrefix(ecSignature.r)}${ethUtil.stripHexPrefix(
+ ecSignature.s,
+ )}`;
+ return vrs;
+}
+
+export function isValidECSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
assert.isHexString('data', data);
assert.doesConformToSchema('signature', signature, schemas.ecSignatureSchema);
assert.isETHAddressHex('signerAddress', signerAddress);
const normalizedSignerAddress = signerAddress.toLowerCase();
- const dataBuff = ethUtil.toBuffer(data);
- const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff);
+ const msgHashBuff = ethUtil.toBuffer(data);
try {
const pubKey = ethUtil.ecrecover(
msgHashBuff,
@@ -36,6 +105,7 @@ export function isValidSignature(data: string, signature: ECSignature, signerAdd
return false;
}
}
+
/**
* Signs an orderHash and returns it's elliptic curve signature.
* This method currently supports TestRPC, Geth and Parity above and below V1.6.6
@@ -48,7 +118,7 @@ export function isValidSignature(data: string, signature: ECSignature, signerAdd
* before sending the request.
* @return An object containing the Elliptic curve signature parameters generated by signing the orderHash.
*/
-export async function signOrderHashAsync(
+export async function ecSignOrderHashAsync(
provider: Provider,
orderHash: string,
signerAddress: string,
@@ -76,7 +146,7 @@ export async function signOrderHashAsync(
const validVParamValues = [27, 28];
const ecSignatureVRS = parseSignatureHexAsVRS(signature);
if (_.includes(validVParamValues, ecSignatureVRS.v)) {
- const isValidVRSSignature = isValidSignature(orderHash, ecSignatureVRS, normalizedSignerAddress);
+ const isValidVRSSignature = isValidECSignature(orderHash, ecSignatureVRS, normalizedSignerAddress);
if (isValidVRSSignature) {
return ecSignatureVRS;
}
@@ -84,7 +154,7 @@ export async function signOrderHashAsync(
const ecSignatureRSV = parseSignatureHexAsRSV(signature);
if (_.includes(validVParamValues, ecSignatureRSV.v)) {
- const isValidRSVSignature = isValidSignature(orderHash, ecSignatureRSV, normalizedSignerAddress);
+ const isValidRSVSignature = isValidECSignature(orderHash, ecSignatureRSV, normalizedSignerAddress);
if (isValidRSVSignature) {
return ecSignatureRSV;
}
@@ -93,6 +163,39 @@ export async function signOrderHashAsync(
throw new Error(OrderError.InvalidSignature);
}
+function hashTrezorPersonalMessage(message: Buffer): Buffer {
+ const prefix = ethUtil.toBuffer('\x19Ethereum Signed Message:\n' + String.fromCharCode(message.length));
+ return ethUtil.sha3(Buffer.concat([prefix, message]));
+}
+
+function parseECSignature(signature: string): ECSignature {
+ const signatureTypeIndexIfExists = getSignatureTypeIndexIfExists(signature);
+ const ecSignatureTypes = [SignatureType.Ecrecover, SignatureType.EIP712, SignatureType.Trezor];
+ const isECSignatureType = _.includes(ecSignatureTypes, signatureTypeIndexIfExists);
+ if (!isECSignatureType) {
+ throw new Error(`Cannot parse non-ECSignature type: ${signatureTypeIndexIfExists}`);
+ }
+
+ // tslint:disable-next-line:custom-no-magic-numbers
+ const vrsHex = `0x${signature.substr(4)}`;
+ const ecSignature = parseSignatureHexAsVRS(vrsHex);
+
+ return ecSignature;
+}
+
+function intToHex(i: number): string {
+ const hex = ethUtil.bufferToHex(ethUtil.toBuffer(i));
+ return hex;
+}
+
+function getSignatureTypeIndexIfExists(signature: string): number {
+ const unprefixedSignature = ethUtil.stripHexPrefix(signature);
+ const signatureTypeHex = unprefixedSignature.substr(0, 2);
+ const base = 16;
+ const signatureTypeInt = parseInt(signatureTypeHex, base);
+ return signatureTypeInt;
+}
+
function parseSignatureHexAsVRS(signatureHex: string): ECSignature {
const signatureBuffer = ethUtil.toBuffer(signatureHex);
let v = signatureBuffer[0];
diff --git a/packages/order-utils/test/order_hash_test.ts b/packages/order-utils/test/order_hash_test.ts
index db5489509..7cb87c8ab 100644
--- a/packages/order-utils/test/order_hash_test.ts
+++ b/packages/order-utils/test/order_hash_test.ts
@@ -1,10 +1,11 @@
import { web3Factory } from '@0xproject/dev-utils';
+import { Order } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import 'make-promises-safe';
import 'mocha';
-import { constants, getOrderHashHex } from '../src';
+import { constants, orderHashUtils } from '../src';
import { chaiSetup } from './utils/chai_setup';
import { web3Wrapper } from './utils/web3_wrapper';
@@ -14,24 +15,25 @@ const expect = chai.expect;
describe('Order hashing', () => {
describe('#getOrderHashHex', () => {
- const expectedOrderHash = '0x39da987067a3c9e5f1617694f1301326ba8c8b0498ebef5df4863bed394e3c83';
+ const expectedOrderHash = '0x367ad7730eb8b5feab8a9c9f47c6fcba77a2d4df125ee6a59cc26ac955710f7e';
const fakeExchangeContractAddress = '0xb69e673309512a9d726f87304c6984054f87a93b';
- const order = {
- maker: constants.NULL_ADDRESS,
- taker: constants.NULL_ADDRESS,
- feeRecipient: constants.NULL_ADDRESS,
- makerTokenAddress: constants.NULL_ADDRESS,
- takerTokenAddress: constants.NULL_ADDRESS,
- exchangeContractAddress: fakeExchangeContractAddress,
+ const order: Order = {
+ makerAddress: constants.NULL_ADDRESS,
+ takerAddress: constants.NULL_ADDRESS,
+ senderAddress: constants.NULL_ADDRESS,
+ feeRecipientAddress: constants.NULL_ADDRESS,
+ makerAssetData: constants.NULL_ADDRESS,
+ takerAssetData: constants.NULL_ADDRESS,
+ exchangeAddress: fakeExchangeContractAddress,
salt: new BigNumber(0),
makerFee: new BigNumber(0),
takerFee: new BigNumber(0),
- makerTokenAmount: new BigNumber(0),
- takerTokenAmount: new BigNumber(0),
- expirationUnixTimestampSec: new BigNumber(0),
+ makerAssetAmount: new BigNumber(0),
+ takerAssetAmount: new BigNumber(0),
+ expirationTimeSeconds: new BigNumber(0),
};
it('calculates the order hash', async () => {
- const orderHash = getOrderHashHex(order);
+ const orderHash = orderHashUtils.getOrderHashHex(order);
expect(orderHash).to.be.equal(expectedOrderHash);
});
it('throws a readable error message if taker format is invalid', async () => {
@@ -41,7 +43,7 @@ describe('Order hashing', () => {
};
const expectedErrorMessage =
'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
- expect(() => getOrderHashHex(orderWithInvalidtakerFormat)).to.throw(expectedErrorMessage);
+ expect(() => orderHashUtils.getOrderHashHex(orderWithInvalidtakerFormat)).to.throw(expectedErrorMessage);
});
});
});
diff --git a/packages/order-utils/test/signature_utils_test.ts b/packages/order-utils/test/signature_utils_test.ts
index e24fa0ce5..4babd5582 100644
--- a/packages/order-utils/test/signature_utils_test.ts
+++ b/packages/order-utils/test/signature_utils_test.ts
@@ -7,8 +7,8 @@ import 'make-promises-safe';
import 'mocha';
import * as Sinon from 'sinon';
-import { generatePseudoRandomSalt, isValidOrderHash, isValidSignature, signOrderHashAsync } from '../src';
-import * as signatureUtils from '../src/signature_utils';
+import { ecSignOrderHashAsync, generatePseudoRandomSalt, orderHashUtils } from '../src';
+import { isValidECSignature, isValidSignatureAsync } from '../src/signature_utils';
import { chaiSetup } from './utils/chai_setup';
import { provider, web3Wrapper } from './utils/web3_wrapper';
@@ -20,7 +20,62 @@ const SHOULD_ADD_PERSONAL_MESSAGE_PREFIX = false;
describe('Signature utils', () => {
describe('#isValidSignature', () => {
- // The Exchange smart contract `isValidSignature` method only validates orderHashes and assumes
+ let dataHex = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
+ const ethSignSignature =
+ '0x031B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254';
+ let address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
+
+ it("should return false if the data doesn't pertain to the signature & address", async () => {
+ expect(await isValidSignatureAsync(provider, '0x0', ethSignSignature, address)).to.be.false();
+ });
+ it("should return false if the address doesn't pertain to the signature & data", async () => {
+ const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
+ expect(
+ await isValidSignatureAsync(provider, dataHex, ethSignSignature, validUnrelatedAddress),
+ ).to.be.false();
+ });
+ it("should return false if the signature doesn't pertain to the dataHex & address", async () => {
+ const signatureArray = ethSignSignature.split('');
+ // tslint:disable-next-line:custom-no-magic-numbers
+ signatureArray[5] = 'C'; // V = 28, instead of 27
+ const wrongSignature = signatureArray.join('');
+ expect(await isValidSignatureAsync(provider, dataHex, wrongSignature, address)).to.be.false();
+ });
+
+ it('should throw if signatureType is invalid', () => {
+ const signatureArray = ethSignSignature.split('');
+ signatureArray[3] = '9'; // SignatureType w/ index 9 doesn't exist
+ const signatureWithInvalidType = signatureArray.join('');
+ expect(isValidSignatureAsync(provider, dataHex, signatureWithInvalidType, address)).to.be.rejected();
+ });
+
+ it('should return true for a valid Ecrecover (EthSign) signature', async () => {
+ const isValidSignatureLocal = await isValidSignatureAsync(provider, dataHex, ethSignSignature, address);
+ expect(isValidSignatureLocal).to.be.true();
+ });
+
+ it('should return true for a valid EIP712 signature', async () => {
+ dataHex = '0xa1d7403bcbbcd75ec233cfd6584ff8dabed677d0e9bb32c2bea94e9dd8a109da';
+ address = '0x6ecbe1db9ef729cbe972c83fb886247691fb6beb';
+ const eip712Signature =
+ '0x041bdde07aac4bf12c12ddbb155919c43eba4146a2cfcf904a862950dbebe332554c6674975603eb5a4eaf8fd7f2e06350267e5b36cda9851a89f8bb49fe2fc9afe2';
+ const isValidSignatureLocal = await isValidSignatureAsync(provider, dataHex, eip712Signature, address);
+ expect(isValidSignatureLocal).to.be.true();
+ });
+
+ it('should return true for a valid Trezor signature', async () => {
+ dataHex = '0xd0d994e31c88f33fd8a572552a70ed339de579e5ba49ee1d17cc978bbe1cdd21';
+ address = '0x6ecbe1db9ef729cbe972c83fb886247691fb6beb';
+ const trezorSignature =
+ '0x051ce4760660e6495b5ae6723087bea073b3a99ce98ea81fdf00c240279c010e63d05b87bc34c4d67d4776e8d5aeb023a67484f4eaf0fd353b40893e5101e845cd99';
+ const isValidSignatureLocal = await isValidSignatureAsync(provider, dataHex, trezorSignature, address);
+ expect(isValidSignatureLocal).to.be.true();
+ });
+
+ // TODO: remaining sigs
+ });
+ describe('#isValidECSignature', () => {
+ // The Exchange smart contract `isValidECSignature` method only validates orderHashes and assumes
// the length of the data is exactly 32 bytes. Thus for these tests, we use data of this size.
const dataHex = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
const signature = {
@@ -30,18 +85,18 @@ describe('Signature utils', () => {
};
const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
it("should return false if the data doesn't pertain to the signature & address", async () => {
- expect(isValidSignature('0x0', signature, address)).to.be.false();
+ expect(isValidECSignature('0x0', signature, address)).to.be.false();
});
it("should return false if the address doesn't pertain to the signature & data", async () => {
const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
- expect(isValidSignature(dataHex, signature, validUnrelatedAddress)).to.be.false();
+ expect(isValidECSignature(dataHex, signature, validUnrelatedAddress)).to.be.false();
});
it("should return false if the signature doesn't pertain to the dataHex & address", async () => {
const wrongSignature = _.assign({}, signature, { v: 28 });
- expect(isValidSignature(dataHex, wrongSignature, address)).to.be.false();
+ expect(isValidECSignature(dataHex, wrongSignature, address)).to.be.false();
});
it('should return true if the signature does pertain to the dataHex & address', async () => {
- const isValidSignatureLocal = isValidSignature(dataHex, signature, address);
+ const isValidSignatureLocal = isValidECSignature(dataHex, signature, address);
expect(isValidSignatureLocal).to.be.true();
});
});
@@ -60,20 +115,20 @@ describe('Signature utils', () => {
});
describe('#isValidOrderHash', () => {
it('returns false if the value is not a hex string', () => {
- const isValid = isValidOrderHash('not a hex');
+ const isValid = orderHashUtils.isValidOrderHash('not a hex');
expect(isValid).to.be.false();
});
it('returns false if the length is wrong', () => {
- const isValid = isValidOrderHash('0xdeadbeef');
+ const isValid = orderHashUtils.isValidOrderHash('0xdeadbeef');
expect(isValid).to.be.false();
});
it('returns true if order hash is correct', () => {
const orderHashLength = 65;
- const isValid = isValidOrderHash('0x' + Array(orderHashLength).join('0'));
+ const isValid = orderHashUtils.isValidOrderHash('0x' + Array(orderHashLength).join('0'));
expect(isValid).to.be.true();
});
});
- describe('#signOrderHashAsync', () => {
+ describe('#ecSignOrderHashAsync', () => {
let stubs: Sinon.SinonStub[] = [];
let makerAddress: string;
before(async () => {
@@ -92,7 +147,7 @@ describe('Signature utils', () => {
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
};
- const ecSignature = await signOrderHashAsync(
+ const ecSignature = await ecSignOrderHashAsync(
provider,
orderHash,
makerAddress,
@@ -126,7 +181,7 @@ describe('Signature utils', () => {
},
};
- const ecSignature = await signOrderHashAsync(
+ const ecSignature = await ecSignOrderHashAsync(
fakeProvider,
orderHash,
makerAddress,
@@ -157,7 +212,7 @@ describe('Signature utils', () => {
},
};
- const ecSignature = await signOrderHashAsync(
+ const ecSignature = await ecSignOrderHashAsync(
fakeProvider,
orderHash,
makerAddress,
diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts
index 7831f580e..8ec82034d 100644
--- a/packages/types/src/index.ts
+++ b/packages/types/src/index.ts
@@ -292,18 +292,15 @@ export interface Order {
makerAssetData: string;
takerAssetData: string;
salt: BigNumber;
+ exchangeAddress: string;
feeRecipientAddress: string;
expirationTimeSeconds: BigNumber;
}
-export interface SignedOrder extends UnsignedOrder {
+export interface SignedOrder extends Order {
signature: string;
}
-export interface UnsignedOrder extends Order {
- exchangeAddress: string;
-}
-
/**
* Elliptic Curve signature
*/
@@ -386,3 +383,46 @@ export interface Token {
symbol: string;
decimals: number;
}
+
+export enum SignatureType {
+ Illegal,
+ Invalid,
+ Caller,
+ Ecrecover,
+ EIP712,
+ Trezor,
+ Contract,
+ PreSigned,
+}
+
+/**
+ * Elliptic Curve signature
+ */
+export interface ECSignature {
+ v: number;
+ r: string;
+ s: string;
+}
+
+export enum AssetProxyId {
+ INVALID,
+ ERC20,
+ ERC721,
+}
+
+export interface ERC20ProxyData {
+ assetProxyId: AssetProxyId;
+ tokenAddress: string;
+}
+
+export interface ERC721ProxyData {
+ assetProxyId: AssetProxyId;
+ tokenAddress: string;
+ tokenId: BigNumber;
+}
+
+export interface ProxyData {
+ assetProxyId: AssetProxyId;
+ tokenAddress?: string;
+ data?: any;
+}