In the TimeWeightedAverage library, there's a logical error in the updateValue
function where it incorrectly accumulates the total duration of a period, despite this value being fixed when the period is created. This leads to incorrect calculations when computing time-weighted averages such as in boost calculations.
The issue stems from how duration is handled across two functions:
In createPeriod:
In updateValue:
The fundamental problem is that totalDuration
represents the total fixed duration of a period (endTime - startTime), but updateValue
keeps adding intermediate durations between updates to it. This creates several issues:
The total duration becomes inflated with each value update
This affects any calculation that relies on totalDuration
. i.e calculateTimeWeightedAverage
The period's actual duration (endTime - startTime) no longer matches the tracked totalDuration
For instance in veRAACToken, boost update is done when RAACTokens are locked or increased in the lock. Now the _updateBoostState uses the BoostCalculator library which uses the TimeWeightedAverage Library when updating boost period, updateBoostPeriod;
From the code above we see that the global boost period, i.e state.boostPeriod
is created and also updated. Now by the current implementation, the totalDuration will be incorrectly updated.
Incorrect time-weighted average calculations, (for example calculateTimeWeightedAverage) due to inflated duration
Distorted period tracking for all contracts using the TimeWeightedAverage library.
Manual code review
Only update if the totalDuration is zero (I do acknowledge that a period can be created without using createPeriod
so make the incrementing conditional)
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.