NTTドコモR&Dの技術ブログです。

Ethereumで独自コントラクトのNFTを発行してみる & Managed Blockchain Queryを使ってみる

はじめに

NTTドコモ サービスイノベーション部 ビッグデータ基盤担当の渡邉です。1年目です。社内のビッグデータ基盤の保守運用や新規機能開発を担当しています。

最近、業務においてWeb3関係の研究開発に携わることになりました。学部生時代に触れたことがありましたが大学院では全く違う研究をしていたこともあり期間が空いてしまったので色々と勉強をし直しているところです。 今回は、テストチェーンの現状や簡単に独自コントラクトの作成を行い、最終的にNFT発行をゴールにしていきたいと思います。おまけでAWSのManaged Blockchain QueryでNFTをやり取りしたブロックを確認してみます。

テストネットについて

Ethereumでは正常に動作するのかの確認などをする目的としていくつかのテストネットが存在しています。

  • Ropsten
  • Kovan
  • Rinkeby

以前であればこの辺りが思いついたのですが、これらはEthereumのPoS移行に伴い廃止になりました。浦島太郎状態です。ですが検索をするとまだまだこれらを使用した情報が上位に表示されてくるのが実情であり日々updateが必要そうです。

現在主に使用できるのは以下の2つです。(2023年12月現在)

  • Sepolia
  • Goerli(非推奨)→Holesky

参考 : https://ethereum.org/ja/developers/docs/networks/

Goerliは近く廃止される予定で、Holeskyに移行予定となっています。アプリケーション開発目的では執筆現在ではSepoliaが推奨されているので今回はこちらを使用していきます。

NFTを発行してみる

1. 画像の準備とスクリプトの作成

今回はオープンソースのSolidityライブラリであるOpenZeppelinを利用して独自コントラクトのスクリプトを作成していきます。

WebUI上で手軽にスクリプトの作成ができるOpenZeppelin Contract Wizardがあるので、今回はこちらを使用してスクリプトの作成をしていきます。

https://wizard.openzeppelin.com/

上部で規格の種類が選択できますが、今回はNFTでよく使用されるERC721を選択します。

ERC721を選択

余談ですが、ERC1155という比較的新しい規格が出てこちらも使用することができますが、https://etherscan.io/ で確認をすると現状もまだどちらもNFT発行において選択されているようです。

設定は以下のように設定します。

コントラクトのメソッドの選択

Name,Symbol,Base URIは各自で設定してください。

Name,Symbolは自分が可愛がれるNFTの名前をつけましょう。今回は、私が撮影した写真フォルダから適当に選んだダムの写真からNFTを発行していきたいと思いますので、Dam-NFTと名付けておきます。

Base URIについて説明をすると、ここでNFTの根幹となるメタデータ(URIや画像など)Ethereumチェーン上では容量が大きいため保管することができません(厳密には大量のコストを費やせば保管は可能ですが非現実的です)なので、「オフチェーン」(=Ethereumチェーンの外)で保管することが一般的です。実際のところこのURIはファイルサーバでも良いのですが、せっかくNFTにしてもファイルサーバの管理者が勝手に書き換えたりすることができてしまうため、IPFS(InterPlanetary File System)が使用されています。

今回は、それに倣ってIPFSを使用してファイルをアップロードする方式を選択しています。自分用でのお試しであればS3でもストレージサービスでもなんでも良いと思います。(発行を体験する意味ではもはや画像すらいらない気がしますが、とはいえ適当な画像を指定したほうが最後に発行できたことが確認できるので適当な画像は用意することをお勧めします)IPFSを利用できるサービスはいくつかありますが、有償サービスであったりサービス内容が流動的であったりするので説明は割愛させていただきます。IPFSで実践される方は、アップロードした画像は基本的にインターネット上で流通し続けて自分の意思では削除できなくなってしまうものなので十分に注意をしてください。

Base URIにMint(≒NFTの発行)をした際にIDがURIの末尾に挿入され、NFTとしてMintされます。

また、別途JSONメタデータも準備する必要があるのでこちらも作成し、IPFSなどにアップロードします。

作成したjson

{
    "name": "Dam-NFT",
    "description": "Dam NFT",
    "image": "https://ipfs.io/ipfs/Qmbg7Xht1b6AP87SwVKrGPWEqEx9WoxLABP2puW1YcahoV",
    "attributes": [
        {
            "value": 10
        }
    ]
}

生成されたスクリプト

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

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract DamNFT is ERC721, ERC721URIStorage, Ownable {
    uint256 private _nextTokenId;

    constructor(address initialOwner)
        ERC721("Dam-NFT", "DAM")
        Ownable(initialOwner)
    {}

    function _baseURI() internal pure override returns (string memory) {
        return "https://ipfs.io/ipfs/";
    }

    function safeMint(address to, string memory uri) public onlyOwner {
        uint256 tokenId = _nextTokenId++;
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }

    // The following functions are overrides required by Solidity.

    function tokenURI(uint256 tokenId)
        public
        view
        override(ERC721, ERC721URIStorage)
        returns (string memory)
    {
        return super.tokenURI(tokenId);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, ERC721URIStorage)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}

