QuantAMM

QuantAMM
49,600 OP
View results
Submission Details
Severity: low
Invalid

Precision Loss in Moving Average Calculation Can Lead to Price Manipulation

Vulnerability Detail

The QuantAMMMathMovingAverage contract implements an exponential moving average calculation for price updates. The critical calculation occurs in _calculateQuantAMMMovingAverage():

newMovingAverage[i] = movingAverageI + oneMinusLambda.mul(_newData[i] - movingAverageI);

The implementation uses fixed-point arithmetic with PRBMath's SD59x18, where values are scaled by 1e18. However, the order of operations in this calculation can lead to significant precision loss when dealing with large price values or extreme lambda parameters.

The issue arises because:

  1. The subtraction _newData[i] - movingAverageI is performed first

  2. This difference is then multiplied by oneMinusLambda

  3. Finally, the result is added to movingAverageI

If _newData[i] and movingAverageI are large numbers, their difference might still be significant in absolute terms but could lose precision after the fixed-point multiplication with oneMinusLambda. This precision loss can be exploited by an attacker to manipulate the moving average in their favor.

For example:

  • If _newData[i] = 1e24 (1,000,000 * 1e18)

  • movingAverageI = 1e24 - 1e20

  • oneMinusLambda = 0.1 * 1e18
    The calculation will lose significant digits in the multiplication step, potentially leading to an incorrect moving average.

Impact

Moving average calculations can be manipulated through precision loss, leading to incorrect price updates and potential economic attacks.

Recommendation

Restructure the calculation to minimize precision loss by rearranging the operations:

function _calculateQuantAMMMovingAverage(
int256[] memory _prevMovingAverage,
int256[] memory _newData,
int128[] memory _lambda,
uint _numberOfAssets
) internal pure returns (int256[] memory) {
// ...
// Restructured calculation to preserve precision
newMovingAverage[i] = (movingAverageI.mul(convertedLambda) + _newData[i].mul(oneMinusLambda)).div(ONE);
// ...
}
Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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