When users call the removeLiquidityProportional function, it triggers the onAfterRemoveLiquidity callback, which calculates fees and attempts to add them back to the pool using vault.addLiquidity. If the fees fall below _MINIMUM_TRADE_AMOUNT of the vault, the addLiquidity function reverts, causing the entire liquidity removal process to fail. This unintentionally locks user funds and imposes additional constraints on liquidity providers.
Entry Point: removeLiquidityProportional
This function indirectly triggers the onAfterRemoveLiquidity callback, where the issue arises.
Callback Function: onAfterRemoveLiquidity
This function calculates fees, including the localData.accruedQuantAMMFees and localData.accruedFees, and attempts to reinvest them into the pool via vault.addLiquidity.
When the calculated fee amount (e.g., localData.feeAmount.mulDown(localData.adminFeePercent)) is less than _MINIMUM_TRADE_AMOUNT, the addLiquidity call reverts.
Unintended Consequences:
Users with accrued fees below the threshold cannot successfully remove their liquidity.
The _MINIMUM_TRADE_AMOUNT for removing liquidity becomes indirectly tied to accrued fees, deviating from the globally set value.
Example Scenarios:
minWithdrawalFeeBps = 5 //0.0005%
QuantAMMUpliftFeeTake = 200 //2%
_MINIMUM_TRADE_AMOUNT = 0.5e18
Above test will revert with TradeAmountTooSmall() error from the vault.
As the test above the user is allowed to add 1e18 of each token, but not allowed to removeLiquidty
this is because after calculation, one or both of the fees is below the _MINIMUM_TRADE_AMOUNT of the vault.
Hence for such user to remove liquidity, using the above example scenerio, the user need to add almost 2000e18 of each token. users below who dont add up to this amount cannot remove liquidity.
Note: you can manually set the _MINIMUM_TRADE_AMOUNT in the vault just to test as it is 0 be default
Locked Funds: Users unable to meet the _MINIMUM_TRADE_AMOUNT threshold for fees have their liquidity effectively locked.
Higher Costs: Users are forced to pay more fees than intended by adding more liquidity to complete their removal process.
System Inconsistencies: _MINIMUM_TRADE_AMOUNT behaves differently in the context of fee reinvestment compared to its intended global behavior. This issue forces a new _MINIMUM_TRADE_AMOUNT for liquidity removal to complete
Manual Code Review
Adding liquidity should not go through, if removal will not work with the same amount
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.
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.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.