Core Contracts

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

GaugeController.vote() will revert if trying to update weight for a given pool and user has more votingPower

Summary

GaugeController.vote() will revert if trying to update weight for a given pool and user has more votingPower

Vulnerability Details

GaugeController.vote() calls internal function _updateGaugeWeight(), which updated weight for given gauge with previous and new weight and votingPower values, however this will revert if called to update the weight for a gauge for which caller has already voted for in case that votingPower has increased.

This happens because Solidity will try to compute a negative unsigned integer. `oldGaugeWeight` is the weight * votingPower / WEIGHT_PRECISION set the first time it was called, if votingPower has increased `oldGaugeWeight - (oldWeight * votingPower / WEIGHT_PRECISION)` expression will be a negative number:

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

Impact

Users cannot update the vote for a gauge if their votingPower is higher than when they first voted for that gauge, totally breaking the expected behaviour of the contract.

Tools Used

Manual review

Recommendations

Do not allow function to compute negative numbers, directly setting weight input weight and current votingPower:

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);
+ uint256 newGaugeWeight = newWeight * votingPower / WEIGHT_PRECISION;
g.weight = newGaugeWeight;
g.lastUpdateTime = block.timestamp;
}
Updates

Lead Judging Commences

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