Core Contracts

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

Valid new periods are incorrectly rejected due to incorrect tracking of `totalDuration`

Summary

totalDuration must equal the sum of all elapsed durations between updates but this can be broken.

Vulnerability Details

function createPeriod(
Period storage self,
uint256 startTime,
uint256 duration,
uint256 initialValue,
uint256 weight
) internal {
if (self.startTime != 0 && startTime < self.startTime + self.totalDuration) {
revert PeriodNotElapsed();
}
if (duration == 0) revert ZeroDuration();
if (weight == 0) revert ZeroWeight();
self.startTime = startTime;
self.endTime = startTime + duration;
self.lastUpdateTime = startTime;
self.value = initialValue;
self.weightedSum = 0;
self.totalDuration = duration;
self.weight = weight;
emit PeriodCreated(startTime, duration, initialValue);
}
/**
* @notice Updates current value and accumulates time-weighted sums
* @dev Calculates weighted sum based on elapsed time since last update
* @param self Storage reference to Period struct
* @param newValue New value to set
* @param timestamp Time of update
*/
function updateValue(
Period storage self,
uint256 newValue,
uint256 timestamp
) internal {
if (timestamp < self.startTime || timestamp > self.endTime) {
revert InvalidTime();
}
unchecked {
uint256 duration = timestamp - self.lastUpdateTime;
if (duration > 0) {
uint256 timeWeightedValue = self.value * duration;
if (timeWeightedValue / duration != self.value) revert ValueOverflow();
self.weightedSum += timeWeightedValue;
self.totalDuration += duration;
}
}
self.value = newValue;
self.lastUpdateTime = timestamp;
}

totalDuration is initialized to the period's initial duration in createPeriod, then incremented by update intervals in updateValue. This causes totalDuration to exceed the actual period duration (endTime - startTime)

// When creating a period:
self.totalDuration = duration; // Set to initial duration (e.g., 100 seconds)
// When updating the value:
unchecked {
uint256 duration = timestamp - self.lastUpdateTime;
self.totalDuration += duration; // Adds time between updates
}

totalDuration must equal the actual elapsed time of the period (endTime - startTime).

totalDuration is initialized to the initial duration (e.g., 100 seconds).

Every call to updateValue adds the time since the last update to totalDuration.

This causes totalDuration to exceed the actual period duration (endTime - startTime).

3. Example Scenario

Period Setup:

  • startTime = 0

  • endTime = 100 (duration = 100 seconds)

  • totalDuration initialized to 100.

Update 1 at t=50:

  • duration = 50 - 0 = 50

  • totalDuration becomes 100 + 50 = 150.

Update 2 at t=100:

  • duration = 100 - 50 = 50

  • totalDuration becomes 150 + 50 = 200.

Result:

  • Actual period duration: 100 seconds (endTime - startTime).

  • totalDuration incorrectly reports 200 seconds.

Impact

Valid new periods are incorrectly rejected

Tools Used

Manual Review

Recommendations

totalDuration should only track the initial duration (endTime - startTime).

Time between updates should be tracked separately (e.g., elapsedTime).

Updates

Lead Judging Commences

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

TimeWeightedAverage::createPeriod incorrectly initializes totalDuration to period duration instead of zero, causing double-counting and inflated duration accumulation

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

TimeWeightedAverage::createPeriod incorrectly initializes totalDuration to period duration instead of zero, causing double-counting and inflated duration accumulation

Support

FAQs

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