The FeeCollector::claimRewards function incorrectly updates the userRewards mapping by setting it to totalDistributed instead of accumulating the pending rewards. This bug prevents users from claiming rewards after their first claim, as subsequent claims will always revert with an InsufficientBalance error.
The issue arises in the claimRewards function, where the userRewards mapping is updated incorrectly. Instead of adding the pendingReward to the existing userRewards[user], the function sets userRewards[user] to totalDistributed. This leads to incorrect reward tracking and prevents users from claiming rewards more than once.
In the claimRewards function, the following line is problematic:
This line overwrites the user's reward balance with totalDistributed, which is incorrect. The correct behavior should be to accumulate the pending rewards by adding them to the existing balance:
Additionally, the _calculatePendingRewards function calculates the user's share of rewards based on their voting power and compares it to their current userRewards balance:
Since userRewards[user] is incorrectly set to totalDistributed after the first claim, the share will always be less than or equal to userRewards[user] in subsequent claims after the FeeCollector collects more fees. This causes the function to return 0, triggering the InsufficientBalance error.
First Claim: A user claims their rewards successfully. The userRewards mapping is incorrectly set to totalDistributed.
Second Claim: The user attempts to claim rewards after additional fees are collected. The _calculatePendingRewards function returns 0 because share <= userRewards[user], causing the transaction to revert with an InsufficientBalance error.
The vulnerability is demonstrated in the following Foundry test suite. Convert to foundry project using the steps highlighted here. Then in the test/ folder create a Test file named FeeCollectorTest.t.sol and paste the test into it. Make sure the imports path are correct and run the test using forge test --mt testUnableClaimSubsequentReward :
In this test:
The user claims rewards successfully the first time.
The user attempts to claim rewards again after additional fees are collected and distributed.
The second claim fails with an InsufficientBalance error due to the incorrect update of userRewards.
Loss of Rewards: Users lose access to their rightful rewards due to the incorrect implementation.
Protocol Inefficiency: The protocol's reward distribution mechanism becomes inefficient and unreliable.
Foundry: Used to write and execute the test suite that demonstrates the vulnerability.
Manual Review
Fix Reward Accumulation:
Update the claimRewards function to correctly accumulate the pending rewards by adding them to the existing userRewards balance.
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.