Reward calculations must use historical staking balances, not current values.
veRAACToken.getVotingPower() returns current balances, not balances at distribution time.
Users can manipulate rewards by:
Staking right before claiming → Inflate share.
Unstaking immediately after → Repeat.
Reward calculations use real-time voting power instead of historical snapshots, allowing users to manipulate their share by changing their veRAAC balance after distributions but before claiming.
First Distribution:
Total veRAAC supply = 100
totalDistributed = 100
Attacker stakes 100 veRAAC and claims 100 tokens (legitimate)
Attacker unstakes all 100 veRAAC → Total supply = 0
Second Distribution:
FeeCollector distributes 100 tokens to "veRAAC holders"
Since total supply = 0, all 100 tokens go to treasury (totalDistributed still increments to 200)
Attacker re-stakes 100 veRAAC (total supply = 100)
Claims: (100 * 200) / 100 = 200 tokens
Steals 100 tokens from Distribution 2 when they had 0 balance!
The root cause can be seen below:
Protocol distributes 500K tokens to legitimate stakers.
Attacker frontruns distribution → stakes → claims → unstakes.
Steals rewards from periods they weren't staked.
Foundry
Use veRAAC's historical balance snapshots for accurate 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.