From 4a62ddc6cc0a8167cf4300aac566a4d9b5edf1ff Mon Sep 17 00:00:00 2001 From: Keating Date: Thu, 12 Dec 2024 10:45:44 -0500 Subject: [PATCH] Subtract unclaimed rewards --- src/GovernanceStaker.sol | 2 ++ test/GovernanceStaker.t.sol | 41 +++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/GovernanceStaker.sol b/src/GovernanceStaker.sol index 9bfb63b..b3f57dc 100644 --- a/src/GovernanceStaker.sol +++ b/src/GovernanceStaker.sol @@ -506,6 +506,8 @@ abstract contract GovernanceStaker is INotifiableRewardReceiver, Multicall { // Send tip to the receiver SafeERC20.safeTransfer(REWARD_TOKEN, _tipReceiver, _requestedTip); + deposit.scaledUnclaimedRewardCheckpoint = + deposit.scaledUnclaimedRewardCheckpoint - (_requestedTip * SCALE_FACTOR); } /// @notice Live value of the unclaimed rewards earned by a given deposit with the diff --git a/test/GovernanceStaker.t.sol b/test/GovernanceStaker.t.sol index 6da8ee7..7b69cd3 100644 --- a/test/GovernanceStaker.t.sol +++ b/test/GovernanceStaker.t.sol @@ -2983,6 +2983,47 @@ contract BumpEarningPower is GovernanceStakerRewardsTest { assertEq(_tipReceiverBalanceIncrease, _requestedTip); } + function testFuzz_TipRemovedFromUnclaimedWhenEarningPowerIsBumpedUp( + address _depositor, + address _delegatee, + uint256 _stakeAmount, + uint256 _rewardAmount, + address _bumpCaller, + address _tipReceiver, + uint256 _requestedTip, + uint96 _earningPowerIncrease + ) public { + vm.assume(_tipReceiver != address(0) && _tipReceiver != address(govStaker)); + _stakeAmount = _boundToRealisticStake(_stakeAmount); + _rewardAmount = _boundToRealisticReward(_rewardAmount); + uint256 _initialTipReceiverBalance = rewardToken.balanceOf(_tipReceiver); + _earningPowerIncrease = uint96(bound(_earningPowerIncrease, 1, type(uint48).max)); + + // A user deposits staking tokens + (, GovernanceStaker.DepositIdentifier _depositId) = + _boundMintAndStake(_depositor, _stakeAmount, _delegatee); + // The contract is notified of a reward + _mintTransferAndNotifyReward(_rewardAmount); + // The full duration passes + _jumpAheadByPercentOfRewardDuration(101); + + uint256 _unclaimedRewards = govStaker.unclaimedReward(_depositId); + // Tip must be less than the max bump, but also less than rewards for the sake of this test + _requestedTip = bound(_requestedTip, 0, _min(maxBumpTip, _unclaimedRewards)); + + // The staker's earning power increases + earningPowerCalculator.__setEarningPowerForDelegatee( + _delegatee, _stakeAmount + _earningPowerIncrease + ); + // Bump earning power is called + vm.prank(_bumpCaller); + govStaker.bumpEarningPower(_depositId, _tipReceiver, _requestedTip); + + uint256 _tipReceiverBalanceIncrease = + rewardToken.balanceOf(_tipReceiver) - _initialTipReceiverBalance; + assertEq(govStaker.unclaimedReward(_depositId), _unclaimedRewards - _requestedTip); + } + function testFuzz_BumpsTheDepositsEarningPowerDown( address _depositor, address _delegatee,