QuantAMM

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

fees sent to QuantAMMAdmin is stuck forever as there is no function to retrieve them

Summary

When a user removes liquidity from the pool he pays fees and a portion of the fees is liquidity added back for QuantAMMAdmin

Those funds are stuck in, and can't be removed as there is no mapping or NFT minted for those shares so any attempt to removeliquidity will revert

Vulnerability Details

Here is the call inside onAfterREmoveLiquidity to add fees to quantAMMAdmin

File: UpliftOnlyExample.sol
536: if (localData.adminFeePercent > 0) {
537: _vault.addLiquidity(
538: AddLiquidityParams({
539: pool: localData.pool,
540: to: IUpdateWeightRunner(_updateWeightRunner).getQuantAMMAdmin(),
541: maxAmountsIn: localData.accruedQuantAMMFees,
542: minBptAmountOut: localData.feeAmount.mulDown(localData.adminFeePercent) / 1e18,
543: kind: AddLiquidityKind.PROPORTIONAL,
544: userData: bytes("")
545: })

In removeLiquidityProportional there is a check for the length of poolsFeeData in this case, would be zero and any attempt to remove will revert

File: UpliftOnlyExample.sol
265: function removeLiquidityProportional(
266: uint256 bptAmountIn,
267: uint256[] memory minAmountsOut,
268: bool wethIsEth,
269: address pool
270: ) external payable saveSender(msg.sender) returns (uint256[] memory amountsOut) {
271: uint depositLength = poolsFeeData[pool][msg.sender].length;
272:
273: if (depositLength == 0) {
274: revert WithdrawalByNonOwner(msg.sender, pool, bptAmountIn);
275: }

POC

Add this anywhere in UpliftExample.t.sol

function testRemoveLiquidity_Stuck_Admin_Fees() public {
vm.prank(address(vaultAdmin));
updateWeightRunner.setQuantAMMUpliftFeeTake(0.5e18);
vm.stopPrank();
// Add liquidity so bob has BPT to remove liquidity.
uint256[] memory maxAmountsIn = [dai.balanceOf(bob), usdc.balanceOf(bob)].toMemoryArray();
vm.prank(bob);
upliftOnlyRouter.addLiquidityProportional(pool, maxAmountsIn, bptAmount, false, bytes(""));
vm.stopPrank();
uint256[] memory minAmountsOut = [uint256(0), uint256(0)].toMemoryArray();
vm.startPrank(bob);
upliftOnlyRouter.removeLiquidityProportional(bptAmount, minAmountsOut, false, pool);
vm.stopPrank();
BaseVaultTest.Balances memory balancesAfter = getBalances(updateWeightRunner.getQuantAMMAdmin());
//trying to remove liquidity added to QuantAMMAdmin with the value added from bob removing liquidity the remove attempt will revert with `WithdrawalByNonOwner` error
vm.prank(updateWeightRunner.getQuantAMMAdmin());
vm.expectRevert();
upliftOnlyRouter.removeLiquidityProportional(500000000000000000, minAmountsOut, false, pool);
vm.stopPrank();
}

Impact

  • Loss of Funds: Fees added as liquidity for QuantAMMAdmin are stuck and cannot be removed.

Tools Used

manual review

Recommendations

  • create a new array while creating as done for normal addition

Updates

Lead Judging Commences

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

finding_Uplift_admin_cannot_withdraw_without_nft

Likelihood: High, won’t be able to withdraw. Impact: High, funds stuck.

Support

FAQs

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

Give us feedback!