原作者:Beary Cucumber
编译:Rama
基于 Pyth 构建按需价格馈送 🔮
预言机帮助将区块链与现实世界连接起来。现有的预言机模式围绕着预言机运营者不断地将价格更新推送到链上(并支付相关费用)。随着价格馈送数量和支持的链数量的增加,这种模式的扩展性可能会变差。
Pyth 网络旨在通过按需价格更新消除这种权衡,在这种模式下,用户仅在需要时才提取链上价格——点击这里了解更多。
本文将引导你完成创建一个智能合约的过程,该合约利用 Pyth 预言机来消费 ETH/USD 价格馈送。
交互概述
📋 要求
在开始之前,请确保您已经在计算机上安装并设置了以下内容。
- NodeJS v20.11.0 或更高版本
- pnpm
- jq ——用于处理 JSON 数据
- 配置了 Berachain Artio 网络的钱包
- 钱包中有 $BERA 或 Berachain 测试网代币 ——请参见 Berachain 水龙头
Foundry
本指南需要安装 Foundry。在终端窗口中运行:
curl -L https://foundry.paradigm.xyz | bash;
foundryup;
# foundryup installs the 'forge' and 'cast' binaries, used later
关更多安装说明,请参阅 Foundry 的安装指南。有关在 Berachain 上使用 Foundry 的更多详细信息,请参阅本指南。
创建我们的 Pyth 预言机项目
首先,我们将使用 Foundry 设置您的开发环境。
从创建一个新的项目文件夹并初始化 Foundry 开始:
forge init pyth-oracle --no-git --no-commit;
cd pyth-oracle;
# We observe the following basic layout
# .
# ├── foundry.toml
# ├── script
# │ └── Counter.s.sol
# ├── src
# │ └── Counter.sol
# └── test
# └── Counter.t.sol
安装 Pyth 依赖项
我们将使用 Pyth 的合约,因此您必须首先将 Pyth 的合约接口作为节点依赖项进行安装:
# FROM: ./pyth-oracle
pnpm init;
pnpm add @pythnetwork/pyth-sdk-solidity;
Forge 可以重新映射依赖项,使导入更加易读。因此,让我们重新映射我们的 Pyth 导入:
# FROM: ./pyth-oracle
echo "remappings = ['@pythnetwork/pyth-sdk-solidity/=node_modules/@pythnetwork/pyth-sdk-soli
编写 Oracle 消费合约
现在我们准备进入令人兴奋的部分,在 Solidity 智能合约中消费 Pyth 价格馈送。
创建一个新文件 ./src/ConsumerContract.sol
,并粘贴以下内容:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@pythnetwork/pyth-sdk-solidity/IPyth.sol";
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";
contract ConsumerContract {
IPyth pyth;
/**
* Network: Berachain Artio (testnet)
* Address: 0x8D254a21b3C86D32F7179855531CE99164721933
*/
constructor() {
pyth = IPyth(0x8D254a21b3C86D32F7179855531CE99164721933);
}
function updatePrice(bytes[] calldata priceUpdateData) public payable {
uint fee = pyth.getUpdateFee(priceUpdateData);
pyth.updatePriceFeeds{value: fee}(priceUpdateData);
}
function getPrice() public view returns (PythStructs.Price memory) {
// ETH/USD priceID
bytes32 priceID = 0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace;
return pyth.getPrice(priceID);
}
function getLatestPrice(
bytes[] calldata priceUpdateData
) public payable returns (PythStructs.Price memory) {
updatePrice(priceUpdateData);
return getPrice();
}
}
我们首先导入了 IPyth
和 PythStructs
,它们提供了与已部署的 Pyth 预言机合约交互的接口。有关使用 Pyth SDK 的更多信息,请参阅相关文档。
在构造函数中,我们将 pyth
实例连接到 Berachain Artio 测试网上部署的 Pyth 预言机,地址为 0x8D254a21b3C86D32F7179855531CE99164721933。
updatePrice
函数接受 priceUpdateData
作为输入,这是一个来自 Pyth 的链下签名价格更新(下文会讨论)。
价格更新后,可以调用 getPrice()
,它返回与请求的 priceId
对应的 Price
对象。这里我们使用的 priceId
是 0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace,对应 Pyth 的 ETH/USD 价格馈送。完整的可用价格馈送列表请参见此处。
getLatestPrice
函数简单地将上述两个调用聚合在一起。
(您可以删除项目中生成的 src/Counter.sol
、test/Counter.t.sol
和 script/Counter.s.sol
文件。)
部署智能合约
您几乎已经准备好将合约部署到 Berachain 了。首先,您需要为部署设置一个钱包。
部署设置
运行以下命令,将您的钱包私钥导入 Foundry 的密钥库(使用 deployer
别名):
cast wallet import deployer --interactive;
# [Example Output]
# Enter private key:
# Enter password:
# `deployer` keystore was saved successfully. Address: <YOUR_WALLET_ADDRESS>
确认钱包已导入,运行以下命令:
cast wallet list;
# [Example Output]
# deployer (Local)
让我们将 Berachain RPC 加载到终端会话中:
export BERACHAIN_ARTIO_RPC="https://rpc.ankr.com/berachain_testnet"
部署到 Berachain 测试网
首先,编译智能合约:
# FROM: ./pyth-oracle
forge build;
您会注意到多个构建输出出现在 ./out
目录中。
我们将使用 forge create
命令将新合约部署到 Berachain 测试网上(有关该命令的更多信息,请参阅此处):
c# FROM: ./pyth-oracle
forge create ./src/ConsumerContract.sol:ConsumerContract --rpc-url $BERACHAIN_ARTIO_RPC --account deployer
# [Expected Similar Output]:
# Enter keystore password:
# Deployer: 0x529CA3A690E1bB4e9F04d132bd99D4398f626A44
# Deployed to: 0x9106b2041C896224Af2142ea9C7349aa283Df7C6
# Transaction hash: 0xc8efdd3132080491b42c469fb2219bc6f0432981a46cdd3f6ae73b9e834ff4e4
请注意已部署合约的地址,您将在接下来的部分中需要它。
系统将提示您输入之前设置的密钥库密码。您需要拥有 $BERA 来支付部署费用。可以通过 https://artio.faucet.berachain.com/ 获取水龙头资金。
与您的智能合约交互
最后,我们将从已部署的智能合约中获取 ETH/USD 价格。
回想一下,我们在调用 updatePrice
之前需要获取 priceUpdateData
。我们通过 Hermes 获取此数据包,这是一个监听 Pyth 网络价格更新并通过 REST API 提供服务的网络服务。
使用我们的 ETH/USD priceId
发出请求以获取 priceUpdateData
:\
# FROM: ./pyth-oracle
curl -s "https://hermes.pyth.network/v2/updates/price/latest?&ids[]=0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace" | jq -r ".binary.data[0]" > price_update.txt
jq
工具用于将输出写入 price_update.txt
文件,方便后续检索。
一旦我们有了这些数据,就可以使用以下命令调用 updatePrice
,并传入从 Pyth 获取的数据包(将占位符替换为您已部署的合约地址):
# FROM: ./pyth-oracle
cast send <YOUR_DEPLOYED_CONTRACT> --rpc-url $BERACHAIN_ARTIO_RPC "updatePrice(bytes[])" "[0x`cat price_update.txt`]" --account deployer --value 0.0001ether
# [Expected Similar Output]:
# blockHash 0xf00e38ea8197d088973dc51502b9fb62d089ac31b6fe01002e83a969e9c05f93
# blockNumber 1037572
# contractAddress
# cumulativeGasUsed 208351
# effectiveGasPrice 3000000017
# from 0x529CA3A690E1bB4e9F04d132bd99D4398f626A44
接下来,我们使用 getPrice()
查询价格:
cast call <YOUR_DEPLOYED_CONTRACT> --rpc-url $BERACHAIN_ARTIO_RPC "getPrice()"
# [Expected Similar Output]
# 0x0000000000000000000000000000000000000000000000000000005eb4cf6d2800000000000000000000000000000000000000000000000000000000130c6cd8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000000000000000000000065ef9853
这将以 Solidity 的 Price
结构(来自 ./pyth-oracle/lib/pyth-sdk-solidity/PythStructs.sol
)提供我们 ETH/USD 的价格:
struct Price {
// Price
int64 price;
// Confidence interval around the price
uint64 conf;
// Price exponent
int32 expo;
// Unix timestamp describing when the price was published
uint publishTime;
}
要将十六进制输出解码为人类可读的格式,您可以使用以下 abi-decode
命令:
# FROM: ./pyth-oracle
cast abi-decode "getPrice()(int64,uint64,int32,uint)" <YOUR_GETPRICE_OUTPUT>
# [Example Decoded Output of ETH/USD Feed]
# 406760418600 [4.067e11]
# 319581400 [3.195e8]
# -8
# 1710200915 [1.71e9]
故障排除
如果您动作不够快,可能会遇到错误代码 0x19abf40e
,这是 StalePrice
错误。这意味着 price_update.txt
文件过旧,不能被合约使用。请重新运行本小节中的命令序列以重试。
错误代码 0x025dbdd4
代表 InsufficientFee
(费用不足)错误。尝试在 updatePrice
调用中增加 $BERA 的数值,例如 0.0005ether。
总结
恭喜,您已经成功部署了一个从 Pyth 预言机获取价格数据的智能合约,并在 Berachain 测试网上运行 🎉
🐻 完整代码库
如果您想查看最终代码并浏览其他指南,请查看 Berachain Pyth Guide Code。
https://github.com/berachain/guides/tree/main
🛠️ 想构建更多项目吗?
想在 Berachain 上构建更多内容并查看更多示例吗?请查看我们的 Berachain GitHub 指南仓库,其中包含各种实现示例,包括 NextJS、Hardhat、Viem、Foundry 等等。
寻求开发支持?
请务必加入我们的 Berachain Discord 服务器,并查看我们的开发者频道以提出问题。
❤️ 别忘了为这篇文章点赞支持 👏🏼
原创文章,作者:Rama Ai,如若转载,请注明出处:https://www.dappchaser.com/query-price-data-on-berachain-using-pyth-price-feeds/