基本可以了解喂价服务了。
数据提供商收集数据源,chainlink 节点接收数据,在chainlink的分布式网络进行共识,之后再输入数据给到专门部署再区块链上的chainlink合约,最后再将数据传给用户的智能合约。
chainlink在链上有两个合约,一个是代理合约(Proxy),另一个是聚合合约(Aggregator),我们用户使用的合约相当于是消费合约,我们先与代理合约进行交互,之后代理合约会与聚合合约交互,聚合合约从多个预言机节点收集数据,并通过特定的算法(如中位数算法)对数据进行聚合,以生成最终的可信数据,在返还给链上的代理合约,最后再传给消费合约
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)
,每个变量有特定的意义。让我们逐个分析这些变量的含义:
roundId
(uint80
)roundId
。这个 roundId
用于标识这是第几轮价格更新或报告。roundId
,你可以知道当前的价格数据是哪一轮生成的。answer
(int256
)answer
通常是某种资产的价格,例如 ETH/USD 或 BTC/USD 的价格。int256
是因为价格可能为负数(尽管在实际使用中很少见)。例如,它可以用于某些负值的经济数据。startedAt
(uint256
)startedAt
代表这一轮价格数据采集的开始时间,通常是 UNIX 时间戳(即从1970年1月1日以来的秒数)。updatedAt
(uint256
)updatedAt
代表预言机在这一轮价格更新的确切时间,也是 UNIX 时间戳格式。answeredInRound
(uint80
)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;
}
}
// 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");
}
}
在这个页面可以获得提供喂价服务的地址,就是我在代码中填入的地址
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!