Pyth Price Feedsを使ったBerachain上の価格データの照会 [Berachain翻訳]


:::note info
本記事は下記の翻訳となります。
[『Query Price Data on Berachain using Pyth Price Feeds』](https://blog.berachain.com/blog/query-price-data-on-berachain-using-pyth-price-feeds)
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1926720/84194477-58dc-c917-b1f2-b0024cd072a9.png)

## Pyth を使用してオンデマンド価格フィードを構築する 🔮

オラクルは、ブロックチェーンと現実世界をつなぐ役割を果たします。既存のオラクルのパラダイムは、オラクルオペレータが連続して価格の更新をオンチェーンにプッシュし（関連する手数料を支払う）、価格フィードとサポートされるチェーンの数が増えるとスケーリングが悪化する可能性があります。

[**_Pyth Network_**](https://pyth.network/?ref=berachain.ghost.io)は、ユーザーが必要な時にのみオンチェーンの価格を取得することで、このトレードオフを解消することを目指しています。詳細は[こちら](https://pyth.network/blog/pyth-a-new-model-to-the-price-oracle?ref=berachain.ghost.io)をご覧ください。

**この記事では、Pyth オラクルを活用して ETH/USD 価格フィードを消費するスマートコントラクトの作成手順を案内します。**

![](https://super-translator.inaridiy.workers.dev/assets/image/06b2bc17-f496-4358-8e8e-85358bedce76)
_Overview of Interactions_

### 📋 要件

次に進む前に、コンピュータに以下のものがインストールされ、セットアップされていることを確認してください。

- NodeJS `v20.11.0` 以上
- [pnpm](https://pnpm.io/installation?ref=berachain.ghost.io)
- [jq](https://jqlang.github.io/jq/download/?ref=berachain.ghost.io) — JSON データの処理に使用します
- [**Berachain Artio Network**](https://docs.berachain.com/developers/?ref=berachain.ghost.io)で構成されたウォレット
- そのウォレットに`$BERA`または Berachain テストネットトークンがあること  — [**_Berachain Faucet_**](http://artio.faucet.berachain.com/?ref=berachain.ghost.io)を参照してください

### Foundry

このガイドでは Foundry のインストールが必要です。ターミナルウィンドウで次のコマンドを実行してください。

```terminal
curl -L https://foundry.paradigm.xyz | bash;

foundryup;
# foundryup installs the 'forge' and 'cast' binaries, used later
```

インストール手順の詳細については、Foundry の[インストールガイド](https://book.getfoundry.sh/getting-started/installation?ref=berachain.ghost.io)を参照してください。Berachain で Foundry を使用する詳細については、この[ガイド](https://docs.berachain.com/developers/guides/create-erc20-contract-using-foundry?ref=berachain.ghost.io)を参照してください。

### Pyth Oracle プロジェクトの作成

まず、Foundry を使用して開発環境をセットアップします。

新しいプロジェクトフォルダを作成し、Foundry を初期化します：

```terminal
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 のコントラクトインターフェースをノードの依存関係としてインストールする必要があります。

```terminal
# FROM: ./pyth-oracle

pnpm init;
pnpm add @pythnetwork/pyth-sdk-solidity;
```

Forge は依存関係を remap して、インポートをより読みやすくすることができます。したがって、Pyth のインポートを remap しましょう:

```terminal
# FROM: ./pyth-oracle

echo "remappings = ['@pythnetwork/pyth-sdk-solidity/=node_modules/@pythnetwork/pyth-sdk-solidity']" >> ./foundry.toml
```

### Oracle Consumer コントラクトの作成

さあ、Solidity スマートコントラクトで Pyth の価格フィードを消費するエキサイティングな部分に入っていきましょう。

新しいファイル `./src/ConsumerContract.sol` を作成し、以下のコードを貼り付けてください。

```solidity
// 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`を**import**しています。これにより、デプロイされた Pyth オラクルコントラクトとのやり取りのためのインターフェースが提供されます。[Pyth SDK](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ethereum/sdk/solidity?ref=berachain.ghost.io)の使用方法についての詳細は、こちらをご覧ください。

**constructor**では、Berachain Artio テストネット上に展開された Pyth オラクルに`pyth`インスタンスを接続しています。アドレスは[`0x8D254a21b3C86D32F7179855531CE99164721933`](https://artio.beratrail.io/address/0x8D254a21b3C86D32F7179855531CE99164721933/contract/80085/code?ref=berachain.ghost.io)です。

`**updatePrice**`関数は、Pyth オフチェーンからストリーミングされる署名付き価格更新データである`priceUpdateData`を入力として受け取ります（後述）。

価格の更新後には、`**getPrice()**`を呼び出すことができます。これにより、要求された`priceId`に対応する`Price`オブジェクトが返されます。ここでは、`priceId`として`0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace`を使用しています。使用可能なフィードの完全なリストについては、[**こちら**](https://pyth.network/developers/price-feed-ids?ref=berachain.ghost.io)をご覧ください。

`getLatestPrice`は、上記の 2 つの呼び出しを単純に集約しています。
（プロジェクトで生成された`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>
```

ウォレットがインポートされたことを確認するには、次のコマンドを実行してください:

```terminal
cast wallet list;

# [Example Output]
# deployer (Local)
```

ターミナルセッションに Berachain RPC をロードしましょう：

```terminal
export BERACHAIN_ARTIO_RPC="https://rpc.ankr.com/berachain_testnet"
```

### Berachain テストネットへのデプロイ

まず、スマートコントラクトをコンパイルします：

```terminal
# FROM: ./pyth-oracle

forge build;
```

`./out`ディレクトリにいくつかのビルド出力が表示されることに気付くでしょう。

新しいコントラクトを Berachain Testnet に展開するために、`forge create`コマンドを利用します（コマンドの詳細は[こちら](https://book.getfoundry.sh/reference/forge/forge-create?ref=berachain.ghost.io)を参照してください）:

```terminal
# 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
```

**Take note of the deployed contract address**, 次のセクションで必要になります。

先に設定したキーストアパスワードの入力を求められます。デプロイメント費用の支払いに$BERA が必要です。Faucet 資金は[https://artio.faucet.berachain.com/](https://artio.faucet.berachain.com/?ref=berachain.ghost.io)で入手できます。

## スマートコントラクトとのやり取り

最後に、デプロイされたスマートコントラクトから`ETH/USD`の価格を取得します。

`updatePrice`を呼び出す前に、`priceUpdateData`を取得する必要がありました。これは、[Hermes](https://github.com/pyth-network/pyth-crosschain/tree/main/hermes?ref=berachain.ghost.io)を使用して取得します。Hermes は、Pyth Network から価格の更新を受信し、REST API を介して提供するウェブサービスです。

`ETH/USD`の priceId を使用して、`priceUpdateData`を取得するためのリクエストを行います:

```terminal
# 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 から受け取ったペイロードを使用し、デプロイされたコントラクトでプレースホルダーを置き換えます。

```terminal
# 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` 価格を提供します：

```solidity
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`コマンドを使うことができます:

```terminal
# 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`に上げてみるのがよいでしょう。

## まとめ

おめでとうございます！あなたは、Berachain Testnet 上の Pyth オラクルから価格データを引き出すスマートコントラクトのデプロイに成功しました 🎉。

---

### 🐻 Full Code Repository

最終的なコードや他のガイドを見たい場合は、[**_Berachain Pyth Guide Code_**](https://github.com/berachain/guides/tree/main/apps/pyth-oracle?ref=berachain.ghost.io)を参照してください。

https://github.com/berachain/guides/tree/main/apps/pyth-oracle?ref=berachain.ghost.io

### 🛠️ さらに開発を進めたいですか？

Berachain でさらに開発を進めたい、より多くの実装例を見たいとお考えですか？私たちの[**_Berachain GitHub ガイドリポジトリ_**](https://github.com/berachain/guides?ref=berachain.ghost.io)をぜひご覧ください。このリポジトリには、NextJS、Hardhat、Viem、Foundry など、様々な技術を使用した幅広い実装例が用意されています。

https://github.com/berachain/guides/tree/main?ref=berachain.ghost.io

より詳細な情報を探求したい場合は、[**_Berachain ドキュメント_**](https://docs.berachain.com/?ref=berachain.ghost.io)をご覧ください。

https://docs.berachain.com/?ref=berachain.ghost.io

### 開発者サポートをお探しですか？

質問をするために、[**_Berachain Discord_**](https://discord.com/invite/berachain?ref=berachain.ghost.io)サーバーに参加し、開発者チャンネルをチェックしてください。

❤️ この記事に対して愛を示すのを忘れないでください 👏🏼

---

:::note info
【Sunrise とは】
Sunrise は Proof of Liquidity(PoL)と Fee Abstraction（手数料抽象化）を備えたデータ可用性レイヤーです。 私たちは DA の体験を再構築し、多様なエコシステムからのモジュラー型流動性を活用してロールアップを立ち上げています。

- [Sunrise - Specialized DA Layer for Proof of Liquidity](https://sunriselayer.io/)
- [Sunrise / Gluon Docs](https://docs.sunriselayer.io/)

【Social Links】

- [X(旧 Twitter)[英語])](https://twitter.com/SunriseLayer)
- [X(旧 Twitter)[日本語])](https://twitter.com/SunriseLayer)
- [Discord Community](https://discord.com/invite/sunrise)
- [Medium](https://sunriselayer.medium.com/)
- [Github](https://github.com/sunriselayer)
- [Linkedin](https://www.linkedin.com/company/sunriselayer)

【お問合せ】
Sunrise へのお問い合わせはこちらから 👉 [Google Form](https://forms.gle/h8RVahxRtXUvYwnv6)

![1080x360.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839047/8971d83b-3331-4757-dc72-320d28618735.jpeg)

:::