2. コンパイル

OpenZeppelin Contracts Wizardではスクリプトの生成しかできないため、生成したコードのコンパイルとデプロイのためにはWEB IDEであるRemixを使用します。

OpenZeppelin Contracts Wizardの右上の「Open in Remix」からRemixで生成したスクリプトを開くことができます。(画像ではわかりやすくするためにファイル名を変更しています)

Remix上でコンパイル
左側の「Solidity Compiler」を選択し、Compileします。エラーが出なければコンパイル完了です。

3. ウォレットの準備

ここまで進めてきましたが、そもそもウォレットを所持しておらず、デプロイすることができません。なので、まずはウォレットの準備としてMetaMaskを使用していきます。MetaMaskはパスワードやリカバリーフレーズを忘れると再発行不可能です。また、不審なところに接続をしないようにご注意ください。

https://metamask.io/

拡張機能をブラウザにインストールし、アカウントを作成します。完了したら右上の「Ethereum Mainnet」から使用するチェーンを変更します。

Sepoliaを選択

「テストネットワークを表示」をオンにするとSepoliaが出てくるので今回はこれを使用していきます。

デプロイする上でEthereumの仕組み上、ネットワークの使用手数料としてGAS Feeを支払う必要があります。よって、Etherをある程度ウォレット上で保有している必要があります。

テストネットではfaucetと呼ばれるところからEtherを取得することができます。取得方法については様々な手段がありますが、執筆現在、Infuraやalchemyなどから提供をされています。仕組み上いつでも提供が保証されるものではないので詳細については省略させていただきます。

4. デプロイ

Remixに戻り、「Deploy & run trunsactions」を選択し、Environmentで「Injected Provider」を選択するとMetamaskとRemixを接続することができます。

MetamaskとRemixを接続
接続後、Deployボタンの右側にウォレットのIDをMetamaskで確認し貼り付けます。
GAS Feeの確認
そして、DeployをするとMatamask上でGAS Feeの確認を求められるので確認をします。

無事にデプロイされるとMetamask上で確認することができます。

デプロイの確認
また、これをクリックするとTransactionIDが確認でき、Etherscanでトランザクションを確認することもできます。

5. NFTの発行

ようやく、ここまでで独自コントラクトが作成され、NFT発行の準備が整いました。

コントラクトのメソッド
「Deployed Contracts」にコントラクトのメソッドが列挙されるので、この中の「safeMint」でNFTの発行をします。
safeMint
toには自分のウォレットのアドレス、uriにはアップロードしたIPFSなどのIDを入力し、transactを押します。再びMetamaskでのGAS Feeの確認があります。

少し待ち、NFTが発行されると、OpenSeaから確認することができます。

https://opensea.io/ja ではなく、テストネット用である https://testnets.opensea.io/ja にログインする必要があることに注意が必要です。

OpenSeaからDam-NFTを確認
確認することができました。

おまけ : Amazon Managed Blockchain Query で確認してみる

おまけとして、今回発行したスマートコントラクトをAmazon Managed Blockchain Queryから確認してみましょう。

Amazon Managed Blockchain Queryは、パブリックネットワークに対してトークンに対してAWS上のAPIを通して様々な情報をQuery形式で取得することができるマネージドサービスです。

注意点として、執筆時点ではバージニア北部(us-east-1)リージョンのみで利用可能な機能となっています。また、2023/10/23にSepoliaに対応したばかりの新しい機能です。

https://aws.amazon.com/jp/about-aws/whats-new/2023/10/amazon-managed-blockchain-query-sepolia-testnet/

コンソール上からクエリエディタを確認

  • ブロックチェーンネットワーク : ETHEREUM_SEPOLIA_TESTNET
  • クエリタイプ : GetTransaction
  • トランザクションハッシュ : 今回発行したトランザクションのハッシュ

クエリの実行結果

このようにクエリを実行することで、トランザクションの内容をAWS上でも確認をすることができました。

まとめ

今回は独自コントラクトでのNFT発行をしてみました。Ethereumを取り巻く環境も数年前とは変わっており、典型的な作業ではありますが、かなり変わった部分がありました。

これからも対外発信を続け、ぜひ力をつけていきたいと考えていますのでこのブログも含め注目していただければと思います。

最後までお読みいただきありがとうございました。

参考文献

https://ethereum.org/ja/developers/

https://sepolia.etherscan.io/

https://docs.alchemy.com/docs/how-to-develop-an-nft-smart-contract-erc721-with-alchemy

https://zenn.dev/zzz/articles/25a2ab19fc9185