Uniswapv2流动性addLiquidity源码分析,结合公式和部署结果进行分析 [addLiquidity] [ 2 ]

流动性addLiquidity源码分析,同时结合部署和使用进行分析 [ 2 ]

部署和使用博客

用户调用 addLiquidity 函数

  1. 进入_addLiquidity()函数,获取铸造流动性所需要的tokenA的数量、tokenB的数量
  2. 将tokenA的数量、tokenB的数量转给pair合约
  3. mint流动性给用户
    在这里插入图片描述

1、进入_addLiquidity()函数,获取铸造流动性所需要的tokenA的数量、tokenB的数量

在这里插入图片描述

_addLiquidity()函数

1.1 先调用getReserves函数获取tokenA和tokenB的reserve

在这里插入图片描述

1.2 再调用quote函数,根据 amountADesired 用户希望添加的tokenA金额参数计算出tokenB的需要的数量

quote()函数

公式为: a m o u n t B = ( a m o u n t A × r e s e r v e B ) ÷ r e s e r v e A {amountB = {(amountA \times reserveB) \div reserveA}} amountB=(amountA×reserveB)÷reserveA
在这里插入图片描述

1.3 比较amountOptimal和amountDesired的大小,来决定amountA和amountB

原因:铸造流动币,需要amountA和amountB的比例与reserveA和reserveB的比例一致。

例如: reserveA = 10000 TokenA 和 reserveB = 20000 TokenB
条件1:用户打算存入amountDesired A= 1000,amountDesired B=2200
条件2:用户打算存入amountDesired A= 1200,amountDesired B=2000
根据比例原则,条件1和条件2下都是 amountA=1000,amountB=2000

2、将调用者的amountA个tokenA和amountB个tokenB转移给pair合约

在这里插入图片描述

3、调用pair合约的mint函数铸造Liquidity币

在这里插入图片描述

3.1 首次添加流动性

从源码可以看出首次添加的公式是: L i q u i d i t y = t o k e n 0 A m o u n t × t o k e n 1 A m o u n t − m i n Liquidity={\sqrt{token0Amount \times token1Amount}}-min Liquidity=token0Amount×token1Amount min
而min=1000
在这里插入图片描述
在本例子中,

step1、首次添加token0Amount数量为50个,token1Amount数量为100个,单位是18

因此
L P = 50 ∗ 1 0 18 × 100 ∗ 1 0 18 − 1000 = 70710678118654751440 LP={\sqrt{50*10^{18}\times100*10^{18}}}-1000 =70710678118654751440 LP=501018×1001018 1000=70710678118654751440
owner 持有的 LP 代币数量:70710678118654751440

对比终端输出

在这里插入图片描述

3.2 再次添加流动性

从源码可以看出后续添加的公式是:
在这里插入图片描述

step2、用户再次添加:amountA数量为80个,amountB数量为60个,忽略单位

而系统会根据比例计算真实的添加数量:
amount0:80个amount1:40个 (比例是库存reserveA和reserveB的比)
其中 t o t a l S u p p l y = 70.71 ∗ 1 0 18 , a m o u n t 0 = 80 ∗ 1 0 18 , a m o u n t 1 = 60 ∗ 1 0 18 , r e s e r v e 0 = 100 ∗ 1 0 18 , r e s e r v e 1 = 50 ∗ 1 0 18 totalSupply=70.71*10^{18}, amount0=80*10^{18}, amount1 = 60*10^{18}, reserve0=100*10^{18},reserve1=50*10^{18} totalSupply=70.711018,amount0=801018,amount1=601018,reserve0=1001018reserve1=501018
代入公式可得
L P = m i n ( 56.56 ∗ 1 0 18 , 56.56 ∗ 1 0 18 ) = 56.56 ∗ 1 0 18 LP={min(56.56*10^{18} , 56.56*10^{18}) =56.56*10^{18}} LP=min(56.561018,56.561018)=56.561018
因此owner 的 LP 代币数量 = 70.71 ∗ 1 0 18 + 56.56 ∗ 1 0 18 = 127.27 ∗ 1 0 18 =70.71*10^{18}+56.56*10^{18}=127.27*10^{18} =70.711018+56.561018=127.271018

对比终端输出

在这里插入图片描述

遇到的问题:Error: Transaction reverted: function call to a non-contract account

在这里插入图片描述

解决方法:

用address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB);
替代address pair = IUniswapV2Factory(factory).getPair(tokenA, tokenB);
在这里插入图片描述

错误分析:

通过排查发现是pairFor函数的有问题
在这里插入图片描述

在这里插入图片描述

可以看出,错误是UniswapV2Library合约中的pairFor函数所获得的合约地址与UniswapV2Factory合约中createPair函数所创造的合约地址不一致导致的。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值