The claimRewards
function in the FeeCollector
contract has a flaw in how it calculates pending rewards based on the userRewards
mapping. This flaw can lead to situations where users may either claim more or less than they are entitled to after changes in their voting power, resulting in incorrect reward distribution.
The issue arises from the way pending rewards are calculated in the _calculatePendingRewards
function. The calculation does not take into account the percentage of voting power a user had during previous claims, leading to potential discrepancies in the rewards they can claim.
For simplicity, the numbers in the report are taken to such, but this can happen with any numbers.
Initial State:
totalDistributed
= 100e18
User A has 20% of the voting power, making them eligible to claim 20e18 tokens.
User A claims their 20e18 tokens.
State Change:
Over time, totalDistributed
increases to 200e18 (an additional 100e18 is distributed).
During this time, User A's voting power drops from 20% to 15%.
Pending Reward Calculation:
User A should now be eligible to claim 15e18 of the new 100e18 tokens (15% of 100e18).
However, the formula in _calculatePendingRewards
calculates the share as follows:
Claim Logic Flaw:
There is currently other vulnerability, that set the user's current claimed to 100e18, however, we need to ignore that here, to continue with the example. userRewards[user] should track how much the user has claimed until now, and it should be 20e18).
The function checks if the calculated share
(30e18) is greater than userRewards[user]
Since 30e18 > 20e18, it calculates the pending reward as:
This means User A can claim an additional 10e18 tokens, even though they should only be entitled to 15e18 based on their current voting power.
Resulting Issue:
The flaw lies in the fact that the calculation does not consider the percentage of voting power User A had during previous claims. When calculating the pending rewards, it incorrectly applies the new voting power percentage to the total distributed rewards.
If User A's voting power decreases, they end up claiming less than they are entitled to. Conversely, if their voting power increases, they could claim more than they are entitled to, leading to unfair distribution of rewards.
The situation could also happen in the current codebase (with the vulnerability where userRewards[user] is wrongly set to totalDistributions), if at the start the user had 100 % of the voting power, and later it decreased. They would be able to claim less rewards, than they are entitled to.
This vulnerability leads to some users claiming more rewards than they are entitled to and other users claiming less.
Manual code review
Recalculate Pending Rewards: Adjust the logic in _calculatePendingRewards
to ensure that it considers the user's historical voting power during previous claims, preventing any over-claiming or under-claiming of rewards.
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.