Urban Coffee Nuthatch
Medium
The notifyRewardAmount
function suffers from precision loss when calculating the reward rate, leading to some rewards being locked and unclaimable.
there is a precision loss in the notifyRewardAmount
function when calculating scaledRewardRate
, which results in some of the reward funds being locked in the contract and not being available for distribution. This leads to economic loss.
function notifyRewardAmount(uint256 _amount) external virtual { if (!isRewardNotifier[msg.sender]) { revert GovernanceStaker__Unauthorized("not notifier", msg.sender); }
// We checkpoint the accumulator without updating the timestamp at which it was updated,
// because that second operation will be done after updating the reward rate.
rewardPerTokenAccumulatedCheckpoint = rewardPerTokenAccumulated();
if (block.timestamp >= rewardEndTime) {
scaledRewardRate = (_amount * SCALE_FACTOR) / REWARD_DURATION;
} else {
uint256 _remainingReward = scaledRewardRate * (rewardEndTime - block.timestamp);
scaledRewardRate = (_remainingReward + _amount * SCALE_FACTOR) / REWARD_DURATION;
}
rewardEndTime = block.timestamp + REWARD_DURATION;
lastCheckpointTime = block.timestamp;
if ((scaledRewardRate / SCALE_FACTOR) == 0) revert GovernanceStaker__InvalidRewardRate();
// This check cannot _guarantee_ sufficient rewards have been transferred to the contract,
// because it cannot isolate the unclaimed rewards owed to stakers left in the balance. While
// this check is useful for preventing degenerate cases, it is not sufficient. Therefore, it is
// critical that only safe reward notifier contracts are approved to call this method by the
// admin.
if (
(scaledRewardRate * REWARD_DURATION) > (REWARD_TOKEN.balanceOf(address(this)) * SCALE_FACTOR)
) revert GovernanceStaker__InsufficientRewardBalance();
emit RewardNotified(_amount, msg.sender);
}
notifyRewardAmount
function results in a portion of the reward funds being locked in the contract and unavailable for distribution.
https://github.com/sherlock-audit/2024-11-tally/blob/main/staker/src/GovernanceStaker.sol#L430
Manual Review
Add an admin function to extract the reward tokens that remain undistributed due to precision loss.