Core Contracts

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

`TimeWeightedAverage::calculateAverage` Incorrectly Calculates Average Value,Because `totalWeightedSum` And `endtime` Are Not Corresponding.

Summary

The TimeWeightedAverage::calculateAverage function erroneously uses self.weightedSum as the totalWeightedSum despite temporal misalignment between these values. The current implementation only handles scenarios where endTime exceeds lastUpdateTime, while ignoring cases where endTime predates lastUpdateTime.

Vulnerability Details

function calculateAverage(
Period storage self,
uint256 timestamp
) internal view returns (uint256) {
if (timestamp <= self.startTime) return self.value;
uint256 endTime = timestamp > self.endTime ? self.endTime : timestamp;
uint256 totalWeightedSum = self.weightedSum; <==@found
if (endTime > self.lastUpdateTime) {
uint256 duration = endTime - self.lastUpdateTime;
uint256 timeWeightedValue = self.value * duration;
if (duration > 0 && timeWeightedValue / duration != self.value) revert ValueOverflow();
totalWeightedSum += timeWeightedValue;
}
return totalWeightedSum / (endTime - self.startTime);
}

Impact

The calculated average is inflated.

Tools Used

  • Manual Review

Recommendations

1.Record the previous self.value as lastValue, and use it when endtime <= lastUpdateTime.

+ uint256 lastValue;
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;
}
}
+ lastValue = self.value;
self.value = newValue;
self.lastUpdateTime = timestamp;
}

2 To address scenarios where endtime ≤ lastUpdateTime, the logic should be refined as follows:

function calculateAverage(
Period storage self,
uint256 timestamp
) internal view returns (uint256) {
if (timestamp <= self.startTime) return self.value;
uint256 endTime = timestamp > self.endTime ? self.endTime : timestamp;
uint256 totalWeightedSum = self.weightedSum; <==@found
if (endTime > self.lastUpdateTime) {
uint256 duration = endTime - self.lastUpdateTime;
uint256 timeWeightedValue = self.value * duration;
if (duration > 0 && timeWeightedValue / duration != self.value) revert ValueOverflow();
totalWeightedSum += timeWeightedValue;
+ }else{
+ uint256 duration = self.lastUpdateTime - endTime;
+ uint256 timeWeightedValue = lastValue * duration;
+ totalWeightedSum -= timeWeightedValue;
+ }
return totalWeightedSum / (endTime - self.startTime);
}
Updates

Lead Judging Commences

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

Support

FAQs

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