Core Contracts

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

Missing Check for Gauge Activation Status in vote :: GaugeController.sol

Summary

The vote function in the GaugeController contract lacks a critical check to ensure that voting can only occur on active gauges. This oversight allows users to vote on gauges that have been shut down via the emergencyShutdown function, potentially affecting the fairness and integrity of the gauge weight distribution.

Vulnerability Details

The vote function currently performs several checks, including:

  • Validating whether the gauge exists.

  • Ensuring the voting weight does not exceed the defined precision.

  • Confirming the voter has sufficient voting power.

    function vote(address gauge, uint256 weight) external override whenNotPaused {
    // @audit-issue : Missing check for activation status of gauge .
    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);
    }

    However, it does not verify if the gauge is active. The emergencyShutdown function can deactivate a gauge, rendering it unsuitable for voting. Without a proper active status check, users can still vote on these inactive gauges, which could manipulate or distort the intended gauge weight distribution.

Impact

  • Gauge Manipulation: Users could unfairly influence the weight distribution by voting on deactivated gauges.

  • Protocol Integrity Risks: The system might allocate resources or make decisions based on invalid gauge votes, undermining trust and operational correctness.

  • Governance Exploits: Attackers could exploit this loophole to favor certain gauges during emergency conditions, potentially affecting overall protocol governance decisions.

Proof Of Concept

  1. The initialOwner calls emergencyShutdown(gauge) to deactivate a gauge.

  2. Despite the deactivation, a user (anon) can still execute gaugeController.vote(gauge, 5); because there is no check preventing voting on inactive gauges.

Proof Of Code

  1. Use this guide to intergrate foundry into your project: foundry

  2. Create a new file FortisAudits.t.sol in the test directory.

  3. Add the following gist code to the file:

  4. Run the test using forge test --mt test_Fortis_UserCanVoteOnInactiveGauge -vvvv.

function test_Fortis_UserCanVoteOnInactiveGauge() public {
address mahi = makeAddr("mahi");
address minter = makeAddr("minter");
uint256 amount = 100e6;
uint256 duration = 31536000 seconds ;
address gauge = makeAddr("gauge");
vm.startPrank(initialOwner);
raacToken.setMinter(minter);
gaugeController.addGauge(gauge , IGaugeController.GaugeType.RWA, 10);
vm.stopPrank();
vm.startPrank(minter);
raacToken.mint(anon , amount);
vm.stopPrank();
vm.startPrank(anon);
raacToken.approve(address(veraacToken), amount);
veraacToken.lock(amount, duration);
uint256 locked_balance = veraacToken.getLockedBalance(anon);
vm.stopPrank();
// Initial owner triggers emergency shutdown on the gauge
vm.startPrank(initialOwner);
gaugeController.emergencyShutdown(gauge);
vm.stopPrank();
vm.startPrank(anon);
gaugeController.vote(gauge , 5);
vm.stopPrank();
}

Tools Used

Manual review

Recommendations

Introduce an activation status check within the vote function to ensure that only active gauges can be voted on.

function vote(address gauge, uint256 weight) external override whenNotPaused {
if (!isGauge(gauge)) revert GaugeNotFound();
++ if (!gauges[gauge].isActive) revert GaugeNotActive(); // ✅ Added check for active gauge
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);
}
Updates

Lead Judging Commences

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

GaugeController::vote allows users to waste voting power on inactive gauges that don't receive rewards

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

GaugeController::vote allows users to waste voting power on inactive gauges that don't receive rewards

Support

FAQs

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

Give us feedback!