@0x/contracts-exchange: Fixing tests and writing new ones.
This commit is contained in:
committed by
Lawrence Forman
parent
d548ddac0d
commit
a1aad2e55e
@@ -146,6 +146,15 @@ export class StakerActor extends BaseActor {
|
||||
expect(finalZrxBalanceOfVault, 'final balance of zrx vault').to.be.bignumber.equal(initZrxBalanceOfVault);
|
||||
}
|
||||
|
||||
public async stakeWithPoolAsync(poolId: string, amount: BigNumber): Promise<void> {
|
||||
await this.stakeAsync(amount);
|
||||
await this.moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
amount,
|
||||
);
|
||||
}
|
||||
|
||||
public async goToNextEpochAsync(): Promise<void> {
|
||||
// cache balances
|
||||
const initZrxBalanceOfVault = await this._stakingApiWrapper.utils.getZrxTokenBalanceOfZrxVaultAsync();
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
expect,
|
||||
filterLogsToArguments,
|
||||
hexRandom,
|
||||
Numberish,
|
||||
randomAddress,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { StakingRevertErrors } from '@0x/order-utils';
|
||||
@@ -54,9 +55,26 @@ blockchainTests('Protocol Fee Unit Tests', env => {
|
||||
wethAssetData = await testContract.getWethAssetData.callAsync();
|
||||
});
|
||||
|
||||
async function createTestPoolAsync(stake: BigNumber, makers: string[]): Promise<string> {
|
||||
interface CreatePoolOpts {
|
||||
operatorStake: Numberish;
|
||||
membersStake: Numberish;
|
||||
makers: string[];
|
||||
}
|
||||
|
||||
async function createTestPoolAsync(opts: Partial<CreatePoolOpts>): Promise<string> {
|
||||
const _opts = {
|
||||
operatorStake: 0,
|
||||
membersStake: 0,
|
||||
makers: [],
|
||||
...opts,
|
||||
};
|
||||
const poolId = hexRandom();
|
||||
await testContract.createTestPool.awaitTransactionSuccessAsync(poolId, stake, makers);
|
||||
await testContract.createTestPool.awaitTransactionSuccessAsync(
|
||||
poolId,
|
||||
new BigNumber(_opts.operatorStake),
|
||||
new BigNumber(_opts.membersStake),
|
||||
_opts.makers,
|
||||
);
|
||||
return poolId;
|
||||
}
|
||||
|
||||
@@ -154,7 +172,7 @@ blockchainTests('Protocol Fee Unit Tests', env => {
|
||||
}
|
||||
|
||||
it('should not transfer WETH if value is sent', async () => {
|
||||
await createTestPoolAsync(minimumStake, []);
|
||||
await createTestPoolAsync({ operatorStake: minimumStake });
|
||||
const receipt = await testContract.payProtocolFee.awaitTransactionSuccessAsync(
|
||||
makerAddress,
|
||||
payerAddress,
|
||||
@@ -164,8 +182,8 @@ blockchainTests('Protocol Fee Unit Tests', env => {
|
||||
assertNoWETHTransferLogs(receipt.logs);
|
||||
});
|
||||
|
||||
it('should update `protocolFeesThisEpochByPool` if the maker is in a pool', async () => {
|
||||
const poolId = await createTestPoolAsync(minimumStake, [makerAddress]);
|
||||
it('should credit pool if the maker is in a pool', async () => {
|
||||
const poolId = await createTestPoolAsync({ operatorStake: minimumStake, makers: [makerAddress] });
|
||||
const receipt = await testContract.payProtocolFee.awaitTransactionSuccessAsync(
|
||||
makerAddress,
|
||||
payerAddress,
|
||||
@@ -177,8 +195,8 @@ blockchainTests('Protocol Fee Unit Tests', env => {
|
||||
expect(poolFees).to.bignumber.eq(DEFAULT_PROTOCOL_FEE_PAID);
|
||||
});
|
||||
|
||||
it('should not update `protocolFeesThisEpochByPool` if maker is not in a pool', async () => {
|
||||
const poolId = await createTestPoolAsync(minimumStake, []);
|
||||
it('should not credit the pool if maker is not in a pool', async () => {
|
||||
const poolId = await createTestPoolAsync({ operatorStake: minimumStake });
|
||||
const receipt = await testContract.payProtocolFee.awaitTransactionSuccessAsync(
|
||||
makerAddress,
|
||||
payerAddress,
|
||||
@@ -191,7 +209,7 @@ blockchainTests('Protocol Fee Unit Tests', env => {
|
||||
});
|
||||
|
||||
it('fees paid to the same maker should go to the same pool', async () => {
|
||||
const poolId = await createTestPoolAsync(minimumStake, [makerAddress]);
|
||||
const poolId = await createTestPoolAsync({ operatorStake: minimumStake, makers: [makerAddress] });
|
||||
const payAsync = async () => {
|
||||
const receipt = await testContract.payProtocolFee.awaitTransactionSuccessAsync(
|
||||
makerAddress,
|
||||
@@ -225,7 +243,7 @@ blockchainTests('Protocol Fee Unit Tests', env => {
|
||||
}
|
||||
|
||||
it('should transfer WETH if no value is sent and the maker is not in a pool', async () => {
|
||||
await createTestPoolAsync(minimumStake, []);
|
||||
await createTestPoolAsync({ operatorStake: minimumStake });
|
||||
const receipt = await testContract.payProtocolFee.awaitTransactionSuccessAsync(
|
||||
makerAddress,
|
||||
payerAddress,
|
||||
@@ -236,7 +254,7 @@ blockchainTests('Protocol Fee Unit Tests', env => {
|
||||
});
|
||||
|
||||
it('should update `protocolFeesThisEpochByPool` if the maker is in a pool', async () => {
|
||||
const poolId = await createTestPoolAsync(minimumStake, [makerAddress]);
|
||||
const poolId = await createTestPoolAsync({ operatorStake: minimumStake, makers: [makerAddress] });
|
||||
const receipt = await testContract.payProtocolFee.awaitTransactionSuccessAsync(
|
||||
makerAddress,
|
||||
payerAddress,
|
||||
@@ -249,7 +267,7 @@ blockchainTests('Protocol Fee Unit Tests', env => {
|
||||
});
|
||||
|
||||
it('should not update `protocolFeesThisEpochByPool` if maker is not in a pool', async () => {
|
||||
const poolId = await createTestPoolAsync(minimumStake, []);
|
||||
const poolId = await createTestPoolAsync({ operatorStake: minimumStake });
|
||||
const receipt = await testContract.payProtocolFee.awaitTransactionSuccessAsync(
|
||||
makerAddress,
|
||||
payerAddress,
|
||||
@@ -262,7 +280,7 @@ blockchainTests('Protocol Fee Unit Tests', env => {
|
||||
});
|
||||
|
||||
it('fees paid to the same maker should go to the same pool', async () => {
|
||||
const poolId = await createTestPoolAsync(minimumStake, [makerAddress]);
|
||||
const poolId = await createTestPoolAsync({ operatorStake: minimumStake, makers: [makerAddress] });
|
||||
const payAsync = async () => {
|
||||
const receipt = await testContract.payProtocolFee.awaitTransactionSuccessAsync(
|
||||
makerAddress,
|
||||
@@ -280,7 +298,7 @@ blockchainTests('Protocol Fee Unit Tests', env => {
|
||||
});
|
||||
|
||||
it('fees paid to the same maker in WETH then ETH should go to the same pool', async () => {
|
||||
const poolId = await createTestPoolAsync(minimumStake, [makerAddress]);
|
||||
const poolId = await createTestPoolAsync({ operatorStake: minimumStake, makers: [makerAddress] });
|
||||
const payAsync = async (inWETH: boolean) => {
|
||||
await testContract.payProtocolFee.awaitTransactionSuccessAsync(
|
||||
makerAddress,
|
||||
@@ -303,7 +321,7 @@ blockchainTests('Protocol Fee Unit Tests', env => {
|
||||
describe('Multiple makers', () => {
|
||||
it('fees paid to different makers in the same pool go to that pool', async () => {
|
||||
const otherMakerAddress = randomAddress();
|
||||
const poolId = await createTestPoolAsync(minimumStake, [makerAddress, otherMakerAddress]);
|
||||
const poolId = await createTestPoolAsync({ operatorStake: minimumStake, makers: [makerAddress, otherMakerAddress] });
|
||||
const payAsync = async (_makerAddress: string) => {
|
||||
await testContract.payProtocolFee.awaitTransactionSuccessAsync(
|
||||
_makerAddress,
|
||||
@@ -322,8 +340,8 @@ blockchainTests('Protocol Fee Unit Tests', env => {
|
||||
it('fees paid to makers in different pools go to their respective pools', async () => {
|
||||
const [fee, otherFee] = _.times(2, () => getRandomPortion(DEFAULT_PROTOCOL_FEE_PAID));
|
||||
const otherMakerAddress = randomAddress();
|
||||
const poolId = await createTestPoolAsync(minimumStake, [makerAddress]);
|
||||
const otherPoolId = await createTestPoolAsync(minimumStake, [otherMakerAddress]);
|
||||
const poolId = await createTestPoolAsync({ operatorStake: minimumStake, makers: [makerAddress] });
|
||||
const otherPoolId = await createTestPoolAsync({ operatorStake: minimumStake, makers: [otherMakerAddress]});
|
||||
const payAsync = async (_poolId: string, _makerAddress: string, _fee: BigNumber) => {
|
||||
// prettier-ignore
|
||||
await testContract.payProtocolFee.awaitTransactionSuccessAsync(
|
||||
@@ -346,7 +364,7 @@ blockchainTests('Protocol Fee Unit Tests', env => {
|
||||
|
||||
describe('Dust stake', () => {
|
||||
it('credits pools with stake > minimum', async () => {
|
||||
const poolId = await createTestPoolAsync(minimumStake.plus(1), [makerAddress]);
|
||||
const poolId = await createTestPoolAsync({ operatorStake: minimumStake.plus(1), makers: [makerAddress] });
|
||||
await testContract.payProtocolFee.awaitTransactionSuccessAsync(
|
||||
makerAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
@@ -358,7 +376,7 @@ blockchainTests('Protocol Fee Unit Tests', env => {
|
||||
});
|
||||
|
||||
it('credits pools with stake == minimum', async () => {
|
||||
const poolId = await createTestPoolAsync(minimumStake, [makerAddress]);
|
||||
const poolId = await createTestPoolAsync({ operatorStake: minimumStake, makers: [makerAddress] });
|
||||
await testContract.payProtocolFee.awaitTransactionSuccessAsync(
|
||||
makerAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
@@ -370,7 +388,7 @@ blockchainTests('Protocol Fee Unit Tests', env => {
|
||||
});
|
||||
|
||||
it('does not credit pools with stake < minimum', async () => {
|
||||
const poolId = await createTestPoolAsync(minimumStake.minus(1), [makerAddress]);
|
||||
const poolId = await createTestPoolAsync({ operatorStake: minimumStake.minus(1), makers: [makerAddress] });
|
||||
await testContract.payProtocolFee.awaitTransactionSuccessAsync(
|
||||
makerAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
|
||||
@@ -6,6 +6,7 @@ import * as _ from 'lodash';
|
||||
import { artifacts } from '../src';
|
||||
|
||||
import { FinalizerActor } from './actors/finalizer_actor';
|
||||
import { PoolOperatorActor } from './actors/pool_operator_actor';
|
||||
import { StakerActor } from './actors/staker_actor';
|
||||
import { deployAndConfigureContractsAsync, StakingApiWrapper } from './utils/api_wrapper';
|
||||
import { toBaseUnitAmount } from './utils/number_utils';
|
||||
@@ -26,8 +27,9 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
let erc20Wrapper: ERC20Wrapper;
|
||||
// test parameters
|
||||
let stakers: StakerActor[];
|
||||
let poolOperatorStaker: StakerActor;
|
||||
let poolId: string;
|
||||
let poolOperator: string;
|
||||
let poolOperator: PoolOperatorActor;
|
||||
let finalizer: FinalizerActor;
|
||||
// tests
|
||||
before(async () => {
|
||||
@@ -43,7 +45,7 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
stakingApiWrapper = await deployAndConfigureContractsAsync(env, owner, erc20Wrapper, artifacts.TestStaking);
|
||||
// set up staking parameters
|
||||
await stakingApiWrapper.utils.setParamsAsync({
|
||||
minimumPoolStake: new BigNumber(0),
|
||||
minimumPoolStake: new BigNumber(1),
|
||||
cobbDouglasAlphaNumerator: new BigNumber(1),
|
||||
cobbDouglasAlphaDenominator: new BigNumber(6),
|
||||
rewardVaultAddress: stakingApiWrapper.rewardVaultContract.address,
|
||||
@@ -51,22 +53,26 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
zrxVaultAddress: stakingApiWrapper.zrxVaultContract.address,
|
||||
});
|
||||
// setup stakers
|
||||
stakers = [new StakerActor(actors[0], stakingApiWrapper), new StakerActor(actors[1], stakingApiWrapper)];
|
||||
stakers = actors.slice(0, 2).map(a => new StakerActor(a, stakingApiWrapper));
|
||||
// setup pools
|
||||
poolOperator = actors[2];
|
||||
poolId = await stakingApiWrapper.utils.createStakingPoolAsync(poolOperator, 0, true); // add operator as maker
|
||||
poolOperator = new PoolOperatorActor(actors[2], stakingApiWrapper);
|
||||
// Create a pool where all rewards go to members.
|
||||
poolId = await poolOperator.createStakingPoolAsync(0, true);
|
||||
// Stake something in the pool or else it won't get any rewards.
|
||||
poolOperatorStaker = new StakerActor(poolOperator.getOwner(), stakingApiWrapper);
|
||||
await poolOperatorStaker.stakeWithPoolAsync(poolId, new BigNumber(1));
|
||||
// set exchange address
|
||||
await stakingApiWrapper.stakingContract.addExchangeAddress.awaitTransactionSuccessAsync(exchangeAddress);
|
||||
// associate operators for tracking in Finalizer
|
||||
const operatorByPoolId: OperatorByPoolId = {};
|
||||
operatorByPoolId[poolId] = poolOperator;
|
||||
operatorByPoolId[poolId] = poolOperator;
|
||||
operatorByPoolId[poolId] = poolOperator.getOwner();
|
||||
// associate actors with pools for tracking in Finalizer
|
||||
const membersByPoolId: MembersByPoolId = {};
|
||||
membersByPoolId[poolId] = [actors[0], actors[1]];
|
||||
membersByPoolId[poolId] = [actors[0], actors[1]];
|
||||
// create Finalizer actor
|
||||
finalizer = new FinalizerActor(actors[3], stakingApiWrapper, [poolId], operatorByPoolId, membersByPoolId);
|
||||
// Skip to next epoch so operator stake is realized.
|
||||
await stakingApiWrapper.utils.skipToNextEpochAndFinalizeAsync();
|
||||
});
|
||||
describe('Reward Simulation', () => {
|
||||
interface EndBalances {
|
||||
@@ -154,7 +160,7 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
const fee = _fee !== undefined ? _fee : ZERO;
|
||||
if (!fee.eq(ZERO)) {
|
||||
await stakingApiWrapper.stakingContract.payProtocolFee.awaitTransactionSuccessAsync(
|
||||
poolOperator,
|
||||
poolOperator.getOwner(),
|
||||
takerAddress,
|
||||
fee,
|
||||
{ from: exchangeAddress, value: fee },
|
||||
@@ -196,12 +202,7 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
(staker joins this epoch but is active next epoch)`, async () => {
|
||||
// delegate
|
||||
const amount = toBaseUnitAmount(4);
|
||||
await stakers[0].stakeAsync(amount);
|
||||
await stakers[0].moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
amount,
|
||||
);
|
||||
await stakers[0].stakeWithPoolAsync(poolId, amount);
|
||||
// finalize
|
||||
const reward = toBaseUnitAmount(10);
|
||||
await payProtocolFeeAndFinalize(reward);
|
||||
@@ -213,12 +214,7 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
it('Should give pool reward to delegator', async () => {
|
||||
// delegate
|
||||
const amount = toBaseUnitAmount(4);
|
||||
await stakers[0].stakeAsync(amount);
|
||||
await stakers[0].moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
amount,
|
||||
);
|
||||
await stakers[0].stakeWithPoolAsync(poolId, amount);
|
||||
// skip epoch, so staker can start earning rewards
|
||||
await payProtocolFeeAndFinalize();
|
||||
// finalize
|
||||
@@ -232,22 +228,12 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
});
|
||||
});
|
||||
it('Should split pool reward between delegators', async () => {
|
||||
// first staker delegates
|
||||
const stakeAmounts = [toBaseUnitAmount(4), toBaseUnitAmount(6)];
|
||||
const totalStakeAmount = toBaseUnitAmount(10);
|
||||
await stakers[0].stakeAsync(stakeAmounts[0]);
|
||||
await stakers[0].moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmounts[0],
|
||||
);
|
||||
// first staker delegates
|
||||
await stakers[0].stakeWithPoolAsync(poolId, stakeAmounts[0]);
|
||||
// second staker delegates
|
||||
await stakers[1].stakeAsync(stakeAmounts[1]);
|
||||
await stakers[1].moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmounts[1],
|
||||
);
|
||||
await stakers[1].stakeWithPoolAsync(poolId, stakeAmounts[1]);
|
||||
// skip epoch, so staker can start earning rewards
|
||||
await payProtocolFeeAndFinalize();
|
||||
// finalize
|
||||
@@ -299,24 +285,14 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
});
|
||||
});
|
||||
it('Should give pool reward to delegators only for the epoch during which they delegated', async () => {
|
||||
// first staker delegates (epoch 0)
|
||||
const stakeAmounts = [toBaseUnitAmount(4), toBaseUnitAmount(6)];
|
||||
const totalStakeAmount = toBaseUnitAmount(10);
|
||||
await stakers[0].stakeAsync(stakeAmounts[0]);
|
||||
await stakers[0].moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmounts[0],
|
||||
);
|
||||
// first staker delegates (epoch 0)
|
||||
await stakers[0].stakeWithPoolAsync(poolId, stakeAmounts[0]);
|
||||
// skip epoch, so first staker can start earning rewards
|
||||
await payProtocolFeeAndFinalize();
|
||||
// second staker delegates (epoch 1)
|
||||
await stakers[1].stakeAsync(stakeAmounts[1]);
|
||||
await stakers[1].moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmounts[1],
|
||||
);
|
||||
await stakers[1].stakeWithPoolAsync(poolId, stakeAmounts[1]);
|
||||
// only the first staker will get this reward
|
||||
const rewardForOnlyFirstDelegator = toBaseUnitAmount(10);
|
||||
await payProtocolFeeAndFinalize(rewardForOnlyFirstDelegator);
|
||||
@@ -349,24 +325,14 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
return v.toNumber();
|
||||
});
|
||||
const totalSharedRewards = new BigNumber(totalSharedRewardsAsNumber);
|
||||
// first staker delegates (epoch 0)
|
||||
const stakeAmounts = [toBaseUnitAmount(4), toBaseUnitAmount(6)];
|
||||
const totalStakeAmount = toBaseUnitAmount(10);
|
||||
await stakers[0].stakeAsync(stakeAmounts[0]);
|
||||
await stakers[0].moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmounts[0],
|
||||
);
|
||||
// first staker delegates (epoch 0)
|
||||
await stakers[0].stakeWithPoolAsync(poolId, stakeAmounts[0]);
|
||||
// skip epoch, so first staker can start earning rewards
|
||||
await payProtocolFeeAndFinalize();
|
||||
// second staker delegates (epoch 1)
|
||||
await stakers[1].stakeAsync(stakeAmounts[1]);
|
||||
await stakers[1].moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmounts[1],
|
||||
);
|
||||
await stakers[1].stakeWithPoolAsync(poolId, stakeAmounts[1]);
|
||||
// only the first staker will get this reward
|
||||
await payProtocolFeeAndFinalize(rewardForOnlyFirstDelegator);
|
||||
// earn a bunch of rewards
|
||||
@@ -386,14 +352,9 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
});
|
||||
});
|
||||
it('Should send existing rewards from reward vault to eth vault correctly when undelegating stake', async () => {
|
||||
// first staker delegates (epoch 0)
|
||||
const stakeAmount = toBaseUnitAmount(4);
|
||||
await stakers[0].stakeAsync(stakeAmount);
|
||||
await stakers[0].moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmount,
|
||||
);
|
||||
// first staker delegates (epoch 0)
|
||||
await stakers[0].stakeWithPoolAsync(poolId, stakeAmount);
|
||||
// skip epoch, so first staker can start earning rewards
|
||||
await payProtocolFeeAndFinalize();
|
||||
// earn reward
|
||||
@@ -412,26 +373,16 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
});
|
||||
});
|
||||
it('Should send existing rewards from reward vault to eth vault correctly when delegating more stake', async () => {
|
||||
// first staker delegates (epoch 0)
|
||||
const stakeAmount = toBaseUnitAmount(4);
|
||||
await stakers[0].stakeAsync(stakeAmount);
|
||||
await stakers[0].moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmount,
|
||||
);
|
||||
// first staker delegates (epoch 0)
|
||||
await stakers[0].stakeWithPoolAsync(poolId, stakeAmount);
|
||||
// skip epoch, so first staker can start earning rewards
|
||||
await payProtocolFeeAndFinalize();
|
||||
// earn reward
|
||||
const reward = toBaseUnitAmount(10);
|
||||
await payProtocolFeeAndFinalize(reward);
|
||||
// add more stake
|
||||
await stakers[0].stakeAsync(stakeAmount);
|
||||
await stakers[0].moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmount,
|
||||
);
|
||||
await stakers[0].stakeWithPoolAsync(poolId, stakeAmount);
|
||||
// sanity check final balances
|
||||
await validateEndBalances({
|
||||
stakerRewardVaultBalance_1: ZERO,
|
||||
@@ -453,23 +404,13 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
return v.toNumber();
|
||||
}),
|
||||
);
|
||||
// first staker delegates (epoch 0)
|
||||
const stakeAmounts = [toBaseUnitAmount(4), toBaseUnitAmount(6)];
|
||||
await stakers[0].stakeAsync(stakeAmounts[0]);
|
||||
await stakers[0].moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmounts[0],
|
||||
);
|
||||
// first staker delegates (epoch 0)
|
||||
await stakers[0].stakeWithPoolAsync(poolId, stakeAmounts[0]);
|
||||
// skip epoch, so first staker can start earning rewards
|
||||
await payProtocolFeeAndFinalize();
|
||||
// second staker delegates (epoch 1)
|
||||
await stakers[0].stakeAsync(stakeAmounts[1]);
|
||||
await stakers[0].moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmounts[1],
|
||||
);
|
||||
await stakers[1].stakeWithPoolAsync(poolId, stakeAmounts[1]);
|
||||
// only the first staker will get this reward
|
||||
await payProtocolFeeAndFinalize(rewardBeforeAddingMoreStake);
|
||||
// earn a bunch of rewards
|
||||
@@ -488,12 +429,7 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
const rewardForDelegator = toBaseUnitAmount(10);
|
||||
const rewardNotForDelegator = toBaseUnitAmount(7);
|
||||
const stakeAmount = toBaseUnitAmount(4);
|
||||
await stakers[0].stakeAsync(stakeAmount);
|
||||
await stakers[0].moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmount,
|
||||
);
|
||||
await stakers[0].stakeWithPoolAsync(poolId, stakeAmount);
|
||||
// skip epoch, so first staker can start earning rewards
|
||||
await payProtocolFeeAndFinalize();
|
||||
// earn reward
|
||||
@@ -534,12 +470,7 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
}),
|
||||
);
|
||||
const stakeAmount = toBaseUnitAmount(4);
|
||||
await stakers[0].stakeAsync(stakeAmount);
|
||||
await stakers[0].moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmount,
|
||||
);
|
||||
await stakers[0].stakeWithPoolAsync(poolId, stakeAmount);
|
||||
// skip epoch, so first staker can start earning rewards
|
||||
await payProtocolFeeAndFinalize();
|
||||
// earn reward
|
||||
@@ -566,12 +497,7 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
const rewardsForDelegator = [toBaseUnitAmount(10), toBaseUnitAmount(15)];
|
||||
const rewardNotForDelegator = toBaseUnitAmount(7);
|
||||
const stakeAmount = toBaseUnitAmount(4);
|
||||
await stakers[0].stakeAsync(stakeAmount);
|
||||
await stakers[0].moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmount,
|
||||
);
|
||||
await stakers[0].stakeWithPoolAsync(poolId, stakeAmount);
|
||||
// skip epoch, so first staker can start earning rewards
|
||||
await payProtocolFeeAndFinalize();
|
||||
// earn reward
|
||||
@@ -668,12 +594,7 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
const staker = stakers[0];
|
||||
const stakeAmount = toBaseUnitAmount(5);
|
||||
// stake and delegate
|
||||
await staker.stakeAsync(stakeAmount);
|
||||
await staker.moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmount,
|
||||
);
|
||||
await stakers[0].stakeWithPoolAsync(poolId, stakeAmount);
|
||||
// skip epoch, so staker can start earning rewards
|
||||
await payProtocolFeeAndFinalize();
|
||||
// undelegate some stake
|
||||
@@ -703,12 +624,7 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
// stake and delegate both
|
||||
const stakersAndStake = _.zip(stakers.slice(0, 2), stakeAmounts) as Array<[StakerActor, BigNumber]>;
|
||||
for (const [staker, stakeAmount] of stakersAndStake) {
|
||||
await staker.stakeAsync(stakeAmount);
|
||||
await staker.moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmount,
|
||||
);
|
||||
await staker.stakeWithPoolAsync(poolId, stakeAmount);
|
||||
}
|
||||
// skip epoch, so staker can start earning rewards
|
||||
await payProtocolFeeAndFinalize();
|
||||
@@ -739,12 +655,7 @@ blockchainTests.resets('Testing Rewards', env => {
|
||||
// stake and delegate both
|
||||
const stakersAndStake = _.zip(stakers.slice(0, 2), stakeAmounts) as Array<[StakerActor, BigNumber]>;
|
||||
for (const [staker, stakeAmount] of stakersAndStake) {
|
||||
await staker.stakeAsync(stakeAmount);
|
||||
await staker.moveStakeAsync(
|
||||
new StakeInfo(StakeStatus.Active),
|
||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||
stakeAmount,
|
||||
);
|
||||
await staker.stakeWithPoolAsync(poolId, stakeAmount);
|
||||
}
|
||||
// skip epoch, so staker can start earning rewards
|
||||
await payProtocolFeeAndFinalize();
|
||||
|
||||
@@ -7,7 +7,7 @@ blockchainTests('delegator rewards', env => {
|
||||
|
||||
before(async () => {
|
||||
testContract = await TestDelegatorRewardsContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestLibFixedMath,
|
||||
artifacts.TestDelegatorRewards,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
55
contracts/staking/test/unit_tests/finalizer_test.ts
Normal file
55
contracts/staking/test/unit_tests/finalizer_test.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { blockchainTests, expect, filterLogsToArguments, Numberish } from '@0x/contracts-test-utils';
|
||||
|
||||
import {
|
||||
artifacts,
|
||||
IStakingEventsEpochEndedEventArgs,
|
||||
IStakingEventsEpochFinalizedEventArgs,
|
||||
IStakingEventsEvents,
|
||||
TestFinalizerContract,
|
||||
} from '../../src';
|
||||
|
||||
blockchainTests.resets.only('finalization tests', env => {
|
||||
let testContract: TestFinalizerContract;
|
||||
const INITIAL_EPOCH = 0;
|
||||
|
||||
before(async () => {
|
||||
testContract = await TestFinalizerContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestFinalizer,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
});
|
||||
|
||||
describe('endEpoch()', () => {
|
||||
it('emits an `EpochEnded` event', async () => {
|
||||
const receipt = await testContract.endEpoch.awaitTransactionSuccessAsync();
|
||||
const [epochEndedEvent] = filterLogsToArguments<IStakingEventsEpochEndedEventArgs>(
|
||||
receipt.logs,
|
||||
IStakingEventsEvents.EpochEnded,
|
||||
);
|
||||
expect(epochEndedEvent.epoch).to.bignumber.eq(INITIAL_EPOCH);
|
||||
expect(epochEndedEvent.numActivePools).to.bignumber.eq(0);
|
||||
expect(epochEndedEvent.rewardsAvailable).to.bignumber.eq(0);
|
||||
expect(epochEndedEvent.totalFeesCollected).to.bignumber.eq(0);
|
||||
expect(epochEndedEvent.totalWeightedStake).to.bignumber.eq(0);
|
||||
});
|
||||
|
||||
it('advances the epoch', async () => {
|
||||
await testContract.endEpoch.awaitTransactionSuccessAsync();
|
||||
const currentEpoch = await testContract.getCurrentEpoch.callAsync();
|
||||
expect(currentEpoch).to.be.bignumber.eq(INITIAL_EPOCH + 1);
|
||||
});
|
||||
|
||||
it('immediately finalizes if there are no active pools', async () => {
|
||||
const receipt = await testContract.endEpoch.awaitTransactionSuccessAsync();
|
||||
const [epochFinalizedEvent] = filterLogsToArguments<IStakingEventsEpochFinalizedEventArgs>(
|
||||
receipt.logs,
|
||||
IStakingEventsEvents.EpochFinalized,
|
||||
);
|
||||
expect(epochFinalizedEvent.epoch).to.bignumber.eq(INITIAL_EPOCH);
|
||||
expect(epochFinalizedEvent.rewardsPaid).to.bignumber.eq(0);
|
||||
expect(epochFinalizedEvent.rewardsRemaining).to.bignumber.eq(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user