Check revert reasons in declarative and combinatorial tests

This commit is contained in:
Fabio Berger
2018-06-25 13:51:00 +02:00
parent 1353723b58
commit ad67a6add5
2 changed files with 67 additions and 61 deletions

View File

@@ -16,7 +16,7 @@ import 'make-promises-safe';
import { ExchangeContract, FillContractEventArgs } from '../generated_contract_wrappers/exchange'; import { ExchangeContract, FillContractEventArgs } from '../generated_contract_wrappers/exchange';
import { artifacts } from '../utils/artifacts'; import { artifacts } from '../utils/artifacts';
import { expectRevertOrAlwaysFailingTransactionAsync } from '../utils/assertions'; import { expectRevertReasonOrAlwaysFailingTransactionAsync } from '../utils/assertions';
import { AssetWrapper } from '../utils/asset_wrapper'; import { AssetWrapper } from '../utils/asset_wrapper';
import { chaiSetup } from '../utils/chai_setup'; import { chaiSetup } from '../utils/chai_setup';
import { constants } from '../utils/constants'; import { constants } from '../utils/constants';
@@ -298,7 +298,7 @@ export class CoreCombinatorialUtils {
const lazyStore = new BalanceAndProxyAllowanceLazyStore(balanceAndProxyAllowanceFetcher); const lazyStore = new BalanceAndProxyAllowanceLazyStore(balanceAndProxyAllowanceFetcher);
const exchangeTransferSimulator = new ExchangeTransferSimulator(lazyStore); const exchangeTransferSimulator = new ExchangeTransferSimulator(lazyStore);
let isFillFailureExpected = false; let fillRevertReasonIfExists;
try { try {
await orderValidationUtils.validateFillOrderThrowIfInvalidAsync( await orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
exchangeTransferSimulator, exchangeTransferSimulator,
@@ -312,7 +312,7 @@ export class CoreCombinatorialUtils {
logUtils.log(`Expecting fillOrder to succeed.`); logUtils.log(`Expecting fillOrder to succeed.`);
} }
} catch (err) { } catch (err) {
isFillFailureExpected = true; fillRevertReasonIfExists = err.message;
if (isVerbose) { if (isVerbose) {
logUtils.log(`Expecting fillOrder to fail with:`); logUtils.log(`Expecting fillOrder to fail with:`);
logUtils.log(err); logUtils.log(err);
@@ -324,7 +324,7 @@ export class CoreCombinatorialUtils {
signedOrder, signedOrder,
takerAssetFillAmount, takerAssetFillAmount,
lazyStore, lazyStore,
isFillFailureExpected, fillRevertReasonIfExists,
provider, provider,
); );
} }
@@ -332,12 +332,13 @@ export class CoreCombinatorialUtils {
signedOrder: SignedOrder, signedOrder: SignedOrder,
takerAssetFillAmount: BigNumber, takerAssetFillAmount: BigNumber,
lazyStore: BalanceAndProxyAllowanceLazyStore, lazyStore: BalanceAndProxyAllowanceLazyStore,
isFillFailureExpected: boolean, fillRevertReasonIfExists: string | undefined,
provider: Provider, provider: Provider,
): Promise<void> { ): Promise<void> {
if (isFillFailureExpected) { if (!_.isUndefined(fillRevertReasonIfExists)) {
return expectRevertOrAlwaysFailingTransactionAsync( return expectRevertReasonOrAlwaysFailingTransactionAsync(
this.exchangeWrapper.fillOrderAsync(signedOrder, this.takerAddress, { takerAssetFillAmount }), this.exchangeWrapper.fillOrderAsync(signedOrder, this.takerAddress, { takerAssetFillAmount }),
fillRevertReasonIfExists,
); );
} }

View File

@@ -1,4 +1,5 @@
import { ExchangeContractErrs, Order, SignedOrder } from '@0xproject/types'; import { Order, SignedOrder } from '@0xproject/types';
import { RevertReasons } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Provider } from 'ethereum-types'; import { Provider } from 'ethereum-types';
import * as _ from 'lodash'; import * as _ from 'lodash';
@@ -54,66 +55,70 @@ export class OrderValidationUtils {
senderAddress: string, senderAddress: string,
zrxAssetData: string, zrxAssetData: string,
): Promise<void> { ): Promise<void> {
const fillMakerTokenAmount = utils.getPartialAmount( try {
fillTakerAssetAmount, const fillMakerTokenAmount = utils.getPartialAmount(
signedOrder.takerAssetAmount, fillTakerAssetAmount,
signedOrder.makerAssetAmount, signedOrder.takerAssetAmount,
); signedOrder.makerAssetAmount,
await exchangeTradeEmulator.transferFromAsync( );
signedOrder.makerAssetData, await exchangeTradeEmulator.transferFromAsync(
signedOrder.makerAddress, signedOrder.makerAssetData,
senderAddress, signedOrder.makerAddress,
fillMakerTokenAmount, senderAddress,
TradeSide.Maker, fillMakerTokenAmount,
TransferType.Trade, TradeSide.Maker,
); TransferType.Trade,
await exchangeTradeEmulator.transferFromAsync( );
signedOrder.takerAssetData, await exchangeTradeEmulator.transferFromAsync(
senderAddress, signedOrder.takerAssetData,
signedOrder.makerAddress, senderAddress,
fillTakerAssetAmount, signedOrder.makerAddress,
TradeSide.Taker, fillTakerAssetAmount,
TransferType.Trade, TradeSide.Taker,
); TransferType.Trade,
const makerFeeAmount = utils.getPartialAmount( );
fillTakerAssetAmount, const makerFeeAmount = utils.getPartialAmount(
signedOrder.takerAssetAmount, fillTakerAssetAmount,
signedOrder.makerFee, signedOrder.takerAssetAmount,
); signedOrder.makerFee,
await exchangeTradeEmulator.transferFromAsync( );
zrxAssetData, await exchangeTradeEmulator.transferFromAsync(
signedOrder.makerAddress, zrxAssetData,
signedOrder.feeRecipientAddress, signedOrder.makerAddress,
makerFeeAmount, signedOrder.feeRecipientAddress,
TradeSide.Maker, makerFeeAmount,
TransferType.Fee, TradeSide.Maker,
); TransferType.Fee,
const takerFeeAmount = utils.getPartialAmount( );
fillTakerAssetAmount, const takerFeeAmount = utils.getPartialAmount(
signedOrder.takerAssetAmount, fillTakerAssetAmount,
signedOrder.takerFee, signedOrder.takerAssetAmount,
); signedOrder.takerFee,
await exchangeTradeEmulator.transferFromAsync( );
zrxAssetData, await exchangeTradeEmulator.transferFromAsync(
senderAddress, zrxAssetData,
signedOrder.feeRecipientAddress, senderAddress,
takerFeeAmount, signedOrder.feeRecipientAddress,
TradeSide.Taker, takerFeeAmount,
TransferType.Fee, TradeSide.Taker,
); TransferType.Fee,
);
} catch (err) {
throw new Error(RevertReasons.TransferFailed);
}
} }
private static _validateRemainingFillAmountNotZeroOrThrow( private static _validateRemainingFillAmountNotZeroOrThrow(
takerAssetAmount: BigNumber, takerAssetAmount: BigNumber,
filledTakerTokenAmount: BigNumber, filledTakerTokenAmount: BigNumber,
): void { ): void {
if (takerAssetAmount.eq(filledTakerTokenAmount)) { if (takerAssetAmount.eq(filledTakerTokenAmount)) {
throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero); throw new Error(RevertReasons.OrderUnfillable);
} }
} }
private static _validateOrderNotExpiredOrThrow(expirationTimeSeconds: BigNumber): void { private static _validateOrderNotExpiredOrThrow(expirationTimeSeconds: BigNumber): void {
const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec(); const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
if (expirationTimeSeconds.lessThan(currentUnixTimestampSec)) { if (expirationTimeSeconds.lessThan(currentUnixTimestampSec)) {
throw new Error(ExchangeContractErrs.OrderFillExpired); throw new Error(RevertReasons.OrderUnfillable);
} }
} }
constructor(orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher) { constructor(orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher) {
@@ -153,7 +158,7 @@ export class OrderValidationUtils {
zrxAssetData: string, zrxAssetData: string,
): Promise<BigNumber> { ): Promise<BigNumber> {
if (fillTakerAssetAmount.eq(0)) { if (fillTakerAssetAmount.eq(0)) {
throw new Error(ExchangeContractErrs.OrderFillAmountZero); throw new Error(RevertReasons.TakerAssetFillAmount);
} }
const orderHash = orderHashUtils.getOrderHashHex(signedOrder); const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
const isValid = await isValidSignatureAsync( const isValid = await isValidSignatureAsync(
@@ -171,7 +176,7 @@ export class OrderValidationUtils {
filledTakerTokenAmount, filledTakerTokenAmount,
); );
if (signedOrder.takerAddress !== constants.NULL_ADDRESS && signedOrder.takerAddress !== takerAddress) { if (signedOrder.takerAddress !== constants.NULL_ADDRESS && signedOrder.takerAddress !== takerAddress) {
throw new Error(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker); throw new Error(RevertReasons.InvalidTaker);
} }
OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationTimeSeconds); OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationTimeSeconds);
const remainingTakerTokenAmount = signedOrder.takerAssetAmount.minus(filledTakerTokenAmount); const remainingTakerTokenAmount = signedOrder.takerAssetAmount.minus(filledTakerTokenAmount);
@@ -192,7 +197,7 @@ export class OrderValidationUtils {
signedOrder.makerAssetAmount, signedOrder.makerAssetAmount,
); );
if (wouldRoundingErrorOccur) { if (wouldRoundingErrorOccur) {
throw new Error(ExchangeContractErrs.OrderFillRoundingError); throw new Error(RevertReasons.RoundingError);
} }
return filledTakerTokenAmount; return filledTakerTokenAmount;
} }
@@ -213,7 +218,7 @@ export class OrderValidationUtils {
zrxAssetData, zrxAssetData,
); );
if (filledTakerTokenAmount !== fillTakerAssetAmount) { if (filledTakerTokenAmount !== fillTakerAssetAmount) {
throw new Error(ExchangeContractErrs.InsufficientRemainingFillAmount); throw new Error(RevertReasons.OrderUnfillable);
} }
} }
} }