Core Contracts

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

`calculateTimeWeightedAverage` should normalize the weighted sum

Summary

calculateTimeWeightedAverage should normalize the weighted sum

Vulnerability details

calculateTimeWeightedAverage compute the time weighted average over multiple periods, each one having its own weight, indicating its importance over the other ones.
The issue is that while the values are scaled by their weights, the end result is not normalized to 1, which is usually done by dividing the final result by the sum of all weights, as described by the definition of a time weighted average

Example (all period having a duration of 1 for simplicity):

  • Period1: value = 10, weight = 2

  • Period2: value = 50, weight = 1

  • Period1: value = 5, weight = 2

The actual implementation will return 10*2 + 50*1 + 5*2 = 80, which is definitely not the weighted average of the periods.
While it should have returned (10*2 + 50*1 + 5*2)/(2+1+2) = 16

Impact

Overly inflated value of the average

Recommended Mitigation Steps

function calculateTimeWeightedAverage(
PeriodParams[] memory periods,
uint256 timestamp
) public pure returns (uint256 weightedAverage) {
uint256 totalWeightedSum;
uint256 totalDuration;
+ uint256 totalWeight
// 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;
+ totalWeight += periods[i].weight;
}
}
- return totalDuration == 0 ? 0 : totalWeightedSum / (totalDuration * 1e18);
+ return totalDuration == 0 ? 0 : totalWeightedSum / (totalDuration * totalWeight);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month 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.