QuantAMM

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

Low Bits Instead of High Bits Extraction for Final Element in Odd-length Array Corrupts Pool Parameters

Summary

An vulnerability exists in the _quantAMMUnpack128Array function's handling of odd-length arrays that affects both the base ScalarRuleQuantAMMStorage contract and its implementations in the QuantAMM system.

https://github.com/Cyfrin/2024-12-quantamm/blob/main/pkg/pool-quantamm/contracts/QuantAMMStorage.sol#L335

// In ScalarRuleQuantAMMStorage.sol
function _quantAMMUnpack128Array(int256[] memory _sourceArray, uint _targetArrayLength) internal pure returns (int256[] memory targetArray) {
// ...
if (!divisibleByTwo) {
targetArray[_targetArrayLength - 1] = int256(int128(_sourceArray[sourceArrayLengthMinusOne])); // Incorrect extraction
}
}

This inconsistency manifests in gradient calculations:

https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/base/QuantammGradientBasedRule.sol#L47

// In QuantAMMGradientBasedRule.sol
locals.intermediateGradientState = _quantAMMUnpack128Array(
intermediateGradientStates[_poolParameters.pool],
_poolParameters.numberOfAssets
);
// For odd-length arrays, the last gradient value is corrupted
locals.finalValues[numberOfAssetsMinusOne] = locals.mulFactor.mul(locals.intermediateValue);

And similarly affects variance calculations:

https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/base/QuantammVarianceBasedRule.sol#L58

// In QuantAMMVarianceBasedRule.sol
locals.intermediateVarianceState = _quantAMMUnpack128Array(
intermediateVarianceStates[_poolParameters.pool],
locals.n
);
// Last variance value is incorrect for odd-length arrays
locals.finalState[locals.nMinusOne] = locals.oneMinusLambda.mul(locals.intermediateState);

The issue stems from a mismatch between packing and unpacking operations for the final element in odd-length arrays. The corruption of the final element in odd-length arrays has serious implications for pool operations. When the final weight, gradient, or variance value is extracted incorrectly, it creates a persistent error in core calculations that involve complete vector operations. For example, if the final element represents a critical pool weight or variance measure, its corruption directly impacts price calculations and risk assessments for that specific asset or parameter. Given that AMM operations require precise mathematical calculations across all elements, this corruption can cause significant mispricing and incorrect token allocations. The impact is particularly severe in pools with odd numbers of assets, where the corrupted final element could represent a major token's weight or risk parameter, leading to substantial financial losses through incorrect pricing and swaps.

Recommended mitigation step

Modify the final element handling to extract high bits instead of low bits:

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;
uint sourceArrayLengthMinusOne = _sourceArray.length - 1;
bool divisibleByTwo = _targetArrayLength % 2 == 0;
// Main unpacking loop
for (uint i; i < sourceArrayLengthMinusOne; ) {
// ... existing unpacking logic
}
// Handle final element for odd-length arrays
if (!divisibleByTwo) {
// Extract high bits instead of low bits
targetArray[_targetArrayLength - 1] = int256(uint256(_sourceArray[sourceArrayLengthMinusOne]) >> 128);
}
}
Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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