I have the next code to get familiar with uniswap mechanics:
getAmountsOut
and provide all UNI token reserves const pairAddress = await _V2Factory.getPair(uniToken, wethToken);
const pairContract = new ethers.Contract(
pairAddress,
IUniswapV2Pair.abi,
_provider
);
const tmpReserves = await pairContract.getReserves();
const reserves = [reserves.reserve0, reserves.reserve1];
console.log("reserves", reserves);
const output = await router.getAmountsOut(reserves[0], [
uniToken.address,
wethToken.address,
]);
console.log("output", output);
Output is:
[ 36851089197799104779745113323n, 281312509765248795074n ]
[ 36851089197799104779745113323n, 140444953548298972803n ]
The question is why I do not receive as the second element of output
array equals to 281312509765248795074n
- the full WETH
liquidity in pair but just part of liquidity equals to 140444953548298972803n
value?
I'm running local hardhat node and 3-rd parties actions should not affect the result. I tried on mainnet as well, obviously results are the same.
Tried also switch from getAmountsOut
to getAmountOut
, but it behaves the same way:
const output2 = await router.getAmountOut(
reserves[0],
reserves[0],
reserves[1]
);
console.log("output2", output2);
output: 143271499822164119007n
Uniswap and other constant product automated market makers (AMM) use the following invariant for each pool:
Where x
and y
are the amounts of the tokens in the pool and k
is a constant.
The function getAmountsOut
simulates a trade in the pool. After any trade, x
and y
changes, but the invariant still holds:
If you call getAmountsOut
with x
as the parameter, you essentially ask (ignoring the swap fees for a moment) "how much y
would I get if I doubled x
in the pool?" Then x' = 2x
and the invariant is:
Solving it for y'
you get y' = y / 2
balances in the pool. The expected output from this trade is y - y'
, which is again equal to y / 2
and approximately matches your output. Incidentally, this trade would also push up the price in the pool 4 times, since price is defined as y/x
.
In the real code, the result is slightly different, since:
x
before the trade is made.