QuantAMM

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

Out-of-bounds indexing bug in QuantAMMGradientBasedRule::_calculateQuantAMMGradient

Summary

The QuantAMMGradientBasedRule::_calculateQuantAMMGradient function will revert due to accessing an out-of-bounds index in the intermediateGradientStates[_poolParameters.pool] array.

Vulnerability Details

In the QuantAMMGradientBasedRule::_calculateQuantAMMGradient function, when _poolParameters.lambda.length != 1, the function mistakenly uses the loop variable i as the index for accessing the intermediateGradientStates[_poolParameters.pool] array instead of locals.storageArrayIndex.

QuantAMMGradientBasedRule::_calculateQuantAMMGradient function:

function _calculateQuantAMMGradient(
int256[] memory _newData,
QuantAMMPoolParameters memory _poolParameters
) internal returns (int256[] memory) {
...
if (_poolParameters.lambda.length == 1) {
...
} else {
if (notDivisibleByTwo) {
--numberOfAssetsMinusOne;
}
for (uint i; i < numberOfAssetsMinusOne; ) {
...
locals.finalValues[locals.secondIndex] = locals.mulFactor.mul(locals.secondIntermediateValue);
=> // @audit Access incorrect index `i` instead of `locals.storageArrayIndex`
=> intermediateGradientStates[_poolParameters.pool][i] = _quantAMMPackTwo128(
locals.intermediateGradientState[i],
locals.secondIntermediateValue
);
unchecked {
i += 2;
++locals.storageArrayIndex;
}
}
...
}

For instance, if _poolParameters.numberOfAssets == 6, the length of the intermediateGradientStates[_poolParameters.pool] array will be 3. However, the loop variable i increments from 0 to 4 (inclusive) with a step of 2. When i == 4, the function attempts to access intermediateGradientStates[_poolParameters.pool][4], causing an out-of-bounds error.

Impact

The QuantAMMGradientBasedRule::_calculateQuantAMMGradient function reverts in case where _poolParameters.lambda.length != 1.

Recommendations

Update the QuantAMMGradientBasedRule::_calculateQuantAMMGradient function:

function _calculateQuantAMMGradient(
int256[] memory _newData,
QuantAMMPoolParameters memory _poolParameters
) internal returns (int256[] memory) {
...
if (_poolParameters.lambda.length == 1) {
...
} else {
if (notDivisibleByTwo) {
--numberOfAssetsMinusOne;
}
for (uint i; i < numberOfAssetsMinusOne; ) {
...
locals.finalValues[locals.secondIndex] = locals.mulFactor.mul(locals.secondIntermediateValue);
- intermediateGradientStates[_poolParameters.pool][i] = _quantAMMPackTwo128(
+ intermediateGradientStates[_poolParameters.pool][locals.storageArrayIndex] = _quantAMMPackTwo128(
locals.intermediateGradientState[i],
locals.secondIntermediateValue
);
unchecked {
i += 2;
++locals.storageArrayIndex;
}
}
...
}
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.

Give us feedback!