当前位置: 首页 > news >正文

solidity 中 Eth 和 Usd 到底如何转换

在Solidity中通过预言机(Oracle)实现ETH与USD的换算,核心是利用预言机提供的实时ETH/USD价格数据,结合整数运算处理精度问题。以下是详细步骤和代码示例,带你从零实现。<理解预言机的同学可以先看第五点>

一、核心原理回顾

  1. 预言机的作用:提供ETH与USD的实时汇率(如1 ETH = 2000.12345678 USD),但返回的是放大后的整数(如200012345678,放大了1e8倍,保留8位小数)。
  2. 单位转换:ETH在链上以wei为最小单位(1 ETH = 1e18 wei),USD通常以“美元分”或“美元单位”计算(需明确精度,如1 USD = 1e18单位,避免小数)。
  3. 运算逻辑:利用整数乘法和除法处理换算,避免小数运算(Solidity不直接支持小数)。

二、准备工作:选择预言机

最常用的是Chainlink预言机,它提供标准化的价格接口AggregatorV3Interface。不同网络的预言机地址不同(如以太坊主网、Sepolia测试网等),需提前查询(Chainlink地址列表)。

Sepolia测试网的ETH/USD价格预言机为例,地址为:0x694AA1769357215DE4FAC081bf1f309aDC325306

三、完整实现步骤

1. 引入预言机接口

Chainlink的AggregatorV3Interface定义了获取价格的方法,需导入或直接定义接口。

2. 初始化预言机

在合约构造函数中,传入预言机地址,初始化接口实例。

3. 获取实时ETH/USD价格

调用预言机的latestRoundData()方法,获取放大后的价格(整数),并检查数据新鲜度(避免使用过时价格)。

4. 实现ETH转USD的函数

已知ETH数量(以wei为单位),计算对应的USD金额。

5. 实现USD转ETH的函数

已知USD金额,计算对应的ETH数量(以wei为单位)。

四、代码示例(附详细注释)

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;// 引入Chainlink预言机接口(或直接定义)
interface AggregatorV3Interface {function latestRoundData()externalviewreturns (uint80 roundId,    // 轮次IDint256 answer,     // 价格(放大后的整数)uint256 startedAt, // 开始时间uint256 updatedAt, // 更新时间uint80 answeredInRound // 回答轮次);
}contract EthUsdConverter {// 预言机实例(ETH/USD价格源)AggregatorV3Interface public priceFeed;// 常量定义(精度控制)uint256 public constant ETH_DECIMALS = 1e18; // 1 ETH = 1e18 weiuint256 public constant PRICE_DECIMALS = 1e8; // 预言机价格放大倍数(8位小数)uint256 public constant USD_DECIMALS = 1e18; // 假设USD以1e18为单位(可根据需求调整)// 构造函数:初始化预言机(Sepolia测试网ETH/USD地址)constructor() {priceFeed = AggregatorV3Interface(0x694AA1769357215DE4FAC081bf1f309aDC325306);}/*** 内部函数:获取最新ETH/USD价格(放大后的整数,如200012345678)* 并检查价格是否新鲜(1小时内更新)*/function getLatestEthUsdPrice() internal view returns (uint256) {(, int256 price,, uint256 updatedAt,) = priceFeed.latestRoundData();// 检查价格是否过时(超过1小时)require(updatedAt > block.timestamp - 3600, "Price is stale");// 确保价格为正数require(price > 0, "Invalid price");return uint256(price);}/*** 功能1:ETH转USD(输入wei,返回USD单位)* 公式:USD = (ETH_wei × 预言机价格) ÷ (ETH_DECIMALS × PRICE_DECIMALS)*/function ethToUsd(uint256 ethWei) external view returns (uint256) {uint256 ethUsdPrice = getLatestEthUsdPrice(); // 预言机价格(放大1e8后)// 计算:(ethWei * 价格) / (1e18 * 1e8) → 转换为USDuint256 usd = (ethWei * ethUsdPrice) / (ETH_DECIMALS * PRICE_DECIMALS);return usd * USD_DECIMALS; // 按USD精度返回(可选)}/*** 功能2:USD转ETH(输入USD单位,返回wei)* 公式:ETH_wei = (USD × ETH_DECIMALS × PRICE_DECIMALS) ÷ (预言机价格 × USD_DECIMALS)*/function usdToEth(uint256 usd) external view returns (uint256) {uint256 ethUsdPrice = getLatestEthUsdPrice(); // 预言机价格(放大1e8后)// 计算:(usd * 1e18 * 1e8) / (价格 * 1e18) → 简化为 (usd * 1e8) / 价格uint256 ethWei = (usd * PRICE_DECIMALS) / ethUsdPrice;return ethWei;}
}

五、关键公式解析

1. ETH转USD(已知ETH数量,求USD)
  • 现实公式:USD金额 = ETH数量(ETH) × ETH/USD价格(USD/ETH)
  • 链上转换(ETH以wei为单位):
    • ETH数量(ETH)= ethWei ÷ 1e18(将wei转为ETH)
    • ETH/USD价格 = 预言机价格 ÷ 1e8(将放大后的整数转为实际价格)
    • 合并得:USD = (ethWei × 预言机价格) ÷ (1e18 × 1e8)
2. USD转ETH(已知USD金额,求ETH)
  • 现实公式:ETH数量(ETH)= USD金额 ÷ ETH/USD价格(USD/ETH)
  • 链上转换(ETH以wei为单位):
    • ETH数量(wei)= ETH数量(ETH) × 1e18
    • 合并得:ETH_wei = (USD金额 × 1e18 × 1e8) ÷ 预言机价格

六、测试与验证

假设预言机返回的ETH/USD价格为200012345678(即2000.12345678 USD/ETH):

