Core Contracts

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

Inconsistent Decimal Scaling of periodWeight in addGauge::gaugeController.sol

Summary

addGauge initializes a new gauge and sets up a TimeWeightedAverage.Period for tracking its weight over time. When initialWeight = 0, it assigns periodWeight = 1 as a minimum value to ensure period tracking functions, as noted by the comment // Use minimum weight (1) for period tracking if initialWeight is 0.

However,

struct Period {
uint256 startTime; // Beginning timestamp of the period
uint256 endTime; // End timestamp of the period
uint256 lastUpdateTime; // Last timestamp the value was updated
uint256 value; // Current value being tracked
uint256 weightedSum; // Running sum of time-weighted values
uint256 totalDuration; // Total duration of accumulated values
>> uint256 weight; // Weight applied to period (scaled by 1e18)
}

struct Period in TimeWeightedAverage.sol expects weight scaled by 1e18 and calculateAverage::TimeWeightedAverage.sol suggest that self.value (mapped to periodWeight) should be in 18-decimal precision (e.g., 1e18 for 1 unit). This mismatch—using 1 instead of 1e18—introduces an inconsistency in decimal scaling, leading to incorrect weight calculations in the time-weighted average system.

Vulnerability Details

addGauge::GaugeController.sol

function addGauge(
address gauge,
GaugeType gaugeType,
uint256 initialWeight
) external onlyGaugeAdmin {
if (gauges[gauge].lastUpdateTime != 0) revert GaugeAlreadyExists();
if (gaugeType != GaugeType.RWA && gaugeType != GaugeType.RAAC) {
revert InvalidGaugeType();
}
>> uint256 periodWeight = initialWeight == 0 ? 1 : initialWeight; // Minimum set to 1
uint256 duration = gaugeType == GaugeType.RWA ? 30 days : 7 days;
gauges[gauge] = Gauge({
weight: initialWeight,
typeWeight: 0,
lastUpdateTime: block.timestamp,
gaugeType: gaugeType,
isActive: true,
lastRewardTime: block.timestamp
});
TimeWeightedAverage.Period storage period = gaugePeriods[gauge];
TimeWeightedAverage.createPeriod(
period,
block.timestamp,
duration,
>> periodWeight,
>> periodWeight
);
_gaugeList.push(gauge);
emit GaugeAdded(gauge, gaugeType);
}

Impact

The use of 1 instead of 1e18 for periodWeight when initialWeight == 0 has the following consequences: grossly underestimated weight. self.value = 1 (instead of 1e18) is used in calculateAverage, making the gauge’s time-weighted average weight 10^18 times smaller than intended.

The gauge appears to have negligible weight (e.g., 1 wei vs. 1 unit), drastically underrepresenting its influence.

Tools Used

Manual review

Recommendations

Scale periodWeight to 18 Decimals

function addGauge(
address gauge,
GaugeType gaugeType,
uint256 initialWeight
) external onlyGaugeAdmin {
if (gauges[gauge].lastUpdateTime != 0) revert GaugeAlreadyExists();
if (gaugeType != GaugeType.RWA && gaugeType != GaugeType.RAAC) {
revert InvalidGaugeType();
}
- uint256 periodWeight = initialWeight == 0 ? 1e18 : initialWeight;
+ uint256 periodWeight = initialWeight == 0 ? 1e18 : initialWeight; // Fix to 1e18
uint256 duration = gaugeType == GaugeType.RWA ? 30 days : 7 days;
//rest of the code ...
}
Updates

Lead Judging Commences

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

GaugeController::addGauge uses unscaled value 1 for periodWeight when initialWeight is 0, causing gauge influence to be 10^18 times smaller than intended in TimeWeightedAverage calculations

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

GaugeController::addGauge uses unscaled value 1 for periodWeight when initialWeight is 0, causing gauge influence to be 10^18 times smaller than intended in TimeWeightedAverage calculations

Support

FAQs

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