Core Contracts

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

Missing Vote Delay Enforcement in `GaugeController`

Summary

Users could vote more frequently than intended since the vote delay constraints are not being enforced despite being defined

Vulnerability Details

The GaugeController contract defines the following constants:

uint256 public constant VOTE_DELAY = 10 days;
uint256 public constant MIN_VOTE_DELAY = 1 days;
uint256 public constant MAX_VOTE_DELAY = 10 days;

And maintains a mapping to track last vote times:

mapping(address => uint256) public lastVoteTime;

However, in the vote() function implementation:

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

it never enforces:

  • The minimum time that must elapse between votes (MIN_VOTE_DELAY)

  • The standard voting delay period (VOTE_DELAY)

  • The maximum allowed delay (MAX_VOTE_DELAY)

  • Updates to the lastVoteTime mapping

The intended 10-day delay between votes was likely designed to provide stability and prevent rapid changes in gauge weights. Without this enforcement, the governance system becomes unstable and unpredictable.

Impact

Users can vote repeatedly in quick succession, manipulating gauge weights and reward distributions more frequently than the protocol design intended

Tools Used

Manua Review

Recommendations

function vote(address gauge, uint256 weight) external override whenNotPaused {
// Existing checks
if (!isGauge(gauge)) revert GaugeNotFound();
if (weight > WEIGHT_PRECISION) revert InvalidWeight();
+ // Add vote delay enforcement
+ uint256 timeElapsed = block.timestamp - lastVoteTime[msg.sender];
+ if (timeElapsed < VOTE_DELAY) revert VoteDelayNotElapsed();
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);
+ // Update last vote time
+ lastVoteTime[msg.sender] = block.timestamp;
}

.

Updates

Lead Judging Commences

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