Core Contracts

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

User Vote On Multiple Gauges Using The Full Balance Of Their `veRAACToken` For Each Vote.

Summary

The GaugeController contract is designed to allow veRAACToken holders to vote for gauges by allocating weights that determine reward distributions. However, a flaw in the voting mechanism permits a single user to vote on multiple gauges using the full balance of their veRAACToken for each vote. This oversight allows an individual to amplify their influence across all gauges, leading to an imbalance in weight distribution and an unfair advantage in the reward allocation process.

Vulnerability Details

In the vote function, the contract retrieves the user's voting power using: uint256 votingPower = veRAACToken.balanceOf(msg.sender);

function vote(address gauge, uint256 weight) external override whenNotPaused {
if (!isGauge(gauge)) revert GaugeNotFound();
if (weight > WEIGHT_PRECISION) revert InvalidWeight();
@>> uint256 votingPower = veRAACToken.balanceOf(msg.sender);
if (votingPower == 0) revert NoVotingPower();
uint256 oldWeight = userGaugeVotes[msg.sender][gauge];
userGaugeVotes[msg.sender][gauge] = weight;
_updateGaugeWeight(gauge, oldWeight, weight, votingPower);
emit WeightUpdated(gauge, oldWeight, weight);
}

This value is then applied to update the gauge’s weight via the _updateGaugeWeight function:

uint256 newGaugeWeight = oldGaugeWeight - (oldWeight * votingPower / WEIGHT_PRECISION)
+ (newWeight * votingPower / WEIGHT_PRECISION);

The key issue is that there is no mechanism to account for the voting power already allocated across different gauges. Every time a user votes, the contract uses their full token balance, regardless of previous votes. This means that a user with a veRAACToken balance of, for example, 1,000 tokens can vote for Gauge A and Gauge B (and any additional gauges), effectively applying their 1,000-token influence multiple times.

Proof of Concept (POC):

  1. Initial State:

    • User holds 1,000 veRAACTokens.

    • No votes have been cast yet.

  2. First Vote:

    • The user votes on Gauge A with a weight of 5,000 (50% of the maximum allowed, where WEIGHT_PRECISION is 10,000).

    • The weight contribution to Gauge A is calculated as:

    Contribution = 5000 x 1000 / 10000 = 500
    
    • Gauge A's weight increases by 500.

  3. Second Vote:

    • The same user then votes on Gauge B with the same weight of 5,000.

    • Again, the weight contribution is:

    Contribution = 5000 x 1000 / 10000 = 500
    
    • Gauge B's weight also increases by 500.

Result:
Even though the user only has 1,000 tokens, their votes have effectively allocated a total influence of 1,000 tokens (500 per gauge) on each gauge. This can be repeated for additional gauges, meaning the user can multiply their voting power across the system without any deduction or cap on total allocated voting power.

Impact

  • Unfair Reward Distribution: Malicious users can disproportionately influence the gauge weights by voting on multiple gauges with the same voting power, leading to skewed reward distributions.

  • Economic Distortion: The manipulation of gauge weights could distort the intended emission rates, undermining the economic model and trustworthiness of the protocol.

  • User holds N veRAACTokens (voting power = N)

  • Votes 100% weight on Gauge A → Applies N weight

  • Votes 100% weight on Gauge B → Applies another N weight

  • Total influence becomes 2N from N tokens

Tools Used

Manual Review

Recommendations

It is recommended to implement a mechanism that tracks and deducts the total voting power allocated by a user across all gauges to ensure it does not exceed their available veRAACToken balance. This would prevent users from over-allocating their influence and ensure a fair distribution of rewards.

Updates

Lead Judging Commences

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

GaugeController::vote lacks total weight tracking, allowing users to allocate 100% of voting power to multiple gauges simultaneously

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

GaugeController::vote lacks total weight tracking, allowing users to allocate 100% of voting power to multiple gauges simultaneously

Support

FAQs

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