Fuzz testing for matchOrders and matchOrdersWithMaximalFill.
This commit is contained in:
@@ -1,13 +1,7 @@
|
||||
import { ERC20TokenEvents, ERC20TokenTransferEventArgs } from '@0x/contracts-erc20';
|
||||
import { ExchangeEvents, ExchangeFillEventArgs } from '@0x/contracts-exchange';
|
||||
import { ReferenceFunctions } from '@0x/contracts-exchange-libs';
|
||||
import {
|
||||
AggregatedStats,
|
||||
constants as stakingConstants,
|
||||
PoolStats,
|
||||
StakingEvents,
|
||||
StakingStakingPoolEarnedRewardsInEpochEventArgs,
|
||||
} from '@0x/contracts-staking';
|
||||
import { AggregatedStats, PoolStats } from '@0x/contracts-staking';
|
||||
import { expect, orderHashUtils, verifyEvents } from '@0x/contracts-test-utils';
|
||||
import { FillResults, Order } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
@@ -18,6 +12,7 @@ import { Maker } from '../actors/maker';
|
||||
import { filterActorsByRole } from '../actors/utils';
|
||||
import { DeploymentManager } from '../deployment_manager';
|
||||
import { SimulationEnvironment } from '../simulation';
|
||||
import { assertProtocolFeePaidAsync, getPoolInfoAsync } from '../utils/assert_protocol_fee';
|
||||
|
||||
import { FunctionAssertion, FunctionResult } from './function_assertion';
|
||||
|
||||
@@ -109,8 +104,8 @@ export function validFillOrderAssertion(
|
||||
deployment: DeploymentManager,
|
||||
simulationEnvironment: SimulationEnvironment,
|
||||
): FunctionAssertion<[Order, BigNumber, string], FillOrderBeforeInfo | void, FillResults> {
|
||||
const { stakingWrapper } = deployment.staking;
|
||||
const { actors } = simulationEnvironment;
|
||||
const expectedProtocolFee = DeploymentManager.protocolFee;
|
||||
|
||||
return new FunctionAssertion<[Order, BigNumber, string], FillOrderBeforeInfo | void, FillResults>(
|
||||
deployment.exchange,
|
||||
@@ -118,27 +113,9 @@ export function validFillOrderAssertion(
|
||||
{
|
||||
before: async (args: [Order, BigNumber, string]) => {
|
||||
const [order] = args;
|
||||
const { currentEpoch } = simulationEnvironment;
|
||||
const maker = filterActorsByRole(actors, Maker).find(actor => actor.address === order.makerAddress);
|
||||
|
||||
const poolId = maker!.makerPoolId;
|
||||
if (poolId === undefined) {
|
||||
return;
|
||||
} else {
|
||||
const poolStats = PoolStats.fromArray(
|
||||
await stakingWrapper.poolStatsByEpoch(poolId, currentEpoch).callAsync(),
|
||||
);
|
||||
const aggregatedStats = AggregatedStats.fromArray(
|
||||
await stakingWrapper.aggregatedStatsByEpoch(currentEpoch).callAsync(),
|
||||
);
|
||||
const { currentEpochBalance: poolStake } = await stakingWrapper
|
||||
.getTotalStakeDelegatedToPool(poolId)
|
||||
.callAsync();
|
||||
const { currentEpochBalance: operatorStake } = await stakingWrapper
|
||||
.getStakeDelegatedToPoolByOwner(simulationEnvironment.stakingPools[poolId].operator, poolId)
|
||||
.callAsync();
|
||||
return { poolStats, aggregatedStats, poolStake, poolId, operatorStake };
|
||||
}
|
||||
const poolInfo = getPoolInfoAsync(maker!, simulationEnvironment, deployment);
|
||||
return poolInfo;
|
||||
},
|
||||
after: async (
|
||||
beforeInfo: FillOrderBeforeInfo | void,
|
||||
@@ -150,69 +127,20 @@ export function validFillOrderAssertion(
|
||||
expect(result.success, `Error: ${result.data}`).to.be.true();
|
||||
|
||||
const [order, fillAmount] = args;
|
||||
const { currentEpoch } = simulationEnvironment;
|
||||
|
||||
// Ensure that the correct events were emitted.
|
||||
verifyFillEvents(txData, order, result.receipt!, deployment, fillAmount);
|
||||
|
||||
// If the maker is not in a staking pool, there's nothing to check
|
||||
if (beforeInfo === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const expectedPoolStats = { ...beforeInfo.poolStats };
|
||||
const expectedAggregatedStats = { ...beforeInfo.aggregatedStats };
|
||||
const expectedEvents = [];
|
||||
|
||||
// Refer to `payProtocolFee`
|
||||
if (beforeInfo.poolStake.isGreaterThanOrEqualTo(stakingConstants.DEFAULT_PARAMS.minimumPoolStake)) {
|
||||
if (beforeInfo.poolStats.feesCollected.isZero()) {
|
||||
const membersStakeInPool = beforeInfo.poolStake.minus(beforeInfo.operatorStake);
|
||||
const weightedStakeInPool = beforeInfo.operatorStake.plus(
|
||||
ReferenceFunctions.getPartialAmountFloor(
|
||||
stakingConstants.DEFAULT_PARAMS.rewardDelegatedStakeWeight,
|
||||
new BigNumber(stakingConstants.PPM),
|
||||
membersStakeInPool,
|
||||
),
|
||||
);
|
||||
expectedPoolStats.membersStake = membersStakeInPool;
|
||||
expectedPoolStats.weightedStake = weightedStakeInPool;
|
||||
expectedAggregatedStats.totalWeightedStake = beforeInfo.aggregatedStats.totalWeightedStake.plus(
|
||||
weightedStakeInPool,
|
||||
);
|
||||
expectedAggregatedStats.numPoolsToFinalize = beforeInfo.aggregatedStats.numPoolsToFinalize.plus(
|
||||
1,
|
||||
);
|
||||
// StakingPoolEarnedRewardsInEpoch event emitted
|
||||
expectedEvents.push({
|
||||
epoch: currentEpoch,
|
||||
poolId: beforeInfo.poolId,
|
||||
});
|
||||
}
|
||||
// Credit a protocol fee to the maker's staking pool
|
||||
expectedPoolStats.feesCollected = beforeInfo.poolStats.feesCollected.plus(
|
||||
DeploymentManager.protocolFee,
|
||||
);
|
||||
// Update aggregated stats
|
||||
expectedAggregatedStats.totalFeesCollected = beforeInfo.aggregatedStats.totalFeesCollected.plus(
|
||||
DeploymentManager.protocolFee,
|
||||
// If the maker is in a staking pool then validate the protocol fee.
|
||||
if (beforeInfo !== undefined) {
|
||||
await assertProtocolFeePaidAsync(
|
||||
beforeInfo,
|
||||
result,
|
||||
simulationEnvironment,
|
||||
deployment,
|
||||
expectedProtocolFee,
|
||||
);
|
||||
}
|
||||
|
||||
// Check for updated stats and event
|
||||
const poolStats = PoolStats.fromArray(
|
||||
await stakingWrapper.poolStatsByEpoch(beforeInfo.poolId, currentEpoch).callAsync(),
|
||||
);
|
||||
const aggregatedStats = AggregatedStats.fromArray(
|
||||
await stakingWrapper.aggregatedStatsByEpoch(currentEpoch).callAsync(),
|
||||
);
|
||||
expect(poolStats).to.deep.equal(expectedPoolStats);
|
||||
expect(aggregatedStats).to.deep.equal(expectedAggregatedStats);
|
||||
verifyEvents<StakingStakingPoolEarnedRewardsInEpochEventArgs>(
|
||||
result.receipt!,
|
||||
expectedEvents,
|
||||
StakingEvents.StakingPoolEarnedRewardsInEpoch,
|
||||
);
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import { MatchedFillResults, Order } from '@0x/types';
|
||||
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';
|
||||
import { verifyMatchEvents } from '../utils/verify_match_events';
|
||||
|
||||
import { FunctionAssertion, FunctionResult } from './function_assertion';
|
||||
|
||||
export const matchOrderRuntimeAssertion = (
|
||||
deployment: DeploymentManager,
|
||||
simulationEnvironment: SimulationEnvironment,
|
||||
withMaximalFill: boolean,
|
||||
) => {
|
||||
const { actors } = simulationEnvironment;
|
||||
const expectedProtocolFee = DeploymentManager.protocolFee.times(2);
|
||||
|
||||
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);
|
||||
return poolInfo;
|
||||
},
|
||||
after: async (
|
||||
beforeInfo: PoolInfo | void,
|
||||
result: FunctionResult,
|
||||
args: [Order, Order, string, string],
|
||||
txData: Partial<TxData>,
|
||||
) => {
|
||||
// Ensure that the correct events were emitted.
|
||||
const [leftOrder, rightOrder] = args;
|
||||
|
||||
verifyMatchEvents(
|
||||
txData,
|
||||
leftOrder,
|
||||
rightOrder,
|
||||
// tslint:disable-next-line no-non-null-assertion no-unnecessary-type-assertion
|
||||
result.receipt!,
|
||||
deployment,
|
||||
withMaximalFill,
|
||||
);
|
||||
|
||||
// If the maker is in a staking pool then validate the protocol fee.
|
||||
if (beforeInfo !== undefined) {
|
||||
await assertProtocolFeePaidAsync(
|
||||
beforeInfo,
|
||||
result,
|
||||
simulationEnvironment,
|
||||
deployment,
|
||||
expectedProtocolFee,
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* A function assertion that verifies that a complete and valid `matchOrders` succeeded and emitted the correct logs.
|
||||
*/
|
||||
/* tslint:disable:no-unnecessary-type-assertion */
|
||||
/* tslint:disable:no-non-null-assertion */
|
||||
export function validMatchOrdersAssertion(
|
||||
deployment: DeploymentManager,
|
||||
simulationEnvironment: SimulationEnvironment,
|
||||
): FunctionAssertion<[Order, Order, string, string], PoolInfo | void, MatchedFillResults> {
|
||||
return new FunctionAssertion<[Order, Order, string, string], PoolInfo | void, MatchedFillResults>(
|
||||
deployment.exchange,
|
||||
'matchOrders',
|
||||
matchOrderRuntimeAssertion(deployment, simulationEnvironment, false),
|
||||
);
|
||||
}
|
||||
/* tslint:enable:no-non-null-assertion */
|
||||
/* tslint:enable:no-unnecessary-type-assertion */
|
||||
@@ -0,0 +1,27 @@
|
||||
import { MatchedFillResults, Order } from '@0x/types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { DeploymentManager } from '../deployment_manager';
|
||||
import { SimulationEnvironment } from '../simulation';
|
||||
import { PoolInfo } from '../utils/assert_protocol_fee';
|
||||
|
||||
import { FunctionAssertion } from './function_assertion';
|
||||
import { matchOrderRuntimeAssertion } from './matchOrders';
|
||||
|
||||
/**
|
||||
* A function assertion that verifies that a complete and valid `matchOrdersWithMaximalFill` succeeded and emitted the correct logs.
|
||||
*/
|
||||
/* tslint:disable:no-unnecessary-type-assertion */
|
||||
/* tslint:disable:no-non-null-assertion */
|
||||
export function validMatchOrdersWithMaximalFillAssertion(
|
||||
deployment: DeploymentManager,
|
||||
simulationEnvironment: SimulationEnvironment,
|
||||
): FunctionAssertion<[Order, Order, string, string], PoolInfo | void, MatchedFillResults> {
|
||||
return new FunctionAssertion<[Order, Order, string, string], PoolInfo | void, MatchedFillResults>(
|
||||
deployment.exchange,
|
||||
'matchOrdersWithMaximalFill',
|
||||
matchOrderRuntimeAssertion(deployment, simulationEnvironment, true),
|
||||
);
|
||||
}
|
||||
/* tslint:enable:no-non-null-assertion */
|
||||
/* tslint:enable:no-unnecessary-type-assertion */
|
||||
@@ -0,0 +1,118 @@
|
||||
import { ReferenceFunctions } from '@0x/contracts-exchange-libs';
|
||||
import {
|
||||
AggregatedStats,
|
||||
constants as stakingConstants,
|
||||
PoolStats,
|
||||
StakingEvents,
|
||||
StakingStakingPoolEarnedRewardsInEpochEventArgs,
|
||||
} from '@0x/contracts-staking';
|
||||
import { expect, verifyEvents } from '@0x/contracts-test-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { Maker } from '../actors/maker';
|
||||
import { DeploymentManager } from '../deployment_manager';
|
||||
import { SimulationEnvironment } from '../simulation';
|
||||
|
||||
import { FunctionResult } from '../assertions/function_assertion';
|
||||
|
||||
export interface PoolInfo {
|
||||
poolStats: PoolStats;
|
||||
aggregatedStats: AggregatedStats;
|
||||
poolStake: BigNumber;
|
||||
operatorStake: BigNumber;
|
||||
poolId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets info for a given maker's pool.
|
||||
*/
|
||||
export async function getPoolInfoAsync(
|
||||
maker: Maker,
|
||||
simulationEnvironment: SimulationEnvironment,
|
||||
deployment: DeploymentManager,
|
||||
): Promise<PoolInfo | undefined> {
|
||||
const { stakingWrapper } = deployment.staking;
|
||||
// tslint:disable-next-line no-non-null-assertion no-unnecessary-type-assertion
|
||||
const poolId = maker!.makerPoolId;
|
||||
const { currentEpoch } = simulationEnvironment;
|
||||
if (poolId === undefined) {
|
||||
return;
|
||||
} else {
|
||||
const poolStats = PoolStats.fromArray(await stakingWrapper.poolStatsByEpoch(poolId, currentEpoch).callAsync());
|
||||
const aggregatedStats = AggregatedStats.fromArray(
|
||||
await stakingWrapper.aggregatedStatsByEpoch(currentEpoch).callAsync(),
|
||||
);
|
||||
const { currentEpochBalance: poolStake } = await stakingWrapper
|
||||
.getTotalStakeDelegatedToPool(poolId)
|
||||
.callAsync();
|
||||
const { currentEpochBalance: operatorStake } = await stakingWrapper
|
||||
.getStakeDelegatedToPoolByOwner(simulationEnvironment.stakingPools[poolId].operator, poolId)
|
||||
.callAsync();
|
||||
return { poolStats, aggregatedStats, poolStake, poolId, operatorStake };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a protocol fee was paid.
|
||||
*/
|
||||
export async function assertProtocolFeePaidAsync(
|
||||
poolInfo: PoolInfo,
|
||||
result: FunctionResult,
|
||||
simulationEnvironment: SimulationEnvironment,
|
||||
deployment: DeploymentManager,
|
||||
expectedProtocolFee: BigNumber,
|
||||
): Promise<void> {
|
||||
const { currentEpoch } = simulationEnvironment;
|
||||
const { stakingWrapper } = deployment.staking;
|
||||
const expectedPoolStats = { ...poolInfo.poolStats };
|
||||
const expectedAggregatedStats = { ...poolInfo.aggregatedStats };
|
||||
const expectedEvents = [];
|
||||
|
||||
// Refer to `payProtocolFee`
|
||||
if (poolInfo.poolStake.isGreaterThanOrEqualTo(stakingConstants.DEFAULT_PARAMS.minimumPoolStake)) {
|
||||
if (poolInfo.poolStats.feesCollected.isZero()) {
|
||||
const membersStakeInPool = poolInfo.poolStake.minus(poolInfo.operatorStake);
|
||||
const weightedStakeInPool = poolInfo.operatorStake.plus(
|
||||
ReferenceFunctions.getPartialAmountFloor(
|
||||
stakingConstants.DEFAULT_PARAMS.rewardDelegatedStakeWeight,
|
||||
new BigNumber(stakingConstants.PPM),
|
||||
membersStakeInPool,
|
||||
),
|
||||
);
|
||||
expectedPoolStats.membersStake = membersStakeInPool;
|
||||
expectedPoolStats.weightedStake = weightedStakeInPool;
|
||||
expectedAggregatedStats.totalWeightedStake = poolInfo.aggregatedStats.totalWeightedStake.plus(
|
||||
weightedStakeInPool,
|
||||
);
|
||||
expectedAggregatedStats.numPoolsToFinalize = poolInfo.aggregatedStats.numPoolsToFinalize.plus(1);
|
||||
// StakingPoolEarnedRewardsInEpoch event emitted
|
||||
expectedEvents.push({
|
||||
epoch: currentEpoch,
|
||||
poolId: poolInfo.poolId,
|
||||
});
|
||||
}
|
||||
// Credit a protocol fee to the maker's staking pool
|
||||
expectedPoolStats.feesCollected = poolInfo.poolStats.feesCollected.plus(expectedProtocolFee);
|
||||
// Update aggregated stats
|
||||
expectedAggregatedStats.totalFeesCollected = poolInfo.aggregatedStats.totalFeesCollected.plus(
|
||||
expectedProtocolFee,
|
||||
);
|
||||
}
|
||||
|
||||
// Check for updated stats and event
|
||||
const poolStats = PoolStats.fromArray(
|
||||
await stakingWrapper.poolStatsByEpoch(poolInfo.poolId, currentEpoch).callAsync(),
|
||||
);
|
||||
const aggregatedStats = AggregatedStats.fromArray(
|
||||
await stakingWrapper.aggregatedStatsByEpoch(currentEpoch).callAsync(),
|
||||
);
|
||||
expect(poolStats).to.deep.equal(expectedPoolStats);
|
||||
expect(aggregatedStats).to.deep.equal(expectedAggregatedStats);
|
||||
verifyEvents<StakingStakingPoolEarnedRewardsInEpochEventArgs>(
|
||||
// tslint:disable-next-line no-non-null-assertion no-unnecessary-type-assertion
|
||||
result.receipt!,
|
||||
expectedEvents,
|
||||
StakingEvents.StakingPoolEarnedRewardsInEpoch,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
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 { MatchedFillResults, Order } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { TransactionReceiptWithDecodedLogs, TxData } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { DeploymentManager } from '../deployment_manager';
|
||||
|
||||
/**
|
||||
* Verifies `Fill` and `Transfer` events emitted by `matchOrders` or `matchOrdersWithMaximalFill`.
|
||||
*/
|
||||
export function verifyMatchEvents(
|
||||
txData: Partial<TxData>,
|
||||
leftOrder: Order,
|
||||
rightOrder: Order,
|
||||
receipt: TransactionReceiptWithDecodedLogs,
|
||||
deployment: DeploymentManager,
|
||||
withMaximalFill: boolean,
|
||||
): void {
|
||||
const matchResults = ReferenceFunctions.calculateMatchResults(
|
||||
leftOrder,
|
||||
rightOrder,
|
||||
DeploymentManager.protocolFeeMultiplier,
|
||||
DeploymentManager.gasPrice,
|
||||
withMaximalFill,
|
||||
);
|
||||
const takerAddress = txData.from as string;
|
||||
const value = new BigNumber(txData.value || 0);
|
||||
|
||||
verifyMatchFilledEvents(leftOrder, rightOrder, receipt, matchResults, takerAddress);
|
||||
verifyMatchTransferEvents(leftOrder, rightOrder, receipt, matchResults, takerAddress, value, deployment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies `Fill` events emitted by `matchOrders` or `matchOrdersWithMaximalFill`.
|
||||
*/
|
||||
const verifyMatchFilledEvents = (
|
||||
leftOrder: Order,
|
||||
rightOrder: Order,
|
||||
receipt: TransactionReceiptWithDecodedLogs,
|
||||
matchResults: MatchedFillResults,
|
||||
takerAddress: string,
|
||||
) => {
|
||||
const expectedFillEvents = [
|
||||
{
|
||||
makerAddress: leftOrder.makerAddress,
|
||||
feeRecipientAddress: leftOrder.feeRecipientAddress,
|
||||
makerAssetData: leftOrder.makerAssetData,
|
||||
takerAssetData: leftOrder.takerAssetData,
|
||||
makerFeeAssetData: leftOrder.makerFeeAssetData,
|
||||
takerFeeAssetData: leftOrder.takerFeeAssetData,
|
||||
orderHash: orderHashUtils.getOrderHashHex(leftOrder),
|
||||
takerAddress,
|
||||
senderAddress: takerAddress,
|
||||
...matchResults.left,
|
||||
},
|
||||
{
|
||||
makerAddress: rightOrder.makerAddress,
|
||||
feeRecipientAddress: rightOrder.feeRecipientAddress,
|
||||
makerAssetData: rightOrder.makerAssetData,
|
||||
takerAssetData: rightOrder.takerAssetData,
|
||||
makerFeeAssetData: rightOrder.makerFeeAssetData,
|
||||
takerFeeAssetData: rightOrder.takerFeeAssetData,
|
||||
orderHash: orderHashUtils.getOrderHashHex(rightOrder),
|
||||
takerAddress,
|
||||
senderAddress: takerAddress,
|
||||
...matchResults.right,
|
||||
},
|
||||
];
|
||||
|
||||
verifyEvents<ExchangeFillEventArgs>(receipt, expectedFillEvents, ExchangeEvents.Fill);
|
||||
};
|
||||
|
||||
/**
|
||||
* Verifies `Transfer` events emitted by `matchOrders` or `matchOrdersWithMaximalFill`.
|
||||
*/
|
||||
const verifyMatchTransferEvents = (
|
||||
leftOrder: Order,
|
||||
rightOrder: Order,
|
||||
receipt: TransactionReceiptWithDecodedLogs,
|
||||
matchResults: MatchedFillResults,
|
||||
takerAddress: string,
|
||||
value: BigNumber,
|
||||
deployment: DeploymentManager,
|
||||
) => {
|
||||
const expectedTransferEvents = [
|
||||
{
|
||||
_from: rightOrder.makerAddress,
|
||||
_to: leftOrder.makerAddress,
|
||||
_value: matchResults.left.takerAssetFilledAmount,
|
||||
},
|
||||
{
|
||||
_from: leftOrder.makerAddress,
|
||||
_to: rightOrder.makerAddress,
|
||||
_value: matchResults.right.takerAssetFilledAmount,
|
||||
},
|
||||
{
|
||||
_from: rightOrder.makerAddress,
|
||||
_to: rightOrder.feeRecipientAddress,
|
||||
_value: matchResults.right.makerFeePaid,
|
||||
},
|
||||
{
|
||||
_from: leftOrder.makerAddress,
|
||||
_to: leftOrder.feeRecipientAddress,
|
||||
_value: matchResults.left.makerFeePaid,
|
||||
},
|
||||
{
|
||||
_from: leftOrder.makerAddress,
|
||||
_to: takerAddress,
|
||||
_value: matchResults.left.makerAssetFilledAmount.minus(matchResults.right.takerAssetFilledAmount),
|
||||
},
|
||||
{
|
||||
_from: rightOrder.makerAddress,
|
||||
_to: takerAddress,
|
||||
_value: matchResults.right.makerAssetFilledAmount.minus(matchResults.left.takerAssetFilledAmount),
|
||||
},
|
||||
{
|
||||
_from: takerAddress,
|
||||
_to: deployment.staking.stakingProxy.address,
|
||||
_value: value.isLessThan(DeploymentManager.protocolFee.times(2))
|
||||
? DeploymentManager.protocolFee
|
||||
: new BigNumber(0),
|
||||
},
|
||||
{
|
||||
_from: takerAddress,
|
||||
_to: deployment.staking.stakingProxy.address,
|
||||
_value: value.isLessThan(DeploymentManager.protocolFee) ? DeploymentManager.protocolFee : new BigNumber(0),
|
||||
},
|
||||
{
|
||||
_from: takerAddress,
|
||||
_to: rightOrder.feeRecipientAddress,
|
||||
_value:
|
||||
leftOrder.feeRecipientAddress === rightOrder.feeRecipientAddress
|
||||
? new BigNumber(0)
|
||||
: matchResults.right.takerFeePaid,
|
||||
},
|
||||
{
|
||||
_from: takerAddress,
|
||||
_to: leftOrder.feeRecipientAddress,
|
||||
_value:
|
||||
leftOrder.feeRecipientAddress === rightOrder.feeRecipientAddress
|
||||
? matchResults.left.takerFeePaid.plus(matchResults.right.takerFeePaid)
|
||||
: matchResults.left.takerFeePaid,
|
||||
},
|
||||
].filter(event => event._value.isGreaterThan(0));
|
||||
|
||||
verifyEvents<ERC20TokenTransferEventArgs>(receipt, expectedTransferEvents, ERC20TokenEvents.Transfer);
|
||||
};
|
||||
Reference in New Issue
Block a user