QuantAMM

QuantAMM
49,600 OP
View results
Submission Details
Severity: high
Valid

Using of incorrect array index in `QuantAMMGradientBasedRule`

Summary

The QuantAMMGradientBasedRule._calculateQuantAMMGradient function stores new values in the intermediateGradientStates array using the index of the unpacked array which is twice larger. This can cause unexpected errors for the _poolParameters.lambda.length > 1 case.

Vulnerability Details

The QuantAMMGradientBasedRule._calculateQuantAMMGradient function stores in the intermediateGradientStates array packed values . That is why it tracks two indexes. When value is stored in the intermediateGradientStates array the locals.storageArrayIndex should be used. But for the _poolParameters.lambda.length > 1 case the i is used.

function _calculateQuantAMMGradient(
int256[] memory _newData,
QuantAMMPoolParameters memory _poolParameters
) internal returns (int256[] memory) {
QuantAMMGradientLocals memory locals;
locals.finalValues = new int256[](_poolParameters.numberOfAssets);
locals.intermediateGradientState = _quantAMMUnpack128Array(
intermediateGradientStates[_poolParameters.pool],
_poolParameters.numberOfAssets
);
// lots initialised before looping to save gas
bool notDivisibleByTwo = _poolParameters.numberOfAssets % 2 != 0;
uint numberOfAssetsMinusOne = _poolParameters.numberOfAssets - 1;
int256 convertedLambda = int256(_poolParameters.lambda[0]);
int256 oneMinusLambda = ONE - convertedLambda;
//You cannot have a one token pool so if its one element you know it's scalar
if (_poolParameters.lambda.length == 1) {
<...>
>> intermediateGradientStates[_poolParameters.pool][locals.storageArrayIndex] = _quantAMMPackTwo128(
locals.intermediateGradientState[i],
locals.secondIntermediateValue
);
// the storage array is tracked separately
unchecked {
>> i += 2;
>> ++locals.storageArrayIndex;
}
}
<...>
} else {
// if the parameters are defined as per constituent we do the same as the if loop but
//tracking the appropriate lambda for each asset and the appropriate storage index
if (notDivisibleByTwo) {
--numberOfAssetsMinusOne;
}
for (uint i; i < numberOfAssetsMinusOne; ) {
<...>
>> intermediateGradientStates[_poolParameters.pool][i] = _quantAMMPackTwo128(
locals.intermediateGradientState[i],
locals.secondIntermediateValue
);
unchecked {
>> i += 2;
>> ++locals.storageArrayIndex;
}
}

Impact

DoS of the core functionality

Tools used

Manual Review

Recommendations

Consider using locals.storageArrayIndex instead of i index.

Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding_gradient_rules_more_than_3_assets_and_1_lambda_will_DoS_the_update

Likelihood: Medium/High, assets>4, lambdas > 1. Impact: Medium/High, DoS update but pool works fine. Pool with 5 assets will use incorrect weights.

Support

FAQs

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