QuantAMM

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

Array Index Out of Bounds / Negative Index

Summary

The UpliftOnlyExample.sol contains a potential Array Index Out of Bounds or Negative Index vulnerability in the loop that iterates over feeDataArray in the onAfterRemoveLiquidity function. This vulnerability could lead to accessing invalid memory locations, causing unintended behavior, potential reverts, or unexpected contract execution. The issue arises from improper handling of array indexing when the loop reaches index 0.

Affected Code:

https://github.com/Cyfrin/2024-12-quantamm/blob/main/pkg/pool-hooks/contracts/hooks-quantamm/UpliftOnlyExample.sol#L471

for (uint256 i = localData.feeDataArrayLength - 1; i >= 0; --i) {
// loop body
}

Vulnerability Details

  • In the loop above, the variable i is used to iterate over feeDataArray in reverse, starting from the last element and decrementing towards 0.

  • However, since i is of type uint256 (an unsigned integer), it cannot hold negative values. When i reaches 0, the subsequent decrement --i will cause i to underflow and wrap around to a very large number (2^256 - 1), which is not a valid index in the array.

  • This causes :

    1. Out of Bounds Access: The array index could exceed the bounds of the array.

    2. Infinite Loop: The loop may never terminate if it continues to decrement i past 0, causing the contract to enter an infinite loop.

Impact

It causes the loop to attempt accessing an invalid index (i >= 0 underflow), leading to an infinite loop or a revert due to invalid memory access. This could result in gas exhaustion, causing the transaction to fail, that disrupt the fee distribution logic, potentially allowing for incorrect fee calculations or loss of liquidity data.

Tools Used

Manually source code review.

Recommendations

To fix this issue, the loop condition should be modified to prevent underflow when i reaches 0. A proper solution would involve:

  1. Checking if the array is empty (feeDataArrayLength == 0) before the loop starts.

  2. Modifying the loop to ensure i stops at 0 and does not attempt to decrement below it.

Here is the fixed code:

if (localData.feeDataArrayLength == 0) {
revert("Fee data is empty");
}
for (uint256 i = localData.feeDataArrayLength; i > 0; --i) {
// Loop body
}
Updates

Lead Judging Commences

n0kto Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

invalid_onAfterRemoveLiquidity_loop_underflow

That’s definitely not the best way to handle that but there is indeed no impact. If someone tries to get more than their deposits, it must revert, and thanks to that "fancy mistake"(or genius code ?), it does.

Appeal created

mathew20h Submitter
7 months ago
n0kto Lead Judge
7 months ago
n0kto Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

invalid_onAfterRemoveLiquidity_loop_underflow

That’s definitely not the best way to handle that but there is indeed no impact. If someone tries to get more than their deposits, it must revert, and thanks to that "fancy mistake"(or genius code ?), it does.

Support

FAQs

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