Core Contracts

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

Missing Vote Delay Logic in GaugeController

Summary

The GaugeController.sol contract lacks proper implementation of the intended VOTE_DELAY mechanism. The contract defines constants for VOTE_DELAY, MIN_VOTE_DELAY, and MAX_VOTE_DELAY, but it fails to enforce a waiting period between user votes. This oversight allows users to repeatedly vote within short time intervals, potentially manipulating gauge weights and reward distribution in unintended ways.

Vulnerability Details

The vote function (lines 174-187) is responsible for updating gauge weights based on user votes. However, it does not check whether the user has voted recently. This allows a user to call the vote function multiple times within a short period, effectively overriding previous votes and potentially gaining disproportionate influence over the gauge weighting.

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);
}

The lastVoteTime mapping is intended to track the last vote timestamp for each user, but it is never updated within the vote function. This omission prevents the contract from enforcing the VOTE_DELAY.

Impact

The absence of vote delay enforcement can lead to several critical issues:

  1. Gauge Weight Manipulation: Malicious actors can repeatedly vote to rapidly increase or decrease the weight of specific gauges, potentially diverting rewards to gauges they control.

  2. Front-Running: Attackers can monitor the mempool for pending vote transactions and quickly submit their own votes to counteract or amplify the effect of the original transaction.

  3. Sybil Attacks: Attackers can create multiple accounts and use them to repeatedly vote, further amplifying their influence over gauge weights.

  4. Unfair Reward Distribution: The intended reward distribution mechanism is compromised, as gauge weights can be manipulated to favor certain participants over others.

Tools Used

  • Manual code review

  • Static analysis

Recommendations

  1. Implement Vote Delay Check: Add a check at the beginning of the vote function to ensure that the user has not voted within the VOTE_DELAY period. Revert the transaction if the delay has not elapsed.

  2. Update lastVoteTime: Update the lastVoteTime mapping with the current timestamp after a successful vote.

Here's the suggested code modification:

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();
if (block.timestamp < lastVoteTime[msg.sender] + VOTE_DELAY) {
revert VoteTooSoon();
}
uint256 oldWeight = userGaugeVotes[msg.sender][gauge];
userGaugeVotes[msg.sender][gauge] = weight;
_updateGaugeWeight(gauge, oldWeight, weight, votingPower);
lastVoteTime[msg.sender] = block.timestamp;
emit WeightUpdated(gauge, oldWeight, weight);
}
  1. Consider Minimum Vote Weight: Implement a minimum vote weight to prevent dust votes from affecting gauge weights.

  2. Add Revert Reason: Add a custom error VoteTooSoon() for better clarity.

By implementing these recommendations, the GaugeController.sol contract can effectively enforce the intended vote delay mechanism, mitigating the risk of gauge weight manipulation and ensuring a fairer reward distribution.

Updates

Lead Judging Commences

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

GaugeController::vote never enforces VOTE_DELAY or updates lastVoteTime, allowing users to spam votes and manipulate gauge weights without waiting

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

GaugeController::vote never enforces VOTE_DELAY or updates lastVoteTime, allowing users to spam votes and manipulate gauge weights without waiting

Support

FAQs

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