おみくじNFTを作りました
NFT第2弾として、おみくじNFT を作ってみました。
- フルオンチェーンNFT
- drawOmikujiでおみくじを引けます (ガス代のみ)
- ランダムで大吉~大凶のNFTがもらえます
- burn可能です (お焚き上げ?)
- 発行数の制限はありません (何枚でもどうぞ)
- Polygonのメインネットに公開しました
コード解説
前回はとてもシンプルなNFTだったので、今回はいくつか新しいことにチャレンジしました。
- ERC721EnumerableとERC721Burnableを多重継承する
- ReentrancyGuardを使ってみる
- ランダム値を扱う
- 日本語を扱う
ERC721EnumerableとERC721Burnableを多重継承
totalSupplyを使いたかったのでERC721Enumerable、burnさせたかったのでERC721Burnableを継承しました。 しかし、前回の記事 で書いたようにtotalSupplyは使わないことになりました。
後で思ったのですが、まず2つを継承した ERC721EnumerableBurnable を作り、 それを継承して OmikujiNftを作ったほうが、コードの見通しがよくなったかもしれません。
ReentrancyGuardを使ってみる
リエントランシー攻撃対策としてdrawOmikuji関数にnonReentrantを付けています。 (Check-Effects-Interactionsパターンを守っていると思うので、無くてもいい気がしますが。)
ランダム値を扱う
uint256 rand = uint256(keccak256(abi.encodePacked(block.timestamp, tokenId))); uint8 kujiResult = uint8(rand % 7); // 0:大吉, 1:中吉, 2:小吉, 3:吉, 4:末吉, 5:凶, 6:大凶
block.timestampとtokenIdを使って擬似的なランダム値を求めて、 そこからおみくじの結果(大吉~大凶)を決めています。
日本語を扱う
Solidityの文字列リテラルでは日本語をそのまま使えないので、\x形式でエンコードするか、unicodeリテラルを使います。
string memory s = "大吉"; // エラー string memory s = unicode"大吉"; string memory s = "\xE5\xA4\xA7\xE5\x90\x89";
- Escape Unicode - Online Unicode Tools ←エンコードはここでできます
- Types — Solidity 0.8.7 documentation ←Unicode Literalsについて
メインネットへのデプロイ
今回、初めてPolygonのメインネットへデプロイしました。 基本的には テストネットへのデプロイ と同じです。
truffle-config.jsのnetworksの設定に matic_mainnet を追加します。
networks: { ... matic_mainnet: { provider: () => new HDWalletProvider(mnemonic, `https://matic-mainnet.chainstacklabs.com`), network_id: 137, confirmations: 2, timeoutBlocks: 200, skipDryRun: true }, },
マイグレーションを実行して、しばらく待てばデプロイ完了です。
> truffle migrate --network matic_mainnet
デプロイは無事にできたのですが、その後にconsoleでコントラクトを触っていると、 なぜか応答しなくなる、という問題が繰り返し発生しました。
Polygonでトランザクションが詰まっていたのかもしれませんし、 truffle側に問題があったのかもしれません。 (原因はよくわかりませんが、無事にデプロイできてるので、良しとします。。。 )
おわりに
次回は、発行数に制限のあるタイプのNFTを考えています。