Solidity Uniswap V2 Router swapTokensForExactTokens

        最初的router合约实现了许多不同的交换方式。我们不会实现所有的方式,但我想向大家展示如何实现倒置交换:用未知量的输入Token交换精确量的输出代币。这是一个有趣的用例,可能并不常用,但仍有可能实现。

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

        让我们回到交换公式:

        (x+rΔx)(y−Δy)=xy

        现在,我们要找到的不是 Δy,而是 Δx:我们知道想要得到的输出Token的确切数量,但不知道需要提供多少输入Token。

        同样,在应用基本的代数运算后,我们可以得到

        同样,这是一个考虑到产出量(Δy)和费用 r 的储备金(x/y)关系式。

        现在我们就可以实现这一公式:

function getAmountIn(uint256 amountOut,uint256 reserveIn,uint256 reserveOut) public pure returns (uint256) {if (amountOut == 0) revert InsufficientAmount();if (reserveIn == 0 || reserveOut == 0) revert InsufficientLiquidity();uint256 numerator = reserveIn * amountOut * 1000;uint256 denominator = (reserveOut - amountOut) * 997;return (numerator / denominator) + 1;}

        一切都很清楚,除了最后的结果多了一个 1 ,为什么会这样?原因在于,Solidity 中的除法(即整除)会将结果向下舍入,这意味着结果会被截断。在计算输入金额时,我们希望保证计算出的金额能达到要求的输出金额。如果结果被截断,输出的金额就会稍小。

        接下来,我们需要 getAmountsIn 函数:

function getAmountsIn(address factory,uint256 amountOut,address[] memory path) public returns (uint256[] memory) {if (path.length < 2) revert InvalidPath();uint256[] memory amounts = new uint256[](path.length);amounts[amounts.length - 1] = amountOut;for (uint256 i = path.length - 1; i > 0; i--) {(uint256 reserve0, uint256 reserve1) = getReserves(factory,path[i - 1],path[i]);amounts[i - 1] = getAmountIn(amounts[i], reserve0, reserve1);}return amounts;}

        它复制了 getAmountsOut,但有一个显著的变化:遍历路径的顺序颠倒了。由于我们知道输出金额,并希望找到输入金额,因此我们从路径的末尾开始,以相反的顺序将输入金额填入金额数组。

        高级交换函数看起来也很熟悉:

function swapTokensForExactTokens(uint256 amountOut,uint256 amountInMax,address[] calldata path,address to) public returns (uint256[] memory amounts) {amounts = ZuniswapV2Library.getAmountsIn(address(factory),amountOut,path);if (amounts[amounts.length - 1] > amountInMax)revert ExcessiveInputAmount();_safeTransferFrom(path[0],msg.sender,ZuniswapV2Library.pairFor(address(factory), path[0], path[1]),amounts[0]);_swap(amounts, path, to);}

        它与我们之前实现的 swap 函数几乎完全相同,但它调用的是 getAmountsIn。同样有趣的是,即使金额是输入的,我们也可以使用相同的 _swap 函数。

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

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

相关文章

修改Docker Gitlab root 的密码

一、进入git docker 容器 docker exec -it [容器ID或名称] /bin/bash 二、查找并修改账号 user User.find_by(username: ‘root’) user.password ‘root********’ user.password_confirmation ‘root********’ user.save! 三、重启生效 附&#xff1a;第一次&#xff…

Golang实战:深入hash/crc64标准库的应用与技巧

Golang实战&#xff1a;深入hash/crc64标准库的应用与技巧 引言hash/crc64简介基本原理核心功能 环境准备安装Golang创建一个新的Golang项目引入hash/crc64包测试环境配置 hash/crc64的基本使用计算字符串的CRC64校验和计算文件的CRC64校验和 高级技巧与应用数据流和分块处理网…

Jmeter 配置说明之线程组

一、线程组介绍&#xff1a; 线程组元件是任何一个测试计划的开始点。在一个测试计划中的所有元件都必须在某个线程组下。所有的任务都是基于线程组&#xff1a; 通俗理解&#xff1a; 线程组&#xff1a;就是一个线程组&#xff0c;里面有若干个请求&#xff1b; 线程&am…

vue3.0 + ts + eslint报错:error Parsing error: ‘>‘ expected

eslint报错 这里加上对应的 eslint配置即可&#xff1a; parser: vue-eslint-parser, parserOptions: {parser: "typescript-eslint/parser",ecmaVersion: 2020,sourceType: module, }具体如下&#xff1a; module.exports {parser: vue-eslint-parser,parserOpti…

企业数据定制:营销/画像/大数据模型

随着信息技术的发展&#xff0c;数据已经成为企业发展的重要基石。现在信息广泛地分布在网络&#xff0c;人工收集对于企业运作来说效率太低了。 因此&#xff0c;很多企业选择将数据采集工作交给专业的团队来做&#xff0c;选择直接外包或者购买数据。 不管是哪种情况&#…

​马来语翻译中文去哪比较好?

据了解&#xff0c;马来语是马来西亚、文莱的官方语言&#xff0c;也是新加坡的官方语言之一&#xff0c;马来语跟印尼语是同一种语言&#xff0c;它在整个东南亚有着极大的影响力。如今在国内市场上&#xff0c;马来语翻译的需求也是供不应求&#xff0c;那么&#xff0c;如何…

