Core Contracts

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

Updating gauge weight will revert if the callers voting power has increased

Summary

We want to allow user to adjust the weight they want to use in each gauge. The main issue is if user already set a weight for a gauge and his/her voting power (amount of veRAAC token that he/she holds) has increased. The user won't be able to update the weight for himself and the gauge he desiers to do so. The main root cause of this issue is located in the _updateGaugeWeight function of the GaugeController contract.

function _updateGaugeWeight(
address gauge,
uint256 oldWeight,
uint256 newWeight,
uint256 votingPower
) internal {
Gauge storage g = gauges[gauge];
uint256 oldGaugeWeight = g.weight;
//@Audit could revert if voting power is high enough to upscale the first substraction to be bigger than the oldGaugeWeight
uint256 newGaugeWeight = oldGaugeWeight - (oldWeight * votingPower / WEIGHT_PRECISION)
+ (newWeight * votingPower / WEIGHT_PRECISION);
g.weight = newGaugeWeight;
g.lastUpdateTime = block.timestamp;
}

Vulnerability Details

The root cause of the issue is that when we update the weight of the gauge we first substract the oldWeight of the user scaled by his/her current voting power. This means if the voting power is big enough(increased for some user that already has set the gauge weight). We would get a negative number when we do oldGaugeWeight - (oldWeight * votingPower / WEIGHT_PRECISION), this would cause an instnt revert before we add the final pice of the calculation that is (newWeight * votingPower / WEIGHT_PRECISION). In our test scenario any increase of the user voting power would do the trick as he/she is the only user that has voted for the weight of the gauge so far.

Impact

Users with an increased voting power might not be able to change their gauge weight in specific gauges. This would lead to unsatisfactory rewards payouts from some gagues as gauge weight is no longer satisfactory for the user.

Tools Used

  • Manual Review

  • Unit tests

PoC

Place the test inside of the GaugeController.test.js in the describe("Weight Management") test suite group.

it("Poc incorrect weight update for gauge causes a revert", async () => {
//User votes for a weight of 50% for the given rwaGauge
await gaugeController.connect(user1).vote(await rwaGauge.getAddress(), 5000);
const weight = await gaugeController.getGaugeWeight(await rwaGauge.getAddress());
//We validate that the total weight of the gauge is 50% of the user voting power currently
expect(weight).to.equal(ethers.parseEther("500"));
//We mint 100 veRAAC tokens to user one and with this we effectivly increase users voting power
await veRAACToken.mint(user1.address, ethers.parseEther("100"));
//We try to change the gauge weight to 60% but we will panic revert stating and overflow
await expect(
gaugeController.connect(user1).vote(await rwaGauge.getAddress(), 6000)
).to.be.revertedWithPanic(0x11);
//We try to change the gauge weight to 40% but we will panic revert again stating and overflow
await expect(
gaugeController.connect(user1).vote(await rwaGauge.getAddress(), 4000)
).to.be.revertedWithPanic(0x11);
});

Recommendations

Switch the order of the arithmetic operation so addition comes before substraction:

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 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.