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)publicreturns (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:它也必须在我们的最小期望范围内。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/746303.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux-TCP并发模型相关函数接口-014

1【TCP】多线程模型 相关函数接口已在前面章节介绍&#xff0c;这里不再赘述源码示例&#xff08;1&#xff09;&#xff1a; //【client.c】 int CreateTcpClient(char *pip, int port) {int ret 0;int sockfd 0;struct sockaddr_in seraddr;sockfd socket(AF_INET, SOCK…

Nginx:配置拦截/禁用ip地址

分析nginx日志 1、分析截止目前为止访问量最高的ip排行 awk {print $1} access.log |sort |uniq -c|sort -nr |head -20过滤出access.log日志文件中访问量前20的ip sort &#xff1a;将文件进行排序&#xff0c;并将排序结果标准输出uniq -nr &#xff1a; 去重并在右边显示…

第110讲:Mycat实践指南:指定Hash算法分片下的水平分表详解

文章目录 1.应用指定Hash算法分片的概念2.使用应用指定Hash算法分片对某张表进行水平拆分2.1.在所有的分片节点中创建表结构2.2.配置Mycat实现应用指定Hash算法分片的水平分表2.2.1.配置Schema配置文件2.2.2.配置Rule分片规则配置文件2.2.3.配置Server配置文件2.2.4.重启Mycat …

前置机的使用以及个跳板机介绍

前言 前置机、网闸和摆渡机都是为了内网安全&#xff0c;尤其是银行、券商、电信运营商等的内网核心后台系统的安全&#xff0c;而使用的技术手段。跳板机和堡垒机则是为了运维人员远程访问控制系统而搭建的机器。 一、前置机 1. 作用 前置机&#xff0c;指代的是设置在后台系…

2014-2023年各地级市空气质量指数AQI指数日度数据

2014-2023年各地级市空气质量指数AQI指数日度数据 1、时间&#xff1a;2014-2023.3.8 2、来源&#xff1a;https://www.qweather.com/air/beiliu-101300903.htm 3、指标&#xff1a;统计日期、地区编码ID、地区代码、地区名称、AQI指数、空气质量级别、首要污染物 4、样本量…

教你三指针拿捏链表翻转

类似上图&#xff0c;其实步骤很简单&#xff0c;用三个指针pre&#xff0c;cur&#xff0c;temp&#xff0c;看英文也知道具体含义&#xff0c;前向&#xff0c;当前&#xff0c;和用于保存剩余的链表 &#xff0c;具体看下图&#xff0c;很清晰 class Solution { public:List…

CH343 使用USB转串口发送CAN报文

文章目录 原启UART 走CAN收发器CH343 模拟CAN发送CPP ASIO SocketCANVXCANGithub Link 原启 早些年自动驾驶激光雷达还不支持PTP之类的时间同步, 很多都是用PPS时间同步, 激光雷达一般装的离控制器或者GNSS天线较远, 车上的线束一般数据电源各种都包在一起的, 如果3.3V直接从域…

JAVA内存屏障、volatile关键字、synchronized关键字

内存屏障&#xff08;Memory Barrier&#xff09;&#xff0c;也称为内存栅栏或内存屏障指令&#xff0c;是一种硬件或软件机制&#xff0c;用于限制对内存操作的重排序和优化。它们用于确保多线程程序中的内存访问操作按照预期顺序执行&#xff0c;以避免由于并发访问导致的数…

使用maven打生产环境可执行包

一、程序为什么要打包 程序打包的主要目的是将项目的源代码、依赖库和其他资源打包成一个可执行的文件或者部署包&#xff0c;方便程序的发布和部署。以下是一些打包程序的重要理由&#xff1a; 方便部署和分发&#xff1a;打包后的程序可以作为一个独立的实体&#xff0c;方便…

leetCode刷题 13. 罗马数字转整数

目录 题目&#xff1a; 1. 思路 2. 解题方法 3. 复杂度 4. Code 题目&#xff1a; 罗马数字包含以下七种字符: I&#xff0c; V&#xff0c; X&#xff0c; L&#xff0c;C&#xff0c;D 和 M。 字符 数值 I 1 V 5 X 10 L …

降低cpu占用率的方法

在 C 中&#xff0c;sleep(0) 并不会真正让线程休眠 0 秒。相反&#xff0c;它会暂停当前线程&#xff0c;使得其他线程有机会在当前线程之后执行。这在多线程环境中常用于实现一种简单的自旋锁。 当你调用 sleep(0) 时&#xff0c;它会让当前线程放弃 CPU 使用权&#xff0c;…

Vmware虚拟机使用过程中断电后无法重启处理

背景 今天在用新装的虚拟机进行测试的过程中&#xff0c;忽然笔记本关机了&#xff08;没插电源线&#xff09;&#xff0c;重启电脑后发现虚拟机提示“正在使用中“&#xff0c;具体如下所示&#xff1a; 解决 在相关虚拟机文件夹内查找以 .lck 结尾的文件&#xff0c;名称一…

Vue:封装响应式数据的防抖函数

代码&#xff1a; ts文件&#xff1a; import { customRef } from "vue"; export function useFangdou<T>(value: T, delay 200) {let timeout: number;return customRef((track, trigger) > {return {get() {track();return value;},set(newValue: T) {…

java中Volatile关键字的原理

Volitile的主要作用就是保持内存可见性和防止指令重排序。我分别说一下这两个作用的实现原理 1.保持内存可见性的实现原理 volatile内存可见性主要通过lock前缀指令实现的&#xff0c;它会锁定当前内存区域的缓存&#xff0c;并且立即将当前缓存的数据写入到主内存&#xff0…

记录dockers中Ubuntu安装python3.11

参考&#xff1a; docker-ubuntu 安装python3.8,pip3_dockerfile ubuntu22 python3.8-CSDN博客

解释“RNN encode-decode”

“RNN encode-decode” 涉及使用循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;来执行编码和解码操作。这种结构常用于处理序列数据&#xff0c;例如自然语言处理、语音识别和时间序列预测等任务。 以下是 “RNN encode-decode” 的一般概念&a…

西门子PLC常用底层逻辑块分享_单/双输出电磁阀

文章目录 前言一、功能概述二、单输出电磁阀程序编写1.创建自定义数据类型2.创建FB功能块“单输出电磁阀”3.编写程序 三、双输出电磁阀程序编写1.创建自定义数据类型2.创建FB功能块“双输出电磁阀”3.编写程序 前言 本文分享一个自己编写的电磁阀控制逻辑块。 一、功能概述 …

【代码随想录】【二叉树】补day21:二叉搜索树的最小绝对差 、二叉搜索树中的众数 、二叉树的最近公共祖先

最小绝对差 1.申请一个数组&#xff0c;比较两两之间最小的差值 def getresult3(self,node:TreeNode):self.nums[]self.getMinimumDifference(node)mindifferencefloat(inf)for i in range(len(self.nums)-1):mindself.nums[i1]-self.nums[i]if mindifference>mind:mindiff…

每日一面——C++11的新特性

写前声明&#xff1a;参考链接 C面经、面试宝典 等 ✊✊✊每日一面——C11的新特性 一、C11有哪些新特性&#xff1f;二、说一说了解的Lambda函数的全部知识三、C中的NULL和nullptr的区别&#xff1f;四、auto、decltype和 decltype(auto)的用法五、说说C中的智能指针和指针的区…

流程控制 JAVA语言基础

任何简单或复杂的算法都可以由三种基本结构组成&#xff1a;顺序结构&#xff0c;选择结构&#xff0c;循环结构。 顺序结构 比较一般的结构&#xff0c;程序从上到下执行。 选择结构 我们从最简单的单路选择开始&#xff0c;符合条件的进入语句序列&#xff0c;不符合条件的…