diff --git a/contracts/exchange-libs/package.json b/contracts/exchange-libs/package.json index 38939fb6da..a6c65c502b 100644 --- a/contracts/exchange-libs/package.json +++ b/contracts/exchange-libs/package.json @@ -54,7 +54,6 @@ "devDependencies": { "@0x/abi-gen": "^5.0.3", "@0x/contracts-gen": "^2.0.3", - "@0x/contracts-test-utils": "^5.1.0", "@0x/dev-utils": "^3.1.0", "@0x/sol-compiler": "^4.0.3", "@0x/subproviders": "^6.0.3", @@ -82,6 +81,7 @@ }, "dependencies": { "@0x/base-contract": "^6.0.3", + "@0x/contracts-test-utils": "^5.1.0", "@0x/contracts-utils": "^4.0.3", "@0x/order-utils": "^10.1.0", "@0x/types": "^3.1.1", diff --git a/contracts/exchange-libs/src/reference_functions.ts b/contracts/exchange-libs/src/reference_functions.ts index 50247332d1..2966545e68 100644 --- a/contracts/exchange-libs/src/reference_functions.ts +++ b/contracts/exchange-libs/src/reference_functions.ts @@ -1,6 +1,7 @@ +import { orderHashUtils } from '@0x/contracts-test-utils'; import { ReferenceFunctions } from '@0x/contracts-utils'; import { FillResults, MatchedFillResults, Order } from '@0x/types'; -import { BigNumber, LibMathRevertErrors } from '@0x/utils'; +import { BigNumber, ExchangeRevertErrors, LibMathRevertErrors } from '@0x/utils'; const { safeAdd, safeSub, safeMul, safeDiv } = ReferenceFunctions; @@ -148,20 +149,19 @@ export function calculateMatchResults( .times(rightOrder.makerAssetAmount) .lt(leftOrder.takerAssetAmount.times(rightOrder.takerAssetAmount)) ) { - throw new Error( - `Orders Cannot Be Matched.\nLeft Order: ${JSON.stringify(leftOrder, null, 4)}\Right Order: ${JSON.stringify( - rightOrder, - null, - 4, - )}`, + throw new ExchangeRevertErrors.NegativeSpreadError( + orderHashUtils.getOrderHashHex(leftOrder), + orderHashUtils.getOrderHashHex(rightOrder), ); } // Asset Transfer Amounts if (leftOrder.takerAssetAmount.gt(rightOrder.makerAssetAmount)) { - leftFillResults.makerAssetFilledAmount = leftOrder.makerAssetAmount - .multipliedBy(rightOrder.makerAssetAmount) - .dividedToIntegerBy(leftOrder.takerAssetAmount); + leftFillResults.makerAssetFilledAmount = safeGetPartialAmountFloor( + leftOrder.makerAssetAmount, + leftOrder.takerAssetAmount, + rightOrder.makerAssetAmount, + ); leftFillResults.takerAssetFilledAmount = rightOrder.makerAssetAmount; rightFillResults.makerAssetFilledAmount = rightOrder.makerAssetAmount; rightFillResults.takerAssetFilledAmount = rightOrder.takerAssetAmount; diff --git a/contracts/integrations/test/framework/actors/maker.ts b/contracts/integrations/test/framework/actors/maker.ts index 06e4ddef7c..050ad75a32 100644 --- a/contracts/integrations/test/framework/actors/maker.ts +++ b/contracts/integrations/test/framework/actors/maker.ts @@ -99,7 +99,7 @@ export function MakerMixin(Base: TBase): TBase & Cons ); // Maker and taker set balances/allowances to guarantee that the fill succeeds. - // Amounts are chosen to be within each actor's balance (divided by 2, in case + // Amounts are chosen to be within each actor's balance (divided by 8, in case // e.g. makerAsset = makerFeeAsset) const [makerAssetAmount, makerFee, takerAssetAmount, takerFee] = await Promise.all( [ diff --git a/contracts/integrations/test/framework/actors/taker.ts b/contracts/integrations/test/framework/actors/taker.ts index c55998153d..a2aefa9c81 100644 --- a/contracts/integrations/test/framework/actors/taker.ts +++ b/contracts/integrations/test/framework/actors/taker.ts @@ -79,7 +79,6 @@ export function TakerMixin(Base: TBase): TBase & Cons .matchOrders(leftOrder, rightOrder, leftOrder.signature, rightOrder.signature) .awaitTransactionSuccessAsync({ from: this.actor.address, - gasPrice: DeploymentManager.gasPrice, value: DeploymentManager.protocolFee, ...txData, }); @@ -97,7 +96,6 @@ export function TakerMixin(Base: TBase): TBase & Cons .matchOrdersWithMaximalFill(leftOrder, rightOrder, leftOrder.signature, rightOrder.signature) .awaitTransactionSuccessAsync({ from: this.actor.address, - gasPrice: DeploymentManager.gasPrice, value: DeploymentManager.protocolFee, ...txData, }); diff --git a/contracts/integrations/test/framework/assertions/matchOrders.ts b/contracts/integrations/test/framework/assertions/matchOrders.ts index 2b08700f82..6c90e429b6 100644 --- a/contracts/integrations/test/framework/assertions/matchOrders.ts +++ b/contracts/integrations/test/framework/assertions/matchOrders.ts @@ -3,7 +3,6 @@ import { TxData } from 'ethereum-types'; import * as _ from 'lodash'; import { Maker } from '../actors/maker'; -import { filterActorsByRole } from '../actors/utils'; import { DeploymentManager } from '../deployment_manager'; import { SimulationEnvironment } from '../simulation'; import { assertProtocolFeePaidAsync, getPoolInfoAsync, PoolInfo } from '../utils/assert_protocol_fee'; @@ -11,7 +10,7 @@ import { verifyMatchEvents } from '../utils/verify_match_events'; import { FunctionAssertion, FunctionResult } from './function_assertion'; -export const matchOrderRuntimeAssertion = ( +export const matchOrdersRuntimeAssertion = ( deployment: DeploymentManager, simulationEnvironment: SimulationEnvironment, withMaximalFill: boolean, @@ -22,9 +21,9 @@ export const matchOrderRuntimeAssertion = ( return { before: async (args: [Order, Order, string, string]) => { const [order] = args; - const maker = filterActorsByRole(actors, Maker).find(actor => actor.address === order.makerAddress); - // tslint:disable-next-line no-non-null-assertion - const poolInfo = getPoolInfoAsync(maker!, simulationEnvironment, deployment); + // tslint:disable-next-line no-unnecessary-type-assertion + const maker = actors.find(actor => actor.address === order.makerAddress) as Maker; + const poolInfo = getPoolInfoAsync(maker, simulationEnvironment, deployment); return poolInfo; }, after: async ( @@ -72,7 +71,7 @@ export function validMatchOrdersAssertion( return new FunctionAssertion<[Order, Order, string, string], PoolInfo | void, MatchedFillResults>( deployment.exchange, 'matchOrders', - matchOrderRuntimeAssertion(deployment, simulationEnvironment, false), + matchOrdersRuntimeAssertion(deployment, simulationEnvironment, false), ); } /* tslint:enable:no-non-null-assertion */ diff --git a/contracts/integrations/test/framework/assertions/matchOrdersWithMaximalFill.ts b/contracts/integrations/test/framework/assertions/matchOrdersWithMaximalFill.ts index e8f5257507..7ecdc54f41 100644 --- a/contracts/integrations/test/framework/assertions/matchOrdersWithMaximalFill.ts +++ b/contracts/integrations/test/framework/assertions/matchOrdersWithMaximalFill.ts @@ -6,7 +6,7 @@ import { SimulationEnvironment } from '../simulation'; import { PoolInfo } from '../utils/assert_protocol_fee'; import { FunctionAssertion } from './function_assertion'; -import { matchOrderRuntimeAssertion } from './matchOrders'; +import { matchOrdersRuntimeAssertion } from './matchOrders'; /** * A function assertion that verifies that a complete and valid `matchOrdersWithMaximalFill` succeeded and emitted the correct logs. @@ -20,7 +20,7 @@ export function validMatchOrdersWithMaximalFillAssertion( return new FunctionAssertion<[Order, Order, string, string], PoolInfo | void, MatchedFillResults>( deployment.exchange, 'matchOrdersWithMaximalFill', - matchOrderRuntimeAssertion(deployment, simulationEnvironment, true), + matchOrdersRuntimeAssertion(deployment, simulationEnvironment, true), ); } /* tslint:enable:no-non-null-assertion */ diff --git a/contracts/integrations/test/framework/utils/assert_protocol_fee.ts b/contracts/integrations/test/framework/utils/assert_protocol_fee.ts index edefea6263..fefeac146e 100644 --- a/contracts/integrations/test/framework/utils/assert_protocol_fee.ts +++ b/contracts/integrations/test/framework/utils/assert_protocol_fee.ts @@ -34,7 +34,7 @@ export async function getPoolInfoAsync( ): Promise { const { stakingWrapper } = deployment.staking; // tslint:disable-next-line no-non-null-assertion no-unnecessary-type-assertion - const poolId = maker!.makerPoolId; + const poolId = maker.makerPoolId; const { currentEpoch } = simulationEnvironment; if (poolId === undefined) { return; diff --git a/contracts/integrations/test/framework/utils/verify_match_events.ts b/contracts/integrations/test/framework/utils/verify_match_events.ts index 98e0d305ea..334c5dc7aa 100644 --- a/contracts/integrations/test/framework/utils/verify_match_events.ts +++ b/contracts/integrations/test/framework/utils/verify_match_events.ts @@ -1,7 +1,7 @@ import { ERC20TokenEvents, ERC20TokenTransferEventArgs } from '@0x/contracts-erc20'; import { ExchangeEvents, ExchangeFillEventArgs } from '@0x/contracts-exchange'; import { ReferenceFunctions } from '@0x/contracts-exchange-libs'; -import { orderHashUtils, verifyEvents } from '@0x/contracts-test-utils'; +import { constants, orderHashUtils, verifyEvents } from '@0x/contracts-test-utils'; import { MatchedFillResults, Order } from '@0x/types'; import { BigNumber } from '@0x/utils'; import { TransactionReceiptWithDecodedLogs, TxData } from 'ethereum-types'; @@ -122,7 +122,7 @@ const verifyMatchTransferEvents = ( _to: deployment.staking.stakingProxy.address, _value: value.isLessThan(DeploymentManager.protocolFee.times(2)) ? DeploymentManager.protocolFee - : new BigNumber(0), + : constants.ZERO_AMOUNT, }, { _from: takerAddress, @@ -134,7 +134,7 @@ const verifyMatchTransferEvents = ( _to: rightOrder.feeRecipientAddress, _value: leftOrder.feeRecipientAddress === rightOrder.feeRecipientAddress - ? new BigNumber(0) + ? constants.ZERO_AMOUNT : matchResults.right.takerFeePaid, }, {