QuantAMM

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

Anyone can transfer lpNFT to himself to avoid paying fees when withdrawing funds

Summary

In Quantamm, when a user deposit tokens into a pool by calling UpliftOnlyExample::addLiquidityProportional() a NFT is minted to reflect this deposit. When a user try to withdraw his funds, UpliftOnlyExample::onAfterRemoveLiquidity() hook is called and is responsible to manage fees for the position withdrawn.

The issue is before removing liquidity, a user can send the NFT to himself to trigger lpNFT::update which call UpliftOnlyExample::afterUpdate(). afterUpdate is responsible for changing the NFT owner tracked in UpliftOnlyExample, the problem is that it also update the price when depositing.
The fees are supposedly calculated depending on the delta between price when depositing and price when withdrawing
This means that any user can avoid paying protocol and pool owner fees.

Vulnerability Details

  • A user with addressA deposit tokens into a pool, lpTokenDepositValue = 100, mint nft with those values :

poolsFeeData[pool1][addressA] = FeeData({
uint256 tokenID: 1
uint256 amount : 1
uint256 lpTokenDepositValue: 100
uint40 blockTimestampDeposit : timestamp1
uint64 upliftFeeBps: 100
})

He gets his NFT and deposit.

  • Time pass, pool accrued value and now lpTokenDepositValue = 200. User call transferof ERC721 lpNFT to himself. It trigger the overridden update which call afterUpdate and update the nft value to :

poolsFeeData[pool1][addressA] = FeeData({
uint256 tokenID: 1
uint256 amount : 1
uint256 lpTokenDepositValue: 200
uint40 blockTimestampDeposit : timestamp2
uint64 upliftFeeBps: 100
})

There is a reordering of array that simply deletes the last entry and update with the new generated one when _to = _from. Note that this miss of fees also happens if userA send his NFT to userB.

  • User can now withdraw and because lpTokenDepositValue = lpTokenDepositValueNow there is no fee to pay, or just the minimum if configured.

Impact

When a user send a NFT to himself or another one, price is updated without taking any fees. Loss of fees for the protocol and pool owner. Pool owner will be decentivize to maintain pool and protocol will suffer heavy loss of revenu.

Tools Used

Manual

Recommendations

Add fee logic when a NFT is transferred, or block the transferability of NFT.

Updates

Lead Judging Commences

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

finding_afterUpdate_bypass_fee_collection_updating_the_deposited_value

Likelihood: High, any transfer will trigger the bug. Impact: High, will update lpTokenDepositValue to the new current value without taking fees on profit.

Support

FAQs

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