QuantAMM

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

Unhability of removing fees accounted to the quantAMM admin

Summary

The quant amm admin will be unable to withdraw accounted fees because no nfts are registered to him

Vulnerability Details

When someone removes liquidity, the onAfterRemoveLiquidity hook is called in the UpliftOnlyExample. This function computes a fee based on the amount that the user wants to remove and differentiates 2 fees. The first fee is the quant amm admin fee. This fee is set in the UpdateWeightRunner and it is a percentage. This percentage will be taken from the whole fee and will be added as liquidity for the admin address:

if (localData.adminFeePercent > 0) {
_vault.addLiquidity(
AddLiquidityParams({
pool: localData.pool,
to: IUpdateWeightRunner(_updateWeightRunner).getQuantAMMAdmin(),
maxAmountsIn: localData.accruedQuantAMMFees,
minBptAmountOut: localData.feeAmount.mulDown(localData.adminFeePercent) / 1e18,
kind: AddLiquidityKind.PROPORTIONAL,
userData: bytes("")
})
);
emit ExitFeeCharged(
userAddress,
localData.pool,
IERC20(localData.pool),
localData.feeAmount.mulDown(localData.adminFeePercent) / 1e18
);
}

The rest of the fee is donated to the pool which will be distributed among LPs.
The problem is that this liquidity is added on behalf of the quant admin but without calling the addLiquidityProportional function. What this function does is the creation of nfts representing the positions in order to compute fees later on. Hence, the quant amm admin will receive BPT from the pool but without any nft minted to him.
If he wants to remove this liquidity from the pool, he will only be able to call the removeLiquidityProportional because is the only supported method to remove liquidity from the allowed router.

function removeLiquidityProportional(
uint256 bptAmountIn,
uint256[] memory minAmountsOut,
bool wethIsEth,
address pool
) external payable saveSender(msg.sender) returns (uint256[] memory amountsOut) {
uint depositLength = poolsFeeData[pool][msg.sender].length;
if (depositLength == 0) {
revert WithdrawalByNonOwner(msg.sender, pool, bptAmountIn);
}
// Do removeLiquidity operation - tokens sent to msg.sender.
amountsOut = _removeLiquidityProportional(
pool,
address(this),
msg.sender,
bptAmountIn,
minAmountsOut,
wethIsEth,
abi.encodePacked(msg.sender)
);
}

As we can see it ensures that the user has some nfts registered to his account, but in this case it will not have any. So the end result will be the quant amm having his fees locked

Impact

High, lose of funds and high likelihood

Tools Used

Manual review

Recommendations

It has no trivial solution, but maybe registering the nft for the quant amm admin could be a solution

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.