chainlinkからETH価格を取得するコントラクトをデプロイしてみた(foundry)
素人備忘録ですので、自己責任で参考にしてください。
前提は、foundryがインストールされていることになります。
プロジェクトの作成
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をそれぞれ下記のように編集する。
※参考:
// 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);
}
}
// 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);
}
}
// 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用だったりがあるのではないかと考えている。
(完全に私のメモです)