Feisty Opaque Vulture
Medium
lastCheckpointTime
is updated even when the totalEarningPower
is zero and causes reward tokens to be stuck in the contract
Stakers accumulate rewards monotonically over time. But when the totalEarningPower
equals 0
, the lastCheckpointTime
is updated even though the rewardPerTokenAccumulatedCheckpoint
stays the same. Consequently, the total amount of reward tokens that has been sent to the contract cannot be accumulated and will remain in the contract.
When rewardPerTokenAccumulated()
is called but the totalEarningPower
equals 0
, it is not updated. However, the lastCheckpointTime
is updated.
function _checkpointGlobalReward() internal virtual {
rewardPerTokenAccumulatedCheckpoint = rewardPerTokenAccumulated();
lastCheckpointTime = lastTimeRewardDistributed();
}
As a result, reward tokens will remain in the contract and cannot be accumulated in the future.
Reward tokens which have not been accumulated will remain in the contract. If noone staked during the whole reward duration, the whole reward amount remains in the contract.
https://github.com/sherlock-audit/2024-11-tally/blob/b125d1f2b52170a3789b1060a52fc6609e6e2262/staker/src/GovernanceStaker.sol#L439-L441 https://github.com/sherlock-audit/2024-11-tally/blob/b125d1f2b52170a3789b1060a52fc6609e6e2262/staker/src/GovernanceStaker.sol#L304
Manual Review
Consider implementing a withdraw functionality so that leftover reward tokens can be withdrawn.