freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

chainlink喂价服务讲解
浪迹陨灭nd 2025-03-05 20:45:39 13554
所属地 江苏省

data feed(喂价)

业务流程

数据提供商收集数据源,chainlink 节点接收数据,在chainlink的分布式网络进行共识,之后再输入数据给到专门部署再区块链上的chainlink合约,最后再将数据传给用户的智能合约。

具体流程

chainlink在链上有两个合约,一个是代理合约(Proxy),另一个是聚合合约(Aggregator),我们用户使用的合约相当于是消费合约,我们先与代理合约进行交互,之后代理合约会与聚合合约交互,聚合合约从多个预言机节点收集数据,并通过特定的算法(如中位数算法)对数据进行聚合,以生成最终的可信数据,在返还给链上的代理合约,最后再传给消费合约

调用的chainlink接口

AggregatorV3Interface


// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // solhint-disable-next-line interface-starts-with-i interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); function getRoundData( uint80 _roundId ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); }

上述变量的含义

这个函数签名的返回类型是 (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound),每个变量有特定的意义。让我们逐个分析这些变量的含义:

  1. roundId(uint80)
  • 含义:这是当前价格更新的“轮次ID”(Round ID)。
  • 解释:Chainlink 预言机是通过多轮次的方式来聚合数据的,每一轮都会有一个唯一的 roundId。这个 roundId用于标识这是第几轮价格更新或报告。
  • 用途:通过 roundId,你可以知道当前的价格数据是哪一轮生成的。
  1. answer(int256)
  • 含义:这是预言机返回的实际答案,即你请求的数据结果。
  • 解释:对于价格预言机来说,answer通常是某种资产的价格,例如 ETH/USD 或 BTC/USD 的价格。
  • 类型为 int256是因为价格可能为负数(尽管在实际使用中很少见)。例如,它可以用于某些负值的经济数据。
  1. startedAt(uint256)
  • 含义:这是当前这一轮价格更新的启动时间。
  • 解释startedAt代表这一轮价格数据采集的开始时间,通常是 UNIX 时间戳(即从1970年1月1日以来的秒数)。
  • 用途:通过这个时间戳,你可以知道这一轮价格数据什么时候开始聚合的。
  1. updatedAt(uint256)
  • 含义:这是当前价格更新的时间戳。
  • 解释updatedAt代表预言机在这一轮价格更新的确切时间,也是 UNIX 时间戳格式。
  • 用途:可以用于追踪价格数据的最新更新时间,判断数据是否及时。
  1. answeredInRound(uint80)
  • 含义:这是价格数据成功报告的轮次ID。
  • 解释:这表示在哪一轮数据收集的最终答案是有效的。如果 answeredInRound小于 roundId,则表明当前轮次的结果还没有最终确定或回答可能是来自于前几轮。
  • 用途:用来判断当前轮次的 answer是在哪一轮被有效报告的,这可以帮助你验证数据的准确性。

查询数据

// SPDX-License-Identifier: MIT 
import "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol";
pragma solidity ^0.8.7;

contract FeedData{  
  AggregatorV3Interface private priceFeed;
  constructor(){
    priceFeed = AggregatorV3Interface(0x5fb1616F78dA7aFC9FF79e0371741a747D2a7F22);
  }

  function getLatestPrice() public view returns (int256) {
        (, int256 answer, , , ) = priceFeed.latestRoundData(); //该地址支持这个方法
        return answer;
    }
}
  • 根据接口合约可以知道,会返回五个数据,不需要的数据我们可以直接置空,但是数量要一致

实现 ETH/USTD的转换


// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import {AggregatorV3Interface} from "@chainlink/contracts@1.2.0/src/v0.8/shared/interfaces/AggregatorV3Interface.sol"; library PriceConverter{ function getVersion() internal view returns (uint256){ AggregatorV3Interface priceFeed = AggregatorV3Interface(0x694AA1769357215DE4FAC081bf1f309aDC325306); return priceFeed.version(); } function getPrice() internal view returns (uint256) { AggregatorV3Interface priceFeed = AggregatorV3Interface(0x694AA1769357215DE4FAC081bf1f309aDC325306);//实例化一个对象,通过接口,将有对应功能的节点地址导入 (, int256 price, , ,) = priceFeed.latestRoundData();//选择性返回 price uint8 decimals = getDecimals(); uint256 adjustedPrice = uint256(price) * 10**(18 - uint256(decimals));//都可以以最小单位 wei来计算。 return adjustedPrice; } function getDecimals() internal view returns (uint8){ AggregatorV3Interface priceFeed = AggregatorV3Interface(0x694AA1769357215DE4FAC081bf1f309aDC325306); return priceFeed.decimals(); } function getConversionRate(uint ethAmount) internal view returns (uint256) { uint256 ethprice = getPrice(); uint256 ethAmountInUsd = (ethprice * ethAmount) / 1e18; //ethAmount 是以 wei 为单位的 ETH 数量,所以除以 1e18 return ethAmountInUsd; } }

上面的代码使用 library库 封装的函数功能


// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import "./priceConverter.sol"; contract FundMe { using PriceConverter for uint256; event Funded(address indexed from,uint256 amount); mapping (address => uint256) public addressToAmountFunded; address[] public funders; address public owner; modifier onlyOwner(){ require(msg.sender == owner); _; } constructor(){ owner = msg.sender; } uint256 public minimumUsd = 50 * 1e18; function fund() public payable{ require(msg.value.getConversionRate() > minimumUsd,"didn't send enough"); //msg.sender会被当作第一个参数传入函数中,如果要传入第二个参数,现在库合约中定义,再从括号内传入即可 funders.push(msg.sender); addressToAmountFunded[msg.sender] = msg.value; } function withdraw() public onlyOwner{ for (uint i; i < funders.length; ++i){ address funder = funders[i]; addressToAmountFunded[funder] = 0; } funders = new address[](0); //重置数组 payable(msg.sender).transfer(address(this).balance); //将资金转给msg.sender,注意:如果有多个收款人,这个函数只能转给第一个收款人 //bool sendSuccess = payable(msg.sender).send(address(this).balance); //require(sendSuccess,"Send Failed"); //(bool callSuccess,bytes memory returnData) = payable(msg.sender).call{value: address(this).balance}(""); //require(callSuccess,"call failed"); } }

具体操作

image-20241101200631920.png

在这个页面可以获得提供喂价服务的地址,就是我在代码中填入的地址

# 区块链技术 # 区块链开发
本文为 浪迹陨灭nd 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
浪迹陨灭nd LV.4
专注于solidity智能合约开发
  • 6 文章数
  • 0 关注者
稳定币项目构建 (二)
2025-03-06
Chainlink--CCIP--NFT 讲解
2025-03-06
稳定币项目构建 (一)
2025-03-05
文章目录