QuantAMM

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

The `DifferenceMomentumUpdateRule::_getWeights` function does not check whether (res >= 0) when (locals.kappaStore.length == 1).

Summary

The DifferenceMomentumUpdateRule::_getWeightslack a check for (locals.res >= 0) when the (locals.kappaStore.length == 1).

Vulnerability Details

In the _getWeights function, when locals.kappaStore.length == 1, it does not check whether the calculated weights are greater than 0 before storing the value. This could result in invalid or incorrect weight values being stored.

https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/DifferenceMomentumUpdateRule.sol#L118

if (locals.kappaStore.length == 1) {
//scalar logic separate to vector for efficiency
locals.normalizationFactor /= int256(locals.prevWeightLength);
// To avoid intermediate overflows (because of normalization), we only downcast in the end to an uint6
// κ · ( (EWMA_short - EWMA_long) / EWMA_long − ℓp(t))
for (locals.i = 0; locals.i < locals.prevWeightLength; ) {
int256 res = int256(_prevWeights[locals.i]) +
locals.kappaStore[0].mul(locals.newWeights[locals.i] - locals.normalizationFactor);
-> Not checked ->
newWeightsConverted[locals.i] = res;
unchecked {
++locals.i;
}
}
} else {
//vector logic separate to vector for efficiency
int256 sumKappa;
for (locals.i = 0; locals.i < locals.kappaStore.length; ) {
sumKappa += locals.kappaStore[locals.i];
unchecked {
++locals.i;
}
}
locals.normalizationFactor = locals.normalizationFactor.div(sumKappa);
// To avoid intermediate overflows (because of normalization), we only downcast in the end to an uint6
for (locals.i = 0; locals.i < _prevWeights.length; ) {
locals.res =
int256(_prevWeights[locals.i]) +
locals.kappaStore[locals.i].mul(locals.newWeights[locals.i] - locals.normalizationFactor);
-> checked -> require(locals.res >= 0, "Invalid weight");
newWeightsConverted[locals.i] = locals.res;
unchecked {
++locals.i;
}
}
}

Impact

Weights that are less than 0 will also be stored and passed further for calculation, leading to incorrect results

Tools Used

manual review

Recommendations

if (locals.kappaStore.length == 1) {
//scalar logic separate to vector for efficiency
locals.normalizationFactor /= int256(locals.prevWeightLength);
// To avoid intermediate overflows (because of normalization), we only downcast in the end to an uint6
// κ · ( (EWMA_short - EWMA_long) / EWMA_long − ℓp(t))
for (locals.i = 0; locals.i < locals.prevWeightLength; ) {
int256 res = int256(_prevWeights[locals.i]) +
locals.kappaStore[0].mul(locals.newWeights[locals.i] - locals.normalizationFactor);
+ require(res >= 0, "Invalid weight");
newWeightsConverted[locals.i] = res;
unchecked {
++locals.i;
}
}
} else {
//vector logic separate to vector for efficiency
int256 sumKappa;
for (locals.i = 0; locals.i < locals.kappaStore.length; ) {
sumKappa += locals.kappaStore[locals.i];
unchecked {
++locals.i;
}
}
locals.normalizationFactor = locals.normalizationFactor.div(sumKappa);
// To avoid intermediate overflows (because of normalization), we only downcast in the end to an uint6
for (locals.i = 0; locals.i < _prevWeights.length; ) {
locals.res =
int256(_prevWeights[locals.i]) +
locals.kappaStore[locals.i].mul(locals.newWeights[locals.i] - locals.normalizationFactor);
require(locals.res >= 0, "Invalid weight");
newWeightsConverted[locals.i] = locals.res;
unchecked {
++locals.i;
}
}
}
Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
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.

Appeal created

saurabh_singh Submitter
10 months ago
n0kto Lead Judge
10 months ago
n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
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!