QuantAMM

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

Last withdrawer will donate fees to empty pool allowing MEV and having always stuck funds in the pool

Summary

in onAfterRemoveLiquidity() fees of the withdrawn tokens amounts (whatever its upLift or the minimum fees) of the last user withdrawing from the pool will be donated to empty pool.

Vulnerability Details

NOTE!: the bug about accruedQuantAMMFees wrong distribution since Admin don't have position registered in poolsFeeData Is assumed to be solved by sending actual tokens to the admin

in onAfterRemoveLiquidity() The code calculate fees on the withdrawn tokens amounts (whatever its upLift or the minimum fees) and donates part of it to the pool and part of it to the QuantAMM admin, Here:

File: UpliftOnlyExample.sol
function onAfterRemoveLiquidity(
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: })
546: );
547: emit ExitFeeCharged(
548: userAddress,
549: localData.pool,
550: IERC20(localData.pool),
551: localData.feeAmount.mulDown(localData.adminFeePercent) / 1e18
552: );
553: }
554:
555: if (localData.adminFeePercent != 1e18) {
556: // Donates accrued fees back to LPs.
557: _vault.addLiquidity(
558: AddLiquidityParams({
559: pool: localData.pool,
560: to: msg.sender,
561: maxAmountsIn: localData.accruedFees,
562: minBptAmountOut: 0,
563: kind: AddLiquidityKind.DONATION,
564: userData: bytes("")
567: })

But the problem is that There are alot of circumstances where user withdrawing is the last withdrawer of the pool, what happens is:

  1. User will get charged fees, part of it added to the admin (in the correct way) and part of it is donated to the pool

  2. this will create an empty pool that have tokens in it with no corresponding BPT

  3. MEV can immediately add liquidity (to mint BPT) and remove liquidity (burning the BPT and getting the initially deposited tokens Plus the stuck tokens)

  4. The problem is yet that on MEV interactions, they will be charged fees and donated to the again empty pool (after MEV removing liquidity)

  5. This will create some tokens in the end that is never retrievable and always stuck in the pool

The above scenario describes what happens when the first mentioned bug get fixed by sending fees to the admin as actual tokens

Now if they decide to solve it by registering admin fee position in poolsFeeData then

  1. Last withdrawer gets charged fees that part of it mint liquidity to admin, and part of it gets donated to the pool (that now have the admin liquidity, meaning that the admin owns all token Pools)

  2. Admin comes to remove liquidity and he himself will be charged fee that again that of it mint liquidity to admin, and part of it gets donated to the pool

  3. Again and again and again (yet pool will have stuck funds either way after last withdrawer)

Impact

Stuck funds in the pool

Tools Used

Manual Review

Recommendations

if the withdrawer is the last withdrawer (vault supply is 0) send all fees to the admin, or don't charge fees (like any pool does with the last withdrawer, they simply transfer all the balance of the pool to him)

Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational or Gas / Admin is trusted / Pool creation is trusted / User mistake / Suppositions

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelyhood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

Appeal created

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

finding_admin_pay_fees_during_withdrawing

Likelihood: Low/Medium, only impact admin. Impact: Medium, pay the same fees than other people and will collect them later. But admin fees will be decreased because of uplift fees. But this bug won't happen because of H-12: deserves a Low.

finding_Uplift_dead_shares_collect_fees_if_last_LP_withdraw

Likelihood: Low/Medium. Every time the last LP of a pool quits Impact: Medium/High, it will increase the amount of dead shares with the fee amounts (stuck funds).

Support

FAQs

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

Give us feedback!