FoundryのローカルネットにゲームアイテムNFTをデプロイする
Foundryで、ゲームアイテムのNFTを作成してローカルネットにデプロイする方法を紹介します。
Foundryの初期設定がまだの方は、こちらの記事を参考にしてください。
Foundryのプロジェクトを作成します。
forge init nft_foundry
作成したプロジェクトに移動します。
cd nft_foundry
NFTの規格であるERC721を実装するために、SolmateとOpenZeppelinをインストールします。
forge install transmissions11/solmate Openzeppelin/openzeppelin-contracts
インストールが完了したフォルダー構造は下記になります。
$ tree . -L 2
.
├── README.md
├── foundry.toml
├── lib
│ ├── forge-std
│ ├── openzeppelin-contracts
│ └── solmate
├── script
│ └── Counter.s.sol
├── src
│ └── Counter.sol
└── test
└── Counter.t.sol
8 directories, 5 files
VSCodeを開きます。
code .
src/Counter.solのファイル名をGameItem.solに変更します
mv src/Counter.sol src/GameItem.sol
NFTをミントするコードを貼り付けます。
// contracts/GameItem.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {ERC721URIStorage, ERC721} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
contract GameItem is ERC721URIStorage {
uint256 private _nextTokenId;
constructor() ERC721("GameItem", "ITM") {}
function awardItem(
address player,
string memory tokenURI
) public returns (uint256) {
uint256 tokenId = _nextTokenId++;
_mint(player, tokenId);
_setTokenURI(tokenId, tokenURI);
return tokenId;
}
}
ビルドできるか確認します。
forge build
[⠢] Compiling...
[⠊] Compiling 1 files with Solc 0.8.28
[⠒] Solc 0.8.28 finished in 1.73s
Compiler run successful!
次にテストコードを変更します。
ファイル名をGameItem.t.solにして、テストコードを置き換えます。
// test/GameItem.t.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;
import {Test, console} from "forge-std/Test.sol";
import {GameItem} from "../src/GameItem.sol";
contract GameItemTest is Test {
GameItem public gameItem;
address public playerAddress;
function setUp() public {
gameItem = new GameItem();
playerAddress = address(0x123); // テスト用のアドレス
}
function test_AwardItem() public {
uint256 itemIndex = gameItem.awardItem(
playerAddress,
"https://game.example/item-id-8u5h2m.json"
);
assertEq(itemIndex, 0);
}
}
テストコマンドを実行して、テストします。
forge test
[⠒] Compiling...
No files changed, compilation skipped
Ran 1 test for test/GameItem.t.sol:GameItemTest
[PASS] test_AwardItem() (gas: 148104)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 21.54ms (7.22ms CPU time)
Ran 1 test suite in 364.75ms (21.54ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)
最後にローカルネットワークに、作成したNFTコントラクトをデプロイします。
anvilコマンドで、Foundryのローカルネットを立ち上げます。
anvil
_ _
(_) | |
__ _ _ __ __ __ _ | |
/ _` | | '_ \ \ \ / / | | | |
| (_| | | | | | \ V / | | | |
\__,_| |_| |_| \_/ |_| |_|
0.2.0 (58bf161 2024-11-07T00:21:15.535888000Z)
https://github.com/foundry-rs/foundry
Available Accounts
==================
(0) 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000.000000000000000000 ETH)
Private Keys
==================
(0) 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
デプロイ用のスクリプトを作成します。
playerAddressにローカルのAccountsを入れます。
// script/GameItem.s.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {GameItem} from "../src/GameItem.sol";
contract GameItemScript is Script {
function run() external {
// デプロイ用のアカウントとネットワークの設定を開始
vm.startBroadcast();
// GameItem コントラクトをデプロイ
GameItem gameItem = new GameItem();
console.log("GameItem contract deployed at:", address(gameItem));
// トークンを発行するためのプレイヤーアドレスとトークンURIを設定
address playerAddress = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; // ローカルのアドレスに置き換えてください
string memory tokenURI = "https://game.example/item-id-8u5h2m.json";
// awardItem 関数を呼び出してトークンを発行
uint256 tokenId = gameItem.awardItem(playerAddress, tokenURI);
console.log("Awarded token ID:", tokenId);
// 実行完了
vm.stopBroadcast();
}
}
以下のコマンドで、ローカルネットにデプロイします。
forge script script/GameItem.s.sol:GameItemScript --fork-url http://localhost:8545 \
--private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
--broadcast
[⠢] Compiling...
No files changed, compilation skipped
Script ran successfully.
== Logs ==
GameItem contract deployed at: 0x5FbDB2315678afecb367f032d93F642f64180aa3
Awarded token ID: 0
## Setting up 1 EVM.
==========================
Chain 31337
Estimated gas price: 2.000000001 gwei
Estimated total gas used for script: 1725283
Estimated amount required: 0.003450566001725283 ETH
==========================
SIMULATION COMPLETE. To broadcast these transactions, add --broadcast and wallet configuration(s) to the previous command. See forge script --help for more.
Transactions saved to: /Users/maehara/Documents/nft_foundry/broadcast/GameItem.s.sol/31337/dry-run/run-latest.json
Sensitive values saved to: /Users/maehara/Documents/nft_foundry/cache/GameItem.s.sol/31337/dry-run/run-latest.json
Castコマンドで確認します。
cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 \
"ownerOf(uint256)" 0 \
--rpc-url http://localhost:8545
0x0000000000000000000000001234567890123456789012345678901234567890
FoundryのローカルネットにアイテムNFTをデプロイできました!