Solidity Uniswap V2 Pair中添加流动性

        添加流动性的功能的用户入口,UniswapV2在UniswapV2Router中实现,它用来计算新的流动性并发行LP-Token,流动性管理简单地视为LP-Token管理。当你为一个pair增加流动性时,合约会创造LP Token;当你移除流动性时,LP-Token就会被销毁。pair合约中的添加流动性函数,是只执行核心操作的低级函数。

        添加流动性函数

        这是添加流动性的底层函数,

function mint() public {uint256 balance0 = IERC20(token0).balanceOf(address(this));uint256 balance1 = IERC20(token1).balanceOf(address(this));uint256 amount0 = balance0 - reserve0;uint256 amount1 = balance1 - reserve1;uint256 liquidity;if (totalSupply == 0) {liquidity = ???_mint(address(0), MINIMUM_LIQUIDITY);} else {liquidity = ???}if (liquidity <= 0) revert InsufficientLiquidityMinted();_mint(msg.sender, liquidity);_update(balance0, balance1);emit Mint(msg.sender, amount0, amount1);
}

        首先,我们需要计算用户新存入的金额(即没有保存到reserve中的)。然后,计算必须发行的 LP-Token的数量,作为对提供流动性的奖励。然后,我们发行 LP-Token并更新reserve,函数 _update 只是将余额保存到reserve中。

        从代码中可以看出,最初存入pool时,根据totalSupply 是否为0 ,流动性的计算方法是不同的。想想看,当池中没有流动性时,我们需要发行多少 LP-Token?

        对于初始 LP-token的数量,Uniswap V2 最终使用了存入金额的几何平均数:

        这样的主要好处是,确保了初始流动性比率不会影响资产池份额的价值。

        然后,我们在计算,当pool里已经有一些流动性时发行LP-Token的情况。

        这里的主要有两个要求,第一是,按照比例,存入的Token;第二是,按照比例,发行LP-Token。

        发行LP-Token的数量,与token的存款数量成正比。但是,在一个pair中,有两个潜在的Token——我们应该在公式中使用哪一个呢?

        我们可以选择其中任何一个,但存款金额的比例与reserve的比例越接近,差异就越小。因此,如果存款金额的比例不同,LP-Token金额也会不同,而且其中一个会比另一个大。

        如果我们选择更大的,那么我们将通过提供流动性来激励价格变化,这将导致价格操纵。如果我们选择较小的一个,我们将惩罚不平衡流动性的存款(流动性提供者将获得更少的LP-Token)。很明显,选择更小的数字更有益。

if (totalSupply == 0) {liquidity = Math.sqrt(amount0 * amount1) - MINIMUM_LIQUIDITY;_mint(address(0), MINIMUM_LIQUIDITY);} else {liquidity = Math.min((amount0 * totalSupply) / _reserve0,(amount1 * totalSupply) / _reserve1);}

        在第一个分支中,我们在提供初始流动性时减去 MINIMUM_LIQUIDITY(即常数 1000,或 1e-15)。这样可以防止有人把一个pool的份额做得太贵,从而把小规模的流动性提供者拒之门外。对于大多数pool来说,1000 wei的 LP-Token可以忽略不计,但如果有人试图让一份pool的代币成本过高(比如 100 美元),他们就必须烧掉 1000 倍的成本(即 100,000 美元)。

使用solidity编写测试

        我将使用 Foundry 测试我们的智能合约,它无需与 JavaScript 打交道。我们使用智能合约测试智能合约。这就相当于,测试智能合约的智能合约。

这就是我们设置pair合约测试所需要的:

contract ZuniswapV2PairTest is Test {ERC20Mintable token0;ERC20Mintable token1;ZuniswapV2Pair pair;function setUp() public {token0 = new ERC20Mintable("Token A", "TKNA");token1 = new ERC20Mintable("Token B", "TKNB");pair = new ZuniswapV2Pair(address(token0), address(token1));token0.mint(10 ether);token1.mint(10 ether);}}

测试一下交易对初始化(提供初始流动性):

function testMintBootstrap() public {token0.transfer(address(pair), 1 ether);token1.transfer(address(pair), 1 ether);pair.mint();assertEq(pair.balanceOf(address(this)), 1 ether - 1000);assertReserves(1 ether, 1 ether);assertEq(pair.totalSupply(), 1 ether);}

1 个ether的Token0 和 1 个ether的Token1 加入测试池。因此,1 个ether的 LP-Token被发行,我们得到 1 个ether - 1000(减去最小流动性)。pool的reserve和总供应量也会相应改变。

