QuantAMM

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

Accumulation of FeeData Entries Without Proper Decrement

Summary

https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-hooks/contracts/hooks-quantamm/UpliftOnlyExample.sol#L219C5-L238C11

Each time a user adds liquidity in addLiquidityProportional, a new FeeData entry is appended to poolsFeeData[pool][msg.sender].

This array grows with each deposit made by the user.

When a user removes liquidity in removeLiquidityProportional, the function does not remove or update the corresponding FeeData entries in poolsFeeData[pool][msg.sender].

The array does not shrink or reflect the withdrawal of liquidity.

Vulnerability Details

function addLiquidityProportional(
address pool,
uint256[] memory maxAmountsIn,
uint256 exactBptAmountOut,
bool wethIsEth,
bytes memory userData
) external payable saveSender(msg.sender) returns (uint256[] memory amountsIn) {
if (poolsFeeData[pool][msg.sender].length > 100) {
revert TooManyDeposits(pool, msg.sender);
}
// Do addLiquidity operation - BPT is minted to this contract.
amountsIn = _addLiquidityProportional(
pool,
msg.sender,
address(this),
maxAmountsIn,
exactBptAmountOut,
wethIsEth,
userData
);

https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-hooks/contracts/hooks-quantamm/UpliftOnlyExample.sol#L219C5-L238C11

The contract enforces a maximum of 100 deposits per user per pool.

if (poolsFeeData[pool][msg.sender].length > 100) {````revert TooManyDeposits(pool, msg.sender);````}

Since withdrawals do not decrease the array's length, users may hit this limit and be unable to make additional deposits, even if they have withdrawn all their liquidity.

Fees or rewards calculated based on the FeeData entries may be incorrect, as they include data from deposits that have been withdrawn.

Example:

A user makes 100 deposits into a pool, reaching the maximum allowed entries.

The user withdraws all their liquidity using removeLiquidityProportional.

The user attempts to make a new deposit.

The contract reverts with TooManyDeposits, as the poolsFeeData length is still 100.

The user is effectively locked out from adding new liquidity to the pool.

Impact

The array only ever grows, regardless of withdrawals, leading to an inaccurate state. The array does not shrink or reflect the withdrawal of liquidity.

Tools Used

Manual Review

Recommendations

When a user removes liquidity, the function does should remove or update the corresponding FeeData entries in poolsFeeData[pool][msg.sender].

Updates

Lead Judging Commences

n0kto Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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