https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-hooks/contracts/hooks-quantamm/UpliftOnlyExample.sol#L431C1-L441C1
The onAfterRemoveLiquidity function burns the user’s LP NFT token and deletes the user’s feeDataArray after removing liquidity. However, this function only checks onlySelfRouter(router) and does not verify whether the caller is the Vault. As a result, any user can directly invoke onAfterRemoveLiquidity, passing in an arbitrary userAddress, and burn someone else’s LP NFT tokens.
Inside onAfterRemoveLiquidity, the contract checks:
The code ensures the caller is the contract itself (onlySelfRouter(router)) but does not verify whether msg.sender is actually the Vault. Consequently, if the external Router address is set to address(this), a malicious user could call this function directly. Since userAddress is just taken from userData (which the attacker can set arbitrarily), the attacker could specify any victim’s address and proceed to burn that victim’s LP NFT token in the loop:
Because burning the LP NFT effectively destroys the holder’s liquidity position, the victim can no longer withdraw or manage that particular stake.
An attacker can force arbitrary users’ LP NFTs to be burned without requiring those users to initiate any transactions themselves. This results in loss of liquidity and potentially unrecoverable funds for the victim since the position tied to the NFT is permanently destroyed. The overall impact is High, as it compromises user funds and can lead to a severe loss of trust in the protocol.
Below is a Foundry test demonstrating how an attacker can directly invoke onAfterRemoveLiquidity to burn Bob’s LP NFT token, preventing Bob from subsequently removing liquidity:
You can add the test script at the bottom of the file pkg/pool-hooks/test/foundry/UpliftExample.t.sol and execute the PoC by running the following command:
Manual Code Review and Foundry
Add an onlyVault modifier (or an equivalent check) that ensures onAfterRemoveLiquidity can only be invoked by the Vault. For example:
This ensures that only the legitimate Vault process can trigger the liquidity removal flow, preventing attackers from arbitrarily burning users’ LP NFTs.
Likelihood: High, anyone, anytime. Impact: High, Loss of funds
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.