其他分享
首页 > 其他分享> > UniswapV2周边合约学习(二)-- UniswapV2Router02.sol(上)2020-12-29

UniswapV2周边合约学习(二)-- UniswapV2Router02.sol(上)2020-12-29

作者:互联网

转载自https://blog.csdn.net/weixin_39430411/category_10454309.html

    <div id="article_content" class="article_content clearfix">
    <link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-b5506197d8.css">
            <div id="content_views" class="markdown_views prism-atom-one-dark">
                <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
                    <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
                </svg>
                <blockquote> 

记得朋友圈看到过一句话,如果Defi是以太坊的皇冠,那么Uniswap就是这顶皇冠中的明珠。Uniswap目前已经是V2版本,相对V1,它的功能更加全面优化,然而其合约源码却并不复杂。本文为个人学习UniswapV2源码的系列记录文章。

一、Router合约介绍

UniswapV2的周边合约主要作用是作为用户和核心合约之间的桥梁。也就是用户 => 周边合约 => 核心合约。UniswapV2周边合约主要包含接口定义,工具库和核心实现这三部分,在上一篇文章里已经学习了它的工具库函数,这次我们主要学习其核心实现。

UniswapV2周边合约的核心实现包含UniswapV2Router01.solUniswapV2Router02.sol,这里我们把它简称为Router1Router2。查看它们实现的接口我们可以看到,Router2仅在Router1上多了几个接口。那为什么会有两个路由合约呢,我们到底用哪个呢?查看其官方文档我们可以得到:

Because routers are stateless and do not hold token balances, they can be replaced safely and trustlessly, if necessary. This may happen if more efficient smart contract patterns are discovered, or if additional functionality is desired. For this reason, routers have release numbers, starting at 01. This is currently recommended release, 02.

上面那段话的大致意思就是因为Router合约是无状态的并且不拥有任何代币,因此必要的时候它们可以安全升级。当发现更高效的合约模式或者添加更多的功能时就可能升级它。因为这个原因,Router合约具有版本号,从01开始,当前推荐的版本是02

这段话解释了为什么会有两个Router,那么它们的区别是什么呢?还是来看官方文档:

UniswapV2Router01 should not be used any longer, because of the discovery of a low severity bug and the fact that some methods do not work with tokens that take fees on transfer. The current recommendation is to use UniswapV2Router02.

这段话是讲因为在Router1中发现了一个低风险的bug,并且有些方法不支持使用转移的代币支付手续费,所以不再使用Router1,推荐使用Router2

因此本文也是学习的UniswapV2Router02.sol,它的前半部分主要是流动性供给相关的函数(功能),后半部分主要是交易对资产交换相关的函数(功能)。由于篇幅较长,因此该合约学习计划分为上、下两个部分来学习,内容分别为流动性供给函数和资产交换函数。这次先学习流动性供给部分。

建议对UniswapV2不熟的读者在开始学习之前阅读我的另一篇文章:UniswapV2介绍 来对UniswapV2的整体机制有个大致了解;当然也建议阅读前面的系列文章,特别是核心合约学习部分,这样更有助于理解源码。

UniswapV2周边合约在Github上的地址为: uniswap-v2-periphery

二、源码中的公共部分

UniswapV2Router02.sol源码的公共部分从第一行开始,到回调函数receive结束。主要是导入文件和公共变量定义、函数修饰符及构造器等。

三、源码中的流动性供给部分

四、流动性供给接口分类

源码中流动性供给的外部接口可以按照是提供流动性还是移除流动性分为两大类,然后再根据初始资产/最终得到资产是ETH还是普通ERC20代币做了进一步区分。然后移除流动性还增加了支持链下签名消息授权的接口,最后移除流动性增加了支持使用转移代币支付手续费的接口。

注:下文中的TOKEN均为ERC20代币。

4.1、增加流动性

  1. addLiquidity,增加流动性,提供的初始资产为TOKEN/TOKEN。
  2. addLiquidityETH,增加流动性,提供的初始资产为ETH/TOKEN。

4.2、移除流动性

  1. removeLiquidity,移除流动性,得到的最终资产为TOKEN/TOKEN。
  2. removeLiquidityETH,移除流动性,得到的最终资产为ETH/TOKEN。

4.3、移除流动性,支持使用链下签名消息授权

  1. removeLiquidityWithPermit函数,移除流动性,支持使用链下签名消息授权,得到TOKEN/TOKEN。
  2. removeLiquidityETHWithPermit函数,移除流动性,支持使用链下签名消息授权,得到ETH/TOKEN。

4.4、移除流动性,支持使用转移代币支付手续费

  1. removeLiquidityETHSupportingFeeOnTransferTokens函数,移除流动性,支持使用转移代币支付手续费,得到ETH/TOKEN。

4.5、移除流动性,同时支持使用链下签名消息授权和使用转移代币支付手续费

  1. removeLiquidityETHWithPermitSupportingFeeOnTransferTokens函数。功能同标题,得到ETH/TOKEN。

从上面分类也可以得出一些其它结论。

  1. 增加流动性没有使用链下签名消息授权,为什么呢?因为增加流动性其流动性代币是直接增发,没有使用第三方转移,所以就没有授权操作,不需要permit

  2. 移除流动性时,支付使用转移代币支付手续费最后得到的一种资产为ETH,说明交易对为ERC20/WETH交易对,也就是不支持两个此类代币构成的交易对。原因未知,还需要进一步研究。

  3. 既然移除流动性有使用转移代币支付手续费,那么作为同一个交易对,移除流动性之前必定有增加流动性,因此增加流动性时实际上需要支持此类代币的。但是代码中又没有明确写出支持使用转移代币支付手续费接口。为什么呢?

    个人猜想,未必正确:

    • 是因为此类代币转移过程中有损耗,而损耗多少未知,所以无法精确知道到底要提前转移多少代币到交易对中,在进行按比例计算时会得到预期外的值。所以写此类接口无法向用户返回相关数量值。
    • 如果用户不考虑返回值的话,直接使用addLiquidity或者addLiquidityETH函数是可以对此类代币进行增加流动性操作的。因为交易对计算注入代币的数量时是以交易对合约地址当前代币余额减去交易对合约资产池中的代币余额,和损耗没有任何关系,因此,增发的流动性是准确的。

至此,UniswapV2Router02.sol学习(上)–流动性借给函数的学习就到此结束了,下一次计划学习UniswapV2Router02.sol(下)–资产交易函数的学习。

由于个人能力有限,难免有理解错误或者不正确的地方,还请大家多多留言指正。

标签:函数,UniswapV2Router02,--,代币,sol,WETH,uint,address,合约
来源: https://blog.csdn.net/Tesla_Zhou/article/details/111883053