【Go】三、Go指针

文章目录 1、指针2、说明 1、指针 &符号变量 就可以获取这个变量内存的地址*int 是一个指针类型 &#xff08;可以理解为 指向int类型的指针&#xff09; package main import("fmt" ) func main(){var age int 18//&符号变量 就可以获取这个变量内存的地…

ubuntu22 安装docker26

ubuntu22 安装docker 在Ubuntu 22.04上安装Docker&#xff0c;你可以按照以下步骤操作&#xff1a; 1.更新软件包索引&#xff1a; sudo apt-get update 2.安装必要的软件包&#xff0c;以允许apt通过HTTPS来使用仓库&#xff1a; sudo apt-get install ca-certificates c…

Flowable 笔记

目录 FlowableFlowable简介Flowable 的四大引擎Flowable BPMN 业务流程引擎Flowable DMN 决策引擎Flowable CMMN 案例模型引擎Flowable Form 表单引擎 Spring Boot集成Flowable Flowable Flowable简介 Flowable 是一个使用 Java 编写的轻量级业务流程引擎&#xff0c;使用 Ap…

第十五章 Nginx

一、Nginx 1.1 Nginx 相关概念 1.1.1 正向代理 正向代理类似一个跳板机&#xff0c;代理访问外部资源。 比如我们国内访问谷歌&#xff0c;直接访问访问不到&#xff0c;我们可以通过一个正向代理服务器&#xff0c;请求发到代理服&#xff0c;代理服务器能够访问谷歌&am…

TBSI模型论文解读及代码分析

前往我的主页以获得更好的阅读体验 简介 论文来源: Bridging Search Region Interaction With Template for RGB-T Tracking 现有的搜索算法通常会直接连接 RGB 和 T 模态搜索区域, 该方法存在大量冗余背景噪声. 而另一些方法从搜索帧中采样候选框, 对孤立的 RGB 框和 T 框进…

TongWeb7.0-8.0Java代码使用JMX获取应用通道端口

以下通过java代码实现获取TongWeb7.0/8.0应用通道端口使用到的JMX均为TongWeb自带的JMX功能。 一、TongWeb7.0 1、使用本地JMX获取应用通道端口 public String getTw7PortByLocalJmx() { try { MBeanServer beanServer ManagementFactory.getPlatformMBeanServer(); Set&l…

SOLIDWORKS二次开发参数化设计软件 慧德敏学

SOLIDWORKS参数化设计软件-SolidKits.AutoWorks专为规格变化多、变化规律强的产品开发&#xff0c;将变化规律集成到三维设计软件&#xff0c;通过一键点击实现自动化产品再设计&#xff0c;如智能选型、自动化修改产品属性、产品参数、产品状态、图纸更新、重命名、并自动打包…

计算机填空知识点(2)续20个

21&#xff0e;Windows的操作以 鼠标 操作为主&#xff0c;也可以使用 键盘 操作。 22&#xff0e;Windows的窗口可分为 应用程序窗口 、文档窗口和 对话框窗口 三类。 23&#xff0e; Windows 提供了三种菜单形式&#xff1a;一种是 窗口菜单 &#xff0c;另一种是位于任务栏…

LeetCode:300最长递增子序列 C语言

300. 最长递增子序列 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子…

小程序中使用less

在vscode中安装插件 找到左下角齿轮的设置&#xff0c;点击右边图标&#xff0c;进入“settings.json” 加上以下代码配置 "less.compile":{"outExt": ".wxss"}

Mysql数据库:日志管理、备份与恢复

目录 前言 一、MySQL日志管理 1、存放日志和数据文件的目录 2、日志的分类 2.1 错误日志 2.2 通用查询日志 2.3 二进制日志 2.4 慢查询日志 2.5 中继日志 3、日志综合配置 4、查询日志是否开启 二、数据备份概述 1、数据备份的重要性 2、备份类型 2.1 从物理与…

Promise封装ajax

Promise封装原生ajax 1.node的内置模块url, http 2.Promise封装原生ajax 01-node的内置模块 # url: 操作网址 let url require(url) url.parse(网址, [布尔值: 决定是否将查询字符串转换为对象格式])&#xff1a; 将网址解析成对象# http: 创建本地服务器 let http requi…

大数据学习-2024/3/28-xls转csv文件、csv文件转xls文件

九九乘法表写入到d.xls文件中 1.导入模块 import xlwt2.创建工作薄对象 bookxlwt.Workbook()3.根据book对象创建sheet标签页对象 sheetbook.add_sheet(jj)4.写入内容 # 外层循环&#xff1a;控制乘法口诀表的行数 # range(1, 10) 生成一个从1到9的整数序列&#xff0c;共…

镜舟普元揭秘数据中台新范式,引领企业数智化转型与创新实践

在当前数字化浪潮中&#xff0c;数据中台的角色越发重要&#xff0c;承担着将一切业务数据化的重任。近日&#xff0c;北京镜舟科技有限公司&#xff08;简称“镜舟”&#xff09;与普元信息技术股份有限公司&#xff08;简称“普元”&#xff09;联合举办“数据中台新范式”云…