in UpliftOnlyExample::onAfterRemoveLiquidity() absent access control to only allow the vault calls opens up a path to cause loss of funds to LP providers by an attacker calling to with victim address to burn the victim NFTs
onAfterRemoveLiquidity is not access controlled and can be called by any one as long as the passed router is the UpliftOnlyExample it self, which is false access control guard.
Also the function takes the user address that his NFT will be burnt as a passed variable.
What makes it worse is that LPNFT::Burn() doesn't have checks for tokens approvals or ownership, so UpliftOnlyExample can burn any user NFT
Here is what can happen:
1- Attacker calls Unlock() on balancerV3 vault to have a transient unlock of the vault for the txn
2- Attacker calls onAfterRemoveLiquidity after calling unlock passing the:
router as UpliftOnlyExample to pass the onlySelfRouter modifier
userData to be the victim address
bptAmountIn to be the balance registered in poolsFeeData for the victim
3- The NFTs of the victim will be burnt due to this block
4- Attacker will need to call settle() to settle debt taken from the UpliftOnlyExample call to addLiquidity() (the fee distribution Logic)
The loss for attacker is very smaller (fees of minimumSwapFees or UpLiftFee) compared to the complete loss of funds for the victim, since users can only retrieve funds throughremoveLiquidityProportional by their NFT and the poolsFeeData
Complete loss of funds
Manual Review
Add OnlyVault modifier
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.