The FeeCollector::claimRewards function allows users to claim rewards based on their current veRAAC voting power. However, in the current design, users can temporarily lock a large amount of RAAC to acquire a high veRAAC balance in a short period, enabling them to claim a disproportionate amount of rewards. This results in the dilution of rewards for other users.
The FeeCollector::_calculatePendingRewards function determines the user’s reward share using the following formula:
This calculation only considers the current voting power, allowing an attacker to:
Lock a large amount of RAAC shortly before the reward distribution, gaining a high veRAAC voting power.
Claim an excessive share of the rewards, significantly diluting the rewards for long-term users.
Initial State:
Total reward pool: 1,000 RAAC
Total voting power (veRAACToken.getTotalVotingPower()): 5,000
Voting power of existing users: 5,000
Attacker’s Actions:
The attacker locks 50,000 RAAC for 4 years before the reward distribution, obtaining 50,000 veRAAC voting power.
The total voting power increases to: 5,000+50,000=55,0005,000 + 50,000 = 55,0005,000+50,000=55,000
The attacker's reward share is calculated as: 1,000×50,00055,000≈909.09 RAAC1,000 \times \frac{50,000}{55,000} \approx 909.09 \text{ RAAC}1,000×55,00050,000≈909.09 RAAC
Consequences:
The attacker receives 90.9% of the reward pool by locking a large amount of RAAC just before the distribution.
Other long-term users experience severe reward dilution.
Short-term manipulation risk: Users can temporarily lock a large amount of RAAC to capture a disproportionate share of the rewards.
Unfair reward distribution: Other users’ rewards are significantly diluted, undermining the fairness and incentive structure of the protocol.
Manual
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.