Core Contracts

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

Incorrect formula to calculate time-weighed average

Vulnerability Details

In TimeWeightedAveragelibrary, there are 2 functions to calculate time-weighed average: calculateAverage for current period and calculateTimeWeightedAverage for multiple periods:

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;
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); // <--
}
function calculateTimeWeightedAverage(
PeriodParams[] memory periods,
uint256 timestamp
) public pure returns (uint256 weightedAverage) {
uint256 totalWeightedSum;
uint256 totalDuration;
// We will iterate through each period and calculate the time-weighted average
for (uint256 i = 0; i < periods.length; i++) {
if (timestamp <= periods[i].startTime) continue;
uint256 endTime = timestamp > periods[i].endTime ? periods[i].endTime : timestamp;
uint256 duration = endTime - periods[i].startTime;
unchecked {
// Calculate time-weighted value by multiplying value by duration
// This represents the area under the curve for this period
uint256 timeWeightedValue = periods[i].value * duration;
if (timeWeightedValue / duration != periods[i].value) revert ValueOverflow();
totalWeightedSum += timeWeightedValue * periods[i].weight;
totalDuration += duration;
}
}
return totalDuration == 0 ? 0 : totalWeightedSum / (totalDuration * 1e18); // <--
}

Both functions return average return time-weighted average by divide totalWeightedSum by totalDuration. But in function calculateTimeWeightedAverage, it divide with 1e18, while function calculateAveragedon't, which will lead to inaccurate result in one of them.

Impact

Inaccurate result returned

Recommendations

Async return value of both function.

Updates

Lead Judging Commences

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

TimeWeightedAverage library fails to consistently apply weights in calculations, causing incorrect time-weighted averages

Support

FAQs

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

Give us feedback!