Solidity Uniswap V2 价格预言机

        预言机是连接区块链与链下服务的桥梁,这样就可以从智能合约中查询现实世界的数据。Chainlink 是最大的oracle网络之一,创建于 2017 年,如今已成为许多 DeFi 应用的重要组成部分。https://github.com/XuHugo/solidityproject

        Uniswap 虽然是链上应用,但也可以充当oracle。交易者经常使用的每个 Uniswap pair合约也吸引着套利者,他们通过尽量缩小交易所之间的价格差异来赚钱。套利者使 Uniswap 的价格尽可能接近中心化交易所的价格,这也可以看作是将中心化交易所的价格反馈到区块链上。为什么不利用这一事实将pair合约变成价格oracle呢?Uniswap V2 就是这么做的。

        在 Uniswap V2 中,价格oracle提供的价格被称为时间加权平均价格(TWAP)。它基本上可以获得两个时间点之间的平均价格。为了做到这一点,合约存储了累计价格:在每次交换之前,它都会计算当前的边际价格(不包括费用),然后乘以上次交换后的秒数,再把这个数字加到前一个数字上。

我在上一段提到了边际价格,这只是两个reserve的关系:

        对于价格oracle功能,Uniswap V2 使用边际价格,它不包括滑点和交换费,也不取决于交换量。

        由于 Solidity 不支持浮点除法,计算这种价格可能比较麻烦:例如,如果两个reserve的比率是 2/3, 那么价格是0;在计算边际价格时,我们需要提高精确度,Unsiwap V2 为此使用了 UQ112.112 数字。

        UQ112.112 本质上是一个小数部分使用 112 位,整数部分使用 112 位的数字。选择 112 位是为了使储备状态变量的存储更优化,这也是变量使用 uint112 类型的原因。另一方面,reserve存储为 UQ112.112 数字的整数部分,这就是为什么在计算价格前要乘以 2**112 的原因。详情请查看 UQ112x112.sol,非常简单。

        让我们来实现价格累积。我们只需要添加一个状态变量:

uint32 private blockTimestampLast;

        它将存储最后一次交换的时间戳。然后我们需要修改储备更新函数:

function _update(uint256 balance0,uint256 balance1,uint112 reserve0_,uint112 reserve1_) private {...unchecked {uint32 timeElapsed = uint32(block.timestamp) - blockTimestampLast;if (timeElapsed > 0 && reserve0_ > 0 && reserve1_ > 0) {price0CumulativeLast +=uint256(UQ112x112.encode(reserve1_).uqdiv(reserve0_)) *timeElapsed;price1CumulativeLast +=uint256(UQ112x112.encode(reserve0_).uqdiv(reserve1_)) *timeElapsed;}}reserve0 = uint112(balance0);reserve1 = uint112(balance1);blockTimestampLast = uint32(block.timestamp);...}

UQ112x112.encode 将 uint112 值乘以 2**112,使其成为 uint224 值。然后,将其除以其他reserve,再乘以 timeElapsed。结果会与当前存储的值相加,这就是累积值。

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

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

相关文章

Learn OpenGL 03 着色器

GLSL 着色器的开头总是要声明版本,接着是输入和输出变量、uniform和main函数。每个着色器的入口点都是main函数,在这个函数中我们处理所有的输入变量,并将结果输出到输出变量中。 一个典型的着色器有下面的结构: #version vers…

深入理解Java泛型:灵活、安全、可重用的编程利器

Java泛型是一项强大的编程特性,为程序员提供了一种灵活、类型安全、可重用的编码方式。通过泛型,我们能够编写更加通用、适应多种数据类型的代码,从而提高了代码的灵活性和可维护性。在这篇博客中,我们将深入探讨Java泛型的各个方…

【Flink】Flink 的八种分区策略(源码解读)

Flink 的八种分区策略(源码解读) 1.继承关系图1.1 接口:ChannelSelector1.2 抽象类:StreamPartitioner1.3 继承关系图 2.分区策略2.1 GlobalPartitioner2.2 ShufflePartitioner2.3 BroadcastPartitioner2.4 RebalancePartitioner2…

全栈的自我修养 ———— css中常用的布局方法flex和grid

在项目里面有两种常用的主要布局:flex和grid布局(b站布局),今天分享给大家这两种的常用的简单方法! 一、flex布局1、原图2、中心对齐3、主轴末尾或者开始对其4、互相间隔 二、grid布局1、基本效果2、加间隔3、放大某一个元素 一、…

政安晨:【深度学习处理实践】(四)—— 实施一个温度预测示例

在开始使用像黑盒子一样的深度学习模型解决温度预测问题之前,我们先尝试一种基于常识的简单方法。 它可以作为一种合理性检查,还可以建立一个基准,更高级的机器学习模型需要超越这个基准才能证明其有效性。对于一个尚没有已知解决方案的新问…

HTML 学习笔记(四)图片

<!--通过图片标签"<img src "图片路径">"来调用图片在网页中进行显示--> <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthd…

Linux网络套接字之预备知识

(&#xff61;&#xff65;∀&#xff65;)&#xff89;&#xff9e;嗨&#xff01;你好这里是ky233的主页&#xff1a;这里是ky233的主页&#xff0c;欢迎光临~https://blog.csdn.net/ky233?typeblog 点个关注不迷路⌯▾⌯ 目录 一、预备知识 1.理解源IP地址和目的IP地址 …

Chain of Verification(验证链、CoVe)—理解与实现

原文地址&#xff1a;Chain of Verification (CoVe) — Understanding & Implementation 2023 年 10 月 9 日 GitHub 存储库 介绍 在处理大型语言模型&#xff08;LLM&#xff09;时&#xff0c;一个重大挑战&#xff0c;特别是在事实问答中&#xff0c;是幻觉问题。当答案…

Day27:安全开发-PHP应用TP框架路由访问对象操作内置过滤绕过核心漏洞

目录 TP框架-开发-配置架构&路由&MVC模型 TP框架-安全-不安全写法&版本过滤绕过 思维导图 PHP知识点 功能&#xff1a;新闻列表&#xff0c;会员中心&#xff0c;资源下载&#xff0c;留言版&#xff0c;后台模块&#xff0c;模版引用&#xff0c;框架开发等 技…

时间感知自适应RAG(TA-ARE)

原文地址&#xff1a;Time-Aware Adaptive RAG (TA-ARE) 2024 年 3 月 1 日 介绍 随着大型语言模型&#xff08;LLM&#xff09;的出现&#xff0c;出现了新兴能力的概念。前提或假设是LLMs具有隐藏的和未知的能力&#xff0c;等待被发现。企业家们渴望在LLMs中发现一些无人知晓…

Linux学习:权限

目录 1. shell命令的工作原理与存在意义1.1 shell命令解释器存在的意义1.2 shell解释器的工作原理 2. Linux操作系统&#xff1a;用户2.1 什么是用户2.2 用户的切换操作2.3 用户权限划分的意义 3. Linux中权限的种类和意义3.1 什么是权限3.2 sudo指令与短暂提权 4. 文件类型与文…

Django模型层(附带test环境)

Django模型层(附带test环境) 目录 Django模型层(附带test环境)连接数据库Django ORM在models.py中建表允许为空指定默认值数据库迁移命令 开启测试环境建表语句补充(更改默认表名)数据的增加时间数据的时区 多表数据的增加一对多多对多 数据的删除修改数据查询数据查询所有数据…