The BaseGauge contract calculates rewardPerToken using totalSupply(), which represents the total staked tokens. However, when applying a boost during reward distribution, the relationship between rewardPerToken and totalSupply() is broken, allowing users with high boosts to claim more rewards than what should be available per staked token.
Since rewardPerToken is calculated based on totalSupply(), but rewards are distributed using getUserWeight(account), which includes a boost factor, a boosted user can receive more rewards than intended.
Assume totalSupply = 100 and 100 reward tokens are being distributed.
The expected reward per staked token is 1 (rewardPerToken = 100 / 100 = 1).
A user stakes 10 tokens but has a 10x boost applied.
Their effective weight becomes 10 * 10 = 100.
earned(account) multiplies by this boosted weight, giving the user 100 rewards instead of 10.
No rewards remain for other users despite their stake and boost value.
The total rewards distributed exceed the intended rewardPerToken calculation.
Adjust Reward Calculation to Include Boosted Total Supply: Use totalBoostedWeight instead of totalSupply() in getRewardPerToken().
Normalize Boosted Weight Contribution: Scale rewards so the sum of all distributed rewards matches rewardPerToken * totalSupply().
Cap the Effect of Boost in Distribution: Ensure that boosted rewards do not exceed the total available reward pool.
Recommended Fix (Example Implementation):
Modify getRewardPerToken to use the total boosted weight:
This ensures that rewardPerToken correctly accounts for the boosted distribution.
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.