QuantAMM

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

Inability to Remove Liquidity from Vault

Summary

The issue arises when users attempt to add liquidity with an amount less than _MINIMUM_TRADE_AMOUNT, causing the transaction to revert. This constraint is not checked in the UpliftOnlyExample.sol#onAfterRemoveLiquidity() function, potentially leading to failed operations in boundary cases.

Vulnerability Details

Impact

Users are unable to add liquidity if the amount is less than _MINIMUM_TRADE_AMOUNT. This is evident from the following code snippet:

// Minimum token value in or out (applied to scaled18 values), enforced as a security measure to block potential
// exploitation of rounding errors. This is called in the context of adding or removing liquidity, so zero is
// allowed to support single-token operations.
function _ensureValidTradeAmount(uint256 tradeAmount) internal view {
if (tradeAmount != 0) {
_ensureValidSwapAmount(tradeAmount);
}
}
// Minimum token value in or out (applied to scaled18 values), enforced as a security measure to block potential
// exploitation of rounding errors. This is called in the swap context, so zero is not a valid amount. Note that
// since this is applied to the scaled amount, the corresponding minimum raw amount will vary according to token
// decimals. The math functions are called with scaled amounts, and the magnitude of the minimum values is based
// on the maximum error, so this is fine. Trying to adjust for decimals would add complexity and significant gas
// to the critical path, so we don't do it. (Note that very low-decimal tokens don't work well in AMMs generally;
// this is another reason to avoid them.)
function _ensureValidSwapAmount(uint256 tradeAmount) internal view {
if (tradeAmount < _MINIMUM_TRADE_AMOUNT) {
revert TradeAmountTooSmall();
}
}

However, the UpliftOnlyExample.sol#onAfterRemoveLiquidity() function does not account for this constraint:
https://github.com/Cyfrin/2024-12-quantamm/blob/main/pkg/pool-hooks/contracts/hooks-quantamm/UpliftOnlyExample.sol#L537

This is the minted BPT amount when the operation is proportional:
https://github.com/Cyfrin/2024-12-quantamm/blob/main/pkg/pool-hooks/contracts/hooks-quantamm/UpliftOnlyExample.sol#L542

As shown above, there is no check for minBptAmount, which is the BPT amount minted when the kind is AddLiquidityKind.PROPORTIONAL.

In the Vault contract:
https://github.com/Cyfrin/2024-12-quantamm/blob/main/pkg/vault/contracts/Vault.sol#L631

function _addLiquidity(
.................
if (params.kind == AddLiquidityKind.PROPORTIONAL) {
L631-> bptAmountOut = params.minBptAmountOut;
// Initializes the swapFeeAmounts empty array (no swap fees on proportional add liquidity).
swapFeeAmounts = new uint256[](locals.numTokens);
amountsInScaled18 = BasePoolMath.computeProportionalAmountsIn(
poolData.balancesLiveScaled18,
_totalSupply(params.pool),
bptAmountOut
);

In boundary cases, a legitimate user's call may be reverted.

Tools Used

Recommendations

Adjust the logic in UpliftOnlyExample to prevent adding liquidity to the admin when minBptAmount < _MINIMUM_TRADE_AMOUNT.

Updates

Lead Judging Commences

n0kto Lead Judge 11 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding_onAfterRemoveLiquidity_not_enough_fee_revert

Likelihood: Medium, when fees are below the _MINIMUM_TRADE_AMOUNT. Impact: Low/Medium, DoS of withdrawal but could be mitigated adding funds or waiting for more benefits.

Support

FAQs

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

Give us feedback!