The TimeWeightedAverage library is responsible for tracking time-weighted values across defined periods. It does so by maintaining a running weighted sum and total elapsed duration to eventually compute a time-weighted average using the formula:
Time Weighted Average
= Weighted Sum
/ Total Duration
and where the weighted sum
for a constant value is intended to be:
Weighted Sum
= Value
* Weight
* Duration
However, in the current implementation of the library, the external weight provided (e.g., weight = 2.5
) is stored in the period struct but is never applied in the calculation of the time weighted sum in either the updateValue
or calculateAverage
functions. This omission means that the effective value is not scaled by the intended weight, causing the computed average to be incorrect. Over time, especially in systems that continuously update these values (such as reward or governance systems), this miscalculation can lead to a Denial-of-Service (DoS) scenario or significant misallocation of rewards.
TimeWeightedAverage::updateValue
This function updates the period's state by calculating the time elapsed since the last update and then adding the product of the current value and elapsed duration to the running weighted sum. The function is defined as follows:
Issue:
The calculation timeWeightedValue
= self.value
* duration
does not incorporate self.weight
.
The intended calculation should multiply the value by the weight as well, i.e.,
timeWeightedValue
= (self.value
* self.weight
) * duration
TimeWeightedAverage::calculateAverage
This function calculates the time weighted average up to a given timestamp by including any pending time since the last update. Its current implementation is as follows:
Issue:
The line calculating timeWeightedValue
does not include the weight.
The formula should reflect:
timeWeightedValue
= (self.value
* self.weight
) * duration
Consider the following scenario involving Alice:
Initial Setup:
Alice locks tokens with a fixed value of 10
.
A weight of 2.5
is provided externally.
The period is defined with:
startTime = 0
endTime = 10
initialValue = 10
weight = 2.5
Expected Calculation:
Intended Time Weighted Sum:
The effective value should be:
Effective Value
= 10 * 2.5 = 25
For a full duration of 10 time units:
Intended Weighted Sum
= 25 * 10 = 250
Intended Time Weighted Average:
Average
= 250 / 10 = 25
Actual Calculation with Bug:
The functions calculate:
timeWeightedValue
= 10 * 10 = 100
The computed average becomes:
Average
= 100 / 10 = 10
Result: Alice’s boost or reward calculation based on this average is severely underestimated.
Repeated Updates:
As Alice performs multiple updates (via updateValue
) over time, the unweighted calculations continue, leading to further divergence from the intended metrics.
This may eventually cause the system to block further updates (DoS) or misallocate rewards.
updateValue
Function:
calculateAverage
Function:
TODO **********Anil don't forget to paste PoC's Test**************
Short-Term Impact:
Immediate miscalculation of averages leading to inaccurate reward distribution.
Misrepresentation of boost factors or voting power based on the undervalued time weighted average.
Long-Term Impact:
Persistent inaccuracies in critical financial or governance metrics can destabilize the protocol.
Over time, users may lose trust in the system if rewards and governance outcomes do not reflect their true stake.
In extreme cases, the accumulation of errors might cause a Denial-of-Service (DoS) for components relying on period expirations, affecting multiple facets of the protocol.
Manual Review
Foundry
The following diffs outline the recommended changes to correctly incorporate the weight into the time weighted sum calculations.
updateValue
FunctioncalculateAverage
FunctioncalculateTimeWeightedAverage
FunctionTime Weighted Sum Formula:
Time Weighted Sum = (Value
* Weight
) * Duration
Time Weighted Average Formula:
Time Weighted Average = Time Weighted Sum
/ Total Duration
Implementing these changes ensures that the provided weight is properly applied in all calculations, thereby maintaining accurate time weighted averages that reflect the intended significance of the underlying values.
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.