fixing bugs
This commit is contained in:
parent
be0e6c8925
commit
ccb477687a
@ -100,9 +100,9 @@ export function KeeperMixin<TBase extends Constructor>(Base: TBase): TBase & Con
|
||||
|
||||
private async *_validEndEpoch(): AsyncIterableIterator<AssertionResult | void> {
|
||||
const assertion = validEndEpochAssertion(this.actor.deployment, this.actor.simulationEnvironment!);
|
||||
const { currentEpoch } = this.actor.simulationEnvironment!;
|
||||
const { stakingWrapper } = this.actor.deployment.staking;
|
||||
while (true) {
|
||||
const { currentEpoch } = this.actor.simulationEnvironment!;
|
||||
const aggregatedStats = AggregatedStats.fromArray(
|
||||
await stakingWrapper.aggregatedStatsByEpoch(currentEpoch.minus(1)).callAsync(),
|
||||
);
|
||||
|
@ -71,8 +71,8 @@ export function StakerMixin<TBase extends Constructor>(Base: TBase): TBase & Con
|
||||
|
||||
private async *_validStake(): AsyncIterableIterator<AssertionResult> {
|
||||
const { zrx } = this.actor.deployment.tokens;
|
||||
const { deployment, balanceStore, globalStake } = this.actor.simulationEnvironment!;
|
||||
const assertion = validStakeAssertion(deployment, balanceStore, globalStake, this.stake);
|
||||
const { deployment, balanceStore } = this.actor.simulationEnvironment!;
|
||||
const assertion = validStakeAssertion(deployment, this.actor.simulationEnvironment!, this.stake);
|
||||
|
||||
while (true) {
|
||||
await balanceStore.updateErc20BalancesAsync();
|
||||
@ -84,8 +84,8 @@ export function StakerMixin<TBase extends Constructor>(Base: TBase): TBase & Con
|
||||
|
||||
private async *_validUnstake(): AsyncIterableIterator<AssertionResult> {
|
||||
const { stakingWrapper } = this.actor.deployment.staking;
|
||||
const { deployment, balanceStore, globalStake } = this.actor.simulationEnvironment!;
|
||||
const assertion = validUnstakeAssertion(deployment, balanceStore, globalStake, this.stake);
|
||||
const { deployment, balanceStore } = this.actor.simulationEnvironment!;
|
||||
const assertion = validUnstakeAssertion(deployment, this.actor.simulationEnvironment!, this.stake);
|
||||
|
||||
while (true) {
|
||||
await balanceStore.updateErc20BalancesAsync();
|
||||
@ -102,22 +102,23 @@ export function StakerMixin<TBase extends Constructor>(Base: TBase): TBase & Con
|
||||
}
|
||||
|
||||
private async *_validMoveStake(): AsyncIterableIterator<AssertionResult> {
|
||||
const { deployment, globalStake, stakingPools } = this.actor.simulationEnvironment!;
|
||||
const assertion = validMoveStakeAssertion(deployment, globalStake, this.stake, stakingPools);
|
||||
const { deployment, stakingPools } = this.actor.simulationEnvironment!;
|
||||
const assertion = validMoveStakeAssertion(deployment, this.actor.simulationEnvironment!, this.stake);
|
||||
|
||||
while (true) {
|
||||
const { currentEpoch } = this.actor.simulationEnvironment!;
|
||||
const fromPoolId = Pseudorandom.sample(
|
||||
Object.keys(_.omit(this.stake[StakeStatus.Delegated], ['total'])),
|
||||
);
|
||||
const fromStatus =
|
||||
fromPoolId === undefined
|
||||
fromPoolId === undefined || stakingPools[fromPoolId].lastFinalized.isLessThan(currentEpoch.minus(1))
|
||||
? StakeStatus.Undelegated
|
||||
: (Pseudorandom.sample([StakeStatus.Undelegated, StakeStatus.Delegated]) as StakeStatus);
|
||||
const from = new StakeInfo(fromStatus, fromPoolId);
|
||||
|
||||
const toPoolId = Pseudorandom.sample(Object.keys(stakingPools));
|
||||
const toStatus =
|
||||
toPoolId === undefined
|
||||
toPoolId === undefined || stakingPools[toPoolId].lastFinalized.isLessThan(currentEpoch.minus(1))
|
||||
? StakeStatus.Undelegated
|
||||
: (Pseudorandom.sample([StakeStatus.Undelegated, StakeStatus.Delegated]) as StakeStatus);
|
||||
const to = new StakeInfo(toStatus, toPoolId);
|
||||
@ -134,9 +135,17 @@ export function StakerMixin<TBase extends Constructor>(Base: TBase): TBase & Con
|
||||
|
||||
private async *_validWithdrawDelegatorRewards(): AsyncIterableIterator<AssertionResult | void> {
|
||||
const { stakingPools } = this.actor.simulationEnvironment!;
|
||||
const assertion = validWithdrawDelegatorRewardsAssertion(this.actor.deployment, this.actor.simulationEnvironment!);
|
||||
const assertion = validWithdrawDelegatorRewardsAssertion(
|
||||
this.actor.deployment,
|
||||
this.actor.simulationEnvironment!,
|
||||
);
|
||||
while (true) {
|
||||
const poolId = Pseudorandom.sample(Object.keys(stakingPools));
|
||||
const prevEpoch = this.actor.simulationEnvironment!.currentEpoch.minus(1);
|
||||
const poolId = Pseudorandom.sample(
|
||||
Object.keys(stakingPools).filter(poolId =>
|
||||
stakingPools[poolId].lastFinalized.isGreaterThanOrEqualTo(prevEpoch),
|
||||
),
|
||||
);
|
||||
if (poolId === undefined) {
|
||||
yield;
|
||||
} else {
|
||||
|
@ -83,11 +83,9 @@ export function TakerMixin<TBase extends Constructor>(Base: TBase): TBase & Cons
|
||||
token: DummyERC20TokenContract,
|
||||
): Promise<BigNumber> => {
|
||||
let balance = balanceStore.balances.erc20[owner.address][token.address];
|
||||
if (balance === undefined || balance.isZero()) {
|
||||
await owner.configureERC20TokenAsync(token);
|
||||
balance = balanceStore.balances.erc20[owner.address][token.address] =
|
||||
constants.INITIAL_ERC20_BALANCE;
|
||||
}
|
||||
await owner.configureERC20TokenAsync(token);
|
||||
balance = balanceStore.balances.erc20[owner.address][token.address] =
|
||||
constants.INITIAL_ERC20_BALANCE;
|
||||
return Pseudorandom.integer(balance.dividedToIntegerBy(2));
|
||||
};
|
||||
|
||||
|
@ -37,6 +37,9 @@ export function validCreateStakingPoolAssertion(
|
||||
args: [number, boolean],
|
||||
txData: Partial<TxData>,
|
||||
) => {
|
||||
// Ensure that the tx succeeded.
|
||||
expect(result.success, `Error: ${result.data}`).to.be.true();
|
||||
|
||||
const [operatorShare] = args;
|
||||
|
||||
// Checks the logs for the new poolId, verifies that it is as expected
|
||||
|
@ -17,7 +17,10 @@ export function validDecreaseStakingPoolOperatorShareAssertion(
|
||||
const { stakingWrapper } = deployment.staking;
|
||||
|
||||
return new FunctionAssertion<[string, number], {}, void>(stakingWrapper, 'decreaseStakingPoolOperatorShare', {
|
||||
after: async (_beforeInfo, _result: FunctionResult, args: [string, number], _txData: Partial<TxData>) => {
|
||||
after: async (_beforeInfo, result: FunctionResult, args: [string, number], _txData: Partial<TxData>) => {
|
||||
// Ensure that the tx succeeded.
|
||||
expect(result.success, `Error: ${result.data}`).to.be.true();
|
||||
|
||||
const [poolId, expectedOperatorShare] = args;
|
||||
|
||||
// Checks that the on-chain pool's operator share has been updated.
|
||||
|
@ -1,8 +1,14 @@
|
||||
import { WETH9DepositEventArgs, WETH9Events } from '@0x/contracts-erc20';
|
||||
import { AggregatedStats, StakingEvents, StakingEpochEndedEventArgs } from '@0x/contracts-staking';
|
||||
import { expect, verifyEventsFromLogs } from '@0x/contracts-test-utils';
|
||||
import {
|
||||
AggregatedStats,
|
||||
StakingEvents,
|
||||
StakingEpochEndedEventArgs,
|
||||
StakingEpochFinalizedEventArgs,
|
||||
} from '@0x/contracts-staking';
|
||||
import { constants, expect, verifyEventsFromLogs } from '@0x/contracts-test-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { TxData } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { DeploymentManager } from '../deployment_manager';
|
||||
import { SimulationEnvironment } from '../simulation';
|
||||
@ -25,20 +31,25 @@ export function validEndEpochAssertion(
|
||||
simulationEnvironment: SimulationEnvironment,
|
||||
): FunctionAssertion<[], EndEpochBeforeInfo, void> {
|
||||
const { stakingWrapper } = deployment.staking;
|
||||
const { balanceStore, currentEpoch } = simulationEnvironment;
|
||||
const { balanceStore } = simulationEnvironment;
|
||||
|
||||
return new FunctionAssertion(stakingWrapper, 'endEpoch', {
|
||||
before: async () => {
|
||||
await balanceStore.updateEthBalancesAsync();
|
||||
const aggregatedStatsBefore = AggregatedStats.fromArray(
|
||||
await stakingWrapper.aggregatedStatsByEpoch(currentEpoch).callAsync(),
|
||||
await stakingWrapper.aggregatedStatsByEpoch(simulationEnvironment.currentEpoch).callAsync(),
|
||||
);
|
||||
const wethReservedForPoolRewards = await stakingWrapper.wethReservedForPoolRewards().callAsync();
|
||||
return { wethReservedForPoolRewards, aggregatedStatsBefore };
|
||||
},
|
||||
after: async (beforeInfo: EndEpochBeforeInfo, result: FunctionResult, _args: [], _txData: Partial<TxData>) => {
|
||||
// Ensure that the tx succeeded.
|
||||
expect(result.success, `Error: ${result.data}`).to.be.true();
|
||||
|
||||
const { currentEpoch } = simulationEnvironment;
|
||||
|
||||
// Check WETH deposit event
|
||||
const previousEthBalance = balanceStore.balances.eth[stakingWrapper.address];
|
||||
const previousEthBalance = balanceStore.balances.eth[stakingWrapper.address] || constants.ZERO_AMOUNT;
|
||||
if (previousEthBalance.isGreaterThan(0)) {
|
||||
verifyEventsFromLogs<WETH9DepositEventArgs>(
|
||||
result.receipt!.logs,
|
||||
@ -56,9 +67,11 @@ export function validEndEpochAssertion(
|
||||
const { wethReservedForPoolRewards, aggregatedStatsBefore } = beforeInfo;
|
||||
const expectedAggregatedStats = {
|
||||
...aggregatedStatsBefore,
|
||||
rewardsAvailable: balanceStore.balances.erc20[stakingWrapper.address][
|
||||
deployment.tokens.weth.address
|
||||
].minus(wethReservedForPoolRewards),
|
||||
rewardsAvailable: _.get(
|
||||
balanceStore.balances,
|
||||
['erc20', stakingWrapper.address, deployment.tokens.weth.address],
|
||||
constants.ZERO_AMOUNT,
|
||||
).minus(wethReservedForPoolRewards),
|
||||
};
|
||||
|
||||
const aggregatedStatsAfter = AggregatedStats.fromArray(
|
||||
@ -66,22 +79,35 @@ export function validEndEpochAssertion(
|
||||
);
|
||||
expect(aggregatedStatsAfter).to.deep.equal(expectedAggregatedStats);
|
||||
|
||||
const expectedEpochEndedEvents = aggregatedStatsAfter.numPoolsToFinalize.isZero()
|
||||
verifyEventsFromLogs<StakingEpochEndedEventArgs>(
|
||||
result.receipt!.logs,
|
||||
[
|
||||
{
|
||||
epoch: currentEpoch,
|
||||
numPoolsToFinalize: aggregatedStatsAfter.numPoolsToFinalize,
|
||||
rewardsAvailable: aggregatedStatsAfter.rewardsAvailable,
|
||||
totalFeesCollected: aggregatedStatsAfter.totalFeesCollected,
|
||||
totalWeightedStake: aggregatedStatsAfter.totalWeightedStake,
|
||||
},
|
||||
],
|
||||
StakingEvents.EpochEnded,
|
||||
);
|
||||
|
||||
const expectedEpochFinalizedEvents = aggregatedStatsAfter.numPoolsToFinalize.isZero()
|
||||
? [
|
||||
{
|
||||
epoch: currentEpoch,
|
||||
numPoolsToFinalize: aggregatedStatsAfter.numPoolsToFinalize,
|
||||
rewardsAvailable: aggregatedStatsAfter.rewardsAvailable,
|
||||
totalFeesCollected: aggregatedStatsAfter.totalFeesCollected,
|
||||
totalWeightedStake: aggregatedStatsAfter.totalWeightedStake,
|
||||
rewardsPaid: constants.ZERO_AMOUNT,
|
||||
rewardsRemaining: aggregatedStatsAfter.rewardsAvailable,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
verifyEventsFromLogs<StakingEpochEndedEventArgs>(
|
||||
verifyEventsFromLogs<StakingEpochFinalizedEventArgs>(
|
||||
result.receipt!.logs,
|
||||
expectedEpochEndedEvents,
|
||||
StakingEvents.EpochEnded,
|
||||
expectedEpochFinalizedEvents,
|
||||
StakingEvents.EpochFinalized,
|
||||
);
|
||||
|
||||
expect(result.data, 'endEpoch should return the number of unfinalized pools').to.bignumber.equal(
|
||||
aggregatedStatsAfter.numPoolsToFinalize,
|
||||
);
|
||||
|
@ -104,7 +104,7 @@ export function validFillOrderAssertion(
|
||||
simulationEnvironment: SimulationEnvironment,
|
||||
): FunctionAssertion<[Order, BigNumber, string], FillOrderBeforeInfo | void, FillResults> {
|
||||
const { stakingWrapper } = deployment.staking;
|
||||
const { actors, currentEpoch } = simulationEnvironment;
|
||||
const { actors } = simulationEnvironment;
|
||||
|
||||
return new FunctionAssertion<[Order, BigNumber, string], FillOrderBeforeInfo | void, FillResults>(
|
||||
deployment.exchange,
|
||||
@ -112,6 +112,7 @@ export function validFillOrderAssertion(
|
||||
{
|
||||
before: async (args: [Order, BigNumber, string]) => {
|
||||
const [order] = args;
|
||||
const { currentEpoch } = simulationEnvironment;
|
||||
const maker = filterActorsByRole(actors, Maker).find(maker => maker.address === order.makerAddress);
|
||||
|
||||
const poolId = maker!.makerPoolId;
|
||||
@ -138,12 +139,13 @@ export function validFillOrderAssertion(
|
||||
result: FunctionResult,
|
||||
args: [Order, BigNumber, string],
|
||||
txData: Partial<TxData>,
|
||||
) => {
|
||||
const [order, fillAmount] = args;
|
||||
|
||||
) => {
|
||||
// Ensure that the tx succeeded.
|
||||
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);
|
||||
|
||||
|
@ -65,12 +65,12 @@ export function validFinalizePoolAssertion(
|
||||
simulationEnvironment: SimulationEnvironment,
|
||||
): FunctionAssertion<[string], FinalizePoolBeforeInfo, void> {
|
||||
const { stakingWrapper } = deployment.staking;
|
||||
const { currentEpoch } = simulationEnvironment;
|
||||
const prevEpoch = currentEpoch.minus(1);
|
||||
|
||||
return new FunctionAssertion<[string], FinalizePoolBeforeInfo, void>(stakingWrapper, 'finalizePool', {
|
||||
before: async (args: [string]) => {
|
||||
const [poolId] = args;
|
||||
const { currentEpoch } = simulationEnvironment;
|
||||
const prevEpoch = currentEpoch.minus(1);
|
||||
|
||||
const poolStats = PoolStats.fromArray(await stakingWrapper.poolStatsByEpoch(poolId, prevEpoch).callAsync());
|
||||
const aggregatedStats = AggregatedStats.fromArray(
|
||||
@ -90,10 +90,14 @@ export function validFinalizePoolAssertion(
|
||||
};
|
||||
},
|
||||
after: async (beforeInfo: FinalizePoolBeforeInfo, result: FunctionResult, args: [string]) => {
|
||||
// Ensure that the tx succeeded.
|
||||
expect(result.success, `Error: ${result.data}`).to.be.true();
|
||||
|
||||
// // Compute relevant epochs
|
||||
// uint256 currentEpoch_ = currentEpoch;
|
||||
// uint256 prevEpoch = currentEpoch_.safeSub(1);
|
||||
const { stakingPools } = simulationEnvironment;
|
||||
const { stakingPools, currentEpoch } = simulationEnvironment;
|
||||
const prevEpoch = currentEpoch.minus(1);
|
||||
const [poolId] = args;
|
||||
const pool = stakingPools[poolId];
|
||||
|
||||
@ -155,9 +159,8 @@ export function validFinalizePoolAssertion(
|
||||
expect(events.length, 'Number of RewardsPaid events emitted').to.equal(1);
|
||||
const [rewardsPaidEvent] = events;
|
||||
|
||||
expect(rewardsPaidEvent.currentEpoch_, 'RewardsPaid event: currentEpoch_').to.bignumber.equal(currentEpoch);
|
||||
expect(rewardsPaidEvent.poolId, 'RewardsPaid event: poolId').to.bignumber.equal(poolId);
|
||||
expect(rewardsPaidEvent.currentEpoch_, 'RewardsPaid event: currentEpoch_').to.bignumber.equal(currentEpoch);
|
||||
expect(rewardsPaidEvent.poolId, 'RewardsPaid event: poolId').to.equal(poolId);
|
||||
expect(rewardsPaidEvent.epoch, 'RewardsPaid event: currentEpoch_').to.bignumber.equal(currentEpoch);
|
||||
|
||||
const { operatorReward, membersReward } = rewardsPaidEvent;
|
||||
const totalReward = operatorReward.plus(membersReward);
|
||||
@ -189,6 +192,7 @@ export function validFinalizePoolAssertion(
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
// Check for WETH transfer event emitted when paying out operator's reward.
|
||||
verifyEventsFromLogs<WETH9TransferEventArgs>(
|
||||
result.receipt!.logs,
|
||||
|
@ -79,13 +79,15 @@ export class FunctionAssertion<TArgs extends any[], TBefore, ReturnDataType> imp
|
||||
// Initialize the callResult so that the default success value is true.
|
||||
const callResult: FunctionResult = { success: true };
|
||||
|
||||
// Log function name, arguments, and txData
|
||||
logger.logFunctionAssertion(this._functionName, args, txData);
|
||||
|
||||
// Try to make the call to the function. If it is successful, pass the
|
||||
// result and receipt to the after condition.
|
||||
try {
|
||||
const functionWithArgs = (this._contractWrapper as any)[this._functionName](
|
||||
...args,
|
||||
) as ContractTxFunctionObj<ReturnDataType>;
|
||||
logger.logFunctionAssertion(this._functionName, args, txData);
|
||||
callResult.data = await functionWithArgs.callAsync(txData);
|
||||
callResult.receipt =
|
||||
functionWithArgs.awaitTransactionSuccessAsync !== undefined
|
||||
|
@ -15,12 +15,13 @@ export function validJoinStakingPoolAssertion(deployment: DeploymentManager): Fu
|
||||
const { stakingWrapper } = deployment.staking;
|
||||
|
||||
return new FunctionAssertion<[string], {}, void>(stakingWrapper, 'joinStakingPoolAsMaker', {
|
||||
after: async (_beforeInfo, _result: FunctionResult, args: [string], txData: Partial<TxData>) => {
|
||||
after: async (_beforeInfo, result: FunctionResult, args: [string], txData: Partial<TxData>) => {
|
||||
// Ensure that the tx succeeded.
|
||||
expect(result.success, `Error: ${result.data}`).to.be.true();
|
||||
|
||||
const [poolId] = args;
|
||||
|
||||
expect(_result.success).to.be.true();
|
||||
|
||||
const logs = _result.receipt!.logs;
|
||||
const logs = result.receipt!.logs;
|
||||
const logArgs = filterLogsToArguments<StakingMakerStakingPoolSetEventArgs>(
|
||||
logs,
|
||||
StakingEvents.MakerStakingPoolSet,
|
||||
|
@ -1,75 +1,94 @@
|
||||
import {
|
||||
GlobalStakeByStatus,
|
||||
OwnerStakeByStatus,
|
||||
StakeInfo,
|
||||
StakeStatus,
|
||||
StakingPoolById,
|
||||
StoredBalance,
|
||||
} from '@0x/contracts-staking';
|
||||
import { OwnerStakeByStatus, StakeInfo, StakeStatus, StoredBalance } from '@0x/contracts-staking';
|
||||
import { constants, expect } from '@0x/contracts-test-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { TxData } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { DeploymentManager } from '../deployment_manager';
|
||||
import { SimulationEnvironment } from '../simulation';
|
||||
|
||||
import { FunctionAssertion, FunctionResult } from './function_assertion';
|
||||
|
||||
function incrementNextEpochBalance(stakeBalance: StoredBalance, amount: BigNumber): void {
|
||||
function incrementNextEpochBalance(stakeBalance: StoredBalance, amount: BigNumber, currentEpoch: BigNumber): void {
|
||||
stakeBalance.currentEpochBalance = currentEpoch.isGreaterThan(stakeBalance.currentEpoch)
|
||||
? stakeBalance.nextEpochBalance
|
||||
: stakeBalance.currentEpochBalance;
|
||||
stakeBalance.currentEpoch = currentEpoch;
|
||||
_.update(stakeBalance, ['nextEpochBalance'], balance => (balance || constants.ZERO_AMOUNT).plus(amount));
|
||||
}
|
||||
|
||||
function decrementNextEpochBalance(stakeBalance: StoredBalance, amount: BigNumber): void {
|
||||
function decrementNextEpochBalance(stakeBalance: StoredBalance, amount: BigNumber, currentEpoch: BigNumber): void {
|
||||
stakeBalance.currentEpochBalance = currentEpoch.isGreaterThan(stakeBalance.currentEpoch)
|
||||
? stakeBalance.nextEpochBalance
|
||||
: stakeBalance.currentEpochBalance;
|
||||
stakeBalance.currentEpoch = currentEpoch;
|
||||
_.update(stakeBalance, ['nextEpochBalance'], balance => (balance || constants.ZERO_AMOUNT).minus(amount));
|
||||
}
|
||||
|
||||
function loadCurrentBalance(balance: StoredBalance, currentEpoch: BigNumber): StoredBalance {
|
||||
return {
|
||||
...balance,
|
||||
currentEpoch: currentEpoch,
|
||||
currentEpochBalance: currentEpoch.isGreaterThan(balance.currentEpoch)
|
||||
? balance.nextEpochBalance
|
||||
: balance.currentEpochBalance,
|
||||
};
|
||||
}
|
||||
|
||||
function updateNextEpochBalances(
|
||||
globalStake: GlobalStakeByStatus,
|
||||
ownerStake: OwnerStakeByStatus,
|
||||
pools: StakingPoolById,
|
||||
from: StakeInfo,
|
||||
to: StakeInfo,
|
||||
amount: BigNumber,
|
||||
simulationEnvironment: SimulationEnvironment,
|
||||
): string[] {
|
||||
const { globalStake, stakingPools, currentEpoch } = simulationEnvironment;
|
||||
|
||||
// The on-chain state of these updated pools will be verified in the `after` of the assertion.
|
||||
const updatedPools = [];
|
||||
|
||||
// Decrement next epoch balances associated with the `from` stake
|
||||
if (from.status === StakeStatus.Undelegated) {
|
||||
// Decrement owner undelegated stake
|
||||
decrementNextEpochBalance(ownerStake[StakeStatus.Undelegated], amount);
|
||||
decrementNextEpochBalance(ownerStake[StakeStatus.Undelegated], amount, currentEpoch);
|
||||
// Decrement global undelegated stake
|
||||
decrementNextEpochBalance(globalStake[StakeStatus.Undelegated], amount);
|
||||
decrementNextEpochBalance(globalStake[StakeStatus.Undelegated], amount, currentEpoch);
|
||||
} else if (from.status === StakeStatus.Delegated) {
|
||||
// Decrement owner's delegated stake to this pool
|
||||
decrementNextEpochBalance(ownerStake[StakeStatus.Delegated][from.poolId], amount);
|
||||
decrementNextEpochBalance(ownerStake[StakeStatus.Delegated][from.poolId], amount, currentEpoch);
|
||||
// Decrement owner's total delegated stake
|
||||
decrementNextEpochBalance(ownerStake[StakeStatus.Delegated].total, amount);
|
||||
decrementNextEpochBalance(ownerStake[StakeStatus.Delegated].total, amount, currentEpoch);
|
||||
// Decrement global delegated stake
|
||||
decrementNextEpochBalance(globalStake[StakeStatus.Delegated], amount);
|
||||
decrementNextEpochBalance(globalStake[StakeStatus.Delegated], amount, currentEpoch);
|
||||
// Decrement pool's delegated stake
|
||||
decrementNextEpochBalance(pools[from.poolId].delegatedStake, amount);
|
||||
decrementNextEpochBalance(stakingPools[from.poolId].delegatedStake, amount, currentEpoch);
|
||||
updatedPools.push(from.poolId);
|
||||
|
||||
// TODO: Check that delegator rewards have been withdrawn/synced
|
||||
}
|
||||
|
||||
// Increment next epoch balances associated with the `to` stake
|
||||
if (to.status === StakeStatus.Undelegated) {
|
||||
incrementNextEpochBalance(ownerStake[StakeStatus.Undelegated], amount);
|
||||
incrementNextEpochBalance(globalStake[StakeStatus.Undelegated], amount);
|
||||
// Increment owner undelegated stake
|
||||
incrementNextEpochBalance(ownerStake[StakeStatus.Undelegated], amount, currentEpoch);
|
||||
// Increment global undelegated stake
|
||||
incrementNextEpochBalance(globalStake[StakeStatus.Undelegated], amount, currentEpoch);
|
||||
} else if (to.status === StakeStatus.Delegated) {
|
||||
// Initializes the balance for this pool if the user has not previously delegated to it
|
||||
_.defaults(ownerStake[StakeStatus.Delegated], {
|
||||
[to.poolId]: new StoredBalance(),
|
||||
});
|
||||
// Increment owner's delegated stake to this pool
|
||||
incrementNextEpochBalance(ownerStake[StakeStatus.Delegated][to.poolId], amount);
|
||||
incrementNextEpochBalance(ownerStake[StakeStatus.Delegated][to.poolId], amount, currentEpoch);
|
||||
// Increment owner's total delegated stake
|
||||
incrementNextEpochBalance(ownerStake[StakeStatus.Delegated].total, amount);
|
||||
incrementNextEpochBalance(ownerStake[StakeStatus.Delegated].total, amount, currentEpoch);
|
||||
// Increment global delegated stake
|
||||
incrementNextEpochBalance(globalStake[StakeStatus.Delegated], amount);
|
||||
incrementNextEpochBalance(globalStake[StakeStatus.Delegated], amount, currentEpoch);
|
||||
// Increment pool's delegated stake
|
||||
incrementNextEpochBalance(pools[to.poolId].delegatedStake, amount);
|
||||
incrementNextEpochBalance(stakingPools[to.poolId].delegatedStake, amount, currentEpoch);
|
||||
updatedPools.push(to.poolId);
|
||||
|
||||
// TODO: Check that delegator rewards have been withdrawn/synced
|
||||
}
|
||||
return updatedPools;
|
||||
}
|
||||
@ -80,25 +99,28 @@ function updateNextEpochBalances(
|
||||
/* tslint:disable:no-unnecessary-type-assertion */
|
||||
export function validMoveStakeAssertion(
|
||||
deployment: DeploymentManager,
|
||||
globalStake: GlobalStakeByStatus,
|
||||
simulationEnvironment: SimulationEnvironment,
|
||||
ownerStake: OwnerStakeByStatus,
|
||||
pools: StakingPoolById,
|
||||
): FunctionAssertion<[StakeInfo, StakeInfo, BigNumber], {}, void> {
|
||||
const { stakingWrapper } = deployment.staking;
|
||||
const { stakingWrapper, zrxVault } = deployment.staking;
|
||||
|
||||
return new FunctionAssertion<[StakeInfo, StakeInfo, BigNumber], {}, void>(stakingWrapper, 'moveStake', {
|
||||
after: async (
|
||||
_beforeInfo: {},
|
||||
_result: FunctionResult,
|
||||
result: FunctionResult,
|
||||
args: [StakeInfo, StakeInfo, BigNumber],
|
||||
txData: Partial<TxData>,
|
||||
) => {
|
||||
// Ensure that the tx succeeded.
|
||||
expect(result.success, `Error: ${result.data}`).to.be.true();
|
||||
|
||||
const [from, to, amount] = args;
|
||||
const { stakingPools, globalStake, currentEpoch } = simulationEnvironment;
|
||||
|
||||
const owner = txData.from!; // tslint:disable-line:no-non-null-assertion
|
||||
|
||||
// Update local balances to match the expected result of this `moveStake` operation
|
||||
const updatedPools = updateNextEpochBalances(globalStake, ownerStake, pools, from, to, amount);
|
||||
const updatedPools = updateNextEpochBalances(ownerStake, from, to, amount, simulationEnvironment);
|
||||
|
||||
// Fetches on-chain owner stake balances and checks against local balances
|
||||
const ownerUndelegatedStake = {
|
||||
@ -109,16 +131,27 @@ export function validMoveStakeAssertion(
|
||||
...new StoredBalance(),
|
||||
...(await stakingWrapper.getOwnerStakeByStatus(owner, StakeStatus.Delegated).callAsync()),
|
||||
};
|
||||
expect(ownerUndelegatedStake).to.deep.equal(ownerStake[StakeStatus.Undelegated]);
|
||||
expect(ownerDelegatedStake).to.deep.equal(ownerStake[StakeStatus.Delegated].total);
|
||||
expect(ownerUndelegatedStake).to.deep.equal(
|
||||
loadCurrentBalance(ownerStake[StakeStatus.Undelegated], currentEpoch),
|
||||
);
|
||||
expect(ownerDelegatedStake).to.deep.equal(
|
||||
loadCurrentBalance(ownerStake[StakeStatus.Delegated].total, currentEpoch),
|
||||
);
|
||||
|
||||
// Fetches on-chain global stake balances and checks against local balances
|
||||
const globalDelegatedStake = await stakingWrapper.getGlobalStakeByStatus(StakeStatus.Delegated).callAsync();
|
||||
const globalUndelegatedStake = await stakingWrapper
|
||||
.getGlobalStakeByStatus(StakeStatus.Undelegated)
|
||||
.callAsync();
|
||||
const globalDelegatedStake = await stakingWrapper.getGlobalStakeByStatus(StakeStatus.Delegated).callAsync();
|
||||
expect(globalUndelegatedStake).to.deep.equal(globalStake[StakeStatus.Undelegated]);
|
||||
expect(globalDelegatedStake).to.deep.equal(globalStake[StakeStatus.Delegated]);
|
||||
const totalStake = await zrxVault.balanceOfZrxVault().callAsync();
|
||||
expect(globalDelegatedStake).to.deep.equal(
|
||||
loadCurrentBalance(globalStake[StakeStatus.Delegated], currentEpoch),
|
||||
);
|
||||
expect(globalUndelegatedStake).to.deep.equal({
|
||||
currentEpochBalance: totalStake.minus(globalDelegatedStake.currentEpochBalance),
|
||||
nextEpochBalance: totalStake.minus(globalDelegatedStake.nextEpochBalance),
|
||||
currentEpoch,
|
||||
});
|
||||
|
||||
// Fetches on-chain pool stake balances and checks against local balances
|
||||
for (const poolId of updatedPools) {
|
||||
@ -126,8 +159,12 @@ export function validMoveStakeAssertion(
|
||||
.getStakeDelegatedToPoolByOwner(owner, poolId)
|
||||
.callAsync();
|
||||
const totalStakeDelegated = await stakingWrapper.getTotalStakeDelegatedToPool(poolId).callAsync();
|
||||
expect(stakeDelegatedByOwner).to.deep.equal(ownerStake[StakeStatus.Delegated][poolId]);
|
||||
expect(totalStakeDelegated).to.deep.equal(pools[poolId].delegatedStake);
|
||||
expect(stakeDelegatedByOwner).to.deep.equal(
|
||||
loadCurrentBalance(ownerStake[StakeStatus.Delegated][poolId], currentEpoch),
|
||||
);
|
||||
expect(totalStakeDelegated).to.deep.equal(
|
||||
loadCurrentBalance(stakingPools[poolId].delegatedStake, currentEpoch),
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
@ -3,19 +3,23 @@ import { expect } from '@0x/contracts-test-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { TxData } from 'ethereum-types';
|
||||
|
||||
import { BlockchainBalanceStore } from '../balances/blockchain_balance_store';
|
||||
import { LocalBalanceStore } from '../balances/local_balance_store';
|
||||
import { DeploymentManager } from '../deployment_manager';
|
||||
import { SimulationEnvironment } from '../simulation';
|
||||
|
||||
import { FunctionAssertion, FunctionResult } from './function_assertion';
|
||||
|
||||
function expectedUndelegatedStake(
|
||||
initStake: OwnerStakeByStatus | GlobalStakeByStatus,
|
||||
amount: BigNumber,
|
||||
currentEpoch: BigNumber,
|
||||
): StoredBalance {
|
||||
return {
|
||||
currentEpoch: initStake[StakeStatus.Undelegated].currentEpoch,
|
||||
currentEpochBalance: initStake[StakeStatus.Undelegated].currentEpochBalance.plus(amount),
|
||||
currentEpoch: currentEpoch,
|
||||
currentEpochBalance: (currentEpoch.isGreaterThan(initStake[StakeStatus.Undelegated].currentEpoch)
|
||||
? initStake[StakeStatus.Undelegated].nextEpochBalance
|
||||
: initStake[StakeStatus.Undelegated].currentEpochBalance
|
||||
).plus(amount),
|
||||
nextEpochBalance: initStake[StakeStatus.Undelegated].nextEpochBalance.plus(amount),
|
||||
};
|
||||
}
|
||||
@ -28,8 +32,7 @@ function expectedUndelegatedStake(
|
||||
/* tslint:disable:no-unnecessary-type-assertion */
|
||||
export function validStakeAssertion(
|
||||
deployment: DeploymentManager,
|
||||
balanceStore: BlockchainBalanceStore,
|
||||
globalStake: GlobalStakeByStatus,
|
||||
simulationEnvironment: SimulationEnvironment,
|
||||
ownerStake: OwnerStakeByStatus,
|
||||
): FunctionAssertion<[BigNumber], LocalBalanceStore, void> {
|
||||
const { stakingWrapper, zrxVault } = deployment.staking;
|
||||
@ -37,6 +40,7 @@ export function validStakeAssertion(
|
||||
return new FunctionAssertion(stakingWrapper, 'stake', {
|
||||
before: async (args: [BigNumber], txData: Partial<TxData>) => {
|
||||
const [amount] = args;
|
||||
const { balanceStore } = simulationEnvironment;
|
||||
|
||||
// Simulates the transfer of ZRX from staker to vault
|
||||
const expectedBalances = LocalBalanceStore.create(balanceStore);
|
||||
@ -50,11 +54,15 @@ export function validStakeAssertion(
|
||||
},
|
||||
after: async (
|
||||
expectedBalances: LocalBalanceStore,
|
||||
_result: FunctionResult,
|
||||
result: FunctionResult,
|
||||
args: [BigNumber],
|
||||
txData: Partial<TxData>,
|
||||
) => {
|
||||
// Ensure that the tx succeeded.
|
||||
expect(result.success, `Error: ${result.data}`).to.be.true();
|
||||
|
||||
const [amount] = args;
|
||||
const { balanceStore, globalStake, currentEpoch } = simulationEnvironment;
|
||||
|
||||
// Checks that the ZRX transfer updated balances as expected.
|
||||
await balanceStore.updateErc20BalancesAsync();
|
||||
@ -64,7 +72,7 @@ export function validStakeAssertion(
|
||||
const ownerUndelegatedStake = await stakingWrapper
|
||||
.getOwnerStakeByStatus(txData.from!, StakeStatus.Undelegated) // tslint:disable-line:no-non-null-assertion
|
||||
.callAsync();
|
||||
const expectedOwnerUndelegatedStake = expectedUndelegatedStake(ownerStake, amount);
|
||||
const expectedOwnerUndelegatedStake = expectedUndelegatedStake(ownerStake, amount, currentEpoch);
|
||||
expect(ownerUndelegatedStake, 'Owner undelegated stake').to.deep.equal(expectedOwnerUndelegatedStake);
|
||||
// Updates local state accordingly
|
||||
ownerStake[StakeStatus.Undelegated] = expectedOwnerUndelegatedStake;
|
||||
@ -73,7 +81,7 @@ export function validStakeAssertion(
|
||||
const globalUndelegatedStake = await stakingWrapper
|
||||
.getGlobalStakeByStatus(StakeStatus.Undelegated)
|
||||
.callAsync();
|
||||
const expectedGlobalUndelegatedStake = expectedUndelegatedStake(globalStake, amount);
|
||||
const expectedGlobalUndelegatedStake = expectedUndelegatedStake(globalStake, amount, currentEpoch);
|
||||
expect(globalUndelegatedStake, 'Global undelegated stake').to.deep.equal(expectedGlobalUndelegatedStake);
|
||||
// Updates local state accordingly
|
||||
globalStake[StakeStatus.Undelegated] = expectedGlobalUndelegatedStake;
|
||||
|
@ -3,19 +3,23 @@ import { expect } from '@0x/contracts-test-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { TxData } from 'ethereum-types';
|
||||
|
||||
import { BlockchainBalanceStore } from '../balances/blockchain_balance_store';
|
||||
import { LocalBalanceStore } from '../balances/local_balance_store';
|
||||
import { DeploymentManager } from '../deployment_manager';
|
||||
import { SimulationEnvironment } from '../simulation';
|
||||
|
||||
import { FunctionAssertion, FunctionResult } from './function_assertion';
|
||||
|
||||
function expectedUndelegatedStake(
|
||||
initStake: OwnerStakeByStatus | GlobalStakeByStatus,
|
||||
amount: BigNumber,
|
||||
currentEpoch: BigNumber,
|
||||
): StoredBalance {
|
||||
return {
|
||||
currentEpoch: initStake[StakeStatus.Undelegated].currentEpoch,
|
||||
currentEpochBalance: initStake[StakeStatus.Undelegated].currentEpochBalance.minus(amount),
|
||||
currentEpoch: currentEpoch,
|
||||
currentEpochBalance: (currentEpoch.isGreaterThan(initStake[StakeStatus.Undelegated].currentEpoch)
|
||||
? initStake[StakeStatus.Undelegated].nextEpochBalance
|
||||
: initStake[StakeStatus.Undelegated].currentEpochBalance
|
||||
).minus(amount),
|
||||
nextEpochBalance: initStake[StakeStatus.Undelegated].nextEpochBalance.minus(amount),
|
||||
};
|
||||
}
|
||||
@ -29,8 +33,7 @@ function expectedUndelegatedStake(
|
||||
/* tslint:disable:no-non-null-assertion */
|
||||
export function validUnstakeAssertion(
|
||||
deployment: DeploymentManager,
|
||||
balanceStore: BlockchainBalanceStore,
|
||||
globalStake: GlobalStakeByStatus,
|
||||
simulationEnvironment: SimulationEnvironment,
|
||||
ownerStake: OwnerStakeByStatus,
|
||||
): FunctionAssertion<[BigNumber], LocalBalanceStore, void> {
|
||||
const { stakingWrapper, zrxVault } = deployment.staking;
|
||||
@ -38,6 +41,7 @@ export function validUnstakeAssertion(
|
||||
return new FunctionAssertion(stakingWrapper, 'unstake', {
|
||||
before: async (args: [BigNumber], txData: Partial<TxData>) => {
|
||||
const [amount] = args;
|
||||
const { balanceStore } = simulationEnvironment;
|
||||
|
||||
// Simulates the transfer of ZRX from vault to staker
|
||||
const expectedBalances = LocalBalanceStore.create(balanceStore);
|
||||
@ -51,11 +55,15 @@ export function validUnstakeAssertion(
|
||||
},
|
||||
after: async (
|
||||
expectedBalances: LocalBalanceStore,
|
||||
_result: FunctionResult,
|
||||
result: FunctionResult,
|
||||
args: [BigNumber],
|
||||
txData: Partial<TxData>,
|
||||
) => {
|
||||
// Ensure that the tx succeeded.
|
||||
expect(result.success, `Error: ${result.data}`).to.be.true();
|
||||
|
||||
const [amount] = args;
|
||||
const { balanceStore, globalStake, currentEpoch } = simulationEnvironment;
|
||||
|
||||
// Checks that the ZRX transfer updated balances as expected.
|
||||
await balanceStore.updateErc20BalancesAsync();
|
||||
@ -65,7 +73,7 @@ export function validUnstakeAssertion(
|
||||
const ownerUndelegatedStake = await stakingWrapper
|
||||
.getOwnerStakeByStatus(txData.from!, StakeStatus.Undelegated)
|
||||
.callAsync();
|
||||
const expectedOwnerUndelegatedStake = expectedUndelegatedStake(ownerStake, amount);
|
||||
const expectedOwnerUndelegatedStake = expectedUndelegatedStake(ownerStake, amount, currentEpoch);
|
||||
expect(ownerUndelegatedStake, 'Owner undelegated stake').to.deep.equal(expectedOwnerUndelegatedStake);
|
||||
// Updates local state accordingly
|
||||
ownerStake[StakeStatus.Undelegated] = expectedOwnerUndelegatedStake;
|
||||
@ -74,7 +82,7 @@ export function validUnstakeAssertion(
|
||||
const globalUndelegatedStake = await stakingWrapper
|
||||
.getGlobalStakeByStatus(StakeStatus.Undelegated)
|
||||
.callAsync();
|
||||
const expectedGlobalUndelegatedStake = expectedUndelegatedStake(globalStake, amount);
|
||||
const expectedGlobalUndelegatedStake = expectedUndelegatedStake(globalStake, amount, currentEpoch);
|
||||
expect(globalUndelegatedStake, 'Global undelegated stake').to.deep.equal(expectedGlobalUndelegatedStake);
|
||||
// Updates local state accordingly
|
||||
globalStake[StakeStatus.Undelegated] = expectedGlobalUndelegatedStake;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { WETH9TransferEventArgs, WETH9Events } from '@0x/contracts-erc20';
|
||||
import { StoredBalance } from '@0x/contracts-staking';
|
||||
import { expect, verifyEventsFromLogs } from '@0x/contracts-test-utils';
|
||||
import { expect, filterLogsToArguments, verifyEventsFromLogs } from '@0x/contracts-test-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { TxData } from 'ethereum-types';
|
||||
|
||||
@ -13,7 +13,6 @@ interface WithdrawDelegatorRewardsBeforeInfo {
|
||||
delegatorStake: StoredBalance;
|
||||
poolRewards: BigNumber;
|
||||
wethReservedForPoolRewards: BigNumber;
|
||||
delegatorReward: BigNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -27,35 +26,17 @@ export function validWithdrawDelegatorRewardsAssertion(
|
||||
simulationEnvironment: SimulationEnvironment,
|
||||
): FunctionAssertion<[string], WithdrawDelegatorRewardsBeforeInfo, void> {
|
||||
const { stakingWrapper } = deployment.staking;
|
||||
const { currentEpoch } = simulationEnvironment;
|
||||
|
||||
return new FunctionAssertion(stakingWrapper, 'withdrawDelegatorRewards', {
|
||||
before: async (args: [string], txData: Partial<TxData>) => {
|
||||
const [poolId] = args;
|
||||
|
||||
const delegatorStake = await stakingWrapper
|
||||
.getStakeDelegatedToPoolByOwner(txData.from!, poolId)
|
||||
.callAsync();
|
||||
const poolRewards = await stakingWrapper.rewardsByPoolId(poolId).callAsync();
|
||||
const wethReservedForPoolRewards = await stakingWrapper.wethReservedForPoolRewards().callAsync();
|
||||
const delegatorReward = BigNumber.sum(
|
||||
await stakingWrapper
|
||||
.computeMemberRewardOverInterval(
|
||||
poolId,
|
||||
delegatorStake.currentEpochBalance,
|
||||
delegatorStake.currentEpoch,
|
||||
delegatorStake.currentEpoch.plus(1),
|
||||
)
|
||||
.callAsync(),
|
||||
await stakingWrapper
|
||||
.computeMemberRewardOverInterval(
|
||||
poolId,
|
||||
delegatorStake.nextEpochBalance,
|
||||
delegatorStake.currentEpoch.plus(1),
|
||||
currentEpoch,
|
||||
)
|
||||
.callAsync(),
|
||||
); // TODO: Test the reward computation more robustly
|
||||
return { delegatorStake, poolRewards, wethReservedForPoolRewards, delegatorReward };
|
||||
return { delegatorStake, poolRewards, wethReservedForPoolRewards };
|
||||
},
|
||||
after: async (
|
||||
beforeInfo: WithdrawDelegatorRewardsBeforeInfo,
|
||||
@ -63,7 +44,11 @@ export function validWithdrawDelegatorRewardsAssertion(
|
||||
args: [string],
|
||||
txData: Partial<TxData>,
|
||||
) => {
|
||||
// Ensure that the tx succeeded.
|
||||
expect(result.success, `Error: ${result.data}`).to.be.true();
|
||||
|
||||
const [poolId] = args;
|
||||
const { currentEpoch } = simulationEnvironment;
|
||||
|
||||
const expectedDelegatorStake = {
|
||||
...beforeInfo.delegatorStake,
|
||||
@ -77,18 +62,16 @@ export function validWithdrawDelegatorRewardsAssertion(
|
||||
.callAsync();
|
||||
expect(delegatorStake).to.deep.equal(expectedDelegatorStake);
|
||||
|
||||
const expectedPoolRewards = beforeInfo.poolRewards.minus(beforeInfo.delegatorReward);
|
||||
const poolRewards = await stakingWrapper.rewardsByPoolId(poolId).callAsync();
|
||||
expect(poolRewards).to.bignumber.equal(expectedPoolRewards);
|
||||
|
||||
const expectedTransferEvents = beforeInfo.delegatorReward.isZero()
|
||||
? []
|
||||
: [{ _from: stakingWrapper.address, _to: txData.from!, _value: beforeInfo.delegatorReward }];
|
||||
verifyEventsFromLogs<WETH9TransferEventArgs>(
|
||||
const transferEvents = filterLogsToArguments<WETH9TransferEventArgs>(
|
||||
result.receipt!.logs,
|
||||
expectedTransferEvents,
|
||||
WETH9Events.Transfer,
|
||||
);
|
||||
const expectedPoolRewards =
|
||||
transferEvents.length > 0
|
||||
? beforeInfo.poolRewards.minus(transferEvents[0]._value)
|
||||
: beforeInfo.poolRewards;
|
||||
const poolRewards = await stakingWrapper.rewardsByPoolId(poolId).callAsync();
|
||||
expect(poolRewards).to.bignumber.equal(expectedPoolRewards);
|
||||
|
||||
// TODO: Check CR
|
||||
},
|
||||
|
@ -393,7 +393,16 @@ export class DeploymentManager {
|
||||
stakingLogic.address,
|
||||
);
|
||||
|
||||
const stakingWrapper = new TestStakingContract(stakingProxy.address, environment.provider, txDefaults);
|
||||
const logDecoderDependencies = _.mapValues(
|
||||
{ ...stakingArtifacts, ...ERC20Artifacts },
|
||||
v => v.compilerOutput.abi,
|
||||
);
|
||||
const stakingWrapper = new TestStakingContract(
|
||||
stakingProxy.address,
|
||||
environment.provider,
|
||||
txDefaults,
|
||||
logDecoderDependencies,
|
||||
);
|
||||
|
||||
// Add the zrx vault and the weth contract to the staking proxy.
|
||||
await stakingWrapper.setWethContract(tokens.weth.address).awaitTransactionSuccessAsync({ from: owner });
|
||||
|
@ -29,7 +29,7 @@ class Logger {
|
||||
msg: `Function called: ${functionName}(${functionArgs
|
||||
.map(arg => JSON.stringify(arg).replace(/"/g, "'"))
|
||||
.join(', ')})`,
|
||||
step: this._step++,
|
||||
step: ++this._step,
|
||||
txData,
|
||||
}),
|
||||
);
|
||||
|
@ -3,7 +3,7 @@ import { BigNumber } from '@0x/utils';
|
||||
import * as seedrandom from 'seedrandom';
|
||||
|
||||
class PRNGWrapper {
|
||||
public readonly seed = process.env.UUID || Math.random().toString();
|
||||
public readonly seed = process.env.SEED || Math.random().toString();
|
||||
private readonly _rng = seedrandom(this.seed);
|
||||
|
||||
/*
|
||||
|
@ -20,7 +20,6 @@ import { DeploymentManager } from '../framework/deployment_manager';
|
||||
import { Simulation, SimulationEnvironment } from '../framework/simulation';
|
||||
import { Pseudorandom } from '../framework/utils/pseudorandom';
|
||||
|
||||
import { PoolManagementSimulation } from './pool_management_test';
|
||||
import { PoolMembershipSimulation } from './pool_membership_test';
|
||||
import { StakeManagementSimulation } from './stake_management_test';
|
||||
|
||||
@ -30,7 +29,6 @@ export class StakingRewardsSimulation extends Simulation {
|
||||
const stakers = filterActorsByRole(actors, Staker);
|
||||
const keepers = filterActorsByRole(actors, Keeper);
|
||||
|
||||
const poolManagement = new PoolManagementSimulation(this.environment);
|
||||
const poolMembership = new PoolMembershipSimulation(this.environment);
|
||||
const stakeManagement = new StakeManagementSimulation(this.environment);
|
||||
|
||||
@ -38,7 +36,6 @@ export class StakingRewardsSimulation extends Simulation {
|
||||
...stakers.map(staker => staker.simulationActions.validWithdrawDelegatorRewards),
|
||||
...keepers.map(keeper => keeper.simulationActions.validFinalizePool),
|
||||
...keepers.map(keeper => keeper.simulationActions.validEndEpoch),
|
||||
poolManagement.generator,
|
||||
poolMembership.generator,
|
||||
stakeManagement.generator,
|
||||
];
|
||||
@ -66,12 +63,22 @@ blockchainTests('Staking rewards fuzz test', env => {
|
||||
numErc721TokensToDeploy: 0,
|
||||
numErc1155TokensToDeploy: 0,
|
||||
});
|
||||
const [ERC20TokenA, ERC20TokenB, ERC20TokenC, ERC20TokenD] = deployment.tokens.erc20;
|
||||
const balanceStore = new BlockchainBalanceStore(
|
||||
{
|
||||
StakingProxy: deployment.staking.stakingProxy.address,
|
||||
ZRXVault: deployment.staking.zrxVault.address,
|
||||
},
|
||||
{ erc20: { ZRX: deployment.tokens.zrx } },
|
||||
{
|
||||
erc20: {
|
||||
ZRX: deployment.tokens.zrx,
|
||||
WETH: deployment.tokens.weth,
|
||||
ERC20TokenA,
|
||||
ERC20TokenB,
|
||||
ERC20TokenC,
|
||||
ERC20TokenD,
|
||||
},
|
||||
},
|
||||
);
|
||||
const simulationEnvironment = new SimulationEnvironment(deployment, balanceStore);
|
||||
|
||||
|
@ -67,69 +67,6 @@ contract TestStaking is
|
||||
cumulativeRewards = _cumulativeRewardsByPool[poolId][lastStoredEpoch];
|
||||
}
|
||||
|
||||
function computeMemberRewardOverInterval(
|
||||
bytes32 poolId,
|
||||
uint256 memberStakeOverInterval,
|
||||
uint256 beginEpoch,
|
||||
uint256 endEpoch
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (uint256 reward)
|
||||
{
|
||||
// Sanity check if we can skip computation, as it will result in zero.
|
||||
if (memberStakeOverInterval == 0 || beginEpoch == endEpoch) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Sanity check interval
|
||||
require(beginEpoch < endEpoch, "CR_INTERVAL_INVALID");
|
||||
|
||||
// Sanity check begin reward
|
||||
IStructs.Fraction memory beginReward = getCumulativeRewardAtEpoch(poolId, beginEpoch);
|
||||
IStructs.Fraction memory endReward = getCumulativeRewardAtEpoch(poolId, endEpoch);
|
||||
|
||||
// Compute reward
|
||||
reward = LibFractions.scaleDifference(
|
||||
endReward.numerator,
|
||||
endReward.denominator,
|
||||
beginReward.numerator,
|
||||
beginReward.denominator,
|
||||
memberStakeOverInterval
|
||||
);
|
||||
}
|
||||
|
||||
function getCumulativeRewardAtEpoch(bytes32 poolId, uint256 epoch)
|
||||
public
|
||||
view
|
||||
returns (IStructs.Fraction memory cumulativeReward)
|
||||
{
|
||||
// Return CR at `epoch`, given it's set.
|
||||
cumulativeReward = _cumulativeRewardsByPool[poolId][epoch];
|
||||
if (_isCumulativeRewardSet(cumulativeReward)) {
|
||||
return cumulativeReward;
|
||||
}
|
||||
|
||||
// Return CR at `epoch-1`, given it's set.
|
||||
uint256 lastEpoch = epoch.safeSub(1);
|
||||
cumulativeReward = _cumulativeRewardsByPool[poolId][lastEpoch];
|
||||
if (_isCumulativeRewardSet(cumulativeReward)) {
|
||||
return cumulativeReward;
|
||||
}
|
||||
|
||||
// Return the most recent CR, given it's less than `epoch`.
|
||||
uint256 mostRecentEpoch = _cumulativeRewardsByPoolLastStored[poolId];
|
||||
if (mostRecentEpoch < epoch) {
|
||||
cumulativeReward = _cumulativeRewardsByPool[poolId][mostRecentEpoch];
|
||||
if (_isCumulativeRewardSet(cumulativeReward)) {
|
||||
return cumulativeReward;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise return an empty CR.
|
||||
return IStructs.Fraction(0, 1);
|
||||
}
|
||||
|
||||
/// @dev Overridden to use testWethAddress;
|
||||
function getWethContract()
|
||||
public
|
||||
|
Loading…
x
Reference in New Issue
Block a user