Core Contracts

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

Votes calculation can underflow leading preventing user from voting

Summary

In GaugeController voting is based on user voting power and weight provided by user. When the gauge weight is updated, incorrected value is subtracted which can cause underflow revert blocking user from voting.

Vulnerability Details

User can vote using vote function in GaugeController.

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

_updateGaugeWeight is an internal function responsible for GaugeWeight calculations. The issue with that function is that during the newGaugeWeight calculation it uses CURRENT user's voting power multiplied by oldWeight which is later subtracted from oldGaugeWeight.

This is an issue because user's voting power could increase since first voting and this function should consider user's past voting power multiplied by oldWeight and subtract it from the oldGaugeWeight.

function _updateGaugeWeight(
address gauge,
uint256 oldWeight,
uint256 newWeight,
uint256 votingPower
) internal {
Gauge storage g = gauges[gauge];
uint256 oldGaugeWeight = g.weight;
uint256 newGaugeWeight = oldGaugeWeight - (oldWeight * votingPower / WEIGHT_PRECISION)
+ (newWeight * votingPower / WEIGHT_PRECISION);
g.weight = newGaugeWeight;
g.lastUpdateTime = block.timestamp;
}

Let's look at this example where user is only voter.

  1. User votes 100 weight with 100 voting power

  2. Gauge weight is equal to 10000

  3. After some time user wants to vote again because he has higher voting power

  4. User votes again but with 100 weight and 150 voting power

  5. Now the _updateGaugeWeight will revert because it will try to calculate newGaugeWeight like this -> 10000 - (100 (newWeight) * 150 (votingPower)) = 10000 - 15000

_updateGaugeWeight should use user's past voting power that was used during first vote to calcualte the weight that is going to be subtracted from the total gauge weight.

Impact

_updateGaugeWeight can underflow leading to DoS of voting mechansim for some users.

Tools Used

Manual Review, Hardhat

Recommendations

Calculate user's old vote using past voting power not the current.

Updates

Lead Judging Commences

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

GaugeController::_updateGaugeWeight uses current voting power for both old and new vote calculations, causing underflows when voting power increases and incorrect gauge weights

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

GaugeController::_updateGaugeWeight uses current voting power for both old and new vote calculations, causing underflows when voting power increases and incorrect gauge weights

Support

FAQs

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