QuantAMM

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

Uninitialized Storage Variable in QuantAMM's Unpacking Function

Summary

In the ScalarQuantAMMBaseStorage contract's quantAMMUnpack32Array function, the stickyEndSourceElem variable is not properly initialized when handling arrays with length less than 8, potentially leading to data corruption or invalid unpacking of storage slots.

Vulnerability Details

The issue exists in the quantAMMUnpack32Array function where stickyEndSourceElem is declared but not initialized for all code paths:

uint stickyEndSourceElem; // Declared without initialization
if (_targetArrayLength > 8) {
// ... logic ...
if (!divisibleByEight) {
unchecked {
stickyEndSourceElem = _sourceArray.length - 1;
}
}
} else if (_targetArrayLength == 8) {
// ... logic for exactly 8 elements ...
}
// Later used here without guaranteed initialization
if (!divisibleByEight) {
unchecked {
uint offset = 224;
for (uint i = targetIndex; i < targetArray.length; ) {
targetArray[i] = int256(int32(_sourceArray[stickyEndSourceElem] >> offset)) * 1e9;
offset -= 32;
++i;
}
}
}

When _targetArrayLength is less than 8, the code skips both initialization paths but still uses stickyEndSourceElem in the sticky end handling section. This uninitialized variable could contain any arbitrary value, leading to incorrect data unpacking.

Impact

Incorrect unpacking of storage slots when dealing with arrays of length 1-7 and also silent data corruption as the uninitialized variable might point to a valid but incorrect storage slot. There could also be potential array out-of-bounds access if the uninitialized value exceeds the source array length.

Tools Used

  • Manual code review

Recommendations

Initialize stickyEndSourceElem for all code paths.

function quantAMMUnpack32Array(
int256[] memory _sourceArray,
uint _targetArrayLength
) internal pure returns (int256[] memory targetArray) {
require(_sourceArray.length * 8 >= _targetArrayLength, "SRC!=TGT");
targetArray = new int256[](_targetArrayLength);
uint targetIndex;
uint sourceArrayLengthMinusOne = _sourceArray.length - 1;
bool divisibleByEight = _targetArrayLength % 8 == 0;
uint stickyEndSourceElem = _sourceArray.length - 1; // Initialize at declaration
if (_targetArrayLength > 8) {
// ... existing logic ...
} else if (_targetArrayLength == 8) {
// ... existing logic ...
}
// Rest of the function remains the same
}
Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

Informational or Gas / Admin is trusted / Pool creation is trusted / User mistake / Suppositions

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelyhood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

Support

FAQs

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

Give us feedback!