您当前的位置: 首页 > 

33357

暂无认证

  • 2浏览

    0关注

    25博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Uniswap-v2 Router合约分析(上)

33357 发布时间:2022-02-20 22:13:56 ,浏览量:2

原文发布在 https://github.com/33357/smartcontract-apps这是一个面向中文社区,分析市面上智能合约应用的架构与实现的仓库。欢迎关注开源知识项目!

Uniswap-v2 Router合约分析

Router 合约是用户使用 Uniswap-v2 进行交换直接调用的合约,通过分析它可以深入了解 Uniswap-v2 的产品使用和运行逻辑。

演示代码仓库:https://github.com/33357/uniswap-v2-contract,这里使用的是Router02。

增加流动性
  • 内部函数(仅供合约内部调用)

    • _addLiquidity
      • 代码速浏览

        function _addLiquidity(
            address tokenA,
            address tokenB,
            uint amountADesired,
            uint amountBDesired,
            uint amountAMin,
            uint amountBMin
        ) internal virtual returns (uint amountA, uint amountB) {
            if (IUniswapV2Factory(factory).getPair(tokenA, tokenB) == address(0)) {
                IUniswapV2Factory(factory).createPair(tokenA, tokenB);
            }
            (uint reserveA, uint reserveB) = UniswapV2Library.getReserves(factory, tokenA, tokenB);
            if (reserveA == 0 && reserveB == 0) {
                (amountA, amountB) = (amountADesired, amountBDesired);
            } else {
                uint amountBOptimal = UniswapV2Library.quote(amountADesired, reserveA, reserveB);
                if (amountBOptimal = amountBMin, 'UniswapV2Router: INSUFFICIENT_B_AMOUNT');
                    (amountA, amountB) = (amountADesired, amountBOptimal);
                } else {
                    uint amountAOptimal = UniswapV2Library.quote(amountBDesired, reserveB, reserveA);
                    assert(amountAOptimal = amountAMin, 'UniswapV2Router: INSUFFICIENT_A_AMOUNT');
                    (amountA, amountB) = (amountAOptimal, amountBDesired);
                }
            }
        }
        
      • 参数分析

        函数 _addLiquidity 的入参有6个,出参有2个,对应的解释如下:

        function _addLiquidity(
            address tokenA, // 添加流动性 tokenA 的地址
            address tokenB, // 添加流动性 tokenB 的地址
            uint amountADesired, // 期望添加 tokenA 的数量
            uint amountBDesired, // 期望添加 tokenB 的数量
            uint amountAMin, // 添加 tokenA 的最小数量
            uint amountBMin // 添加 tokenB 的最小数量
        ) internal virtual returns (
            uint amountA, // 实际添加 tokenA 的数量
            uint amountB // 实际添加 tokenB 的数量
            ) {
                ...
        }
        

        tokenAtokenB 很好理解,但是为什么要有 amountADesiredamountADesiredamountAMinamountBMin 呢?实际上因为用户在区块链上添加流动性并不是实时完成的,因此会因为其他用户的操作产生数据偏差,因此需要在这里指定一个为 tokenAtokenB 添加流动性的数值范围。在添加流动性的过程中,首先会根据 amountADesired 计算出实际要添加的 amountB,如果 amountB 大于 amountBDesired 就换成根据 amountBDesired 计算出实际要添加的 amountA

      • 实现分析

        ...
        {
            // 如果 tokenA,tokenB 的流动池不存在,就创建流动池
            if (IUniswapV2Factory(factory).getPair(tokenA, tokenB) == address(0)) {
                IUniswapV2Factory(factory).createPair(tokenA, tokenB);
            }
            // 获取 tokenA,tokenB 的目前库存数量
            (uint reserveA, uint reserveB) = UniswapV2Library.getReserves(factory, tokenA, tokenB);
            if (reserveA == 0 && reserveB == 0) {
                // 如果库存数量为0,也就是新建 tokenA,tokenB 的流动池,那么实际添加的amountA, amountB 就是 amountADesired 和 amountBDesired
                (amountA, amountB) = (amountADesired, amountBDesired);
            } else {
                // reserveA*reserveB/amountADesired,算出实际要添加的 tokenB 数量 amountBOptimal
                uint amountBOptimal = UniswapV2Library.quote(amountADesired, reserveA, reserveB);
                if (amountBOptimal             
关注
打赏
1654608207
查看更多评论
0.0567s