Solidity Uniswap V2 Pair中添加流动性

2024-03-06 22:20

本文主要是介绍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。

这篇关于Solidity Uniswap V2 Pair中添加流动性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/781547

相关文章

野火霸天虎V2学习记录

文章目录 嵌入式开发常识汇总1、嵌入式Linux和stm32之间的区别和联系2、stm32程序下载方式3、Keil5安装芯片包4、芯片封装种类5、STM32命名6、数据手册和参考手册7、什么是寄存器、寄存器映射和内存映射8、芯片引脚顺序9、stm32芯片里有什么10、存储器空间的划分11、如何理解寄存器说明12、如何操作寄存器的某一位 STM32F407芯片学习1、stm32单片机启动流程s

翻译Houdini官方对UE4新版插件的介绍:Houdini Engine for Unreal - V2

原视频:Houdini For Unreal - YouTube 目录 介绍0. 总览1. 简介HoudiniEngine2. UE4的HoudiniEngine - 第二版为什么要做“第二版” ?What's new? - 核心What's new? - 输出(1)What's new? - 输出(2)What's new? - 输入What's new? - 参数What's new?

Jaxb - com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 8 counts of IllegalAnnotationExcepti

一、异常 com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 8 counts of IllegalAnnotationExceptions类的两个属性具有相同名称 "orderName"his problem is related to the following location:at public java.lang.Stri

(二十九)STL map容器(映射)与STL pair容器(值对)

C++中的map容器是什么?可以说这个是python中的字典(dict) T = {'1':5, '3':7, '5':4, '4':9, '2':6} print(T) 学过python的都知道字典的每一项都有一个键(key)和一个值(value),而且键是不能重复的 在C++还有一个特点:可以自排序 那值对pair又是个什么东西呢?一个pair可以存储两个数据,这是他的定义: te

MapReduce V2---Yarn的架构及其执行原理

1. MRv1的局限性    1):扩展性差            MRv1中,Jobracker同事兼备了资源管理和作业控制(job的生命周期管理(task调度,跟踪task过程状态,task处理容错)两个功能。     单个的jobtracker无论在内存还是其他资源方面总存在瓶颈,在伸缩性、资源利用率、运行除mapreduce的其他任务等方面都会有限制。 MRv2 Y

[论文笔记]Circle Loss: A Unified Perspective of Pair Similarity Optimization

引言 为了理解CoSENT的loss,今天来读一下Circle Loss: A Unified Perspective of Pair Similarity Optimization。 为了简单,下文中以翻译的口吻记录,比如替换"作者"为"我们"。 这篇论文从对深度特征学习的成对相似度优化角度出发,旨在最大化同类之间的相似度 s p s_p s

Linux 虚拟网络三大基石:Namespace、Veth pair 与 Bridge

引言 在 Linux 的世界里,虚拟网络技术是系统管理、云计算和容器化不可或缺的一部分。今天,我们将深入探讨构建这些虚拟网络的三大基石:Namespace、Veth 对和 Bridge,揭示它们如何在背后默默支撑起你的网络环境。 Namespace:隔离与抽象的艺术 当我们谈起 Namespace,实际上是在讨论一种革命性的资源隔离机制。它让每个进程仿佛拥有一套独立的系统资源。通过将全局资

新文章 - Lua中的ipair 和 pair的区别 / table

参考博客:  https://blog.csdn.net/W_han__/article/details/51376615 (https://blog.csdn.net/heyuchang666/article/details/51003492)  参考博客:  https://www.jianshu.com/p/4db84cf0d61a(初探 lua 的唯一数据结构 table) ----

golang中使用aws-sdk-go-v2

1.aws-sdk-go-v2常用api 1.引入所需包     import ("context""fmt""log""os""path/filepath""sync""time""github.com/aws/aws-sdk-go-v2/aws""github.com/aws/aws-sdk-go-v2/config""github.com/aws/aws-sdk-go-v2/crede

AttributeError: module ‘tensorflow_core._api.v2.config’ has no attribute ‘experimental_list_devices’

找到 tensorflow_backend.py 源文件的第506行 _LOCAL_DEVICES = tf.config.experimental_list_devices() 改成 devices = tf.config.list_logical_devices()_LOCAL_DEVICES = [x.name for x in devices]