  • 测试ethToUsd(1e18)(1 ETH):
    计算:(1e18 × 200012345678) ÷ (1e18 × 1e8) = 200012345678 ÷ 1e8 = 2000.12345678 → 返回2000.12345678 USD(按USD_DECIMALS转换后为对应整数)。

  • 测试usdToEth(200012345678)(2000.12345678 USD):
    计算:(200012345678 × 1e8) ÷ 200012345678 = 1e8 → 1e8 wei?不,这里需要注意USD的单位:如果USD_DECIMALS是1e18,实际输入的USD应为2000.12345678 × 1e18,计算后得到1e18 wei(1 ETH)。

七、注意事项

  1. 价格新鲜度:必须检查updatedAt,避免使用过时价格(如超过1小时)。
  2. 精度匹配:根据业务需求调整USD_DECIMALS(如1 USD = 1e6单位表示“分”)。
  3. 异常处理:确保预言机返回的价格为正数,避免计算错误。
  4. 网络适配:不同网络的预言机地址不同(如主网与测试网),需对应修改。

通过以上步骤,你可以在Solidity中利用预言机实现ETH与USD的精准换算,核心是理解“放大倍数”和“整数运算”的逻辑,避免小数误差。

http://www.lryc.cn/news/604564.html

相关文章:

  • 关于项目的一些完善功能
  • AD里面出现元器件PCB封装不能编辑的情况
  • 使用SpringBoot 3.2.4 + CXF 4.0.0 + JDK17实现WebService服务
  • 招工招聘小程序系统开发——打造一站式招聘服务平台
  • duiLib 自定义资源目录
  • C语言《智能自平衡小车,实现平衡功能的基础上,加入了超声波避障、超声波跟随、蓝牙遥控等功能》+源代码+文档说明
  • ECharts从入门到精通:解锁数据可视化的魔法世界
  • 游戏盾能够防御哪些类型攻击?从哪些方面防护?
  • Spark大数据分与实践笔记(第五章 HBase分布式数据库-04)
  • 【Dv3admin】ORM数据库无法查询的问题
  • Golang 指针与引用深度解析:对比 C/C++ 的内存管理哲学
  • DIY循迹模块多路改造指南
  • 伪装成华硕游戏辅助软件的ArmouryLoader:突破系统安全防护的恶意代码注入器
  • 什么是云原生?
  • Netty的Http解码器源码分析
  • 【解决方案】frida-ps -Ua报错unable to perform ptrace pokedata: I/O error
  • cgroups测试cpu bug
  • 达芬奇速成班-面板介绍
  • 什么是CHO细胞?
  • 深入剖析 StarRocks 与 Hive 的区别、使用场景及协同方案实践
  • Spring Cloud Gateway静态路由实战:Maven多模块高效配置指南
  • 安全和AI方向的学习路线
  • docker常用命令集(6)
  • Shopify Draggable + Vue 3 完整指南:打造现代化拖拽交互体验
  • Apache Ignite 与 Spring Data 集成
  • 人工智能与安全:智能安防的创新与伦理边界
  • 把Java程序部署到本地Docker
  • 常见CMS
  • NVIDIA Isaac平台推动医疗AI机器人发展研究
  • Hyperchain 的分级权限体系如何应对潜在的安全威胁和攻击?