Core Contracts

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

`BaseGauge::voteDirection` Lacks A Vote Interval Check Allowing Users to Inflate Total Votes

Summary

BaseGauge::voteDirection lacks a minimum vote interval check, allowing users to spam votes continuously inflating totalVotes. While vote timestamps are stored, they are never checked to prevent spam voting.

Vulnerability Details

[](https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/governance/gauges/BaseGauge.sol#L407-L420)

Users can repeatedly call BaseGauge::voteDirection without any cooldown period, despite the contract storing vote timestamps:

function voteDirection(uint256 direction) public whenNotPaused updateReward(msg.sender) {
// ... checks ...
// @audit - no check on last vote timestamp before allowing new vote
totalVotes = processVote(
userVotes[msg.sender],
direction,
votingPower,
totalVotes
);
}

The processVote function updates and stores the vote timestamp but never checks it:

[](https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/governance/gauges/BaseGauge.sol#L443)

function processVote(...) internal returns (uint256) {
// ... logic ...
vote.timestamp = block.timestamp; // Timestamp stored but never used
return newTotalVotes;
}

Impact

This creates several issues:

  • Users can spam votes to inflate totalVotes through repeated transactions

  • Potential vote manipulation through rapid voting

  • No protection against vote thrashing (rapidly changing directions)

Tools Used

Foundry

Recommendations

Create a Minimum Vote Interval Time:

uint256 public constant MIN_VOTE_INTERVAL = 1 days; // Or appropriate timeframe

Add a minimum vote interval check inside of voteDirection

function voteDirection(uint256 direction) public whenNotPaused updateReward(msg.sender) {
if (direction > 10000) revert InvalidWeight();
+ // Prevent vote spam
+ if (block.timestamp - userVotes[msg.sender].timestamp < MIN_VOTE_INTERVAL) {
+ revert VoteTooFrequent();
+ }
uint256 votingPower = IERC20(IGaugeController(controller).veRAACToken()).balanceOf(msg.sender);
if (votingPower == 0) revert NoVotingPower();
totalVotes = processVote(
userVotes[msg.sender],
direction,
votingPower,
totalVotes
);
emit DirectionVoted(msg.sender, direction, votingPower);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge
3 months ago
inallhonesty Lead Judge about 2 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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