本研修の目的
本研修では、以下の対象者を想定してコースを立て付けています。
- web3開発として独自にスマートコントラクトを開発したい
- NFT関連に関心がある
- NFT技術の仕組みを理解したい
- 実践レベルで体系的に習得したい
本研修の学習内容
NFTとスマートコントラクトについて開発スキルを体系的に習得できることを目的とした研修内容となっております。
※本領域の技術進化のスピードが速く、サービス自体が終了したりバージョンアップに伴うコード変更が入る可能性がありますので、ご理解ください。
- ERC-721規格準拠のNFTスマートコントラクト開発方法(RemixIDE/Solidity/OpenZeppelin)
- RemixIDEによる開発方法の流れ
- Solidity/OpenZeppelinの基礎
- NFTの作成(mint)、削除(burn)、停止(pause)、権限移譲(approve)、移転(transfer)、資産情報紐付け(tokenURI)の仕組み
- NFTに付与するメタデータとコンテンツデータのオンチェーンとオフチェーン
- NFTのOpenSea上での管理の仕組み
- ランダムNFTのmint方法
- スマートコントラクトをテストネット、プライベートネットに展開する方法
- ブロックエクスプローラ(Etherescan)を使ったトランザクション調査
- スマートコントラクトのコードをEtherescanに公開する方法
- NFTスマートコントラクトのプログラムコードやNFTコンテンツデータの保存先確認方法
事前準備
本研修の前提準備
- インターネット接続可能なパソコン
- Chromeブラウザ
- Twitterアカウント(Ethereumテスト用チェーンの「Goerli」にてLINKトークンを取得するため)
- Googleアカウント(gmailアドレス)
- プログラム入門レベルの経験
- Ethereumもしくはブロックチェーンの入門レベルの知識や経験
本研修の開発環境
開発環境 | RemixIDE |
ブラウザ | Chrome |
開発言語 | Solidity |
ライブラリ | OpenZeppelin |
Ethereum規格 | ERC-721 |
ウォレット | Metamask |
ブロックチェーン(テストネット) | Ethereum Goerli |
エクスプローラ | Etherescan |
リポジトリ管理 | GitHub |
NFTマーケットプレイス | OpenSea |
分散型ストレージ | NFTStorage(IPFS/Pinata/FileCoin/ARweave) |
オンチェーンNFT画像データ形式 | SVG |
Third Partyサービス | Thirdweb, Bubble |
ブロックチェーンの基礎
- NFTがどのように構成されているのか
- EIP/ERC-721 Non-Fungible Token Standard
- 代表的なERC
- NFTの構造
- NFTコンテンツデータの配置
- NFT作成、変更、管理の仕組み
- スマートコントラクト
- スマートコントラクトによる状態管理
- ERC-721による機能定義
- ERC-721実装とNFT作成(mint)の仕組み
EIP/ERC-721 Non-Fungible Token Standard
EthereumにはNFTに関する標準規格があります。
ERC-721は、NFTに関する標準仕様やインターフェースを定義したもので、ERC-721に準拠した開発によりEthereumでNFTを管理できることができます。
- EIP(Ethereum Improvement Proposals)・・・Ethereumに関わる様々な改善提案
- ERC(Ethereum Request for Comments)・・・EthereumのNFTの機能提供を目的にスマートコントラクト内での標準APIを規定したもの
- EIP⊇ERC(ERCはEIPの部分集合)
- ERCxxx→xxx番目に提案されたERC(例 ERC-721は721番目に提案されたERC)
代表的なERC
Category | Contents | EIP/ERC number | Project |
---|---|---|---|
Token design | FT/RFT (Fungible/Re-Fungible Token) | ERC20, ERC223, ERC621 | Omisego, Augar, Bancor |
NFT (Non-Fungible Token) | ERC721, ERC998, ERC1155, ERC721x | CryptoKittles, Etheremon, Decentraland | |
Identity | KYC/AML/CFT対策, Metadata紐付け | ERC948, ERC1337 | uPort, origin protocol |
Subscriotions | Subscriptionモデル | ERC948, ERC1337 | ETH Grants, 8x protocol, Gitcoin |
Compliance | Security Tokenモデル | ERC1400, ERC1410 ——- ERC1411, ERC1462 | Polymath, Atlant |
Other | 互換規格、TXs削減、Gas代削減 | ERC165, ERC827, ERC999, ERC1068 |
CFT(combating the financing of terrorism:テロ資金供与対策)、TXs(Transactions)
- Token design・・・Fungibility(代替可能性)に関する定義
- FT(Fungible Token)・・・代替可能なもの、わかりやすい例だと現金(Aさんの1万円とBさんの1万円は等価で交換可能)
- NFT(Non-Fungible Token)・・・代替不可能でデジタル的に唯一なもの、世界に一つしかないことが証明可能
- Identity・・・サービス提供側と利用者側の双方に信頼性のあるidentityを証明
- Subscriotions・・・EthereumでSubscriptionモデルを組み込むための技術
- Compliance・・・規制関連のSeculityToken管理
NFTの構造
NFTの識別子は、コントラクトアドレスとuint256型のtokenIdで構成されます。
NFT Identifiers
Every NFT is identified by a unique uint256 ID inside the ERC-721 smart contract. This identifying number SHALL NOT change for the life of the contract. The pair (contract address, uint256 tokenId) will then be a globally unique and fully-qualified identifier for a specific asset on an Ethereum chain. While some ERC-721 smart contracts may find it convenient to start with ID 0 and simply increment by one for each new NFT, callers SHALL NOT assume that ID numbers have any specific pattern to them, and MUST treat the ID as a “black box”. Also note that NFTs MAY become invalid (be destroyed). Please see the enumeration functions for a supported enumeration interface.
https://eips.ethereum.org/EIPS/eip-721
直訳:NFT識別子
すべてのNFTは、ERC-721スマートコントラクト内の一意のuint256 IDによって識別されます。
この識別番号は、契約期間中は変更されないものとします。ペア(コントラクトアドレス、uint256 tokenId)は、イーサリアムチェーン上の特定の資産のグローバルに一意で完全修飾された識別子になります。
一部のERC-721スマートコントラクトは、ID 0から始めて、新しいNFTごとに1つずつインクリメントするのが便利だと感じるかもしれませんが、呼び出し元はID番号に特定のパターンがあると想定してはならず、IDを「ブラックボックス」として扱う必要があります。
また、NFTは無効になる(破棄される)可能性があることに注意してください。サポートされている列挙インターフェイスについては、列挙関数を参照してください。
KrisからいただいたNFTをベースに確認してみます。Krisの作品は以下のように多数のNFTが生成されています。
確認したいポイントは、どのNFTもコントラクトアドレス自体は同じになっており、トークンIDが1から順番に払い出されています。
トークンIDにはJSON形式のメタデータを紐づけることができ、このメタデータにコンテンツデータへのURIを設定できます。
コントラクトアドレス
0x77D42edD549E6d36d540cC65E94369bCfabF728E
トークンIDのJSON形式のメタデータ
{
"name":"I met Krs on this day #17",
"description":"Proof that you met the artist Kristoffer \"Krs\" Kullengren in person.",
"image":"ipfs://bafybeic6ycxk77vzre2xhi3ykxbydchujn45vnebifwj4vbvyjel33hjqe",
"background_color":"181818"
}
プロパティ | 概要 |
---|---|
image | これは、アイテムのイメージへの URL です。ほぼすべてのタイプの画像(OpenSeaによってPNGにキャッシュされるSVGを含む)にすることができ、IPFSのURLまたはパスにすることができます。350 x 350 の画像を使用することをお勧めします。 |
image_data | 生のSVG画像データ、その場で画像を生成する場合(推奨されません)。これは、image パラメーターを含めない場合にのみ使用してください。 |
external_url | これは、OpenSea 上のアセットの画像の下に表示される URL であり、ユーザーは OpenSea を離れたサイトでアイテムを表示できます。 |
description | 人間が判読できる項目の説明。マークダウンがサポートされています。 |
name | アイテムの名前。 |
attributes | これらはアイテムの属性であり、アイテムの OpenSea ページに表示されます。 |
background_color | オープンシー上のアイテムの背景色。先頭に # を付けない 6 文字の 16 進数である必要があります。 |
animation_url | アイテムのマルチメディア添付ファイルへの URL。 ファイル拡張子GLTF、GLB、WEBM、MP4、M4V、OGV、およびOGGと、オーディオのみの拡張子MP3、WAV、およびOGAがサポートされています。 Animation_urlはHTMLページもサポートしているため、JavaScriptキャンバスやWebGLなどを使用して、リッチなエクスペリエンスとインタラクティブなNFTを構築できます。HTML ページ内のスクリプトと相対パスがサポートされるようになりました。ただし、ブラウザー拡張機能へのアクセスはサポートされていません。 |
youtube_url | YouTube 動画の URL です。 |
OpenSeaでは、attributesを利用することで、パラメータを付与することも可能です。
NFTコンテンツデータの配置
NFTコンテンツデータをEthereumtに置く(On-Chain)と、最も分散かつ永続に担保されます。
一方で、Ethereumはそもそも大きなコンテンツデータを保存できるように設計されたものではなく、ガス(Gas)代が高額となり、容量制限があります。
このような制約から、大容量のコンテンツデータを保存するには別のチェーン、手段(Off-Chain)が必要になります。
- オンチェーン(On-Chain)・・・NFTコントラクトと同じブロックチェーンシステムに保存
- オフチェーン(Off-Chain)・・・NFTコントラクトと異なる場所に保存
スマートコントラクト
スマートコントラクトは、Ethereum上に保存され実行できるプログラムです。
スマートコントラクトは、EVM(Ethereum Virtual Machine)と呼ばれるプログラム実行環境上で動作します。
スマートコントラクトによる状態管理
各スマートコントラクトは、NFT名などのデータ(状態)を専用のデータベースに保存し、ハッシュ値だけをブロックチェーンヘッダーに書き込みます。この「状態」は、プログラムの実行により変更することができます。
スマートコントラクトによる状態管理
ブロックチェーンに書き込んだデータは変更できない?
→ブロックチェーン上のデータでも変更できるものとできないものがある
→Ethereumでは、「取引履歴のような変更不可なデータ」と「残高などの状態を表す変更可能なデータ」の2種類がある
Ethereumでは、「World State」と呼ばれ、全アカウントの「状態」を保持、管理しています。
ブロックに記録できる容量には制限があるため、それぞれのアカウントステートを合計し、ダブルハッシュを繰り返して得られるルートをState rootとして共有されます。
スマートコントラクト内の関数呼び出しによって、アカウントの状態を変更することができます。
Ethereumでは、2種類のアカウントアドレスが存在します。
- 外部所有アカウント EOA(Externally Owned Account)
ユーザーにより生成されるEthereumを利用するアカウント、Metamaskで使うWalletのアカウント
Ethereumの残高などを管理 - コントラクトアドレス CA(Contract Address)
スマートコントラクトの情報とアドレスを持つアカウント
フィールド | 概要 | EOA | CA |
---|---|---|---|
nonce | アカウントから送信されたトランザクションの総数 | ◯ | ◯ |
balance | アドレスが所有するwei額(weiはETHの最小単位) | ◯ | ◯ |
codeHash | メッセージ呼び出しがあった場合に実行されるコード | × | ◯ |
storageRoot | アカウントのストレージハッシュ | × | ◯ |
スマートコントラクトでは、コントラクトアカウントのcodeHashを呼び出すことで状態を管理しています。
ERC-721による機能定義
EthereumのSpecificationとして、インターフェイスの記述方式が定義されています。
これらのコマンドを用いて状態を変更したり管理したりします。
ERC-721実装とNFT作成(mint)の仕組み
OpenZeppelinは、スマートコントラクト開発を支援するフレームワークで、Contracts(ライブラリ)を提供しています。
OpenZeppelin Contractsは、スマートコントラクトの実践テスト済みのライブラリを使用することで、リスクを最小化するのに役立ちます。ERC20やERC721などのERC標準の最も使用されている実装が含まれています。
OpenZeppelinでは、ERC-721標準の機能だけでなく、その他必須のContractsが提供されております。
デプロイ後のコントラクトコードは、一度デプロイしてしまうと後からコードを変更することは不可です。
全く同じコードを2回デプロイしても、全く異なるコントラクトとして扱われます。
つまり一度デプロイしたコードは修正できない点を注意する必要があります。
一度開発したアプリに対して、都度コントラクトアドレス先を修正する場合は現実的ではないので、あらかじめweb3アプリを開発する際に考慮する必要があります。
NFT mint時には、トークンに対して、外部所有アカウントEOAの紐付けを実施しています。
移転の場合には、この紐付けを変えることによりオーナーの所有者を変更しています。
EOAアドレス生成とトランザクション基礎知識及びウォレット環境準備
- MetaMaskとアカウントアドレス生成の仕組みの概要理解
- MetaMask概要
- EOAアカウントアドレス生成の仕組み
- ハンズオン:リカバリフレーズから派生する鍵の作成
- MetaMaskとテスト用通貨の環境準備
- MetaMaskインストール
- MetaMaskアカウント作成
- Polygon Mumbai(テストネット)の登録
- MetaMaskテストネットの追加とnonce表示設定
- EtherscanでのEOAからEOAへのトランザクション確認方法
- xxx
MetaMask
MetaMaskは、Ethereum系ブロックチェーンの通貨やNFT(非代替性トークン)を一括で補完・管理できるソフトウェアウォレットです。管理しているのは仮想通貨ではなく鍵で、残高自体はEthereumノード側で管理している。
EOAアカウント生成の仕組み
web3時代には、一つのアカウントではなく複数のアカウントを利用することを前提として、一つのシードキーを作っておいて、派生的に複数のアカウントを生成できる仕組みが実装されています。
12のシークレットリカバリーフレーズからシードキーを導出し、秘密鍵、公開鍵、アカウントアドレスを生成します。
シークレットリカバリーフレーズは、BIP39 wordlistとして、2048個が定義されています。
さらに詳細に整理すると、以下のような流れでシークレットリカバリーフレーズからアカウントアドレスを生成しています。
ハッシュ関数とは、任意の文字列から固定調の値(ハッシュ値)を生成する関数です。
ハッシュ値とは、データに対してハッシュ関数を用いて算出される固定調の値です。
同じデータであれば必ず同じ値が算出され、元データが少しでも異なればハッシュ値も異なった結果が出力されるため、データ変更・改ざんに気付けます。ハッシュ値から元データを導くことは現実的に不可能と言われており、詳細なロジックが知りたい方は、「Sha256 Algorithm Explained」による視覚化シミュレーションで勉強してみてください。
アカウントを複数追加する場合は、一つ前の秘密鍵に対してhash関数をかけて次の秘密鍵を生成しています。
12個のシークレットリカバリーフレーズまたは、秘密鍵がバレてしまうと本人であることの証明ができ、操作できてしますので、必ず人に漏らさないようにしましょう。
以下の「Graphical Ethereum Address」では、パスフレーズから生成される流れが可視化されて学ぶことができます。
ハンズオン:リカバリフレーズから派生する鍵を導く
- 15 wordsから12 wordsに変更して「GENERATE」を実行
- Coinを「BIT」から「ETH」に変更
12個のリカバリフレーズから秘密鍵、公開鍵、アカウントアドレスが生成されていることを確認
ハンズオン:MetaMaskインストール
ChromeウェブストアのMetaMaskのサイトに遷移します。「Chromeに追加」を押し、導入します。
Chrome右上の拡張機能のアイコンからMetaMaskを固定して作業しやすい状態にしておきます。
画面のガイドに従って順次入力していきます。
以下のように、Ethereumのメインネットのみが表示される状態で表示されていれば正常にインストール完了
研修では、アカウントを4つ使うため、事前に作成しておきます。
右上のマイアカウントメニューから「アカウントを作成」から新規作成します。アカウント名は自由につけていただいてよいです。ここでは、「Account 2」「Account 3」「Account 4」としました。
以下のように4つのアカウントが作成されていればOK
以下のサイトにブラウザからアクセス
フッター右下の「Add Mumbai Network」からMetaMaskに登録
MetaMaskに戻り「Mumbai」が以下の通り表示されていればOK
今回テスト用のネットワークを使って検証していきますので、追加設定します。
右上のマイアカウントメニューから「設定」→「高度な設定」から以下の2ヶ所を変更します。
- テストネットワークを表示 「オフ」→「オン」
- トランザクション ナンスのカスタマイズ 「オフ」→「オン」
以下のように3つの項目が追加されていればOK、研修ではGoerliテストネットワークを使っていきます。
- Goerliテストネットワーク
- Sepoliaテストネットワーク
- Localhost8545
今回はMubai Faucetを利用して、MATIC Tokenを取得します。以下のリンクに移動します。
TokenのTransferの確認画面が出ますので、Confirmを押します。
無事リクエストが承認されました。
時間をあけずにWalletに発行するとエラーとなります。
仮想通貨が送金できるか確認します。Account 1にMetaMaskで接続します。送金ボタンを押します。
[自分のアカウント間での振替]を押します。
送金したいアカウントを選択してください。(例. Account 2)
送金する金額を入力して、[次へ]を押します。(例. 0.1MATIC)
送金にはガス代が必要となりますので、その時その時に応じて金額が変わっています。
取引をすると、ナンス(トランザクションの総数)が増加します。
Account 2のWalletが増え、無事送金されました。
トランザクションを実際にブロックエクスプローラーと呼ばれるEtherscanで確認していきます。
Ethereumブロックチェーン上で行われたトランザクションを簡単に調べ、確認、検証することができる検索エンジンで、ブロックチェーンの透明性を促進したいという目的で、独立した事業体が無性で運営しています。
トランザクションとは、EOA(Externally-Owned Account)から開始されるアクションで、EVMの状態を変更するものであり、Contract発ではなく人間が管理するアカウント(主にWalletのアドレス)によって発行されます。
トランザクションを受け取ったノードはネットワークに実行要求を伝播。その後マイナーがトランザクションを実行し、状態変化を伝播させます。コンセンサスが取れたらブロックに追加します。トランザクション発行にはガスと呼ばれる手数料が必要で、仮にトランザクション処理が失敗しても支払ったガス料金は戻ってきません。
基本的なトランザクションの流れを以下のチャートでみてみます。
実際に先ほど送金したブロックチェーンを確認していきます。
MetamaskのAccountから[アカウントをエクスプローラーで表示]を選択します。
送金側のアカウント見てみます。
受取側のアカウントを見てみます。
実際のトランザクションの中身になります。