Core Contracts

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

GaugeController#vote() can revert if user increases voting weight

Summary

In GaugeController#vote() , if user first votes with a smaller weight (e.g., 2000), then acquires more veRAACToken and tries to vote again with a larger weight (e.g., 5000), the calculation in _updateGaugeWeight() can revert due to an underflow.

Vulnerability Details

Incorrect Order of Operations in _updateGaugeWeight()

uint256 newGaugeWeight = oldGaugeWeight - (oldWeight * votingPower / WEIGHT_PRECISION)
+ (newWeight * votingPower / WEIGHT_PRECISION);

If votingPower increases between votes, the subtraction can exceed oldGaugeWeight, causing an underflow and revert.

Proof Of Code

Testcode is written in GaugeController.test.js.

describe("Newspace POC", () => {
beforeEach(async () => {
await veRAACToken.mint(user1.address, ethers.parseEther("1000"));
});
it("newspace POC test", async () => {
await gaugeController.connect(user1).vote(await rwaGauge.getAddress(), 2000);
await veRAACToken.mint(user1.address, ethers.parseEther("1000"));
await gaugeController.connect(user1).vote(await rwaGauge.getAddress(), 5000);
const weight = await gaugeController.getGaugeWeight(await rwaGauge.getAddress());
expect(weight).to.be.gt(0);
});
});

Impact

Core function broken

The contract does not handle weight increases properly, making it impossible to adjust votes dynamically.

Tools Used

manual, hardhat

Recommendations

Modify _updateGaugeWeight() so that addition occurs first, preventing underflow.

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

Lead Judging Commences

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

Give us feedback!