The weight allocated for a gauge is not the Time-weighted average. This allows an user to front run the gauge's reward distribution tx and divert an bigger amount of rewards to desired gauge.
Users can vote
gauges and allocate allocate votingPower to gauges. The gauges
mapping is updated.
When the time period for a gauge is updated to the next period, the gaugePeriods[gauge].weight
is set to gauges[gauge].weight
value. But this is not even used.
On distributeRewards the _calculateReward
is used to calculates rewards based on gauge weight.
The latest value stored in gauges[gauge].weight
is used to calculate the %rewards for gauge.
A malicious user can exploit this this and front run the distributeRewards
.
gauges A and B have both 1000 votesweight
admin send rewards to gaugeA and calls distributeRewards
. He needs to send more rewards than the minimum require to ensure the notification tx doesn't revert due to InsufficientRewardBalance check.
Alice frontrun admin's transaction and vote
gaugeA with an additional 1000 votes.
now gaugeA must have have at least (1000 + 1000) / (2000 + 1000) = 2/3 of the total rewards allocated for that gaugeType.
Alice remove her vote from gaugeA and frontruns the next gauge's distributeRewards
.
Alice can repeat these steps to force admin to allocate more rewards
The gauge reward distribution may be manipulated.
When updatePeriod
is called, the weight of a gauge for the next period must be calculated based on the weighted average of its weights over the last N periods.
Use this time-averaged weight to calculate the % of rewards each gauge shall receive.
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.