Solidity Uniswap V2 Router contract addLiquidity

这篇具有很好参考价值的文章主要介绍了Solidity Uniswap V2 Router contract addLiquidity。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        router 合约是一种高级合约,是大多数用户应用程序的入口点。通过该合约,可以更轻松地创建交易对、添加和删除流动性、计算交换中的价格变化以及执行交换。Router 适用于通过工厂合约部署的所有交易对,是一种通用合约。

GitHub - XuHugo/solidityproject: DApp go go go !!!

        它也是一个非常大的合约,我们可能不会实现它的所有功能,因为其中大部分都是交换功能的变形。让我们看看路由器的构造函数:路由器可以部署pair,因此它需要知道工厂合约的地址。

contract ZuniswapV2Router {

    error InsufficientAAmount();

    error InsufficientBAmount();

    error SafeTransferFailed();



    IZuniswapV2Factory factory;



    constructor(address factoryAddress) {

        factory = IZuniswapV2Factory(factoryAddress);

    }

    ...

        今天,我们只实现流动性管理的一部分,让我们从 addLiquidity 开始:

function addLiquidity(

    address tokenA,

    address tokenB,

    uint256 amountADesired,

    uint256 amountBDesired,

    uint256 amountAMin,

    uint256 amountBMin,

    address to

)

    public

    returns (

        uint256 amountA,

        uint256 amountB,

        uint256 liquidity

    )

    ...

        与pair合约中的mint函数相比,该函数有很多参数!

        1、tokenA 和 tokenB 用于查找(或创建)我们希望增加流动性的货币对。

        2、amountADesired 和 amountBDesired 是我们希望存入货币对的金额。这些是上限。

        3、amountAMin 和 amountBMin 是我们希望存入的最小金额。还记得当我们存入不平衡的流动性时,pair合约总是发行较少的 LP-Token吗?。因此,最小参数允许我们控制准备损失多少流动性。

        4、to 地址是接收 LP-Token的地址。

...

if (factory.pairs(tokenA, tokenB) == address(0)) {

    factory.createPair(tokenA, tokenB);

}

...

        如果指定的ERC20 Token没有pair合约,它将由router 合约创建。 factory.pairs方法是pairs映射,由于映射是嵌套的,Solidity 为该辅助方法设置了两个参数。

...

(amountA, amountB) = _calculateLiquidity(

    tokenA,

    tokenB,

    amountADesired,

    amountBDesired,

    amountAMin,

    amountBMin

);

...

        下一步,我们将计算将存入的金额。稍后我们将回到这个函数。

...

address pairAddress = ZuniswapV2Library.pairFor(

    address(factory),

    tokenA,

    tokenB

);

_safeTransferFrom(tokenA, msg.sender, pairAddress, amountA);

_safeTransferFrom(tokenB, msg.sender, pairAddress, amountB);

liquidity = IZuniswapV2Pair(pairAddress).mint(to);

...

        计算完流动性金额后,我们就可以从用户处转移token,并铸造 LP-token作为交换。除了 pairFor 函数之外,这些代码中的大部分你都应该很熟悉了,我们将在实现 _calculateLiquidity 之后立即实现它。此外,请注意该合约并不希望用户手动转移代币,而是使用 ERC20 transferFrom 函数从用户余额中转移代币。

function _calculateLiquidity(

    address tokenA,

    address tokenB,

    uint256 amountADesired,

    uint256 amountBDesired,

    uint256 amountAMin,

    uint256 amountBMin

) internal returns (uint256 amountA, uint256 amountB) {

    (uint256 reserveA, uint256 reserveB) = ZuniswapV2Library.getReserves(

        address(factory),

        tokenA,

        tokenB

    );



    ...

        在这个函数中,我们要找到满足我们所需和最低金额的流动性金额。由于从我们在用户界面选择流动性金额到我们的交易被处理之间存在延迟,实际reserve比率可能会发生变化,这将导致我们损失一些 LP-token(作为对存入不平衡流动性的惩罚)。通过选择所需的最小金额,我们可以最大限度地减少这种损失。

        该功能的第一步是通过使用库合约获取池储备,我们下次就会实现这一点。得到了reserve,我们就可以计算出最佳流动性金额

...

if (reserveA == 0 && reserveB == 0) {

    (amountA, amountB) = (amountADesired, amountBDesired);

...

        如果储备金是空的,那么这是一对新的货币对,这意味着我们的流动性将决定储备金比率,这意味着我们不会因为提供不平衡的流动性而受到惩罚。因此,我们可以存入所需的全额资金。

...

} else {

    uint256 amountBOptimal = ZuniswapV2Library.quote(

        amountADesired,

        reserveA,

        reserveB

    );

    if (amountBOptimal <= amountBDesired) {

        if (amountBOptimal <= amountBMin) revert InsufficientBAmount();

        (amountA, amountB) = (amountADesired, amountBOptimal);

...

        否则,我们需要找到最优数量,我们从找到最优tokenB数量开始。报价是库合约中的另一个函数:通过输入金额和配对储备金,计算输出金额,即tokenA 的价格乘以token B 的输入金额。

        如果amountBOptimal 小于或等于我们的期望金额,并且高于我们的最小金额,则使用该金额。期望金额和最小金额之间的差额可以防止滑点。

        但是,如果最优金额BOptimal 大于我们的期望金额,则不能使用,我们需要找到另一个最优金额 A。

...

} else {

    uint256 amountAOptimal = ZuniswapV2Library.quote(

        amountBDesired,

        reserveB,

        reserveA

    );

    assert(amountAOptimal <= amountADesired);



    if (amountAOptimal <= amountAMin) revert InsufficientAAmount();

    (amountA, amountB) = (amountAOptimal, amountBDesired);

}

        使用相同的逻辑,我们可以找到 amountAOptimal:它也必须在我们的最小期望范围内。文章来源地址https://www.toymoban.com/news/detail-859587.html

到了这里,关于Solidity Uniswap V2 Router contract addLiquidity的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【区块链 | Solidity】跟我学 Solidity(7):事件

    如何使用事件记录数据 原文: https://medium.com/better-programming/learn-solidity-events-2801d6a99a92 作者: wissal haji 欢迎订阅《Solidity智能合约零基础开发教程专栏》系列文章。 在今天的文章中,我们将看到如何使用web3.js从区块链中读取事件。 Solidity中的事件就像你习惯于使用其他语

    2024年01月25日
    浏览(54)
  • solidity函数签名的实现-solidity实现智能合约教程(8)

    猛戳订阅学习专栏🍁🍁 👉 solidity系列合约源码+解析 👈 🍁🍁 函数选择器: solidity调用函数时,calldata的前4个字节为指定要调用的函数,这4个字节称为函数选择器。 以下面的代码为例。它通过地址addr的调用合约的transfer方法。 abi.encodeWithSignature(…)返回的前4个字节是函数

    2024年02月16日
    浏览(53)
  • 【Solidity】Solidity Keccak256 与 SHA3-256

    Solidity Keccak256 与 SHA3-256 区块链的造富神话大家一定都有所耳闻,今天我们讨论以太坊中一项基础技术,主打一个一学就会。 看过以太坊源码或者对区块链有了解的的同学,一定都见过一个哈希算法 Keccak256 。 Keccak256 可以称它是以太坊中第一函数。 那 Keccak256 和 SHA3-256 有什

    2024年02月07日
    浏览(72)
  • 【区块链 | Solidity】Solidity开发教程:用Web3.js构建第一个Dapp

    Web3.js 使用的实用介绍 原文 作者:wissal haji 欢迎订阅《Solidity智能合约零基础开发教程专栏》系列文章。 如果你一直在跟着这个系列学习,那么你已经掌握了编写自己的智能合约。 因此,今天给大家介绍一下构建去中心化应用的全貌,并向大家介绍一下web3.js,这是构建da

    2024年01月24日
    浏览(53)
  • 【solidity三】Solidity中继承、创建合约和外部调用、合约事件event、solidity中元祖的使用、new、delete关键字的使用、solisity创建合约和外部调用

    - 最重要的两个全局变量 msg.sender 每一次和以太坊交互时都会产生一笔交易,这笔交易的执行人就是msg.sender。简而言之:谁调用的,msg.sender就是谁,每笔交易的msg.sender都可以不同。举例: 部署合约的时候,msg.sender就是部署的账户。 调用setMessage时,msg.sender就是调用账户。

    2024年02月03日
    浏览(46)
  • Solidity 构造函数的理解

    构造函数的理解 solidity solidity构造函数指的是在合约部署的时候自动执行,如果在其他合约通过new等方式来实列化合约,则构造函数不会执行 其他高级语言 常用的编程语言java、go、python等高级语言,实列化对象时都会执行其构造函数。 总结 构造函数执行逻辑不一致,solid

    2024年02月11日
    浏览(40)
  • Solidity – 数组

    数组是存储相同数据类型元素的固定集合的数据结构,其中每个元素都有一个称为索引的特定位置。我们不需要创建大量相同类型的单独变量,而是声明一个所需大小的数组并将元素存储在数组中,并且可以使用索引进行访问。在 Solidity 中,数组可以是固定大小或动态大小。

    2023年04月25日
    浏览(11)
  • Solidity 代码执行漏洞原理

    目录 1. 三种 call 方式 2. 两种 call 参数类型 3. 漏洞场景 3.1 delegatecall 3.2 call Solidity 中一个合约调用其他合约的函数有三种方式: 1)call() call 是最常用的调用方式,call 的外部调用上下文是 被调用者合约 ,也就是指执行环境为被调用者的运行环境,调用后内置变量 msg 的值会

    2024年02月03日
    浏览(42)
  • Solidity 智能合约入门

    将一个数据放置在链上 我们对代码进行逐行分析,首先第一行 第一行表明此段代码是被GPL-3.0所授权。默认情况下,在发布源代码时加入机器可读许可证说明是很重要的。 GPL(GNU General Public License Versions) GPL协议一般还可以分为GPL2.0和GPL3.0两种,而GPL3.0是更新一代的开源标准

    2024年02月02日
    浏览(47)
  • Solidity编写合约

     consider是用来声明合约的,conter是声明的合约的名称。  合约是可部署到区块链的最小单元, 一个合约通常由 状态变量(合约数据) 和 合约函数 组成 它的含义是使用大于等于 0.8.0  版本的编译编译  Counter  合约。类似的表示还有:         合约本身也是一个数据类型

    2024年02月22日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包