In the GaugeController contract, the _updateGaugeWeight function updates a gauge's weight using the user's vote and current voting power. However, because it multiplies both the subtraction of the previous vote and the addition of the new vote by the current voting power, an attacker can manipulate the gauge weight. By initially voting with low voting power and a high weight, then later increasing their voting power and voting with a lower weight, the attacker can reduce the gauge’s weight, thereby affecting reward allocation.
What Went Wrong:
The gauge weight update is computed as follows:
Here, oldWeight is the user's previous vote, newWeight is the new vote weight, and votingPower is the current voting power (derived from the user's veRAAC token balance). The problem is that if an attacker increases their voting power after an initial vote and then votes with a lower weight, the subtraction term (which uses the higher current voting power) can outweigh the addition term, effectively reducing the overall gauge weight.
Consider an attacker with a precision factor (WEIGHT_PRECISION) of 10,000:
At Time T1 (Initial Vote):
Attacker's voting power = 500
Attacker votes with a weight of 8,000 (oldWeight = 0, newWeight = 8,000)
Gauge weight increase = (8,000 * 500 / 10,000) = 400
At Time T2 (After Increasing Voting Power):
Attacker's voting power increases to 2,000
The attacker now votes with a lower weight of 2,000
The gauge weight is updated as:
Subtraction term = (previous vote 8,000 * 2,000 / 10,000) = 1,600
Addition term = (new vote 2,000 * 2,000 / 10,000) = 400
Net effect on gauge weight = -1,600 + 400 = -1,200
Thus, the gauge weight decreases by 1,200, allowing the attacker to manipulate and reduce the gauge weight, which could skew the reward distribution mechanism.
Unfair Reward Distribution:
Reducing the gauge weight unfairly can divert rewards away from honest participants and alter the intended reward allocations.
Economic Manipulation:
An attacker can strategically lower a gauge's weight to influence reward distribution, potentially capturing a larger share of rewards or disadvantaging competing gauges.
Governance and Incentive Risks:
Such manipulations can undermine trust in the protocol’s governance mechanism, as voting power and reward allocations become subject to exploitation.
Manual Code Review: We analyzed the _updateGaugeWeight function and simulated vote scenarios to demonstrate how changes in voting power can be exploited to reduce gauge weight.
Decouple Voting Power from Weight Update:
Modify the weight update formula to use the voting power at the time of the previous vote for the subtraction term and the voting power at the time of the new vote for the addition term. This ensures that changes in voting power do not allow an attacker to manipulate gauge weight.
Snapshot Voting Power:
Consider storing a snapshot of the user's voting power at the time of voting so that subsequent changes in the user’s veRAAC balance do not affect the weight update retrospectively.
Implement Additional Checks:
Introduce constraints to prevent drastic reductions in gauge weight from a single vote change, or require a gradual adjustment mechanism when a user’s voting power changes significantly.
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.