Uniswapv2代币交换swap源码分析,结合公式和部署结果进行分析 [swap] [ 3 ]

代币交换swap源码分析,同时结合部署和使用进行分析 [ 3 ]

部署和使用博客
https://blog.csdn.net/weixin_43458715/article/details/141711985

swapExactTokensForTokens函数分析

在这里插入图片描述

1、 通过getAmountsOut函数获取swap所需要的token数量

在这里插入图片描述
从源码可以得出获取输出金额公式:
a m o u n t O u t = a m o u n t I n × 997 × r e s e r v e O u t r e s e r v e I n × 1000 + a m o u n t I n × 997 { amountOut=\frac{amountIn\times997 \times reserveOut }{reserveIn \times1000+amountIn\times997}} amountOut=reserveIn×1000+amountIn×997amountIn×997×reserveOut
公式来源:
a m o u n t I n × 0.997 ( F e e ) × a m o u n t O u t = r e s e r v e I n × r e s e r v e O u t = k amountIn \times 0.997(Fee) \times amountOut=reserveIn \times reserveOut =k amountIn×0.997(Fee)×amountOut=reserveIn×reserveOut=k
a m o u n t O u t = 90 ∗ 1 0 18 × 997 × 100 ∗ 1 0 18 180 ∗ 1 0 18 × 1000 + 997 × 100 ∗ 1 0 18 = 8973 ∗ 1 0 19 2797 amountOut = \frac{90*10^{18} \times 997 \times 100*10^{18} }{180*10^{18} \times 1000+997 \times 100*10^{18}}= \frac{8973*10^{19}}{2797} amountOut=1801018×1000+997×1001018901018×997×1001018=279789731019
a m o u n t O u t = 32080800858062209510 amountOut = 32080800858062209510 amountOut=32080800858062209510

2、将amountIn数量的token转给pair合约,可以理解为用户付款

在这里插入图片描述

3、 _swap()函数

在这里插入图片描述

3.1 根据输入代币和输出代币的关系,确定具体的输出数量(amount0Out和amount1Out)

a m o u n t 0 O u t = 32080800858062209510 , a m o u n t 1 O u t = 0 amount0Out=32080800858062209510,amount1Out=0 amount0Out=32080800858062209510amount1Out=0

3.2 swap函数,执行交换操作

将amountOut数量的token从pair转出给调用者,可以理解为用户支付所获的的,其中有0、1两个是为了区分,是token0换token1,还是token1换token0
在这里插入图片描述
在这里插入图片描述

1. 获取swap完成后的token0和token1的余额

r e s e r v e 0 = 90 ∗ 1 0 18 , r e s e r v e 1 = 180 ∗ 1 0 18 reserve0=90*10^{18},reserve1=180*10^{18} reserve0=901018reserve1=1801018
a m o u n t 0 O u t = 32080800858062209510 , a m o u n t 1 O u t = 0 amount0Out=32080800858062209510,amount1Out=0 amount0Out=32080800858062209510amount1Out=0
b a l a n c e 0 = 57919199141937790490 , b a l a n c e 1 = 280 ∗ 1 0 18 balance0= 57919199141937790490,balance1=280*10^{18} balance0=57919199141937790490balance1=2801018

2. 计算输入代币的数量

b a l a n c e 0 ! > r e s e r v e 0 − a m o u n t 0 O u t = > a m o u n t 0 I n = 0 balance0 !> reserve0-amount0Out => amount0In=0 balance0!>reserve0amount0Out=>amount0In=0
b a l a n c e 1 > r e s e r v e 1 a m o u n t 1 O u t = > a m o u n t 1 I n = 100 ∗ 1 0 18 balance1 > reserve1amount1Out => amount1In=100*10^{18} balance1>reserve1amount1Out=>amount1In=1001018

3. 计算调整后的余额,代码通过从代币的交易额中扣除0.3%的交易费用来调整,这样做是为了确保费用在池中的表现是一致的。

b a l a n c e 0 A d j u s t e d = b a l a n c e 0 ∗ 1000 − a m o u n t 0 I n ∗ 3 = 57919199141937790490000 balance0Adjusted = balance0*1000 - amount0In*3=57919199141937790490000 balance0Adjusted=balance01000amount0In3=57919199141937790490000
b a l a n c e 1 A d j u s t e d = b a l a n c e 1 ∗ 1000 − a m o u n t 1 I n ∗ 3 = 279700 ∗ 1 0 18 balance1Adjusted = balance1*1000 - amount1In*3=279700*10^{18} balance1Adjusted=balance11000amount1In3=2797001018
在这里插入图片描述

不用amountOut,选择amountIn的原因:
假设用户用tokenA类型换tokenB类型
在pair合约中,tokenB所减少的金额已经是扣除手续费后的金额,而tokenA类型增加的金额没有处理手续费,这样手续费就留在了流动池里,因此而奖励了流动性提供者。(可以参考本文最后的TIPS)

4. 保持K值不变: 使用require语句确保交易后的调整余额乘积不小于交易前的储备乘积

K 1 = b a l a n c e 0 A d j u s t e d ∗ b a l a n c e 1 A d j u s t e d = 16200000000000000000053 ∗ 1 0 24 K_1=balance0Adjusted*balance1Adjusted=16200000000000000000053*10^{24} K1=balance0Adjustedbalance1Adjusted=162000000000000000000531024
K = r e s e r v e 0 ∗ r e s e r v e 1 = 16200000000000000 ∗ 1 0 24 K=reserve0*reserve1=16200000000000000*10^{24} K=reserve0reserve1=162000000000000001024
K 1 > K K_1>K K1>K

分析终端输出

swap前owner的
kokoCoin: 1820 ∗ 1 0 18 1820*10^{18} 18201018
acCoin: 2910 ∗ 1 0 18 2910*10^{18} 29101018

swap后owner的
kokoCoin: 1820 ∗ 1 0 18 − 100 ∗ 1 0 18 ( a m o u n t I n ) = 1720 ∗ 1 0 18 1820*10^{18}-100*10^{18}(amountIn)=1720*10^{18} 182010181001018(amountIn)=17201018
acCoin: 2910 ∗ 1 0 18 + 32080800858062209510 ( a m o u n t O u t ) = 2942080800858062209510 2910*10^{18}+32080800858062209510(amountOut)=2942080800858062209510 29101018+32080800858062209510(amountOut)=2942080800858062209510
tip:需要注意一下pair的地址有进行排序,因此pair存储量的前者为acToken,后者为kokoToken
在这里插入图片描述

TIPS:
当一个交易发生时,交易中涉及的代币的数量将根据 0.3% 的费率从交易者手中扣除。
这部分手续费直接加到流动性池中对应的代币储备里。这意味着流动性池的大小会随每笔交易逐渐增加。
流动性提供者在加入流动性池时会获得代表其份额的流动性代币(例如 LP 代币)。
随着手续费的累积,流动性池中的资金增加,但流动性代币的总供应量保持不变。
结果是每个流动性代币代表的底层资产(即流动性池中的代币)增多,增加了流动性代币的价值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值