From 08b48feeac935c26b24d40edd8cfb24bcce88655 Mon Sep 17 00:00:00 2001 From: Ian He <39037239+ianhe8x@users.noreply.github.com> Date: Mon, 22 Apr 2024 10:17:38 +1200 Subject: [PATCH 1/7] implement reward cap and commission cap --- contracts/RewardsDistributor.sol | 63 ++++++++++++++++++++++------- publish/ABI/RewardsDistributor.json | 51 +++++++++++++++++++++++ 2 files changed, 100 insertions(+), 14 deletions(-) diff --git a/contracts/RewardsDistributor.sol b/contracts/RewardsDistributor.sol index 2af137d9..6b94d315 100644 --- a/contracts/RewardsDistributor.sol +++ b/contracts/RewardsDistributor.sol @@ -77,6 +77,14 @@ contract RewardsDistributor is IRewardsDistributor, Initializable, OwnableUpgrad /// @notice Reward information: runner => RewardInfo mapping(address => RewardInfo) private info; + /// @notice perMill, = * + /// 0: disabled + uint256 maxCommissionFactor; + + /// @notice perMill, = * + /// 0: disabled + uint256 maxRewardFactor; + /// @dev ### EVENTS /// @notice Emitted when rewards are distributed for the earliest pending distributed Era. event DistributeRewards( @@ -98,6 +106,8 @@ contract RewardsDistributor is IRewardsDistributor, Initializable, OwnableUpgrad event InstantRewards(address indexed runner, uint256 indexed eraIdx, uint256 token); /// @notice Emitted when rewards arrive via increaseAgreementRewards() event AgreementRewards(address indexed runner, uint256 agreementId, uint256 token); + /// @notice Emitted when rewards return to treasury due to exceed reward cap + event ReturnRewards(address indexed runner, uint256 token, uint256 commission); modifier onlyRewardsStaking() { require(msg.sender == settings.getContractAddress(SQContracts.RewardsStaking), 'G014'); @@ -119,6 +129,14 @@ contract RewardsDistributor is IRewardsDistributor, Initializable, OwnableUpgrad settings = _settings; } + function setMaxCommissionFactor(uint256 _maxCommissionFactor) external onlyOwner { + maxCommissionFactor = _maxCommissionFactor; + } + + function setMaxRewardFactor(uint256 _maxRewardFactor) external onlyOwner { + maxRewardFactor = _maxRewardFactor; + } + /** * @notice Initialize the runner first last claim era. * Only RewardsStaking can call. @@ -347,36 +365,53 @@ contract RewardsDistributor is IRewardsDistributor, Initializable, OwnableUpgrad delete rewardInfo.eraRewardRemoveTable[rewardInfo.lastClaimEra]; if (rewardInfo.eraReward != 0) { uint256 totalStake = rewardsStaking.getTotalStakingAmount(runner); + uint256 selfStake = rewardsStaking.getDelegationAmount(runner, runner); require(totalStake > 0, 'RD006'); uint256 commissionRate = IIndexerRegistry( settings.getContractAddress(SQContracts.IndexerRegistry) ).getCommissionRate(runner); - uint256 commission = MathUtil.mulDiv(commissionRate, rewardInfo.eraReward, PER_MILL); - - info[runner].accSQTPerStake += MathUtil.mulDiv( - rewardInfo.eraReward - commission, + uint256 commission = commissionRate.mulDiv(rewardInfo.eraReward, PER_MILL); + + // 1. total reward can not greater than factor2 * total_stake + // 2. commission can not greater than factor * self_stake + uint256 cappedReward = maxRewardFactor > 0 + ? MathUtil.min(rewardInfo.eraReward, totalStake.mulDiv(maxRewardFactor, PER_MILL)) + : rewardInfo.eraReward; + uint256 cappedCommission = maxCommissionFactor > 0 + ? MathUtil.min(commission, selfStake.mulDiv(maxCommissionFactor, PER_MILL)) + : commission; + info[runner].accSQTPerStake += cappedReward.sub(cappedCommission).mulDiv( PER_TRILL, totalStake ); - if (commission > 0) { + IERC20 SQToken = IERC20(settings.getContractAddress(SQContracts.SQToken)); + if (cappedCommission > 0) { // add commission to unbonding request - IERC20(settings.getContractAddress(SQContracts.SQToken)).safeTransfer( + SQToken.safeTransfer( settings.getContractAddress(SQContracts.Staking), - commission + cappedCommission ); IStaking(settings.getContractAddress(SQContracts.Staking)).unbondCommission( runner, - commission + cappedCommission ); } - emit DistributeRewards( - runner, - rewardInfo.lastClaimEra, - rewardInfo.eraReward, - commission - ); + emit DistributeRewards(runner, rewardInfo.lastClaimEra, cappedReward, cappedCommission); + + if (rewardInfo.eraReward - cappedReward > 0 || commission - cappedCommission > 0) { + uint256 rewardsReturn; + rewardsReturn += rewardInfo.eraReward - cappedReward; + rewardsReturn += commission - cappedCommission; + address treasury = ISettings(settings).getContractAddress(SQContracts.Treasury); + SQToken.safeTransfer(treasury, rewardsReturn); + emit ReturnRewards( + runner, + rewardInfo.eraReward - cappedReward, + commission - cappedCommission + ); + } } return rewardInfo.lastClaimEra; } diff --git a/publish/ABI/RewardsDistributor.json b/publish/ABI/RewardsDistributor.json index e517efde..a932279b 100644 --- a/publish/ABI/RewardsDistributor.json +++ b/publish/ABI/RewardsDistributor.json @@ -137,6 +137,31 @@ "name": "OwnershipTransferred", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "runner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "token", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "commission", + "type": "uint256" + } + ], + "name": "ReturnRewards", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -460,6 +485,32 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxCommissionFactor", + "type": "uint256" + } + ], + "name": "setMaxCommissionFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxRewardFactor", + "type": "uint256" + } + ], + "name": "setMaxRewardFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { From ff001c307489f1ddb41cc71a8696ec6999c92056 Mon Sep 17 00:00:00 2001 From: Ian He <39037239+ianhe8x@users.noreply.github.com> Date: Mon, 22 Apr 2024 10:21:35 +1200 Subject: [PATCH 2/7] add modifier --- contracts/RewardsDistributor.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/RewardsDistributor.sol b/contracts/RewardsDistributor.sol index 6b94d315..4de8f3b6 100644 --- a/contracts/RewardsDistributor.sol +++ b/contracts/RewardsDistributor.sol @@ -79,11 +79,11 @@ contract RewardsDistributor is IRewardsDistributor, Initializable, OwnableUpgrad /// @notice perMill, = * /// 0: disabled - uint256 maxCommissionFactor; + uint256 public maxCommissionFactor; /// @notice perMill, = * /// 0: disabled - uint256 maxRewardFactor; + uint256 public maxRewardFactor; /// @dev ### EVENTS /// @notice Emitted when rewards are distributed for the earliest pending distributed Era. @@ -373,8 +373,8 @@ contract RewardsDistributor is IRewardsDistributor, Initializable, OwnableUpgrad ).getCommissionRate(runner); uint256 commission = commissionRate.mulDiv(rewardInfo.eraReward, PER_MILL); - // 1. total reward can not greater than factor2 * total_stake - // 2. commission can not greater than factor * self_stake + // 1. total reward can not greater than maxRewardFactor * totalStake + // 2. commission can not greater than maxCommissionFactor * selfStake uint256 cappedReward = maxRewardFactor > 0 ? MathUtil.min(rewardInfo.eraReward, totalStake.mulDiv(maxRewardFactor, PER_MILL)) : rewardInfo.eraReward; From 514ec066e71600204bc80dfe5129e92ec87e9eba Mon Sep 17 00:00:00 2001 From: Ian He <39037239+ianhe8x@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:32:12 +1200 Subject: [PATCH 3/7] wip --- test/RewardsDistributer.test.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/RewardsDistributer.test.ts b/test/RewardsDistributer.test.ts index cf7c9b64..5a15466f 100644 --- a/test/RewardsDistributer.test.ts +++ b/test/RewardsDistributer.test.ts @@ -17,7 +17,7 @@ import { StakingManager, } from '../src'; import { DEPLOYMENT_ID, METADATA_HASH, VERSION } from './constants'; -import { acceptPlan, etherParse, startNewEra, time, timeTravel } from './helper'; +import { acceptPlan, addInstantRewards, etherParse, startNewEra, time, timeTravel } from './helper'; import { deployContracts } from './setup'; describe('RewardsDistributor Contract', () => { @@ -131,6 +131,19 @@ describe('RewardsDistributor Contract', () => { }); }); + describe.only('Capped Rewards', async () => { + beforeEach(async () => {}); + it('receive capped commission', async () => { + // self stake 1000 SQT + // commission rate: 10% + // cap 0.1 times + // arrival rewards: 1500 SQT + // const arrivalReward = + const era = await eraManager.eraNumber(); + await addInstantRewards(token, rewardsDistributor, consumer, runner.address, era, 1000); + }); + }); + describe('distribute and claim rewards', async () => { beforeEach(async () => { //a 30 days agreement with 400 rewards come in at Era2 From 72acf4566f6bb635d01b7ee3158ce00e5352d95e Mon Sep 17 00:00:00 2001 From: Ian He <39037239+ianhe8x@users.noreply.github.com> Date: Tue, 23 Apr 2024 16:02:28 +1200 Subject: [PATCH 4/7] fix return amount calc --- contracts/RewardsDistributor.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contracts/RewardsDistributor.sol b/contracts/RewardsDistributor.sol index 4de8f3b6..aa5a82bc 100644 --- a/contracts/RewardsDistributor.sol +++ b/contracts/RewardsDistributor.sol @@ -399,10 +399,11 @@ contract RewardsDistributor is IRewardsDistributor, Initializable, OwnableUpgrad } emit DistributeRewards(runner, rewardInfo.lastClaimEra, cappedReward, cappedCommission); - if (rewardInfo.eraReward - cappedReward > 0 || commission - cappedCommission > 0) { uint256 rewardsReturn; - rewardsReturn += rewardInfo.eraReward - cappedReward; + rewardsReturn += + (rewardInfo.eraReward - commission) - + (cappedReward.sub(cappedCommission)); rewardsReturn += commission - cappedCommission; address treasury = ISettings(settings).getContractAddress(SQContracts.Treasury); SQToken.safeTransfer(treasury, rewardsReturn); From 46134dbbfe94d6d537f670f42027c3cfb4c17e05 Mon Sep 17 00:00:00 2001 From: Ian He <39037239+ianhe8x@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:31:47 +1200 Subject: [PATCH 5/7] fix tests --- contracts/RewardsDistributor.sol | 15 ++--- contracts/StakingManager.sol | 9 +++ publish/ABI/RewardsDistributor.json | 28 ++++++++- publish/ABI/StakingManager.json | 24 ++++++++ test/RewardsDistributer.test.ts | 93 ++++++++++++++++++++++++----- 5 files changed, 147 insertions(+), 22 deletions(-) diff --git a/contracts/RewardsDistributor.sol b/contracts/RewardsDistributor.sol index aa5a82bc..a4e4ecbe 100644 --- a/contracts/RewardsDistributor.sol +++ b/contracts/RewardsDistributor.sol @@ -107,7 +107,7 @@ contract RewardsDistributor is IRewardsDistributor, Initializable, OwnableUpgrad /// @notice Emitted when rewards arrive via increaseAgreementRewards() event AgreementRewards(address indexed runner, uint256 agreementId, uint256 token); /// @notice Emitted when rewards return to treasury due to exceed reward cap - event ReturnRewards(address indexed runner, uint256 token, uint256 commission); + event ReturnRewards(address indexed runner, uint256 rewards, uint256 commission); modifier onlyRewardsStaking() { require(msg.sender == settings.getContractAddress(SQContracts.RewardsStaking), 'G014'); @@ -398,7 +398,12 @@ contract RewardsDistributor is IRewardsDistributor, Initializable, OwnableUpgrad ); } - emit DistributeRewards(runner, rewardInfo.lastClaimEra, cappedReward, cappedCommission); + emit DistributeRewards( + runner, + rewardInfo.lastClaimEra, + MathUtil.max(cappedReward, cappedCommission), + cappedCommission + ); if (rewardInfo.eraReward - cappedReward > 0 || commission - cappedCommission > 0) { uint256 rewardsReturn; rewardsReturn += @@ -407,11 +412,7 @@ contract RewardsDistributor is IRewardsDistributor, Initializable, OwnableUpgrad rewardsReturn += commission - cappedCommission; address treasury = ISettings(settings).getContractAddress(SQContracts.Treasury); SQToken.safeTransfer(treasury, rewardsReturn); - emit ReturnRewards( - runner, - rewardInfo.eraReward - cappedReward, - commission - cappedCommission - ); + emit ReturnRewards(runner, rewardsReturn, commission - cappedCommission); } } return rewardInfo.lastClaimEra; diff --git a/contracts/StakingManager.sol b/contracts/StakingManager.sol index 15ae5573..93fb6b80 100644 --- a/contracts/StakingManager.sol +++ b/contracts/StakingManager.sol @@ -189,6 +189,15 @@ contract StakingManager is IStakingManager, Initializable, OwnableUpgradeable { return StakingUtil.currentStaking(sm, _currentEra); } + function getDelegationAmount(address _source, address _runner) public view returns (uint256) { + uint256 eraNumber = IEraManager(settings.getContractAddress(SQContracts.EraManager)) + .eraNumber(); + Staking staking = Staking(settings.getContractAddress(SQContracts.Staking)); + (uint256 era, uint256 valueAt, uint256 valueAfter) = staking.delegation(_source, _runner); + StakingAmount memory sm = StakingAmount(era, valueAt, valueAfter); + return StakingUtil.currentStaking(sm, eraNumber); + } + function getTotalStakingAmount(address _runner) public view override returns (uint256) { uint256 eraNumber = IEraManager(settings.getContractAddress(SQContracts.EraManager)) .eraNumber(); diff --git a/publish/ABI/RewardsDistributor.json b/publish/ABI/RewardsDistributor.json index a932279b..0d5de298 100644 --- a/publish/ABI/RewardsDistributor.json +++ b/publish/ABI/RewardsDistributor.json @@ -149,7 +149,7 @@ { "indexed": false, "internalType": "uint256", - "name": "token", + "name": "rewards", "type": "uint256" }, { @@ -429,6 +429,32 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "maxCommissionFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxRewardFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "owner", diff --git a/publish/ABI/StakingManager.json b/publish/ABI/StakingManager.json index 89abf26c..88e8bb1d 100644 --- a/publish/ABI/StakingManager.json +++ b/publish/ABI/StakingManager.json @@ -86,6 +86,30 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "_source", + "type": "address" + }, + { + "internalType": "address", + "name": "_runner", + "type": "address" + } + ], + "name": "getDelegationAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/test/RewardsDistributer.test.ts b/test/RewardsDistributer.test.ts index 5a15466f..962540c2 100644 --- a/test/RewardsDistributer.test.ts +++ b/test/RewardsDistributer.test.ts @@ -17,7 +17,7 @@ import { StakingManager, } from '../src'; import { DEPLOYMENT_ID, METADATA_HASH, VERSION } from './constants'; -import { acceptPlan, addInstantRewards, etherParse, startNewEra, time, timeTravel } from './helper'; +import { acceptPlan, addInstantRewards, etherParse, eventFrom, startNewEra, time, timeTravel } from './helper'; import { deployContracts } from './setup'; describe('RewardsDistributor Contract', () => { @@ -69,13 +69,14 @@ describe('RewardsDistributor Contract', () => { eraManager = deployment.eraManager; //init delegator account - await token.connect(root).transfer(delegator.address, etherParse('10')); - await token.connect(root).transfer(delegator2.address, etherParse('10')); - await token.connect(root).transfer(consumer.address, etherParse('10')); - await token.connect(consumer).increaseAllowance(planManager.address, etherParse('10')); - await token.connect(delegator).increaseAllowance(staking.address, etherParse('10')); - await token.connect(delegator2).increaseAllowance(staking.address, etherParse('10')); - await token.connect(root).increaseAllowance(rewardsDistributor.address, etherParse('10')); + await token.connect(root).transfer(runner.address, etherParse('10000')); + await token.connect(root).transfer(delegator.address, etherParse('10000')); + await token.connect(root).transfer(delegator2.address, etherParse('10000')); + await token.connect(root).transfer(consumer.address, etherParse('10000')); + await token.connect(consumer).increaseAllowance(planManager.address, etherParse('10000')); + await token.connect(delegator).increaseAllowance(staking.address, etherParse('10000')); + await token.connect(delegator2).increaseAllowance(staking.address, etherParse('10000')); + await token.connect(root).increaseAllowance(rewardsDistributor.address, etherParse('10000')); //setup era period be 5 days await eraManager.connect(root).updateEraPeriod(time.duration.days(5).toString()); @@ -132,15 +133,79 @@ describe('RewardsDistributor Contract', () => { }); describe.only('Capped Rewards', async () => { - beforeEach(async () => {}); - it('receive capped commission', async () => { + beforeEach(async () => { + await stakingManager.connect(delegator).delegate(runner.address, etherParse(9000)); + await startNewEra(eraManager); + await rewardsHelper.connect(runner).indexerCatchup(runner.address); + }); + it('receive capped rewards', async () => { // self stake 1000 SQT - // commission rate: 10% - // cap 0.1 times + // delegation: 9000 SQT + // commission rate: 5% + // reward cap: 10% + // commission cap: 10% // arrival rewards: 1500 SQT - // const arrivalReward = + await rewardsDistributor.setMaxCommissionFactor(5e4); + await rewardsDistributor.setMaxRewardFactor(1e5); + const totalStake = await stakingManager.getTotalStakingAmount(runner.address); + expect(totalStake).to.eq(etherParse(10000)); + const selfStake = await stakingManager.getDelegationAmount(runner.address, runner.address); + expect(selfStake).to.eq(etherParse(1000)); + const arrivalReward = etherParse(1500); + const era = await eraManager.eraNumber(); + await addInstantRewards(token, rewardsDistributor, consumer, runner.address, era, arrivalReward); + await startNewEra(eraManager); + const tx = await rewardsDistributor.connect(runner).collectAndDistributeRewards(runner.address); + const distributedRewards = await eventFrom( + tx, + rewardsDistributor, + 'DistributeRewards(address,uint256,uint256,uint256)' + ); + expect(distributedRewards.rewards).to.eq(etherParse(1000)); + expect(distributedRewards.commission).to.eq(etherParse(50)); + const returnRewards = await eventFrom(tx, rewardsDistributor, 'ReturnRewards(address,uint256,uint256)'); + expect(returnRewards.rewards).to.eq(etherParse(500)); + expect(returnRewards.commission).to.eq(etherParse(100)); + }); + it('rewards after capped may become zero', async () => { + // self stake 9000 SQT + // delegation: 9000 SQT + // commission rate: 30% + // reward cap: 10% + // commission cap: 25% + // arrival rewards: 10000 SQT + // commission: 3000 SQT + // capped commission: 2250 SQT + // capped reward: 1800 SQT + await rewardsDistributor.setMaxCommissionFactor(2.5e5); + await rewardsDistributor.setMaxRewardFactor(1e5); + await token.connect(runner).increaseAllowance(staking.address, etherParse(8000)); + await stakingManager.connect(runner).stake(runner.address, etherParse(8000)); + await indexerRegistry.connect(runner).setCommissionRate(3e5); + await startNewEra(eraManager); + await rewardsHelper.connect(runner).indexerCatchup(runner.address); + await startNewEra(eraManager); + await rewardsHelper.connect(runner).indexerCatchup(runner.address); + + const totalStake = await stakingManager.getTotalStakingAmount(runner.address); + expect(totalStake).to.eq(etherParse(18000)); + const selfStake = await stakingManager.getDelegationAmount(runner.address, runner.address); + expect(selfStake).to.eq(etherParse(9000)); + const arrivalReward = etherParse(10000); const era = await eraManager.eraNumber(); - await addInstantRewards(token, rewardsDistributor, consumer, runner.address, era, 1000); + await addInstantRewards(token, rewardsDistributor, consumer, runner.address, era, arrivalReward); + await startNewEra(eraManager); + const tx = await rewardsDistributor.connect(runner).collectAndDistributeRewards(runner.address); + const distributedRewards = await eventFrom( + tx, + rewardsDistributor, + 'DistributeRewards(address,uint256,uint256,uint256)' + ); + expect(distributedRewards.rewards).to.eq(etherParse(2250)); // exclude commission + expect(distributedRewards.commission).to.eq(etherParse(2250)); + const returnRewards = await eventFrom(tx, rewardsDistributor, 'ReturnRewards(address,uint256,uint256)'); + expect(returnRewards.rewards).to.eq(etherParse(7750)); + expect(returnRewards.commission).to.eq(etherParse(750)); }); }); From 6694d7bde8c20dcb0a396834818981eee5e20776 Mon Sep 17 00:00:00 2001 From: Ian He <39037239+ianhe8x@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:32:00 +1200 Subject: [PATCH 6/7] remove .only in test --- test/RewardsDistributer.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/RewardsDistributer.test.ts b/test/RewardsDistributer.test.ts index 962540c2..79a70b32 100644 --- a/test/RewardsDistributer.test.ts +++ b/test/RewardsDistributer.test.ts @@ -132,7 +132,7 @@ describe('RewardsDistributor Contract', () => { }); }); - describe.only('Capped Rewards', async () => { + describe('Capped Rewards', async () => { beforeEach(async () => { await stakingManager.connect(delegator).delegate(runner.address, etherParse(9000)); await startNewEra(eraManager); From 11fdce7f089b939d69df384fba3ddf44a82ca9ac Mon Sep 17 00:00:00 2001 From: Ian He <39037239+ianhe8x@users.noreply.github.com> Date: Fri, 26 Apr 2024 11:07:14 +1200 Subject: [PATCH 7/7] fix test --- test/RewardsDistributer.test.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/test/RewardsDistributer.test.ts b/test/RewardsDistributer.test.ts index 79a70b32..ea8716d5 100644 --- a/test/RewardsDistributer.test.ts +++ b/test/RewardsDistributer.test.ts @@ -69,10 +69,9 @@ describe('RewardsDistributor Contract', () => { eraManager = deployment.eraManager; //init delegator account - await token.connect(root).transfer(runner.address, etherParse('10000')); - await token.connect(root).transfer(delegator.address, etherParse('10000')); - await token.connect(root).transfer(delegator2.address, etherParse('10000')); - await token.connect(root).transfer(consumer.address, etherParse('10000')); + await token.connect(root).transfer(delegator.address, etherParse('10')); + await token.connect(root).transfer(delegator2.address, etherParse('10')); + await token.connect(root).transfer(consumer.address, etherParse('10')); await token.connect(consumer).increaseAllowance(planManager.address, etherParse('10000')); await token.connect(delegator).increaseAllowance(staking.address, etherParse('10000')); await token.connect(delegator2).increaseAllowance(staking.address, etherParse('10000')); @@ -134,6 +133,9 @@ describe('RewardsDistributor Contract', () => { describe('Capped Rewards', async () => { beforeEach(async () => { + await token.connect(root).transfer(runner.address, etherParse('10000')); + await token.connect(root).transfer(delegator.address, etherParse('10000')); + await token.connect(root).transfer(consumer.address, etherParse('10000')); await stakingManager.connect(delegator).delegate(runner.address, etherParse(9000)); await startNewEra(eraManager); await rewardsHelper.connect(runner).indexerCatchup(runner.address); @@ -222,14 +224,14 @@ describe('RewardsDistributor Contract', () => { expect((await rewardsHelper.getRewardsAddTable(runner.address, 2, 1))[0]).to.be.eq(etherParse('0')); expect((await rewardsHelper.getRewardsRemoveTable(runner.address, 2, 1))[0]).to.be.eq(etherParse('0')); await rewardsDistributor.connect(runner).claim(runner.address); - + rewards = (await token.balanceOf(runner.address)).div(1e14); //move to Era 4 await startNewEra(eraManager); await rewardsDistributor.collectAndDistributeRewards(runner.address); expect((await rewardsHelper.getRewardsAddTable(runner.address, 3, 1))[0]).to.be.eq(etherParse('0')); expect((await rewardsHelper.getRewardsRemoveTable(runner.address, 3, 1))[0]).to.be.eq(etherParse('0')); await rewardsDistributor.connect(runner).claim(runner.address); - + rewards = (await token.balanceOf(runner.address)).div(1e14); //move to Era 5 await startNewEra(eraManager); await rewardsDistributor.collectAndDistributeRewards(runner.address);