When a liquidity provider adds funds through the UpliftOnlyExample router, they are minted an NFT that represents their position. This NFT can be transferred to another address, allowing the recipient to take ownership of the position. However, it is not enough to simply transfer ownership of the NFT; the internal data must also be updated. To handle this, the UpliftOnlyExample.afterUpdate() function is implemented to perform these updates. The problem is that due to incorrect implementation, a user can transfer their NFT to another address and thereby avoid paying the uplift fees.
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-hooks/contracts/hooks-quantamm/UpliftOnlyExample.sol#L609
Let’s take a closer look at the afterUpdate() function. First, it calculates the current value of the LP token and then locates the corresponding record for that token Id in the feeDataArray. In this record, the lpTokenDepositValue is updated to the newly calculated value, and upliftFeeBps is set to the current fee. This record is then added to the recipient's list of fee data. At the same time, the sender's record is deleted, and the remaining elements are shifted, which could be a costly operation. However, for the purposes of the attack, the attacker can construct a minimal-length array to avoid this cost.
The core issue is that updating the lpTokenDepositValue effectively resets the owed uplift fees to zero, even if the LP token value has significantly increased. As a result, an attacker can transfer their position to another address right before withdrawing liquidity to bypass paying high uplift fees. This transfer operation is not costly if executed as described above.
Loss of funds for the protocol due to unpaid uplift fees.
Profit for the user who avoids paying the uplift fee.
Manual review
The lpTokenDepositValue should not be updated during a transfer. Alternatively, any outstanding uplift fees should be charged at the time of transfer.
Likelihood: High, any transfer will trigger the bug. Impact: High, will update lpTokenDepositValue to the new current value without taking fees on profit.
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.