Merge pull request #2316 from 0xProject/tests/3.0/StakingMixinCumulativeRewardsUnitTEsts
Unit tests for MixinCumulativeRewards
This commit is contained in:
commit
44793a9cf9
@ -29,6 +29,10 @@
|
|||||||
{
|
{
|
||||||
"note": "Unit tests for MixinScheduler",
|
"note": "Unit tests for MixinScheduler",
|
||||||
"pr": 2314
|
"pr": 2314
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Unit tests for MixinCumulativeRewards",
|
||||||
|
"pr": 2316
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
125
contracts/staking/contracts/test/TestMixinCumulativeRewards.sol
Normal file
125
contracts/staking/contracts/test/TestMixinCumulativeRewards.sol
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.9;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "./TestStaking.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract TestMixinCumulativeRewards is
|
||||||
|
TestStaking
|
||||||
|
{
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
address wethAddress,
|
||||||
|
address zrxVaultAddress
|
||||||
|
)
|
||||||
|
public
|
||||||
|
TestStaking(
|
||||||
|
wethAddress,
|
||||||
|
zrxVaultAddress
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_addAuthorizedAddress(msg.sender);
|
||||||
|
init();
|
||||||
|
_removeAuthorizedAddressAtIndex(msg.sender, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Exposes `_isCumulativeRewardSet`
|
||||||
|
function isCumulativeRewardSet(IStructs.Fraction memory cumulativeReward)
|
||||||
|
public
|
||||||
|
pure
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
return _isCumulativeRewardSet(cumulativeReward);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Exposes `_addCumulativeReward`
|
||||||
|
function addCumulativeReward(
|
||||||
|
bytes32 poolId,
|
||||||
|
uint256 reward,
|
||||||
|
uint256 stake
|
||||||
|
)
|
||||||
|
public
|
||||||
|
{
|
||||||
|
_addCumulativeReward(poolId, reward, stake);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Exposes `_updateCumulativeReward`
|
||||||
|
function updateCumulativeReward(bytes32 poolId)
|
||||||
|
public
|
||||||
|
{
|
||||||
|
_updateCumulativeReward(poolId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Exposes _computeMemberRewardOverInterval
|
||||||
|
function computeMemberRewardOverInterval(
|
||||||
|
bytes32 poolId,
|
||||||
|
uint256 memberStakeOverInterval,
|
||||||
|
uint256 beginEpoch,
|
||||||
|
uint256 endEpoch
|
||||||
|
)
|
||||||
|
public
|
||||||
|
view
|
||||||
|
returns (uint256 reward)
|
||||||
|
{
|
||||||
|
return _computeMemberRewardOverInterval(poolId, memberStakeOverInterval, beginEpoch, endEpoch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Increments current epoch by 1
|
||||||
|
function incrementEpoch()
|
||||||
|
public
|
||||||
|
{
|
||||||
|
currentEpoch += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Stores an arbitrary cumulative reward for a given epoch.
|
||||||
|
/// Also sets the `_cumulativeRewardsByPoolLastStored` to the input epoch.
|
||||||
|
function storeCumulativeReward(
|
||||||
|
bytes32 poolId,
|
||||||
|
IStructs.Fraction memory cumulativeReward,
|
||||||
|
uint256 epoch
|
||||||
|
)
|
||||||
|
public
|
||||||
|
{
|
||||||
|
_cumulativeRewardsByPool[poolId][epoch] = cumulativeReward;
|
||||||
|
_cumulativeRewardsByPoolLastStored[poolId] = epoch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Returns the most recent cumulative reward for a given pool.
|
||||||
|
function getMostRecentCumulativeReward(bytes32 poolId)
|
||||||
|
public
|
||||||
|
returns (IStructs.Fraction memory)
|
||||||
|
{
|
||||||
|
uint256 mostRecentEpoch = _cumulativeRewardsByPoolLastStored[poolId];
|
||||||
|
return _cumulativeRewardsByPool[poolId][mostRecentEpoch];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Returns the raw cumulative reward for a given pool in an epoch.
|
||||||
|
/// This is considered "raw" because the internal implementation
|
||||||
|
/// (_getCumulativeRewardAtEpochRaw) will query other state variables
|
||||||
|
/// to determine the most accurate cumulative reward for a given epoch.
|
||||||
|
function getCumulativeRewardAtEpochRaw(bytes32 poolId, uint256 epoch)
|
||||||
|
public
|
||||||
|
returns (IStructs.Fraction memory)
|
||||||
|
{
|
||||||
|
return _cumulativeRewardsByPool[poolId][epoch];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -37,7 +37,7 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||||
"abis": "./generated-artifacts/@(IStaking|IStakingEvents|IStakingProxy|IStorage|IStorageInit|IStructs|IZrxVault|LibCobbDouglas|LibFixedMath|LibFixedMathRichErrors|LibSafeDowncast|LibStakingRichErrors|MixinAbstract|MixinConstants|MixinCumulativeRewards|MixinDeploymentConstants|MixinExchangeFees|MixinExchangeManager|MixinFinalizer|MixinParams|MixinScheduler|MixinStake|MixinStakeBalances|MixinStakeStorage|MixinStakingPool|MixinStakingPoolRewards|MixinStorage|Staking|StakingProxy|TestAssertStorageParams|TestCobbDouglas|TestCumulativeRewardTracking|TestDelegatorRewards|TestExchangeManager|TestFinalizer|TestInitTarget|TestLibFixedMath|TestLibSafeDowncast|TestMixinParams|TestMixinScheduler|TestMixinStake|TestMixinStakeBalances|TestMixinStakeStorage|TestMixinStakingPool|TestMixinStakingPoolRewards|TestProtocolFees|TestProxyDestination|TestStaking|TestStakingNoWETH|TestStakingProxy|TestStakingProxyUnit|TestStorageLayoutAndConstants|ZrxVault).json"
|
"abis": "./generated-artifacts/@(IStaking|IStakingEvents|IStakingProxy|IStorage|IStorageInit|IStructs|IZrxVault|LibCobbDouglas|LibFixedMath|LibFixedMathRichErrors|LibSafeDowncast|LibStakingRichErrors|MixinAbstract|MixinConstants|MixinCumulativeRewards|MixinDeploymentConstants|MixinExchangeFees|MixinExchangeManager|MixinFinalizer|MixinParams|MixinScheduler|MixinStake|MixinStakeBalances|MixinStakeStorage|MixinStakingPool|MixinStakingPoolRewards|MixinStorage|Staking|StakingProxy|TestAssertStorageParams|TestCobbDouglas|TestCumulativeRewardTracking|TestDelegatorRewards|TestExchangeManager|TestFinalizer|TestInitTarget|TestLibFixedMath|TestLibSafeDowncast|TestMixinCumulativeRewards|TestMixinParams|TestMixinScheduler|TestMixinStake|TestMixinStakeBalances|TestMixinStakeStorage|TestMixinStakingPool|TestMixinStakingPoolRewards|TestProtocolFees|TestProxyDestination|TestStaking|TestStakingNoWETH|TestStakingProxy|TestStakingProxyUnit|TestStorageLayoutAndConstants|ZrxVault).json"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -43,6 +43,7 @@ import * as TestFinalizer from '../generated-artifacts/TestFinalizer.json';
|
|||||||
import * as TestInitTarget from '../generated-artifacts/TestInitTarget.json';
|
import * as TestInitTarget from '../generated-artifacts/TestInitTarget.json';
|
||||||
import * as TestLibFixedMath from '../generated-artifacts/TestLibFixedMath.json';
|
import * as TestLibFixedMath from '../generated-artifacts/TestLibFixedMath.json';
|
||||||
import * as TestLibSafeDowncast from '../generated-artifacts/TestLibSafeDowncast.json';
|
import * as TestLibSafeDowncast from '../generated-artifacts/TestLibSafeDowncast.json';
|
||||||
|
import * as TestMixinCumulativeRewards from '../generated-artifacts/TestMixinCumulativeRewards.json';
|
||||||
import * as TestMixinParams from '../generated-artifacts/TestMixinParams.json';
|
import * as TestMixinParams from '../generated-artifacts/TestMixinParams.json';
|
||||||
import * as TestMixinScheduler from '../generated-artifacts/TestMixinScheduler.json';
|
import * as TestMixinScheduler from '../generated-artifacts/TestMixinScheduler.json';
|
||||||
import * as TestMixinStake from '../generated-artifacts/TestMixinStake.json';
|
import * as TestMixinStake from '../generated-artifacts/TestMixinStake.json';
|
||||||
@ -98,6 +99,7 @@ export const artifacts = {
|
|||||||
TestInitTarget: TestInitTarget as ContractArtifact,
|
TestInitTarget: TestInitTarget as ContractArtifact,
|
||||||
TestLibFixedMath: TestLibFixedMath as ContractArtifact,
|
TestLibFixedMath: TestLibFixedMath as ContractArtifact,
|
||||||
TestLibSafeDowncast: TestLibSafeDowncast as ContractArtifact,
|
TestLibSafeDowncast: TestLibSafeDowncast as ContractArtifact,
|
||||||
|
TestMixinCumulativeRewards: TestMixinCumulativeRewards as ContractArtifact,
|
||||||
TestMixinParams: TestMixinParams as ContractArtifact,
|
TestMixinParams: TestMixinParams as ContractArtifact,
|
||||||
TestMixinScheduler: TestMixinScheduler as ContractArtifact,
|
TestMixinScheduler: TestMixinScheduler as ContractArtifact,
|
||||||
TestMixinStake: TestMixinStake as ContractArtifact,
|
TestMixinStake: TestMixinStake as ContractArtifact,
|
||||||
|
@ -41,6 +41,7 @@ export * from '../generated-wrappers/test_finalizer';
|
|||||||
export * from '../generated-wrappers/test_init_target';
|
export * from '../generated-wrappers/test_init_target';
|
||||||
export * from '../generated-wrappers/test_lib_fixed_math';
|
export * from '../generated-wrappers/test_lib_fixed_math';
|
||||||
export * from '../generated-wrappers/test_lib_safe_downcast';
|
export * from '../generated-wrappers/test_lib_safe_downcast';
|
||||||
|
export * from '../generated-wrappers/test_mixin_cumulative_rewards';
|
||||||
export * from '../generated-wrappers/test_mixin_params';
|
export * from '../generated-wrappers/test_mixin_params';
|
||||||
export * from '../generated-wrappers/test_mixin_scheduler';
|
export * from '../generated-wrappers/test_mixin_scheduler';
|
||||||
export * from '../generated-wrappers/test_mixin_stake';
|
export * from '../generated-wrappers/test_mixin_stake';
|
||||||
|
@ -0,0 +1,258 @@
|
|||||||
|
import { blockchainTests, expect } from '@0x/contracts-test-utils';
|
||||||
|
import { BigNumber } from '@0x/utils';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { artifacts, TestMixinCumulativeRewardsContract } from '../../src';
|
||||||
|
|
||||||
|
import { constants as stakingConstants } from '../utils/constants';
|
||||||
|
import { toBaseUnitAmount } from '../utils/number_utils';
|
||||||
|
|
||||||
|
blockchainTests.resets('MixinCumulativeRewards unit tests', env => {
|
||||||
|
const ZERO = new BigNumber(0);
|
||||||
|
const testRewards = [
|
||||||
|
{
|
||||||
|
numerator: new BigNumber(1),
|
||||||
|
denominator: new BigNumber(2),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
numerator: new BigNumber(3),
|
||||||
|
denominator: new BigNumber(4),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const sumOfTestRewardsNormalized = {
|
||||||
|
numerator: new BigNumber(10),
|
||||||
|
denominator: new BigNumber(8),
|
||||||
|
};
|
||||||
|
let testPoolId: string;
|
||||||
|
let testContract: TestMixinCumulativeRewardsContract;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
// Deploy contracts
|
||||||
|
testContract = await TestMixinCumulativeRewardsContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TestMixinCumulativeRewards,
|
||||||
|
env.provider,
|
||||||
|
env.txDefaults,
|
||||||
|
artifacts,
|
||||||
|
stakingConstants.NIL_ADDRESS,
|
||||||
|
stakingConstants.NIL_ADDRESS,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create a test pool
|
||||||
|
const operatorShare = new BigNumber(1);
|
||||||
|
const addOperatorAsMaker = true;
|
||||||
|
const txReceipt = await testContract.createStakingPool.awaitTransactionSuccessAsync(
|
||||||
|
operatorShare,
|
||||||
|
addOperatorAsMaker,
|
||||||
|
);
|
||||||
|
const createStakingPoolLog = txReceipt.logs[0];
|
||||||
|
testPoolId = (createStakingPoolLog as any).args.poolId;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_isCumulativeRewardSet', () => {
|
||||||
|
it('Should return true iff denominator is non-zero', async () => {
|
||||||
|
const isSet = await testContract.isCumulativeRewardSet.callAsync({
|
||||||
|
numerator: ZERO,
|
||||||
|
denominator: new BigNumber(1),
|
||||||
|
});
|
||||||
|
expect(isSet).to.be.true();
|
||||||
|
});
|
||||||
|
it('Should return false iff denominator is zero', async () => {
|
||||||
|
const isSet = await testContract.isCumulativeRewardSet.callAsync({
|
||||||
|
numerator: new BigNumber(1),
|
||||||
|
denominator: ZERO,
|
||||||
|
});
|
||||||
|
expect(isSet).to.be.false();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_addCumulativeReward', () => {
|
||||||
|
it('Should set value to `reward/stake` if this is the first cumulative reward', async () => {
|
||||||
|
await testContract.addCumulativeReward.awaitTransactionSuccessAsync(
|
||||||
|
testPoolId,
|
||||||
|
testRewards[0].numerator,
|
||||||
|
testRewards[0].denominator,
|
||||||
|
);
|
||||||
|
const mostRecentCumulativeReward = await testContract.getMostRecentCumulativeReward.callAsync(testPoolId);
|
||||||
|
expect(mostRecentCumulativeReward).to.deep.equal(testRewards[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should do nothing if a cumulative reward has already been recorded in the current epoch (`lastStoredEpoch == currentEpoch_`)', async () => {
|
||||||
|
await testContract.addCumulativeReward.awaitTransactionSuccessAsync(
|
||||||
|
testPoolId,
|
||||||
|
testRewards[0].numerator,
|
||||||
|
testRewards[0].denominator,
|
||||||
|
);
|
||||||
|
// this call should not overwrite existing value (testRewards[0])
|
||||||
|
await testContract.addCumulativeReward.awaitTransactionSuccessAsync(
|
||||||
|
testPoolId,
|
||||||
|
testRewards[1].numerator,
|
||||||
|
testRewards[1].denominator,
|
||||||
|
);
|
||||||
|
const mostRecentCumulativeReward = await testContract.getMostRecentCumulativeReward.callAsync(testPoolId);
|
||||||
|
expect(mostRecentCumulativeReward).to.deep.equal(testRewards[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should set value to normalized sum of `reward/stake` plus most recent cumulative reward, given one exists', async () => {
|
||||||
|
await testContract.addCumulativeReward.awaitTransactionSuccessAsync(
|
||||||
|
testPoolId,
|
||||||
|
testRewards[0].numerator,
|
||||||
|
testRewards[0].denominator,
|
||||||
|
);
|
||||||
|
await testContract.incrementEpoch.awaitTransactionSuccessAsync();
|
||||||
|
await testContract.addCumulativeReward.awaitTransactionSuccessAsync(
|
||||||
|
testPoolId,
|
||||||
|
testRewards[1].numerator,
|
||||||
|
testRewards[1].denominator,
|
||||||
|
);
|
||||||
|
const mostRecentCumulativeReward = await testContract.getMostRecentCumulativeReward.callAsync(testPoolId);
|
||||||
|
expect(mostRecentCumulativeReward).to.deep.equal(sumOfTestRewardsNormalized);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_updateCumulativeReward', () => {
|
||||||
|
it('Should set current cumulative reward to most recent cumulative reward', async () => {
|
||||||
|
await testContract.addCumulativeReward.awaitTransactionSuccessAsync(
|
||||||
|
testPoolId,
|
||||||
|
testRewards[0].numerator,
|
||||||
|
testRewards[0].denominator,
|
||||||
|
);
|
||||||
|
await testContract.incrementEpoch.awaitTransactionSuccessAsync();
|
||||||
|
await testContract.updateCumulativeReward.awaitTransactionSuccessAsync(testPoolId);
|
||||||
|
const epoch = new BigNumber(2);
|
||||||
|
const mostRecentCumulativeReward = await testContract.getCumulativeRewardAtEpochRaw.callAsync(
|
||||||
|
testPoolId,
|
||||||
|
epoch,
|
||||||
|
);
|
||||||
|
expect(mostRecentCumulativeReward).to.deep.equal(testRewards[0]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_computeMemberRewardOverInterval', () => {
|
||||||
|
const runTest = async (
|
||||||
|
amountToStake: BigNumber,
|
||||||
|
epochOfFirstReward: BigNumber,
|
||||||
|
epochOfSecondReward: BigNumber,
|
||||||
|
epochOfIntervalStart: BigNumber,
|
||||||
|
epochOfIntervalEnd: BigNumber,
|
||||||
|
): Promise<void> => {
|
||||||
|
// Simulate earning reward
|
||||||
|
await testContract.storeCumulativeReward.awaitTransactionSuccessAsync(
|
||||||
|
testPoolId,
|
||||||
|
testRewards[0],
|
||||||
|
epochOfFirstReward,
|
||||||
|
);
|
||||||
|
await testContract.storeCumulativeReward.awaitTransactionSuccessAsync(
|
||||||
|
testPoolId,
|
||||||
|
sumOfTestRewardsNormalized,
|
||||||
|
epochOfSecondReward,
|
||||||
|
);
|
||||||
|
const reward = await testContract.computeMemberRewardOverInterval.callAsync(
|
||||||
|
testPoolId,
|
||||||
|
amountToStake,
|
||||||
|
epochOfIntervalStart,
|
||||||
|
epochOfIntervalEnd,
|
||||||
|
);
|
||||||
|
// Compute expected reward
|
||||||
|
const lhs = sumOfTestRewardsNormalized.numerator.dividedBy(sumOfTestRewardsNormalized.denominator);
|
||||||
|
const rhs = testRewards[0].numerator.dividedBy(testRewards[0].denominator);
|
||||||
|
const expectedReward = lhs.minus(rhs).multipliedBy(amountToStake);
|
||||||
|
// Assert correctness
|
||||||
|
expect(reward).to.bignumber.equal(expectedReward);
|
||||||
|
};
|
||||||
|
|
||||||
|
it('Should successfully compute reward over a valid interval when staking non-zero ZRX', async () => {
|
||||||
|
const amountToStake = toBaseUnitAmount(1);
|
||||||
|
const epochOfFirstReward = new BigNumber(1);
|
||||||
|
const epochOfSecondReward = new BigNumber(2);
|
||||||
|
const epochOfIntervalStart = new BigNumber(1);
|
||||||
|
const epochOfIntervalEnd = new BigNumber(2);
|
||||||
|
await runTest(
|
||||||
|
amountToStake,
|
||||||
|
epochOfFirstReward,
|
||||||
|
epochOfSecondReward,
|
||||||
|
epochOfIntervalStart,
|
||||||
|
epochOfIntervalEnd,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should successfully compute reward if no entry for current epoch, but there is an entry for epoch n-1', async () => {
|
||||||
|
// End epoch = n-1 forces the code to query the previous epoch's cumulative reward
|
||||||
|
const amountToStake = toBaseUnitAmount(1);
|
||||||
|
const epochOfFirstReward = new BigNumber(1);
|
||||||
|
const epochOfSecondReward = new BigNumber(2);
|
||||||
|
const epochOfIntervalStart = new BigNumber(1);
|
||||||
|
const epochOfIntervalEnd = new BigNumber(3);
|
||||||
|
await runTest(
|
||||||
|
amountToStake,
|
||||||
|
epochOfFirstReward,
|
||||||
|
epochOfSecondReward,
|
||||||
|
epochOfIntervalStart,
|
||||||
|
epochOfIntervalEnd,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should successfully compute reward if no entry for current epoch, but there is an entry for epoch n-2', async () => {
|
||||||
|
// End epoch = n-2 forces the code to query the most recent cumulative reward
|
||||||
|
const amountToStake = toBaseUnitAmount(1);
|
||||||
|
const epochOfFirstReward = new BigNumber(1);
|
||||||
|
const epochOfSecondReward = new BigNumber(2);
|
||||||
|
const epochOfIntervalStart = new BigNumber(1);
|
||||||
|
const epochOfIntervalEnd = new BigNumber(4);
|
||||||
|
await runTest(
|
||||||
|
amountToStake,
|
||||||
|
epochOfFirstReward,
|
||||||
|
epochOfSecondReward,
|
||||||
|
epochOfIntervalStart,
|
||||||
|
epochOfIntervalEnd,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should successfully compute reward are no cumulative reward entries', async () => {
|
||||||
|
// No entries forces the default cumulatie reward to be used in computations
|
||||||
|
const stake = toBaseUnitAmount(1);
|
||||||
|
const beginEpoch = new BigNumber(1);
|
||||||
|
const endEpoch = new BigNumber(2);
|
||||||
|
const reward = await testContract.computeMemberRewardOverInterval.callAsync(
|
||||||
|
testPoolId,
|
||||||
|
stake,
|
||||||
|
beginEpoch,
|
||||||
|
endEpoch,
|
||||||
|
);
|
||||||
|
expect(reward).to.bignumber.equal(ZERO);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return zero if no stake was delegated', async () => {
|
||||||
|
const stake = toBaseUnitAmount(0);
|
||||||
|
const beginEpoch = new BigNumber(1);
|
||||||
|
const endEpoch = new BigNumber(2);
|
||||||
|
const reward = await testContract.computeMemberRewardOverInterval.callAsync(
|
||||||
|
testPoolId,
|
||||||
|
stake,
|
||||||
|
beginEpoch,
|
||||||
|
endEpoch,
|
||||||
|
);
|
||||||
|
expect(reward).to.bignumber.equal(ZERO);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return zero if the start/end of the interval are the same epoch', async () => {
|
||||||
|
const stake = toBaseUnitAmount(1);
|
||||||
|
const beginEpoch = new BigNumber(1);
|
||||||
|
const endEpoch = new BigNumber(1);
|
||||||
|
const reward = await testContract.computeMemberRewardOverInterval.callAsync(
|
||||||
|
testPoolId,
|
||||||
|
stake,
|
||||||
|
beginEpoch,
|
||||||
|
endEpoch,
|
||||||
|
);
|
||||||
|
expect(reward).to.bignumber.equal(ZERO);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should revert if start is greater than the end of the interval', async () => {
|
||||||
|
const stake = toBaseUnitAmount(1);
|
||||||
|
const beginEpoch = new BigNumber(2);
|
||||||
|
const endEpoch = new BigNumber(1);
|
||||||
|
const tx = testContract.computeMemberRewardOverInterval.callAsync(testPoolId, stake, beginEpoch, endEpoch);
|
||||||
|
return expect(tx).to.revertWith('CR_INTERVAL_INVALID');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -41,6 +41,7 @@
|
|||||||
"generated-artifacts/TestInitTarget.json",
|
"generated-artifacts/TestInitTarget.json",
|
||||||
"generated-artifacts/TestLibFixedMath.json",
|
"generated-artifacts/TestLibFixedMath.json",
|
||||||
"generated-artifacts/TestLibSafeDowncast.json",
|
"generated-artifacts/TestLibSafeDowncast.json",
|
||||||
|
"generated-artifacts/TestMixinCumulativeRewards.json",
|
||||||
"generated-artifacts/TestMixinParams.json",
|
"generated-artifacts/TestMixinParams.json",
|
||||||
"generated-artifacts/TestMixinScheduler.json",
|
"generated-artifacts/TestMixinScheduler.json",
|
||||||
"generated-artifacts/TestMixinStake.json",
|
"generated-artifacts/TestMixinStake.json",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user