Core Contracts

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

Missing Vote Cooldown Check in GaugeController.vote Allowing Vote Spamming

Summary

The vote function in the GaugeController contract is vulnerable to vote spamming due to a missing check on lastVoteTime[msg.sender]. The contract defines a VOTE_DELAY constant (intended to be 10 days), which should be the minimum time between consecutive votes by the same user. However, the vote function does not enforce this delay, allowing a user to call vote repeatedly within a short period (even within the same block), thereby manipulating the gauge weights.

Vulnerability Details

The vote function in GaugeController.sol is designed to allow veRAAC token holders to vote on the weights assigned to different gauges. The relevant code is as follows:

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 contract does have a lastVoteTime mapping:

mapping(address => uint256) public lastVoteTime;

And a VOTE_DELAY constant:

uint256 public constant VOTE_DELAY = 10 days;

However, the vote function fails to check whether enough time has passed since the user's last vote.

Impact

  • Gauge Weight Manipulation: An attacker can artificially inflate or deflate the weight of a specific gauge, influencing the distribution of rewards.

  • Unfair Reward Distribution: By manipulating gauge weights, an attacker can direct a larger share of rewards to gauges they favor, at the expense of other users.

  • Undermining Governance: The integrity of the gauge voting system is compromised, as the weights do not accurately reflect the long-term preferences of veRAAC holders.

Tools Used

Recommendations

Define a custom error VoteTooFrequent in the IGaugeController interface and implement it in GaugeController.sol for better error handling and clarity.

// In IGaugeController.sol
error VoteTooFrequent();

Add a check to the vote function to ensure that VOTE_DELAY has elapsed since the user's last vote. Also, update lastVoteTime[msg.sender] after a successful vote.

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();
// --- ADDED VOTE COOLDOWN CHECK ---
if (block.timestamp < lastVoteTime[msg.sender] + VOTE_DELAY) {
revert VoteTooFrequent();
}
uint256 oldWeight = userGaugeVotes[msg.sender][gauge];
userGaugeVotes[msg.sender][gauge] = weight;
_updateGaugeWeight(gauge, oldWeight, weight, votingPower);
// --- UPDATE lastVoteTime ---
lastVoteTime[msg.sender] = block.timestamp;
emit WeightUpdated(gauge, oldWeight, weight);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 6 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 6 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.