diff options
author | Leonid Logvinov <logvinov.leon@gmail.com> | 2018-07-09 18:21:32 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-09 18:21:32 +0800 |
commit | ecdc0636d8464c2dd440d7ba57db5cba39a3da5f (patch) | |
tree | da60741407a298274db345a6ce8afccd95d296cc | |
parent | 028184947feca7de420929f587eca9662b3bb1af (diff) | |
parent | ea12e34809225b11fc2a2f25b48995c093f3bf37 (diff) | |
download | dexon-sol-tools-ecdc0636d8464c2dd440d7ba57db5cba39a3da5f.tar.gz dexon-sol-tools-ecdc0636d8464c2dd440d7ba57db5cba39a3da5f.tar.zst dexon-sol-tools-ecdc0636d8464c2dd440d7ba57db5cba39a3da5f.zip |
Merge pull request #841 from 0xProject/feature/v2-contract-wrappers-validation
Feature/v2 contract wrappers validation
9 files changed, 188 insertions, 42 deletions
diff --git a/packages/contract-wrappers/src/contract_wrappers/erc20_proxy_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/erc20_proxy_wrapper.ts index 883d7c4d6..821d1a8a2 100644 --- a/packages/contract-wrappers/src/contract_wrappers/erc20_proxy_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/erc20_proxy_wrapper.ts @@ -1,3 +1,4 @@ +import { AssetProxyId } from '@0xproject/types'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { ContractAbi } from 'ethereum-types'; import * as _ from 'lodash'; @@ -23,9 +24,9 @@ export class ERC20ProxyWrapper extends ContractWrapper { * Get the 4 bytes ID of this asset proxy * @return Proxy id */ - public async getProxyIdAsync(): Promise<string> { + public async getProxyIdAsync(): Promise<AssetProxyId> { const ERC20ProxyContractInstance = await this._getERC20ProxyContractAsync(); - const proxyId = await ERC20ProxyContractInstance.getProxyId.callAsync(); + const proxyId = (await ERC20ProxyContractInstance.getProxyId.callAsync()) as AssetProxyId; return proxyId; } /** diff --git a/packages/contract-wrappers/src/contract_wrappers/erc721_proxy_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/erc721_proxy_wrapper.ts index 648c150df..38ecd4687 100644 --- a/packages/contract-wrappers/src/contract_wrappers/erc721_proxy_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/erc721_proxy_wrapper.ts @@ -1,3 +1,4 @@ +import { AssetProxyId } from '@0xproject/types'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { ContractAbi } from 'ethereum-types'; import * as _ from 'lodash'; @@ -23,9 +24,9 @@ export class ERC721ProxyWrapper extends ContractWrapper { * Get the 4 bytes ID of this asset proxy * @return Proxy id */ - public async getProxyIdAsync(): Promise<string> { + public async getProxyIdAsync(): Promise<AssetProxyId> { const ERC721ProxyContractInstance = await this._getERC721ProxyContractAsync(); - const proxyId = await ERC721ProxyContractInstance.getProxyId.callAsync(); + const proxyId = (await ERC721ProxyContractInstance.getProxyId.callAsync()) as AssetProxyId; return proxyId; } /** diff --git a/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts index 0e8664cc9..8b7148aed 100644 --- a/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts @@ -1,5 +1,5 @@ import { schemas } from '@0xproject/json-schemas'; -import { Order, SignedOrder } from '@0xproject/types'; +import { AssetProxyId, Order, SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { ContractAbi, LogWithDecodedArgs } from 'ethereum-types'; @@ -9,7 +9,15 @@ import { artifacts } from '../artifacts'; import { methodOptsSchema } from '../schemas/method_opts_schema'; import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema'; import { txOptsSchema } from '../schemas/tx_opts_schema'; -import { BlockRange, EventCallback, IndexedFilterValues, MethodOpts, OrderInfo, OrderTransactionOpts } from '../types'; +import { + BlockRange, + EventCallback, + ExchangeWrapperError, + IndexedFilterValues, + MethodOpts, + OrderInfo, + OrderTransactionOpts, +} from '../types'; import { assert } from '../utils/assert'; import { decorators } from '../utils/decorators'; @@ -38,21 +46,17 @@ export class ExchangeWrapper extends ContractWrapper { } /** * Retrieve the address of an asset proxy by signature. - * @param proxySignature The 4 bytes signature of an asset proxy + * @param proxyId The 4 bytes signature of an asset proxy * @param methodOpts Optional arguments this method accepts. * @return The address of an asset proxy for a given signature */ - public async getAssetProxyBySignatureAsync(proxySignature: string, methodOpts: MethodOpts = {}): Promise<string> { - assert.isHexString('proxySignature', proxySignature); + public async getAssetProxyBySignatureAsync(proxyId: AssetProxyId, methodOpts: MethodOpts = {}): Promise<string> { + assert.doesBelongToStringEnum('proxyId', proxyId, AssetProxyId); assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); const exchangeContract = await this._getExchangeContractAsync(); const txData = {}; - const assetProxy = await exchangeContract.getAssetProxy.callAsync( - proxySignature, - txData, - methodOpts.defaultBlock, - ); + const assetProxy = await exchangeContract.getAssetProxy.callAsync(proxyId, txData, methodOpts.defaultBlock); return assetProxy; } /** @@ -143,7 +147,7 @@ export class ExchangeWrapper extends ContractWrapper { signedOrder: SignedOrder, takerAssetFillAmount: BigNumber, takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount); @@ -152,6 +156,13 @@ export class ExchangeWrapper extends ContractWrapper { const normalizedTakerAddress = takerAddress.toLowerCase(); const exchangeInstance = await this._getExchangeContractAsync(); + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.fillOrder.callAsync(signedOrder, takerAssetFillAmount, signedOrder.signature, { + from: normalizedTakerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }); + } const txHash = await exchangeInstance.fillOrder.sendTransactionAsync( signedOrder, @@ -179,7 +190,7 @@ export class ExchangeWrapper extends ContractWrapper { signedOrder: SignedOrder, takerAssetFillAmount: BigNumber, takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount); @@ -188,7 +199,18 @@ export class ExchangeWrapper extends ContractWrapper { const normalizedTakerAddress = takerAddress.toLowerCase(); const exchangeInstance = await this._getExchangeContractAsync(); - + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.fillOrderNoThrow.callAsync( + signedOrder, + takerAssetFillAmount, + signedOrder.signature, + { + from: normalizedTakerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }, + ); + } const txHash = await exchangeInstance.fillOrderNoThrow.sendTransactionAsync( signedOrder, takerAssetFillAmount, @@ -216,7 +238,7 @@ export class ExchangeWrapper extends ContractWrapper { signedOrder: SignedOrder, takerAssetFillAmount: BigNumber, takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount); @@ -225,7 +247,13 @@ export class ExchangeWrapper extends ContractWrapper { const normalizedTakerAddress = takerAddress.toLowerCase(); const exchangeInstance = await this._getExchangeContractAsync(); - + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.fillOrKillOrder.callAsync(signedOrder, takerAssetFillAmount, signedOrder.signature, { + from: normalizedTakerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }); + } const txHash = await exchangeInstance.fillOrKillOrder.sendTransactionAsync( signedOrder, takerAssetFillAmount, @@ -257,7 +285,7 @@ export class ExchangeWrapper extends ContractWrapper { data: string, signature: string, senderAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.isBigNumber('salt', salt); assert.isETHAddressHex('signerAddress', signerAddress); @@ -268,7 +296,13 @@ export class ExchangeWrapper extends ContractWrapper { const normalizedSenderAddress = senderAddress.toLowerCase(); const exchangeInstance = await this._getExchangeContractAsync(); - + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.executeTransaction.callAsync(salt, signerAddress, data, signature, { + from: normalizedSenderAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }); + } const txHash = await exchangeInstance.executeTransaction.sendTransactionAsync( salt, signerAddress, @@ -296,7 +330,7 @@ export class ExchangeWrapper extends ContractWrapper { signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[], takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); _.forEach(takerAssetFillAmounts, takerAssetFillAmount => @@ -308,6 +342,13 @@ export class ExchangeWrapper extends ContractWrapper { const exchangeInstance = await this._getExchangeContractAsync(); const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.batchFillOrders.callAsync(signedOrders, takerAssetFillAmounts, signatures, { + from: normalizedTakerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }); + } const txHash = await exchangeInstance.batchFillOrders.sendTransactionAsync( signedOrders, takerAssetFillAmounts, @@ -334,7 +375,7 @@ export class ExchangeWrapper extends ContractWrapper { signedOrders: SignedOrder[], makerAssetFillAmount: BigNumber, takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); @@ -344,6 +385,13 @@ export class ExchangeWrapper extends ContractWrapper { const exchangeInstance = await this._getExchangeContractAsync(); const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.marketBuyOrders.callAsync(signedOrders, makerAssetFillAmount, signatures, { + from: normalizedTakerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }); + } const txHash = await exchangeInstance.marketBuyOrders.sendTransactionAsync( signedOrders, makerAssetFillAmount, @@ -370,7 +418,7 @@ export class ExchangeWrapper extends ContractWrapper { signedOrders: SignedOrder[], takerAssetFillAmount: BigNumber, takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); @@ -380,6 +428,13 @@ export class ExchangeWrapper extends ContractWrapper { const exchangeInstance = await this._getExchangeContractAsync(); const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.marketSellOrders.callAsync(signedOrders, takerAssetFillAmount, signatures, { + from: normalizedTakerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }); + } const txHash = await exchangeInstance.marketSellOrders.sendTransactionAsync( signedOrders, takerAssetFillAmount, @@ -406,7 +461,7 @@ export class ExchangeWrapper extends ContractWrapper { signedOrders: SignedOrder[], makerAssetFillAmount: BigNumber, takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); @@ -416,6 +471,13 @@ export class ExchangeWrapper extends ContractWrapper { const exchangeInstance = await this._getExchangeContractAsync(); const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.marketBuyOrdersNoThrow.callAsync(signedOrders, makerAssetFillAmount, signatures, { + from: normalizedTakerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }); + } const txHash = await exchangeInstance.marketBuyOrdersNoThrow.sendTransactionAsync( signedOrders, makerAssetFillAmount, @@ -442,7 +504,7 @@ export class ExchangeWrapper extends ContractWrapper { signedOrders: SignedOrder[], takerAssetFillAmount: BigNumber, takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); @@ -452,6 +514,13 @@ export class ExchangeWrapper extends ContractWrapper { const exchangeInstance = await this._getExchangeContractAsync(); const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.marketSellOrdersNoThrow.callAsync(signedOrders, takerAssetFillAmount, signatures, { + from: normalizedTakerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }); + } const txHash = await exchangeInstance.marketSellOrdersNoThrow.sendTransactionAsync( signedOrders, takerAssetFillAmount, @@ -478,7 +547,7 @@ export class ExchangeWrapper extends ContractWrapper { signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[], takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); _.forEach(takerAssetFillAmounts, takerAssetFillAmount => @@ -490,6 +559,13 @@ export class ExchangeWrapper extends ContractWrapper { const exchangeInstance = await this._getExchangeContractAsync(); const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.batchFillOrdersNoThrow.callAsync(signedOrders, takerAssetFillAmounts, signatures, { + from: normalizedTakerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }); + } const txHash = await exchangeInstance.batchFillOrdersNoThrow.sendTransactionAsync( signedOrders, takerAssetFillAmounts, @@ -516,7 +592,7 @@ export class ExchangeWrapper extends ContractWrapper { signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[], takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); _.forEach(takerAssetFillAmounts, takerAssetFillAmount => @@ -528,6 +604,13 @@ export class ExchangeWrapper extends ContractWrapper { const exchangeInstance = await this._getExchangeContractAsync(); const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.batchFillOrKillOrders.callAsync(signedOrders, takerAssetFillAmounts, signatures, { + from: normalizedTakerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }); + } const txHash = await exchangeInstance.batchFillOrKillOrders.sendTransactionAsync( signedOrders, takerAssetFillAmounts, @@ -549,7 +632,7 @@ export class ExchangeWrapper extends ContractWrapper { @decorators.asyncZeroExErrorHandler public async batchCancelOrdersAsync( orders: Array<Order | SignedOrder>, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.doesConformToSchema('orders', orders, schemas.ordersSchema); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); @@ -559,6 +642,13 @@ export class ExchangeWrapper extends ContractWrapper { const normalizedMakerAddress = makerAddress.toLowerCase(); const exchangeInstance = await this._getExchangeContractAsync(); + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.batchCancelOrders.callAsync(orders, { + from: normalizedMakerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }); + } const txHash = await exchangeInstance.batchCancelOrders.sendTransactionAsync(orders, { from: normalizedMakerAddress, gas: orderTransactionOpts.gasLimit, @@ -581,17 +671,37 @@ export class ExchangeWrapper extends ContractWrapper { leftSignedOrder: SignedOrder, rightSignedOrder: SignedOrder, takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.doesConformToSchema('leftSignedOrder', leftSignedOrder, schemas.signedOrderSchema); assert.doesConformToSchema('rightSignedOrder', rightSignedOrder, schemas.signedOrderSchema); await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); const normalizedTakerAddress = takerAddress.toLowerCase(); - // TODO(logvinov): Check that: - // rightOrder.makerAssetData === leftOrder.takerAssetData; - // rightOrder.takerAssetData === leftOrder.makerAssetData; + if ( + rightSignedOrder.makerAssetData !== leftSignedOrder.takerAssetData || + rightSignedOrder.takerAssetData !== leftSignedOrder.makerAssetData + ) { + throw new Error(ExchangeWrapperError.AssetDataMismatch); + } else { + // Smart contracts assigns the asset data from the left order to the right one so we can save gas on reducing the size of call data + rightSignedOrder.makerAssetData = '0x'; + rightSignedOrder.takerAssetData = '0x'; + } const exchangeInstance = await this._getExchangeContractAsync(); + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.matchOrders.callAsync( + leftSignedOrder, + rightSignedOrder, + leftSignedOrder.signature, + rightSignedOrder.signature, + { + from: normalizedTakerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }, + ); + } const txHash = await exchangeInstance.matchOrders.sendTransactionAsync( leftSignedOrder, rightSignedOrder, @@ -620,7 +730,7 @@ export class ExchangeWrapper extends ContractWrapper { signerAddress: string, signature: string, senderAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.isHexString('hash', hash); assert.isETHAddressHex('signerAddress', signerAddress); @@ -629,6 +739,13 @@ export class ExchangeWrapper extends ContractWrapper { assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); const normalizedTakerAddress = senderAddress.toLowerCase(); const exchangeInstance = await this._getExchangeContractAsync(); + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.preSign.callAsync(hash, signerAddress, signature, { + from: normalizedTakerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }); + } const txHash = await exchangeInstance.preSign.sendTransactionAsync(hash, signerAddress, signature, { from: normalizedTakerAddress, gas: orderTransactionOpts.gasLimit, @@ -769,7 +886,7 @@ export class ExchangeWrapper extends ContractWrapper { @decorators.asyncZeroExErrorHandler public async cancelOrderAsync( order: Order | SignedOrder, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.doesConformToSchema('order', order, schemas.orderSchema); await assert.isSenderAddressAsync('order.maker', order.makerAddress, this._web3Wrapper); @@ -777,6 +894,13 @@ export class ExchangeWrapper extends ContractWrapper { const normalizedMakerAddress = order.makerAddress.toLowerCase(); const exchangeInstance = await this._getExchangeContractAsync(); + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.cancelOrder.callAsync(order, { + from: normalizedMakerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }); + } const txHash = await exchangeInstance.cancelOrder.sendTransactionAsync(order, { from: normalizedMakerAddress, gas: orderTransactionOpts.gasLimit, @@ -797,7 +921,7 @@ export class ExchangeWrapper extends ContractWrapper { validatorAddress: string, isApproved: boolean, senderAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.isETHAddressHex('validatorAddress', validatorAddress); assert.isBoolean('isApproved', isApproved); @@ -806,6 +930,13 @@ export class ExchangeWrapper extends ContractWrapper { const normalizedSenderAddress = senderAddress.toLowerCase(); const exchangeInstance = await this._getExchangeContractAsync(); + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.setSignatureValidatorApproval.callAsync(validatorAddress, isApproved, { + from: normalizedSenderAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }); + } const txHash = await exchangeInstance.setSignatureValidatorApproval.sendTransactionAsync( validatorAddress, isApproved, @@ -829,7 +960,7 @@ export class ExchangeWrapper extends ContractWrapper { public async cancelOrdersUpToAsync( targetOrderEpoch: BigNumber, senderAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, ): Promise<string> { assert.isBigNumber('targetOrderEpoch', targetOrderEpoch); await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper); @@ -837,6 +968,13 @@ export class ExchangeWrapper extends ContractWrapper { const normalizedSenderAddress = senderAddress.toLowerCase(); const exchangeInstance = await this._getExchangeContractAsync(); + if (orderTransactionOpts.shouldValidate) { + await exchangeInstance.cancelOrdersUpTo.callAsync(targetOrderEpoch, { + from: normalizedSenderAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }); + } const txHash = await exchangeInstance.cancelOrdersUpTo.sendTransactionAsync(targetOrderEpoch, { from: normalizedSenderAddress, gas: orderTransactionOpts.gasLimit, diff --git a/packages/contract-wrappers/src/types.ts b/packages/contract-wrappers/src/types.ts index 8d19d085f..f9d7a6b9f 100644 --- a/packages/contract-wrappers/src/types.ts +++ b/packages/contract-wrappers/src/types.ts @@ -8,6 +8,10 @@ import { ERC721TokenEventArgs, ERC721TokenEvents } from './contract_wrappers/gen import { ExchangeEventArgs, ExchangeEvents } from './contract_wrappers/generated/exchange'; import { WETH9EventArgs, WETH9Events } from './contract_wrappers/generated/weth9'; +export enum ExchangeWrapperError { + AssetDataMismatch = 'ASSET_DATA_MISMATCH', +} + export enum ContractWrappersError { ExchangeContractDoesNotExist = 'EXCHANGE_CONTRACT_DOES_NOT_EXIST', ZRXContractDoesNotExist = 'ZRX_CONTRACT_DOES_NOT_EXIST', @@ -31,8 +35,6 @@ export enum ContractWrappersError { export enum InternalContractWrappersError { NoAbiDecoder = 'NO_ABI_DECODER', - ZrxNotInTokenRegistry = 'ZRX_NOT_IN_TOKEN_REGISTRY', - WethNotInTokenRegistry = 'WETH_NOT_IN_TOKEN_REGISTRY', } export type LogEvent = LogEntryEvent; diff --git a/packages/contract-wrappers/src/utils/constants.ts b/packages/contract-wrappers/src/utils/constants.ts index 76d805cac..039475b7f 100644 --- a/packages/contract-wrappers/src/utils/constants.ts +++ b/packages/contract-wrappers/src/utils/constants.ts @@ -4,6 +4,7 @@ export const constants = { NULL_ADDRESS: '0x0000000000000000000000000000000000000000', TESTRPC_NETWORK_ID: 50, INVALID_JUMP_PATTERN: 'invalid JUMP at', + REVERT: 'revert', OUT_OF_GAS_PATTERN: 'out of gas', INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string', // tslint:disable-next-line:custom-no-magic-numbers diff --git a/packages/contract-wrappers/src/utils/decorators.ts b/packages/contract-wrappers/src/utils/decorators.ts index ccb4c6e11..6e77450e8 100644 --- a/packages/contract-wrappers/src/utils/decorators.ts +++ b/packages/contract-wrappers/src/utils/decorators.ts @@ -1,3 +1,4 @@ +import { RevertReason } from '@0xproject/types'; import * as _ from 'lodash'; import { AsyncMethod, ContractWrappersError, SyncMethod } from '../types'; @@ -13,6 +14,10 @@ const contractCallErrorTransformer = (error: Error) => { if (_.includes(error.message, constants.OUT_OF_GAS_PATTERN)) { return new Error(ContractWrappersError.OutOfGas); } + if (_.includes(error.message, constants.REVERT)) { + const revertReason = error.message.split(constants.REVERT)[1].trim(); + return new Error(revertReason); + } return error; }; diff --git a/packages/contract_templates/contract.handlebars b/packages/contract_templates/contract.handlebars index d0f74a2bc..0810c4d90 100644 --- a/packages/contract_templates/contract.handlebars +++ b/packages/contract_templates/contract.handlebars @@ -27,6 +27,7 @@ export enum {{contractName}}Events { {{/each}} {{/if}} +/* istanbul ignore next */ // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class {{contractName}}Contract extends BaseContract { diff --git a/packages/contract_templates/partials/callAsync.handlebars b/packages/contract_templates/partials/callAsync.handlebars index 35fbe3c85..fcaae57c6 100644 --- a/packages/contract_templates/partials/callAsync.handlebars +++ b/packages/contract_templates/partials/callAsync.handlebars @@ -1,4 +1,3 @@ -{{#hasReturnValue}} async callAsync( {{> typed_params inputs=inputs}} callData: Partial<CallData> = {}, @@ -27,4 +26,3 @@ async callAsync( resultArray = BaseContract._formatABIDataItemList(outputAbi, resultArray, BaseContract._bnToBigNumber.bind(this)); return resultArray{{#singleReturnValue}}[0]{{/singleReturnValue}}; }, -{{/hasReturnValue}} diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 3b71366f5..03fa2fe8a 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -158,7 +158,6 @@ export interface ECSignature { } export enum AssetProxyId { - INVALID = '0x00000000', ERC20 = '0xf47261b0', ERC721 = '0x08e937fa', } |