如果向一个已有一定流动性的pool提供平衡的流动性,会发生什么情况呢?让我们来看看:

function testMintWhenTheresLiquidity() public {token0.transfer(address(pair), 1 ether);token1.transfer(address(pair), 1 ether);pair.mint(); // + 1 LPtoken0.transfer(address(pair), 2 ether);token1.transfer(address(pair), 2 ether);pair.mint(); // + 2 LPassertEq(pair.balanceOf(address(this)), 3 ether - 1000);assertEq(pair.totalSupply(), 3 ether);assertReserves(3 ether, 3 ether);}

让我们看看提供不平衡流动性时会发生什么:

function testMintUnbalanced() public {token0.transfer(address(pair), 1 ether);token1.transfer(address(pair), 1 ether);pair.mint(); // + 1 LPassertEq(pair.balanceOf(address(this)), 1 ether - 1000);assertReserves(1 ether, 1 ether);token0.transfer(address(pair), 2 ether);token1.transfer(address(pair), 1 ether);pair.mint(); // + 1 LPassertEq(pair.balanceOf(address(this)), 2 ether - 1000);assertReserves(3 ether, 2 ether);}

即使用户提供的Token0流动性多于Token1流动性,他们仍然只能获得1 LP-Token。

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

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

相关文章

【debug】element-ui时间控件回显后不可编辑且显示为空

问题&#xff1a;使用element-ui的时间控件回显数据&#xff0c;编辑数据没有反应&#xff1a;点时间和“确认”按钮都没反应。 输入框中会显示数据&#xff0c;但提交时的校验显示为空。 <el-form-item label"开始时间" prop"limitStartTime"><…

局部最小值问题

局部最小值问题&#xff1a; 条件&#xff1a;n个数的无序数组 array&#xff0c;相邻两个数一定不相等&#xff0c;找出其中的一个局部最小值。 如果array[0]< array[1] ,返回 array[0];如果array[n-1]<array[n-2]&#xff0c;返回array[n-1];其他的位置需要满足 array[…

xss.haozi.me:0X0D

alert(1) -> 记住要回车一下-->是js的一个注释符但是只能用在最前面前面有一个空格都不行

【LeetCode】升级打怪之路 Day 14:二叉树的遍历

今日题目&#xff1a; 144. 二叉树的前序遍历94. 二叉树的中序遍历145. 二叉树的后序遍历102. 二叉树的层序遍历107. 二叉树的层序遍历 II199. 二叉树的右视图637. 二叉树的层平均值429. N 叉树的层序遍历515. 在每个树行中找最大值116. 填充每个节点的下一个右侧节点指针117. …

【YOLO v5 v7 v8 v9小目标改进】RevCol:解决深度学习信息从低层(输入)传递至高层(输出)的过程中,信息会逐层丢失问题

RevCol&#xff1a;解决深度学习信息从低层&#xff08;输入&#xff09;传递至高层&#xff08;输出&#xff09;的过程中&#xff0c;信息会逐层丢失问题 学习解耦表示可逆列网络&#xff08;RevCol&#xff09;子特征1&#xff1a;多级可逆单元子特征2&#xff1a;可逆列架构…

ARM电源策略单元Power Policy Unit

本规范描述了电源策略单元&#xff08;PPU&#xff09;架构。它定义了PPU架构的1.1版本。 PPU规范的1.1版本增加了操作模式支持。这使得能够为功能或更高粒度的电源控制原因提供组件特定的电源模式支持。 在本文档中&#xff0c;对PPU或PPU的引用指的是实现了此PPU架构的设备…

十四、重写与多态

重写、多态 上一讲是&#xff0c;子类对父类横向上的扩展 这一讲是&#xff0c;子类对父类纵向上的扩展 方法重写 使用override关键字重写父类的方法 将父类原本方法的逻辑更新成新版本的逻辑 注&#xff1a;仅能重写可见的父类成员&#xff0c;并且重写要保持签名一致。 签名一…

GEE 将裁剪后的Sentinel-2影像 在ArcGIS中去除空值

在ArcGIS中&#xff0c;可以使用栅格计算器&#xff08;Raster Calculator&#xff09;工具来设置NoData值为空。以下是在ArcGIS中将NoData值设置为空的步骤&#xff1a; 打开ArcGIS软件并加载下载的Sentinel-2影像数据。 影像Nodata空值以黑色背景呈现&#xff0c;影响矢量数据…

SpringCloud2023最新版本该如何进行组件选型?

前言 Developing distributed systems can be challenging. Complexity is moved from the application layer to the network layer and demands greater interaction between services. Making your code ‘cloud-native’ means dealing with 12-factor issues such as exte…

鸿蒙4.0-DevEco Studio界面工程

DevEco Studio界面工程 DevEco Studio 下载与第一个工程新建的第一个工程界面回到Project工程结构来看 DevEco Studio 下载与第一个工程 DevEco Studio 下载地址&#xff1a;点击跳转 https://developer.harmonyos.com/cn/develop/deveco-studio#download 学习课堂以及文档地址…

《金三银四求职攻略》:程序员面试季倒计时

程序员的金三银四求职宝典 大家好&#xff0c;我是小明&#xff0c;一位即将面临春季求职季的程序员。在这个黄金时段&#xff0c;如何在众多应聘者中脱颖而出&#xff0c;拿下理想的offer&#xff0c;成为了我思考的重点。今天&#xff0c;我将分享一些我个人的求职攻略&…

增强型YOLOv5应用于扩展PASCAL VOC数据集

目录 摘要关键词 1. 引言2. 性能研究2.1 YOLO2.2 PASCAL VOC 2007 数据集2.3 MS COCO 数据集 3 实验方法3.1 利用COCO数据集扩展PASCAL VOC 2007&#xff08;以elephant大象为例&#xff09;3.2 方法实现&#xff08;以YOLOv5为例&#xff09;3.2.1 YOLOv5介绍3.2.2 YOLOv5…

【详识C语言】动态内存管理

本章重点 为什么存在动态内存分配 动态内存函数的介绍 malloc free calloc realloc 常见的动态内存错误 几个经典的笔试题 柔性数组 为什么存在动态内存分配 我们已经掌握的内存开辟方式有&#xff1a; int val 20;//在栈空间上开辟四个字节char arr[10] {0};//在栈空间上开…

Three.js--》探寻Cannon.js构建震撼的3D物理交互体验(二)

我们用three.js可以绘制出各种酷炫的画面&#xff0c;但是当我们想要一个更加真实的物理效果的话&#xff0c;这个时候我们就需要一个物理的库&#xff0c;接下来我们就讲解一下今天要学习的canon&#xff0c;它可以给我们提供一个更加真实的物理效果&#xff0c;像物体的张力、…

2024护网面试题精选(一)

0x00.基础漏洞篇 00-TOP10漏洞 1.SQL注入 2.失效的身份认证和会话管理 3.跨站脚本攻击XSS 4.直接引用不安全的对象 5.安全配置错误 6.敏感信息泄露 7.缺少功能级的访问控制 8.跨站请求伪造CSRF 9.实验含有已知漏洞的组件 10.未验证的重定向和转发 01-SQL注入漏洞 …

【Java_JSON】如何从JSON数据中提取value值

如何从JSON数据中提取value值&#xff1f; 首先将JSON数据转成字符串 创建JSONObject 对象 通过kv键值对的特性 使用key值来获取value 值 并输出 结果&#xff1a;

c++: 缺省参数/默认参数的详解及其应用

c缺省参数/默认参数的详解及其应用 缺省参数是什么 #include<iostream> using namespace std;void func(int a 666) {cout << "a " << a << endl; } int main() {func(); //没有传参func(10); //传参return 0; }缺省参数就是在我们不进…

计算机体系结构:VLIW

原文来自知乎 计算机体系结构&#xff1a;VLIW 本文主要介绍计算机体系结构中的VLIW&#xff0c;以供读者能够理解该技术的定义、原理、应用。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;计算机杂记 &#x1f…

腾讯云服务器99元一年购买入口链接

腾讯云服务器99元一年购买入口链接如下&#xff0c;现在已经降价到61元一年&#xff0c;官方活动链接如下&#xff1a; 腾讯云99元服务器一年购买页面腾讯云活动汇聚了腾讯云最新的促销打折、优惠折扣等信息&#xff0c;你在这里可以找到云服务器、域名、数据库、小程序等等多种…

【uniapp】小程序自定义一个通用的返回按钮组件

左边箭头&#xff0c;右边文字可以自定义&#xff0c;但是不要太长&#xff0c;太长可以自己改 .back的width值&#xff0c;改宽一点。 用这个组件的时候首先要在pages.json里把导航栏变成自定义的&#xff1a; ,{"path" : "pages/test/test","style&…