Submitted by Jeiwan, also found by minhtrng, minhquanym, HE1M, wait, hansfriese, BAHOZ, unforgiven, 0xxm, Junnon, bytehat, UNCHAIN, carlitox477, RaymondFam, Chom, CRYP70, 9svR6w, mauricio1802, __141345__, hihen, caventa, koxuan, obront, nicobevi, shung, cccz, Bobface, and chaduke
Liquidity providers may lose a portion of provided liquidity in either of the pair tokens. While the minLpTokenAmount protects from slippage when adding liquidity, it doesnt protect from providing liquidity at different K.
The Pair contract is designed to receive liquidity from liquidity providers (Pair.sol#L63). First liquidity provider in a pool may provide arbitrary token amounts and set the initial price (Pair.sol#L425-L426), but all other liquidity providers must provide liquidity proportionally to current pool reserves (Pair.sol#L420-L423). Since a pool is made of two tokens and liquidity is provided in both tokens, theres a possibility for a discrepancy: token amounts may be provided in different proportions. When this happens, the smaller of the proportions is chosen to calculate the amount of LP tokens minted (Pair.sol#L420-L423):
As a result, the difference in proportions will create an excess of tokens that wont be redeemable for the amount of LP tokens minted. The excess of tokens gets, basically, donated to the pool: itll be shared among all liquidity providers of the pool. While the minLpTokenAmount argument of the add function (Pair.sol#L63) allows liquidity providers to set the minimal amount of LP tokens they want to receive, it doesnt allow them to minimize the disproportion of token amounts or avoid it at all.
In the add function, consider calculating optimal token amounts based on the amounts specified by user, current pool reserves, and the minimal LP tokens amount specified by user. As a reference, consider this piece from the Uniswap V2 Router: UniswapV2Router02.sol#L45-L60.
outdoteth (Caviar) confirmed and commented:
