The claimRewards()
function incorrectly resets the user's reward tracking state to totalDistributed
in FeeCollector.sol, causing all future calls to claimRewards()
to return 0
pendingReward
. As a result, users are unable to claim any newly distributed rewards, leading to a complete lockout from further earnings.
This bug arises due to the incorrect update of the userRewards[user]
state variable, which tracks the user's claimed rewards improperly and prevents correct calculation of pending rewards.
In the claimRewards()
function of the FeeCollector
contract:
The issue is triggered by this line:
And, before hand, the _calculatePendingRewards()
function computes the user’s pending reward as:
On the first claim, userRewards[user]
is 0, and the user correctly receives their initial pending rewards. However, after the first claim, userRewards[user] == totalDistributed
. This causes future calls to claimRewards()
to almost always return 0 pendingReward
because share < userRewards[user]
.
Example Walkthrough:
Step 1. Initial State
totalDistributed
= 1000 tokens
The user’s voting power entitles them to 200 tokens.
Step 2. First Call to claimRewards()
_calculatePendingRewards()
correctly calculates:
pendingReward = (1000 * userVotingPower) / totalVotingPower = 200 tokens
The user receives 200 tokens, and userRewards[user]
is updated:
userRewards[user] = totalDistributed; // 1000
Step 3. Future Calls (After More Rewards Distributed and Assuming the Same Ratio of userVotingPower / totalVotingPower
)
Suppose totalDistributed
= 1500, but _calculatePendingRewards()
calculates:
share = (1500 * userVotingPower) / totalVotingPower = 300 tokens
Since userRewards[user] == 1000
, 300 < 1000
, making the returned pendingReward == 0
.
The user is locked out of future rewards despite new distributions.
Complete Lockout from Future Rewards:
Users will be unable to claim any additional rewards after their first claim, resulting in financial loss for stakeholders and a breakdown of the rewards distribution system.
Stakeholder Trust and Reputation Risk:
As rewards remain locked, users may lose confidence in the protocol, and the protocol could face reputational damage if the issue is not quickly addressed.
Potential Accumulation of Unclaimed Rewards:
Since users cannot claim new rewards, unclaimed rewards will accumulate within the contract, potentially leading to large protocol-wide imbalances and manual interventions.
Manual
Consider the following refactoring:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.