QuantAMM

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

edge case leads to wrong weights calculation in DifferenceMomentum

Summary

The calculation of difference momentum have multiple of exponents and negative signs giving these equation to calculate difference momentum

  • w(t) = w(t − 1) + κ · ( (EWMA_short - EWMA_long) / EWMA_long − ℓp(t))

    • where ℓp(t) = 1/N * ∑((EWMA_short - EWMA_long) / EWMA_long)_i

Focusing on ℓp(t) and the (EWMA_short - EWMA_long) / EWMA_long

The weight[i] calculate the value of (EWMA_short[i] - EWMA_long[i]) / EWMA_long[i]

And the ℓp(t) is sum of all these values so its bigger than each of them leading to negative weights values appear incase of a scalar kappa (kappa.length = 1)

POC

add this test function in DifferenceMomentumRuleTest

function testUpdateWithHigherPrice_scalarParams_negative_weights() public {
/*
ℓp(t) 0.10125
moving average [0.9, 1.2]
alpha [7.7, 10.73333333]
beta [0.297, 0.414]
new weight [0.49775, 0.50225]
*/
// Define local variables for the parameters
int256[][] memory parameters = new int256[][]();
parameters[0] = new int256[]();
parameters[0][0] = PRBMathSD59x18.fromInt(1);
parameters[1] = new int256[]();
parameters[1][0] = 0.5e18;
int256[] memory prevShortMovingAverage = new int256[]();
prevShortMovingAverage[0] = PRBMathSD59x18.fromInt(1);
prevShortMovingAverage[1] = PRBMathSD59x18.fromInt(2);
int256[] memory prevMovingAverages = new int256[]();
prevMovingAverages[0] = PRBMathSD59x18.fromInt(0);
prevMovingAverages[1] = PRBMathSD59x18.fromInt(0);
int256[] memory movingAverages = new int256[]();
movingAverages[0] = 0.9e18;
movingAverages[1] = PRBMathSD59x18.fromInt(1) + 0.2e18;
int128[] memory lambdas = new int128[]();
lambdas[0] = int128(0.7e18);
int256[] memory prevWeights = new int256[]();
prevWeights[0] = 0.005e18;
prevWeights[1] = 0.995e18;
int256[] memory data = new int256[]();
data[0] = PRBMathSD59x18.fromInt(3);
data[1] = PRBMathSD59x18.fromInt(4);
int256[] memory expectedResults = new int256[]();
expectedResults[0] = -0.133888888888888888e18;
expectedResults[1] = 1.133888888888888889e18;
// Now pass the variables into the runInitialUpdate function
runInitialUpdate(
2, // numAssets
parameters,
prevShortMovingAverage,
prevMovingAverages,
movingAverages,
lambdas,
prevWeights,
data,
expectedResults
);
}

Impact

  • Wrong calculation of weights for Difference Momentum role breaks all logic of the contract

  • Calculation of weights is a core to the protocol and can't have any small error as it have huge impact on the protocol

Tools Used

manual review

Recommendations

apply this require with a scalar kappa

++ require(locals.res >= 0, "Invalid weight");
Updates

Lead Judging Commences

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

invalid_weights_can_be_negative_or_extreme_values

_clampWeights will check that these weights are positive and in the boundaries before writing them in storage.

Support

FAQs

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

Give us feedback!