Summary
A vulnerability has been discovered in the _quantAMMUnpack128Array function's bit manipulation logic that incorrectly handles sign extension. This vulnerability affects both the ScalarRuleQuantAMMStorage contract and its inheriting contracts when processing negative values in the QuantAMM system.
https://github.com/Cyfrin/2024-12-quantamm/blob/main/pkg/pool-quantamm/contracts/QuantAMMStorage.sol#L335
function _quantAMMUnpack128Array(int256[] memory _sourceArray, uint _targetArrayLength) internal pure returns (int256[] memory targetArray) {
targetArray[targetIndex] = _sourceArray[i] >> 128;
}
This issue propagates through the gradient calculations:
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/base/QuantammGradientBasedRule.sol#L47
locals.intermediateGradientState = _quantAMMUnpack128Array(
intermediateGradientStates[_poolParameters.pool],
_poolParameters.numberOfAssets
);
locals.intermediateValue = convertedLambda.mul(locals.intermediateGradientState[i]) +
(_newData[i] - _poolParameters.movingAverage[i]).div(oneMinusLambda);
And affects variance calculations:
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/base/QuantammVarianceBasedRule.sol#L58
locals.intermediateVarianceState = _quantAMMUnpack128Array(
intermediateVarianceStates[_poolParameters.pool],
locals.n
);
locals.intermediateState = locals.convertedLambda.mul(locals.intermediateVarianceState[i]) +
(_newData[i] - _poolParameters.movingAverage[locals.n + i]);
When the system processes negative numbers (common in scenarios like negative price impact or variance calculations), the direct right shift operation preserves the sign bit through sign extension. This causes severe corruption of negative values in the AMM's core mathematical computations. For example, a moderately negative price impact could be interpreted as an extreme negative value, causing the AMM to drastically miscalculate token amounts in trades. This directly threatens pool stability and can lead to significant financial losses through incorrect token allocations. The corruption of negative values in variance calculations further compounds the issue by distorting the AMM's risk assessment capabilities.
Recommended mitigation step
Modify the bit shifting operation to handle sign extension correctly:
function _quantAMMUnpack128Array(
int256[] memory _sourceArray,
uint _targetArrayLength
) internal pure returns (int256[] memory targetArray) {
require(_sourceArray.length * 2 >= _targetArrayLength, "SRC!=TGT");
targetArray = new int256[](_targetArrayLength);
uint targetIndex;
for (uint i; i < _sourceArray.length; ) {
int256 highBits = int256(uint256(_sourceArray[i]) >> 128);
require(highBits >= type(int128).min && highBits <= type(int128).max, "Value out of range");
targetArray[targetIndex] = highBits;
}
}