Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: medium
Valid

GaugeController allows weight manipulation through vote and burn

Summary

The GaugeController contract contains a critical vulnerability that allows users to multiply their voting power by recycling RAAC tokens across different addresses. When veRAACTokens are burned, their corresponding gauge votes remain active, allowing users to reuse the same RAAC tokens to vote multiple times through different addresses.

Vulnerability Details

The vulnerability exists in the voting mechanism of the GaugeController contract. When a user votes, the contract uses their current veToken balance to calculate the gauge weight but doesn't store this value for future reference:

function vote(address gauge, uint256 weight) external override whenNotPaused {
...
uint256 votingPower = veRAACToken.balanceOf(msg.sender);
if (votingPower == 0) revert NoVotingPower();
// @audit - previous vote is registered here.
@> uint256 oldWeight = userGaugeVotes[msg.sender][gauge];
@> userGaugeVotes[msg.sender][gauge] = weight;
@> _updateGaugeWeight(gauge, oldWeight, weight, votingPower);
emit WeightUpdated(gauge, oldWeight, weight);
}

The critical issues are:

  1. Gauge weights are not decremented when veRAACTokens are burned

  2. userGaugeVotes mapping remains unchanged after token burning

The _updateGaugeWeight function updates the gauge's weight based on the current vote:

function _updateGaugeWeight(
address gauge,
uint256 oldWeight,
uint256 newWeight,
uint256 votingPower
) internal {
Gauge storage g = gauges[gauge];
uint256 newGaugeWeight = oldGaugeWeight - (oldWeight * votingPower / WEIGHT_PRECISION)
+ (newWeight * votingPower / WEIGHT_PRECISION);
@> g.weight = newGaugeWeight;
}

However, this weight persists even after the veRAACTokens are burned, allowing:

  • The gauge continues counting votes from addresses with 0 veRAAC tokens.

  • Users can reuse their RAAC to mint new veRAAC tokens from a different address, allowing them to vote twice on the same gauge.

PoC

  1. Address A:

    • User has 1000 veRAACTokens, lets say they are 1:1 with RAAC.

    • Votes for Gauge X with weight 5000 (50%)

    • Gauge X weight increases by 500

  2. After lock period:

    • Burns veRAACTokens from Address A to receive back 1000 RAAC

    • Gauge X weight remains at 500

    • Original vote remains active

  3. Address B:

    • Uses same 1000 RAAC tokens to mint new veRAACTokens

    • Votes for same Gauge X with weight 5000 (50%)

    • Gauge X weight increases by another 500

    • Total gauge weight is now 1000 from the same 1000 RAAC tokens

Impact

  • Users can multiply their voting power by recycling the same RAAC tokens across different addresses

  • Gauge weights can be artificially inflated beyond the actual voting power in the system

  • Gauges keep accounting for user votes even when they burn their veRAAC tokens.

Tools Used

Manual Review

Recommendations

The GaugeController should implement a hook that listens to veRAACToken burn events and automatically remove all active votes from the burning address, ensuring the gauge weights are properly decremented

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

GaugeController doesn't decay gauge vote weights when veRAAC voting power expires, allowing users to influence reward distribution with expired voting power

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

GaugeController doesn't decay gauge vote weights when veRAAC voting power expires, allowing users to influence reward distribution with expired voting power

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!