Solidity Uniswap V2 library contract

library contract 

        在 Solidity 中,库是一种无状态合约(即它没有可变状态),它实现了一组可被其他合约使用的函数--这是库的主要目的。与合约不同,库没有状态:它们的函数通过 DELEGATECALL 在调用者的状态下执行。但与合约一样,库也必须部署后才能使用。幸运的是,Forge 支持自动链接库(我们不需要在测试中部署库),这让我们的工作变得更轻松。

library ZuniswapV2Library {error InsufficientAmount();error InsufficientLiquidity();function getReserves(address factoryAddress,address tokenA,address tokenB) public returns (uint256 reserveA, uint256 reserveB) {(address token0, address token1) = _sortTokens(tokenA, tokenB);(uint256 reserve0, uint256 reserve1, ) = IZuniswapV2Pair(pairFor(factoryAddress, token0, token1)).getReserves();(reserveA, reserveB) = tokenA == token0? (reserve0, reserve1): (reserve1, reserve0);}...

        这是一个高级函数,它可以获取任意配对的reserve。

        函数的第一步是token地址排序--当我们想通过token地址查找pair地址时,总是要这样做。这就是我们下一步要做的事情:有了factory地址和排序过的token地址,我们就能获得pair地址--我们接下来会看看 pairFor 函数。

        请注意,在返回之前,我们已经对储备进行了排序:我们希望按照token地址指定的顺序返回它们!

        现在,让我们来看看 pairFor 函数:

function pairFor(address factoryAddress,address tokenA,address tokenB) internal pure returns (address pairAddress) {

        该函数用于通过factory地址和token地址查找pair地址。最直接的方法是从factory合约中获取配对地址,例如

ZuniswapV2Factory(factoryAddress).pairs(address(token0), address(token1))

        但这样做会产生外部调用,从而使函数的运行成本增加。

        Uniswap 使用的是更先进的方法,我们可以从 CREATE2 操作码的确定性地址生成中获的启发。

(address token0, address token1) = sortTokens(tokenA, tokenB);pairAddress = address(uint160(uint256(keccak256(abi.encodePacked(hex"ff",factoryAddress,keccak256(abi.encodePacked(token0, token1)),keccak256(type(ZuniswapV2Pair).creationCode))))));

        这段代码生成地址的方式与 CREATE2 相同。

        1、第一步是对token地址进行排序。还记得 createPair 函数吗?我们使用排序过的令牌地址作为盐。

        2、接下来,我们构建一个字节序列,其中包括:

        0xff - 第一个字节有助于避免与 CREATE 操作码发生碰撞。(更多详情请参见 EIP-1014)。

        factoryAddress - 用于部署配对的工厂。

        salt - 已排序和散列的token地址。

        一对合约字节码的哈希值 - 我们对 creationCode 进行哈希处理以获得该值。

        3、然后,对字节序列进行散列(keccak256)并转换为地址(字节->uint256->uint160->地址)。

        整个过程在 EIP-1014 中定义,并在 CREATE2 操作码中实现。我们要做的就是在 Solidity 中重新实现地址生成!

        最后,我们来到引用函数。

function quote(uint256 amountIn,uint256 reserveIn,uint256 reserveOut) public pure returns (uint256 amountOut) {if (amountIn == 0) revert InsufficientAmount();if (reserveIn == 0 || reserveOut == 0) revert InsufficientLiquidity();return (amountIn * reserveOut) / reserveIn;}

        如前所述,该函数根据输入量和配对储备计算输出量。这样,我们就可以知道用特定数量的token A 换取多少token B。在交换中,使用的是基于恒积公式的公式。

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

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

相关文章

工业制造领域系统:SCADA、PLC、DCS、MES、HMI、ERP等,一文秒懂

工业制造控制系统在工业制造领域起到了关键的作用,帮助企业提高生产效率、降低成本、提高产品质量和安全性。不同的企业根据自身需求和规模,可能会选择使用其中的一种或多种系统。 SCADA系统(Supervisory Control and Data Acquisition&…

数据和类型转换

文章目录 数据类型数字类型数字操作NaNJavaScript算术运算符的执行顺序 字符串类型(string)字符串拼接模板字符串 未定义类型(undefined)布尔类型(boolean)null(空类型) 类型转换显式…

【DL经典回顾】激活函数大汇总(十三)(Sinc SwiGLU附代码和详细公式)

激活函数大汇总(十三)(Sinc & SwiGLU附代码和详细公式) 更多激活函数见激活函数大汇总列表 一、引言 欢迎来到我们深入探索神经网络核心组成部分——激活函数的系列博客。在人工智能的世界里,激活函数扮演着不可…

ARM 寄存器学习:(一)arm多种模式下得寄存器

一.ARM7种状态以及每种状态的寄存器: ARM 处理器共有 7 种不同的处理器模式,在每一种处理器模式中可见的寄存器包括 15 个通用寄存器( R0~R14)、一个或两个(User和Sys不是异常模式,没有spsr寄存器)状态寄存器(cpsr和spsr&…

Unity开发一个FPS游戏之二

在之前的文章中,我介绍了如何开发一个FPS游戏,添加一个第一人称的主角,并设置武器。现在我将继续完善这个游戏,打算添加敌人,实现其智能寻找玩家并进行对抗。完成的效果如下: fps_enemy_demo 下载资源 首先是设计敌人,我们可以在网上找到一些好的免费素材,例如在Unity…

2024年华为OD机试真题-田忌赛马-Java-OD统一考试(C卷)

题目描述: 给定两个只包含数字的数组a,b,调整数组 a 里面数字的顺序,使得尽可能多的 a[i] >b[i]。数组 a和 b 中的数字各不相同。 输出所有可以达到最优结果的 a 数组的数量 输入描述: 输入的第一行是数组 a 中的数字,其中只包含数字,每两个数字之间相隔一个空格,a…

KKView远程控制: todesk内网穿透

Todesk内网穿透:实现远程访问的新途径 在数字化时代,远程访问已成为许多企业和个人的基本需求。Todesk作为一款远程桌面控制软件,其内网穿透功能为用户提供了便捷、安全的远程访问体验。本文将介绍Todesk内网穿透的原理、应用场景及其优势&a…

【C++ 】list 类

1. 标准库中的list类 list 类 的介绍: 1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代 2. list与forward_list非常相似:最主要的不同在于forward_list是单链表 3. 与其他的序列式容器相比(a…

爆肝总结,Python接口自动化测试-接口关联实例,一文打通...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 参数关联&#xf…

Python解释器安装

下载Python解释器 如果您从未安装过Python解释器,那么在编写Python代码前需要安装该解释器。什么是Python解释器呢? “Python解释器”就像是一个能够理解和执行Python编程语言的“翻译官”。你写的Python代码(一系列指令)需要有一…

Redis:持久化、线程模型、大 key

Redis持久化方式有什么方式? Redis 的读写操作都是在内存中,所以 Redis 性能才会高,但是当 Redis 重启后,内存中的数据就会丢失,那为了保证内存中的数据不会丢失,Redis 实现了数据持久化的机制&#xff0c…

宠物食品药品小程序有哪些功能

现在很多人都喜欢养宠物,这带动了宠物相关产业链,例如宠物医院、宠物清理、宠物食品、宠物玩具、宠物药品等。那么今天就介绍宠物食品药品小程序有哪些功能,以帮助您更好地为宠物行业的客户提供服务。 1. **商品展示**:宠物食品小…

二分查找注意事项

目录 1解题思路:首先二分查找分为左闭右闭和左闭右开两种情况,二种情况在细节处理上有所不同 2左闭右闭情况 3左闭右开 4总结: 1解题思路:首先二分查找分为左闭右闭和左闭右开两种情况,二种情况在细…

SpringBoot 如何快速过滤出一次请求的所有日志

在现网出现故障时,我们经常需要获取一次请求流程里的所有日志进行定位 。如果请求只在一个线程里处理,则我们可以通过线程ID来过滤 日志 ,但如果请求包含异步线程的处理,那么光靠线程ID就显得捉襟见肘了。 SLF4J日志框架提供了一个MDC(Mapped Diagnostic Contexts)工具类,…

算法打卡day13|二叉树篇02|Leetcode 102.二叉树的层序遍历、226.翻转二叉树、101. 对称二叉树

在做题之前说明 Deque和Queue 在Java中,Deque和Queue是两种不同的数据结构接口,它们都继承自Collection接口;Deque是Queue的超集,提供了更多的操作和灵活性,以下它们之间存在一些关键的区别: 操作范围&…

【研发日记】Matlab/Simulink技能解锁(一)——在Simulink编辑窗口Debug

文章目录 前言 时间阈值断点 信号阈值断点 周期步进 Signal Value Lable Data Inspector 分析和应用 总结 前言 近期在一些研发项目中使用Matlab/Simulink时,遇到了挺多费时费力的事情。所以利用晚上和周末时间,在这些方面深入研究了一下&#x…

GPT实战系列-LangChain的OutPutParser解析器

GPT实战系列-LangChain的OutPutParser解析器 LangChain GPT实战系列-LangChain如何构建基通义千问的多工具链 GPT实战系列-构建多参数的自定义LangChain工具 GPT实战系列-通过Basetool构建自定义LangChain工具方法 GPT实战系列-一种构建LangChain自定义Tool工具的简单方法…

leetcode 3.11

leetcode hot 100 二分查找1.寻找旋转排序数组中的最小值 矩阵1.搜索二维矩阵 II知识点:upper_bound, lower_bound知识点:二分查找 2.搜索二维矩阵 链表1.合并两个有序链表2.两数相加3. 删除链表的倒数第 N 个结点 二分查找 1.寻找旋转排序数组中的最小…

复习C语言基础中的基础:C语言发展、C89 C99有何区别、C语言特点

参考《C程序设计(第五版)》(谭浩强)一书: 1. 发展、C89 C99 2. 特点 记得时不时回顾一下背景特点,加深对C语言的理解。

git的实际运用

1. SSH配置和Github仓库克隆 注意博主在这里演示的SSH密钥生成方式,下面追加的五行不成功时可手动到.ssh下的config文件中添加即可 $ tail -5 config Host github.comHostName github.comPreferredAuthentications publickeyIdentityFile ~/.ssh/test 演示 2. 关联…