本記事は下記の翻訳となります。
『Fair Random NFT Mints with Pyth Entropy on Berachain』
Pyth を使用したオンデマンド価格フィードの構築 🔮
オラクルは、ブロックチェーンを実世界と接続する役割を果たします。既存のオラクルパラダイムは、オラクル運営者が継続的に価格更新をオンチェーンにプッシュする(および関連する手数料を支払う)ことを中心に展開されています。これは、価格フィードとサポートされるチェーンの数が増加するにつれて、スケールが悪化する可能性があります。
Pyth Networkは、オンデマンドの価格更新を使用してこのトレードオフを解消することを目指しています。ユーザーは必要な時にのみオンチェーン価格を取得します - 詳細はこちらをご覧ください。
この記事では、Pyth オラクルを活用して ETH/USD 価格フィードを利用するスマートコントラクトを作成するプロセスについて説明します。
相互作用の概要
📋 要件
先に進む前に、以下のものがコンピュータにインストールされ、セットアップされていることを確認してください。
- NodeJS
v20.11.0
以上 - pnpm
- jq - JSON データの処理に使用
- Berachain Artio Networkで設定されたウォレット
- そのウォレット内の
$BERA
または Berachain Testnet トークン - Berachain Faucetを参照
Foundry
このガイドでは Foundry のインストールが必要です。ターミナルウィンドウで以下を実行してください:
curl -L https://foundry.paradigm.xyz | bash;
foundryup;
# foundryupは'forge'と'cast'バイナリをインストールします(後で使用)
インストールの詳細については、Foundry のインストールガイドを参照してください。Berachain で Foundry を使用する詳細については、このガイドを参照してください。
Pyth Oracle プロジェクトの作成
まず、Foundry を使用して開発環境をセットアップします。
新しいプロジェクトフォルダを作成し、Foundry を初期化します:
forge init pyth-oracle --no-git --no-commit;
cd pyth-oracle;
# 以下の基本的なレイアウトが表示されます
# .
# ├── foundry.toml
# ├── script
# │ └── Counter.s.sol
# ├── src
# │ └── Counter.sol
# └── test
# └── Counter.t.sol
Pyth の依存関係のインストール
Pyth のコントラクトを活用するため、まず Pyth のコントラクトインターフェースを node 依存関係としてインストールする必要があります:
# 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-solidity']" >> ./foundry.toml
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();
}
}
これを詳しく見ていきましょう:
まず、デプロイされた Pyth オラクルコントラクトと対話するためのインターフェースを提供するIPyth
とPythStructs
をインポートします。Pyth SDKの使用に関する詳細情報をご覧ください。
コンストラクタでは、Berachain Artio Testnet にデプロイされた0x8D254a21b3C86D32F7179855531CE99164721933
の Pyth オラクルにpyth
インスタンスを接続します。
**updatePrice**
関数は、Pyth がオフチェーンでストリーミングする署名付き価格更新であるpriceUpdateData
を入力として受け取ります(後述)。
価格更新の後、**getPrice()**
を呼び出すことができ、これは要求されたpriceId
に対応するPrice
オブジェクトを返します。ここでは、Pyth のETH/USD
価格フィードに対応する0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace
というpriceId
を使用しています。利用可能なフィードの完全なリストはこちらをご覧ください。
getLatestPrice
は上記の 2 つの呼び出しを単に集約したものです。
(プロジェクトと共に生成されたsrc/Counter.sol
、test/Counter.t.sol
、script/Counter.s.sol
は削除してかまいません)
スマートコントラクトのデプロイ
Berachain にコントラクトをデプロイする準備がほぼ整いました。まず、デプロイメント用のウォレットをセットアップする必要があります。
デプロイメントの準備
以下を実行して、ウォレットの秘密鍵を Foundry のキーストアにdeployer
エイリアスでインポートします:
cast wallet import deployer --interactive;
# [出力例]
# Enter private key:
# Enter password:
# `deployer` keystore was saved successfully. Address: <YOUR_WALLET_ADDRESS>
以下を実行して、ウォレットが正しくインポートされたことを確認します:
cast wallet list;
# [出力例]
# deployer (Local)
Berachain RPC をターミナルセッションにロードしましょう:
export BERACHAIN_ARTIO_RPC="https://rpc.ankr.com/berachain_testnet"
Berachain Testnet へのデプロイ
まず、スマートコントラクトをコンパイルします:
# FROM: ./pyth-oracle
forge build;
./out
ディレクトリに多くのビルド出力が表示されることに気付くでしょう。
新しいコントラクトを Berachain Testnet にデプロイするためにforge create
コマンドを使用します(コマンドの詳細についてはこちらを参照):
# FROM: ./pyth-oracle
forge create ./src/ConsumerContract.sol:ConsumerContract --rpc-url $BERACHAIN_ARTIO_RPC --account deployer
# [期待される類似の出力]:
# Enter keystore password:
# Deployer: 0x529CA3A690E1bB4e9F04d132bd99D4398f626A44
# Deployed to: 0x9106b2041C896224Af2142ea9C7349aa283Df7C6
# Transaction hash: 0xc8efdd3132080491b42c469fb2219bc6f0432981a46cdd3f6ae73b9e834ff4e4
デプロイされたコントラクトアドレスをメモしておいてください、次のセクションで必要になります。
先ほど設定したキーストアのパスワードを入力するよう求められます。デプロイメント手数料を支払うために$BERA が必要です。フォーセットの資金はhttps://artio.faucet.berachain.com/で入手可能です。
スマートコントラクトとの対話
最後に、デプロイしたスマートコントラクト内からETH/USD
価格を取得します。
updatePrice
を呼び出す前にpriceUpdateData
を取得する必要があったことを思い出してください。このペイロードはHermesを使用して取得します。これは、Pyth Network の価格更新をリッスンし、REST API を介して提供する Web サービスです。
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
# [期待される類似の出力]:
# blockHash 0xf00e38ea8197d088973dc51502b9fb62d089ac31b6fe01002e83a969e9c05f93
# blockNumber 1037572
# contractAddress
# cumulativeGasUsed 208351
# effectiveGasPrice 3000000017
# from 0x529CA3A690E1bB4e9F04d132bd99D4398f626A44
# ...
次に、getPrice()
で価格を照会します:
cast call <YOUR_DEPLOYED_CONTRACT> --rpc-url $BERACHAIN_ARTIO_RPC "getPrice()"
# [期待される類似の出力]
# 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;
}
16 進数の出力を人間が読める形式にデコードするには、以下のabi-decode
コマンドを使用できます:
# FROM: ./pyth-oracle
cast abi-decode "getPrice()(int64,uint64,int32,uint)" <YOUR_GETPRICE_OUTPUT>
# [ETH/USDフィードのデコード出力例]
# 406760418600 [4.067e11]
# 319581400 [3.195e8]
# -8
# 1710200915 [1.71e9]
トラブルシューティング
- 十分に早く行動しないと、
StalePrice
エラーを表す0x19abf40e
というエラーに遭遇する可能性があります。これはprice_update.txt
がコントラクトで使用するには古すぎたことを意味します。このサブセクションのコマンドのシーケンスを再実行して再試行してください。 - エラーコード
0x025dbdd4
はInsufficientFee
エラーを表します。updatePrice
呼び出しの$BERA 値を例えば0.0005ether
に引き上げてみてください。
まとめ
おめでとうございます!Berachain Testnet で Pyth オラクルから価格データを取得するスマートコントラクトの開発に成功しました 🎉
🐻 完全なコードリポジトリ
最終的なコードを確認し、他のガイドを見たい場合は、Berachain Pyth Guide Codeをチェックしてください。
🛠️ さらに構築したい場合は?
Berachain でさらに構築し、より多くの例を見たい場合は、Berachain GitHub Guides リポジトリをご覧ください。NextJS、Hardhat、Viem、Foundry などを含む、幅広い実装例があります。
より詳細な情報を探索したい場合は、Berachain Docsをご覧ください。
開発サポートをお探しですか?
Berachain Discordサーバーに参加し、開発者チャンネルで質問をしてください。
❤️ この記事への愛を示すことを忘れずに 👏🏼
【Sunrise とは】
Sunrise は Proof of Liquidity(PoL)と Fee Abstraction(手数料抽象化)を備えたデータ可用性レイヤーです。 私たちは DA の体験を再構築し、多様なエコシステムからのモジュラー型流動性を活用してロールアップを立ち上げています。
【Social Links】
【お問合せ】
Sunrise へのお問い合わせはこちらから 👉 Google Form