Core Contracts

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

Incorrect scaling in gauge weight calculation leads to inflated reward distribution

Description

The GaugeController::_updateGaugeWeight function incorrectly scales voting power contributions due to mismatched decimal precision. The calculation uses WEIGHT_PRECISION (1e4) to scale votes while votingPower comes from an ERC20 token with 18 decimals. This results in gauge weights being inflated by 1e18, distorting reward distribution calculations.

Proof of Concept

  1. User with 1.0 veRAAC (1e18) votes 100% (10000 basis points) for a gauge

  2. _updateGaugeWeight calculates:

    newGaugeWeight = 0 - (0 * 1e18 / 10000) + (10000 * 1e18 / 10000) = 1e18
  3. Gauge weight becomes 1e18 instead of expected 1e4 precision value

  4. Subsequent reward calculations use this inflated weight

Test showing the issue:

it("demonstrates gauge weight scaling issue", async () => {
await veRAACToken.mint(user1.address, ethers.parseEther("1")); // 1e18
await gaugeController
.connect(user1)
.vote(await rwaGauge.getAddress(), WEIGHT_PRECISION);
const weight = await gaugeController.getGaugeWeight(await rwaGauge.getAddress());
// Expected: 1e18 * 10000 / 10000 = 1e18 (incorrect, should be 1e4)
expect(weight).to.equal(ethers.parseEther("1"));
const totalWeight = await gaugeController.getTotalWeight();
expect(totalWeight).to.equal(ethers.parseEther("1")); // Inflated total
});

Impact

High severity - Directly impacts reward distribution math causing:

  • Overweight gauges to receive disproportionate rewards

  • Total weight summation becomes astronomically large

  • Protocol emissions distribution fundamentally broken

Recommendation

  • Add decimal normalization:

contracts/core/governance/gauges/GaugeController.sol
function _updateGaugeWeight(address gauge, uint256 oldWeight, uint256 newWeight, uint256 votingPower) internal {
// ... existing code ...
uint256 newGaugeWeight =
- oldGaugeWeight - (oldWeight * votingPower / WEIGHT_PRECISION) + (newWeight * votingPower / WEIGHT_PRECISION);
+ oldGaugeWeight - (oldWeight * votingPower / (WEIGHT_PRECISION * 1e18)) + (newWeight * votingPower / (WEIGHT_PRECISION * 1e18));
}
  • Implement weight ceilings:

uint256 public constant MAX_GAUGE_WEIGHT = 10000 * 1e18; // 1e4 precision with token decimals
require(newGaugeWeight <= MAX_GAUGE_WEIGHT, "Overweight gauge");
Updates

Lead Judging Commences

inallhonesty Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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