The FeeCollector:::claimRewards function incorrectly updates userRewards[user] by setting it to totalDistributed, which is a global variable to store the total tokens distributed historically, instead of incrementing it with the user's actual claimed amount. This can result in users missing out on pending rewards or getting incorrect reward calculations over multiple claims.
In the claimRewards function, the line userRewards[user] = totalDistributed;
overwrites the user’s claimed reward history with the total distributed rewards.
https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/core/collectors/FeeCollector.sol#L206
In the claimRewards function, the user's pendingReward is calcuated in _calculatePendingRewards.
https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/core/collectors/FeeCollector.sol#L479-L487
Example Scenario:
Assume totalDistributed = 1000 RAAC, Bob's voting power = 1000 (10% of total), totalVotingPower = 10,000
First Claim:
share = (1000 * 1000) / 10000 = 100 RAAC
share > userRewards[user] (0), so pending rewards = 100 - 0 = 100
Bob claims 100 RAAC.
Second claim:
New totalDistributed = 2000 RAAC, Bob's voting power remains the same (10%), totalVotingPower remains 10,000.
share = (2000 * 1000) / 10000 = 200 RAAC
However, userRewards[user] = totalDistributed is updated to 1000 in previous claim.
Since share 200 < userRewards[user] (1000), the function will return 0.
Correct second claim:
share = (2000 * 1000) / 10000 = 200 RAAC
share = 200 - 100 (claimed in first claim) = 100
Users lose rewards over multiple claims. The system incorrectly assumes users have already claimed more than they actually have.
Manual code review
Replace:
userRewards[user] = totalDistributed;
with userRewards[user] += pendingReward;
This ensures proper accumulation of rewards and prevents incorrect deductions.
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.