chainlinkからETH価格を取得するコントラクトをデプロイしてみた(foundry)

素人備忘録ですので、自己責任で参考にしてください。

前提は、foundryがインストールされていることになります。

参考:
https://www.solidity-in-foundry.com/Applications/Chainlink/ChainlinkDataFeeds/ChainlinkDataFeeds.html

プロジェクトの作成

chainlink_test(ディレクトリ)にデフォルトプロジェクトを作成
chainlink_testディレクトリが作成され、必要ファイルがその中に作成されます

forge init chainlink_test

chainlinkライブラリのインストール

chainlink_testディレクトリに移動してからインストール(chainlink/libにインストールする)
インストール前にgitのバッファサイズを増やしています

cd chainlink_test
git config --global http.postBuffer 524288000
forge install smartcontractkit/chainlink-brownie-contracts --no-commit

これでchainlink_test/lib内にchainlink-brownie-contractsディレクトリが追加される

chainlinkライブラリへのremapping設定

forgeにremappingを明示するためのremappingファイル(remapping.txtを作成)

forge remappings > remappings.txt

remapping.txtを編集

nano remapping.txt  #エディタでremapping.txtを開く

#下記のように中身を編集
forge-std/=lib/forge-std/src/
@chainlink/=lib/chainlink-brownie-contracts/contracts/src/
#保存はCtr+Xを押すと編集を保存するか聞かれるのでyを押してEnter

solidityファイルの作成

デフォルトテンプレートで作成したプロジェクトの各ファイルを編集する

Counter.sol、Counter.s.sol、Counter.t.solをそれぞれ
ChainlinkDetaFeeds.sol、ChainlinkDetaFeeds.s.sol、ChainlinkDataFeeds.t.solに名前変更

元々
名前変更後

ChainlinkDataFeeds.sol、ChainlinkDataFeeds.s.sol、ChainlinkDataFeeds.t.solをそれぞれ下記のように編集する。
※参考:

ChainlinkDataFeeds.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

// Importing the Chainlink Aggregator interface to interact with Chainlink price feeds.
import "@chainlink/v0.8/interfaces/AggregatorV3Interface.sol";

/**
 * @title ChainlinkDataFeeds
 * @dev This contract reads from Chainlink's price feed aggregator.
 */

contract ChainlinkDataFeeds {
    // Here we initialize an instance of the AggregatorV3Interface.
    AggregatorV3Interface internal immutable priceFeed;

    constructor(address _priceFeed) {
        priceFeed = AggregatorV3Interface(_priceFeed);
    }

    function getLatestPrice() public view returns (uint80 roundID, int price) {
        (roundID, price, , , ) = priceFeed.latestRoundData();
        return (roundID, price);
    }
}

ChainlinkDataFeeds.t.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.21;

import "forge-std/Test.sol";
import {ChainlinkDataFeeds} from "../src/ChainlinkDataFeeds.sol";
import {MockV3Aggregator} from "@chainlink/v0.8/tests/MockV3Aggregator.sol";

contract ChainlinkDataFeeds_test is Test {
    // Configuring the base data for the mock aggregator
    uint8 public _decimals = 8;
    int256 public _initialAnswer = 10 ** 18;

    // Initializing the contract instances
    ChainlinkDataFeeds public chainlinkDataFeeds;
    MockV3Aggregator public mockV3aggregator;

    // Seeting up the initial state
    function setUp() public {
        mockV3aggregator = new MockV3Aggregator(_decimals, _initialAnswer);
        chainlinkDataFeeds = new ChainlinkDataFeeds(address(mockV3aggregator));
    }

    // Checking if our contract can read data from the mock aggregator
    function testgetLatestPrice() public {
        (uint80 roundID, int256 price) = chainlinkDataFeeds.getLatestPrice();

        assertEq(price, _initialAnswer);
        assertEq(roundID, 1);
    }
}

ChainlinkDataFeeds.s.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.21;

import "forge-std/Script.sol";
import {ChainlinkDataFeeds} from "../src/ChainlinkDataFeeds.sol";

contract DeployDataFeed is Script {
    ChainlinkDataFeeds chainlinkDataFeeds;

    function run() external {
        // Using the envUint cheatcode we can read some env variables
        uint256 PrivateKey = vm.envUint("PRIVATE_KEY");

        // Anything within the broadcast cheatcodes is executed on-chain
        vm.startBroadcast(PrivateKey);
        chainlinkDataFeeds = new ChainlinkDataFeeds(
            0x694AA1769357215DE4FAC081bf1f309aDC325306
        );
        vm.stopBroadcast();
    }
}

forge buildおよびforge testが通ることを確認

ブロックチェーンにデプロイ(Sepolia)

.envファイルを作成
※.envファイルは絶対に.gitignoreに含めること!!!

SEPOLIA_RPC_URLにsepolia RPC URL
PRIVATE_KEYは自身のWalletの秘密鍵
ETHERSCAN_API_KEYはEtherScanで取得したAPI KEY

.env
(※xxxxは0x自身のWalletの秘密鍵とすること)

# Base RPC URLs
SEPOLIA_RPC_URL=zzzzzzzzzzz

# Private Key
PRIVATE_KEY=xxxxxxxxxxxxxxxxx

# Etherscan and Polygonscan API keys
ETHERSCAN_API_KEY=yyyyyyyyyyyyyyyy

環境変数を.envから読み込み

source .env

デプロイ

 forge script script/ChainlinkDataFeeds.s.sol:DeployDataFeed --rpc-url $SEPOLIA_RPC_URL --broadcast -vvvv --etherscan-api-key $ETHERSCAN_API_KEY --verify

正常に通るとtxハッシュとコントラクトアドレスが返ってくる

EtherScan(SepoliaTestnet)にてtxハッシュを検索

https://sepolia.etherscan.io/tx/0x8c149e922470995c74db15cffc5ef6eee8816e8181b46d6894dc9846dbac00f0

To:の部分にコントラクトアドレスがあるのでクリックして飛ぶ

https://sepolia.etherscan.io/address/0x6a919dac3e582b30a6863b4738a3f97684fefc0b

ContractタブのReadContractにてConnect Web3でWallet接続してgetLatestPriceをQueryすると、ETHの価格が取得できる。
decimal=8なので10^8で割ると約2572ドルと分かる(2024/09/22現在)。

ちなみに

このコードのまま.envファイルをBase Mainnetに合わせたものに変更してデプロイしたところ、デプロイは正常に完了したがBaseScanでgetLatestPriceをQueryするとエラーした。

おそらく本コードにおいてChainlinkから取得するETH価格はSepoliaネットワークのものであってBaseネットワークで機能させるにはそれ用のチューニングが必要と思われる←次の勉強課題

なんとなく、ChainlinkDataFeeds.s.sol内のnew ChainlinkDataFeeds();の引数となっているアドレスがSepolia用だったりBase用だったりがあるのではないかと考えている。
(完全に私のメモです)


いいなと思ったら応援しよう!