In Uniswap V2, the first liquidity provider must receive sqrt(amountA×amountB) − MINIMUM_LIQUIDITY
(and the contract permanently burns MINIMUM_LIQUIDITY
to lock it).
Every subsequent provider must receive min(amountA×totalSupply/reserveA , amountB×totalSupply/reserveB) .
Likelihood:
When the pool is brand‐new (total LP supply == 0), the code mints √(A·B)
instead of √(A·B) – MINIMUM_LIQUIDITY
; there is no branch distinguishing “first provider” from “subsequent provider.”
Any time total_lp > 0
(pool already has liquidity), callers still get √(A·B)
, which is not proportional to existing reserves. This occurs on every non‐initial provide_liquidity
call.
Impact:
Initial LP: The very first liquidity provider receives too many LP tokens (they should have seen MINIMUM_LIQUIDITY
locked forever). That permanently breaks the invariants of total supply and can allow economic exploits later.
Subsequent LPs: Every subsequent provider receives an incorrect number of LP tokens—often far larger than their fair share—leading to severe dilution of existing LPs and potential loss of value.
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.