目次
Web3とはなんだったのか?体験して理解する技術としての Web3
Web3 という言葉がバズワードとして登場して久しいです。関連する用語に、メタバース、NFT、DeFi、DAO、DAppなど新しいコンセプトが次々に登場しています。
Web3 について語られる記事や、専門家たちがディスカッションしている動画は、コンセプトをよく理解し、将来へのインパクトや可能性を理解するには十分すぎるほどですが、具体的にどんなアクションを起こせば良いのかについてはほとんど語られていません。
そこで、本ブログでは、Web3 の概念的な考え方や、今後何を破壊するのかという点はさておき、Web3 に関連する技術の実体を触って、実際に体験してみて Web3 に関連する技術を理解しようとします。手を動かすシリーズです。
Web3 の知識や、ブロックチェーンの知識は全く必要ありません。一つ一つ説明しながら体験していきます。ところどころコードが登場しますが、体験が目的ですのでコピペするだけで大丈夫です。
最後に Webインターフェースでウォレットを接続し、スマートコントラクトを呼び出す実験をしますが、ここだけ Web エンジニアとしての経験が求められるところになります。こちらは別記事にしました。
このブログで体験することは次のことです。
- Web3 の世界に自分のアドレスを作ってネットワークに接続する
- 無料のテストネットを使って、暗号通貨を取引してみる
テストネットに自分オリジナルの暗号通貨(トークン)を作って億万長者の気分」自分オリジナルのトークンを送金してみる(以下、ネットワーク上のERC20トークンとネットワークのコインを区別なくコインとして呼ぶことがあります) - テストネットに適当に作った絵でNFTをミント(新たに作ること)してみる
NFTの取引サイト OpenSea で自分の作ったNFTをチェック - テストネットにNFTと暗号通貨が組み合わさった新しい概念の暗号資産をミントする
- 【開発者向けの別記事に移行】オリジナルのトークンで感謝を送信し合うアプリを作る(Dapp)
このブログを読んだ後は、ERC20などのトークンを作ったり、NFTをミントしたりできるようになっています。さらに、開発者向けの別記事では、オリジナルの分散型アプリケーション Dapp を作成できるようになっています。こうした体験を通して、Web3 が一過性のブームではなく、まだまだこれから先も活用方法が考えられる技術であることがわかるのではないでしょうか。
内容的には、Web3 無学の筆者が休日に自身で体験したことを記録しているものがメインになりますので、入門者にとってはわかりやすく、上級者にとっては退屈な内容となっているかと思います。また、記事中で開発者と呼ぶ場合は、Web 開発の経験がある人を意識しています。間違い等ありましたら指摘いただけると幸いです。
ここでは、OpenZeppelin というライブラリからコピペコードを作成しますが、Web 上で簡単に発見できるサンプルコードをコピペしてデプロイする(Web3 のネットワークで動作するようにする)ことは避けてください。暗号資産を奪われる可能性があります。
このブログでは、完全無料で再現できるので、どこかからトークンを買ってくる必要はありません。テスト用に用意されているネットワークを使うので本物のイーサリアム等は不要です。テスト用の無料で手に入れられるトークンを使ってガス代を払います。
Web3 の入り口、Metamask(メタマスク) で Wallet(以下、ウォレット) 管理を始める
まずは、Web3 の入り口として、さまざまなブロックチェーンネットワークと接続するためにツール群を用意しましょう。
ウォレット(ウォレットアドレス)とは、財布の電話番号のようなもの
まずは、ウォレットを用意しましょう。今、これを読んでいる読者の方であれば、携帯電話番号を持っていると思います(あんまり使ってないかもしれませんが)。Emailアドレスはどうでしょうか、こちらも仕事以外ではあんまり使わないという人が多いかもしれませんが多くの人が持っていると思います。LINEは使っているでしょうか、LINEのアカウントを交換する時に表示するQRコード、あれもLINEというサービス内でのアドレスです。
このように、電話番号、Emailアドレス、LINEのアカウントなどなど、他の人と決して一緒になることがない文字(正確には数字ですが見た目は文字っぽい)のことです。例えば、電話番号であれば、03-5614-0090は、オートロ株式会社しか持っていない電話番号です。実際のウォレットアドレスの見た目は、「0x8A59F4bd4E585Dd96522cFbFc758155894642117」のようになっています。これは、16進数で表現された巨大な数字です。
ウォレットアドレスという名前(ウォレットは財布のこと)からもそうですし、暗号通貨というとお金のイメージが強いので、銀行口座の口座番号と捉えるとわかりやすいです。しかし、Web3 でのウォレットアドレスは口座番号だけではなく後述するスマートコントラクトを利用してさまざまな応用が効くものになっています。
どんな応用があるかというと、例えば、EmailやLINEのような仕組みもウォレットアドレスとスマートコントラクトを使えば実現可能ですし、オークションや、マーケティングキャンペーンのような取引・契約関係もスマートコントラクトで実装可能です。
Ethereum Network とは、たくさんの独立したコンピュータが繋がったデータセンターのようなもの
ウォレットの前置きが長くなりましたが、このウォレットを使う場所(プラットフォーム)のことを考えてみましょう。Emailであれば、インターネット上でアドレスを処理して、メールサーバーと呼ばれるところに情報を蓄積します。電話であれば、NTTの通信網を通じで電話と電話を繋ぎます。Web3 でこのインフラストラクチャーを提供しているのが、ネットワークと呼ばれるものです。
Ethereum は、その中でいろいろなネットワークを構築できるのですが、Ethereum Network の中でも大元となるものをメインネットと呼んでいます。メインネットは、多数のコンピューター(ノードという)がインターネット上で繋がって矛盾なく処理を行なっています。メールサーバーのような中央で処理をする大きなコンピューターがなく、ノード間が直接通信し処理が分散されています。ものすごく大雑把にいうと、分散されたコンピューター上で矛盾なく処理するための技術がブロックチェーンです。
データセンターが分散されていて、スマートコントラクトなどを計算する基盤を作ってくれていると考えるとイメージしやすいでしょう。Web3で何かをしようとした時に、インフラはすでに用意されています。ただ、無料というわけではありません。処理するために後述するガス代と呼ばれる手数料が発生します。
NTTの電話網に接続するなら、NTTと契約して電話番号をもらって電話機をモジュラーケーブルで接続すれば終わりです。インターネットであれば、サービスプロバイダと契約して光ファイバーを繋いだら接続できます。イーサリアムネットワークに接続するためにはどうすれば良いでしょうか。
イーサリアムネットワークと我々利用者のインターフェースをしてくれるものが、Metamask に代表されるソフトウェアウォレットです。Metamask が、イーサリアムネットワークとインターフェースしてくれるので、Metamask にウォレットアドレスを紐づければイーサリアムネットワークに接続できます。
Metamask がどうやって Ethereum Network に接続しているかというと、infura という Ethereum Network と Web を API で仲介してくれるサービスを介して実現しています。infura は、インフューラみたいな呼び方で呼ばれています。この辺りの仕組みは、開発者向け記事の方で説明します。
次で、Metamaskでウォレットアドレスを利用してみましょう。
メタマスクで始めるウォレット管理
さて、先ほどウォレットアドレスを Metamask に紐づければ良いと言いましたが、ウォレットアドレスはどこで手に入れたらいいのでしょうか。心配無用です。Metamask が初めて人であれば、アカウント作成じにウォレットアドレスを作成できますし、ウォレットアドレスは後からでもいくらでも作成できます。Metamaskでは、自分が所有しているウォレットアドレスのことを「アカウント」と呼んでいます。ここでもアカウントという言葉を使うようにしましょう。Metamask のアカウントのことをウォレットと呼んでおり、ウォレットで管理しているウォレットアドレスをアカウントと呼んでいます。
では、ますは、早速メタマスクアカウントを作成してみましょう。メタマスクは、Chromeの拡張機能、スマートフォンアプリでも利用できますので好きな方を使ってみてください。操作画面にそれほど違いはありません。
メタマスクを Chrome にインストール
ここでは、Chromeの拡張機能のメタマスクの利用方法をご紹介します。
さて、インストールできたでしょうか。
そうするとこんな画面が表示されると思うので、「新規ウォレットを作成」をクリックしましょう。
メタマスクでウォレットを作成
作成を開始すると、パスワードの設定を求められますが、このパスワードは、書いてある通りですが、ウォレットのロック解除に使われます。
一度、ウィンドウを閉じるなどするとウォレットがロックされてメタマスクへのログイン状態が解除されます。再びウォレットを利用するにはこのパスワードを入力する必要がありますので、記憶していられてそれなりに複雑な、ちょうど良いパスワードを設定しておきましょう。
その後、シークレットリカバリーフレーズというものが表示されますが、これはリカバリーフレーズの名の通り、このフレーズがあれば全て復元できてしまうので絶対に人に漏らさないでください)。
諸々完了すると、0 ETH (ETHは、イーサリアムコインのシンボルです。米ドルのUSDのようなものです)の空っぽのアカウントが作成されました!おめでとうございます!
アカウントに表示されている中身を見ていきましょう。
上部の右側に、「イーサリアムメインネット」という表示があります。こちらが、現在接続しているネットワークの名前になります。イーサリアムメインネットは、本物のイーサリアムコインを扱うネットワークです。このブログで体験する時は、お金をかけたくないのでテストネットという開発者向けのコピーのようなところに接続しなおしますので安心してください。
今、0 ETH となっています。一円の価値も入っていません。この状態であれば、どんなことをしても減ることはありません。不安な方は、0 ETH の状態を保ってください。もし、すでにメタマスクにETH 残高がある方は、イーサ残高が 0 の新しいアカウントを作成してそちらで遊びましょう。
さて、その下の Account 1 と表示されているところは、ウォレットアドレスを区別するための名称です。ウォレットアドレスは、すぐ下に中略されて表示されています。これはクリックするとコピーされるので、全て表示する場合は、コピーしてペーストしてみてください。ウォレットアドレス自体は誰ても見えるようになっているので、バレても問題ないものです。しかし、この人のウォレットアドレスはこれ、みたいな個人と結びつくとなんか気持ち悪いですよね。住所が誰でもわかる情報なのに、誰がそこに住んでいるかを知られるのは抵抗があるのに似ています。
Etherscan でウォレットアドレスを確認してみる
ウォレットの作成おめでとうございます。Ethereumの取引台帳で調べてみましょう。
Etherscan という便利なサイトがあって、取引台帳を提供してくれています。Ethereum や対応しているさまざまなブロックチェーンネットワークの取引を閲覧することができます。
Etherscan を開いたら、先ほど作ったアドレスを検索バーに入力してみましょう。
先ほど作ったアドレス 「0x8A59F4bd4E585Dd96522cFbFc758155894642117」 を入力してページを開いて見ます。このアドレスは、このブログ用に作成しました。この後、このアドレスを使ってトランザクションを追加してみるので、どうなっているかこのアドレスで皆さんもスキャンしてみてください。テストネットの取引を確認するには、Multi Chain となっているところから、別のブロックチェーンでの取引台帳をみることができるので、そちらから確認してみてください。
これを表示すると、先ほど作成したウォレットアドレスが表示されています。そのすぐしたの「Overview」というところで、ETH Balance とありますが、これは今イーサをどれくらい持っているかを表しています。怖いですねぇ。いくら持っているか知られてしまいます。ですが安心してください、口座番号と違って誰が持っているか?まではわからないのです。
さらに、したの方で「Transaction」が青くなっていますが、これは、そのしたの領域に表示しているものが取引履歴ですよ、ということを意味しています。タブのようなものです。今はどんな取引もしていないので空です。
これで、イーサリアムネットワークに自分が作ったアドレスが確かに存在して認識されていることがわかりました。これだけだと、何も面白くないので、次は、イーサリアムネットワークではない別のテスト用(というか、開発者向け)ネットワークに接続して、実際にトランザクションを発生させてみましょう。
プライバシーと取引の安全性、コンプライアンス
先ほど、Etherscan でウォレットアドレスを入力すると取引や残高までわかってしまうことに驚きを覚えた方もいるのではないでしょうか。プライバシーはどうなってんの?と。心配無用というとそうでもないのですが、自分の銀行口座の中身を見られるわけではないという理解をしてみてください。アドレスはあくまでアドレスであって、いくらでも作れます。また、アドレスと個人が紐づくことはありませんし、アドレス自体を他の人にあげる(そんなことするのかは別として)こともできます。アドレスをあげたい場合は、秘密鍵を渡せば完了です。なので、秘密鍵は盗まれないようにしてください。そして、秘密鍵は変更できません。
これほどオープンになっているブロックチェーンの取引ですが、初めからオープンになっているものだ、と理解して利用すれば良いのです。ただ、個人の特定は簡単にはできないので誰がこんなにコインを持っているのだ?ということはバレることは滅多にないと思います。
とはいえ、トランザクションは見えるのだから、コインの流れを見ていればどのウォレットとどのウォレットが密接で同一人物が保有しているか、くらいはわかりそうです。前述したようにウォレットも簡単に作れますし、簡単に捨てられます。このような特徴から反社会的勢力が利用しているのではという見方もあります。日本の取引所では、個人の特定がしっかり行われていますので、犯罪組織が関与する可能性は低いと信じていますが、取引所の外では何が行われているかわかりません。反社チェックに関心のある方は、以下のブログを参照してください。
テストネットに接続する
それでは、早速、無料で利用できるテストネットを使ってみましょう。
テストネットとは?
テストネットというのは、Web3 の開発者向けに無料で利用できるネットワークのことです。テストネットは、Ethereum のメインネットと同じように動作するので、取引コスト(ガス代)が発生します。ですが、ガス代を支払えるコインを無料で提供してくれますので、無料で開発できるようになります。コインが出てくるサイトを蛇口(faucet)と呼びます。蛇口を捻ることで、ETHを購入したりすることなく、Web3 の開発を始められるし、たとえ開発しなくても体験できるようになっています。
スマートコントラクトとは?どうやって使うの?
Web3 の開発とか、デプロイとか今まで専門用語を説明なしに使っていましたが、ここでちゃんと説明します。Web3 でアプリケーションを開発するというのは、すなわちスマートコントラクトとスマートコントラクトを利用できる Web サイトやモバイルアプリを作ることです。Dapp(Distributed Application:分散型アプリケーション)と呼ばれます。スマートコントラクトは、solitity というプログラミング言語で書かれた一つのファイルです。プログラミングに詳しい人であれば、スマートコントラクトは、クラスファイルである、と理解する方がわかりやすいかもしれません。
スマートコントラクトは、ウォレットアドレスと他のウォレットアドレスや他のスマートコントラクトとの相互作用を定義します。例えば、Aというアドレスから、Bというアドレスに10コイン送金する、とか。コインが、ERC20の場合(トークンと言います)は、それ自体スマートコントラクトになっています。ネットワーク上でウォレットアドレス間で取引する全ての約束事はスマートコントラクトにコーディングされています。
スマートコントラクトは、全てオープンになっています。ある特殊な機能を持った暗号通貨があるとして、騙していないかをチェックするにはスマートコントラクトを読めばいいわけです。読めば良いと言われても solidity というプログラミング言語で書かれているのでソースコードを読んで理解する力が必要になってきます。この世界の法律家は、裁判する必要はないですが、コードを読んで正しく説明する能力は必要そうです。スマートコントラクトは、コードで書かれた契約のことなので、それ自体がスマートさを実現する仕組みではありません。スマートになるかならないかは、開発者次第です。
開発者でない方は、スマートコントラクトは非常にシンプルなソフトウェアだと理解してください。プログラマーの方は、スマートコントラクトはクラスファイルだと思えば大丈夫です。今、理解しなくても後で具体的にERC20(暗号通貨)、ERC721(NFT)などをデプロイする時に一気に理解が進むと思われます。
スマートコントラクトにアクセスするには、ブロックチェーンネットワークに接続する必要があります。Web3 のアプリケーションの利用者は、Metamask でアクセスします。一方で、Web3 アプリの開発者がどうやってネットワークに接続するのかというと、web3.js というライブラリ(便利な機能をまとめたプログラム)をウェブアプリ内で読み込んで接続します。web3.js については、別記事で説明します。
では、スマートコントラクトをデプロイする(利用できるようにするためにネットワーク内に登録する)だけではなく必ず web3.js を使ったWebアプリを開発しなければならないのでしょうか。実はそんなことはありません。
標準規格 ERC に乗っかったスマートコントラクトは、独自のアプリ開発は必須ではない
Ethereum ネットワークは、分散型のシステムであり多数の人(多分人です)が関わっています。Ethereum ネットワーク自体も固定したものではなく、参加者による改善提案によって仕組みがアップデートされています。この改善提案のことを、EIP(Ethereum Improvement Proposals:イーサリアム改善提案)と言います。この中でも特に重要なものに、ガス代(後で説明します)という取引コストを決める EIP-1559 などがあります。
改善提案の中で、幅広く意見を募集しているものが、ERC(Ethereum Request for Comments:イーサリアム意見募集)というカテゴリになり、この中で、標準規格が定められてきました。
代表的な標準規格は、次のものです。
- ERC-20(暗号通貨)
- ERC-721(NFT→あとで説明します)
- ERC-1155(ERC-20 と ERC-721 と同じようなものを同時に一回の取引で取り扱えるもの)
これらの代表的な標準規格(標準仕様)に則っていると Metamask など各種 ERC に互換しているウォレットサービスなどでは、特別に Web アプリを開発することなくネットワークに接続することができます。それらは、標準の仕様に従っているので、同じ標準仕様に従っている出来合いのアプリケーションで接続することができる、というわけです。例えば、balanceOf(アカウントアドレス) を呼び出すと、アカウントアドレスの残高が示されるのですが、ERC20に則っていると、必ず balanceOf と言う名前の関数になっています。インターフェースを指定する仕組みを ABI(Application Binary Interface)と言いますが、これについては、開発者向けの別記事で解説します。
ERC標準 | URL | いわゆる | 何が嬉しい |
---|---|---|---|
ERC20 | https://eips.ethereum.org/EIPS/eip-20 | 暗号通貨 | 通貨のような取引を定義できる |
ERC721 | https://eips.ethereum.org/EIPS/eip-721 | NFT | 画像などのアイテムの一意性を担保できる |
ERC1155 | https://eips.ethereum.org/EIPS/eip-1155 | パック | ポイントやアイテムをまとめて取引できて効率的 |
テストネットの種類
前置きが長くなりました。とりあえず、次のことがわかりましたね。
- Ethereum メインネットで取引を行うとガス代がかかり、決して安くない
- 開発者向けのテストネットが用意されていて、そこでもガス代はかかるが、無料でコインをゲットできる
- 代表的なERCに準拠したスマートコントラクトは、Dapp 開発することなくMetamask等でデプロイ後すぐに利用できる
こんな利点があるものですから、開発、学習目的には、テストネットは欠かせませんね。
テストネットには、次の種類があります。
- Remix VM
独立したネットワークで、動かしている時だけの記憶があるのでデバッグ用です。毎回消えてしまいますし、Metamask で接続することはできません。 - Hardhat や Ganache など、サードパーティの開発環境
ローカルの開発環境を構築できたり、開発環境をホスティングしてくれるものです。エンジニアであれば、ローカルで開発できるのが便利なのって当たり前ですよね。より複雑なアプリを開発したい場合は、必須でしょう。最近は、Hardhat が人気のようです。 - Testnet
Metamask 等で実際に接続可能な、テスト用のネットワークです。本当に運用されているネットワークに接続するので、ローカル開発環境と比べるとデプロイが若干面倒ですが、Metamask での接続や Etherscan、Opensea などでトランザクションを確認できるので最終確認には一番おすすめです
ここでは、テスト環境としてテストネットを使います。もちろん、複雑な独自のスマートコントラクトをデプロイするには、高頻度にテスト、デバッグできた方が良いので、Remix VM や Hardhat なども利用できた方がよいでしょう。ここでは、それらの使い方は省き別記事で紹介します。
今まで、Rinkeby Testnet など複数のテストネットがありましたが、今は、ほぼ一択で、Goerli Testnet が利用されています。しかし、Goerli のトークンが枯渇して、開発者の間で有償で取引されたり、ガス代が高くて少ない残高ではデプロイすらできないことも出てきています。そんなことから、Sepolia というネットワークに移りつつあります。まだ若くて、小さく長期的にサポートされるものかは不透明と思われていましたが、正式に移行していくことになりそうです。Sepolia は、NFT 取引の大手の OpenSea では、未対応ですが、今後対応されていくと考えられます。
Goerli の読み方ですが、ゴエリとかゲリに近い感じで発音されているのを聞きます。ドイツ語表記では、Görli ですので、ウとエとオが混ざったようなグォエリみたいに発音してみましょう。カタカナでは、ゴエリで記憶しておけばスペルも覚えられるのでおすすめです。Sepolia は、英語の発音を聞いたことがないですが、セポリアで間違いないと思います。
テストネット名 | ネットワーク | コイン | 現状 | Metamask | OpenSea |
---|---|---|---|---|---|
Goerli Testnet | Ethereum Mainnet | Goerli ETH | Rinkeby 廃止後最もメジャーだったが、こちらも2023年で廃止の予定 (2023年4月よりメインネットのETHの所有が条件になり、無料だが始めるにはETHの購入が必要) | 対応 | 対応 |
Sepolia Testnet | Ethereum Mainnet | Sepolia ETH | Goerli からの移行先 | 対応 | 未対応 |
Mumbai Testnet | Polygon Network | Mumbai MATIC | MATIC でテストできる唯一のテストネット | 対応(手動追加) | 対応 |
なぜ Goerli Testnet なのか?
Goerli Testnet で、メインネットのETHを所持していることが取得の条件になりました。テストネットであっても有料のコインを所持している必要があります。なので、代わりにSepoliaテストネットを使うようにしてください。または、Mumbaiテストネットは、ガス代も安く安定しています。 Ethereum メインネットではなく、Polygonネットワークのテストネットにはなってしまいますが、Mumbaiを使う方法もありです。
Goerli Testnet は、現在、日本時間の夕方以降は非常に混んでおり、Faucet でも Goerli ETH を入手できにくい状態になっています。2時以降の深夜帯から昼にかけては比較的ガス代も安く Faucet も動作している印象ですので、その時間帯を狙うか別のテストネットを使ってください。
ERC20 などでは、Sepolia Testnet を使うのも手ですし、ERC721であれば、OpenSeaでも確認できるMumbai Testnet を利用すると良いです。こだわりがなければいろんなテストネットを使ってみてください。Mumbai は、Polygon と言う Layer 2 に属するネットワークのテストネットです。
現実的に Ethereum のテストネットとして利用可能なのは、Goerli と Sepolia です。Goerli は、枯渇しつつあるということと、記事の執筆時点で、Goerli を簡単に無料で手に入れられる faucet で障害が発生しがちということ、また、Goerli Testnet は、2023年末に廃止されます。代わりに Sepolia Testnet を使っていくことになります。Goerli が調子悪い場合は、Sepolia Testnet を利用してください。今後は、Sepolia を使う方が良いでしょう。
ですが、NFT をミントするときは、Goerli Testnet が利用できれば、Goerli Testnet を使用しましょう。というのも、後述する、OpenSea という NFT の交換サイトがまだ、Sepolia Testnet には対応していないようで、OpenSea に互換したNFTをミントできているか確認できないためです。
Goerli Testnet が利用できない方へ
ERC20トークン(暗号通貨)を、Sepolia Testnet (通貨:Sepolia ETH)で、ERC721トークン(NFT)を Mumbai Testnet (通貨:Mumbai MATIC)で、行う方法を付録で説明します。基本的に、ネットワークが異なってもやることは同じですので、ここでは気にせず進めましょう。それぞれ、Goerli となっているところを、Sepolia や Mumbai に読み替えれば同じようにできます。
Goerli Testnet でテスト用 ETH をゲット
実際のネットワークにデプロイするための準備をします。お待たせしました。お待たせしすぎたかもしれません。ここでやっと「あ、そういうことか!」っていう気分を味わえるようになります。ガス代がかかるので、ガス代が支払える分のテスト用 ETH をゲットしましょう。
Ethereum 上の取引コスト、ガス代とは?
Ethereum ネットワーク上で取引を記録するためには、ガス代がかかります。これは、例えば、10コイン送金したいときに、ガス代として0.0001コインが差っ引かれますよ、ってことが起こります。クレジットカードで言えば、トランザクションフィーと手数料、ATMでは手数料に該当するものと思ってください。取引には手数料が決まっていて、Ethereum ネットワーク上でも、それを差っ引かれます。
とはいえ、どの程度の差っ引くのかい?っていうのは、イーサリアム改善提案でオープンにディスカッションされて決められています。ネットワークの負荷や取引の混雑具合でガス代が変わる仕組みになっています。
EIP(イーサリアム改善提案)、そして、EIP-1559 とは?
イーサリアム改善提案は、新しい仕組みやプロセスに関する提案をする規格です。簡単にいうと、イーサリアムの仕組みを変えたり、技術仕様を変えたりする場合には、EIPという方法で提案してくださいねっていう約束事、フォーマットです。提案方法は、一番はじめのEIPである、EIP-1 で定められています。EIP-1559 は、おそらく1559番目の提案で、ガス代に関する提案が行われています。興味のある方は、読んでみてください。
無料で Ethereum Network を試すためにテスト用 ETH をゲットしよう
無料でテスト用のコインをゲットしましょう。
Goerli Faucet で 0.2 GoerliETH をゲット
まず、Goerli Faucet を訪問します。簡単に画面の説明をします。真ん中の辺にインプットフィールドがあります。ここにゲットした GöETH を送りたいアドレスを入力します。その後、Send Me ETH をクリックしてください。(記事、公開時点で、0.1 Goerli ETH しかゲットできなくなっています・・・)
すると、おどろおどろしい画面が表示され、Your Transactions というセクションにトランザクションのアドレスが表示されます。エラーっぽい画面ですが、成功しています。
トランザクションアドレスをクリックすると、Etherscan で内容を確認することができます。
ここで、ガス代なども表示されています。この取引を Metamask で確認してみましょう。
テストネットが見られるように設定する
デフォルトの状態ですと、Metamask にはテストネットが表示されません。テストネットが表示されるように設定変更しましょう。
機能拡張を開いてください。そして、高度な設定の中から、「テストネットワークを表示」というセクションを探して「オン」にしてください。これだけです。
これで、テストネットに表示変更できるようになりますので、イーサリアムテストネットとなっているところをクリックして、Sepolia テストネットワークを選択します。
すると、なんと!今ゲットした Goerli ETH が 0.2 になっています!
現在(2023/03/08)では、一日に取得できる SepoliaETH が 0.5、GoerliETH が 0.2 になっていますので、また明日同じことをすればさらにゲットできます。
テスト用 ETH を交換
今ゲットした Goerli ETH を試しに送金してみましょう。もらう先も自分にしておいた方が色々みられて便利なので、もう一つウォレットを作成しましょう。
もう一つのウォレットを作成する
Metamask を使えば、ものすごく簡単に新しいウォレットを作成できます。右上の抽象的な丸いアイコンをクリックして、「+アカウントを作成」をクリックします。
そうすると、アカウント名を記入するところがあるので、わかりやすい名前をつけておきましょう。例えば、僕のアカウントでは、Account 1 と Account 2 があったので、Account 3 にしました。あとで、どれがなんなのかわからなくなりそうです。
後は、作成ボタンをクリックすれば Metamask に追加されていますので、丸いアイコンをクリックして新しいアカウントに切り替えてみましょう。
Account 3 が表示されました。GoerliETH は、0ですね。
メインのアカウントから、もう一つのアカウントにトークンを送る
たった今作成したアカウントのアドレスは、「0x418C686B5DeA1e0Fa39281E4fD834628AE0e7685」でした。このアドレスの GoerliETH が 0 でかわいそうなので、さっきゲットした0.2 GoerliETH のうちほんの少し送金してみます。例えば、0.0001 GoerliETH 送金してみます。
ますは、今作ったアドレスをコピーして後でペーストできるようにしておきましょう。その次に、送金元になる Account 2 に先ほどと同じ容量で丸いアイコンをクリックして、アカウントを切り替えます。
それから、送金というアイコンをクリックします。
そうしますと、検索フィールドが表示されるので、その中に、コピーしたアカウントのアドレスを入力します。入力されると自動で検索してきて主要な情報が表示されます。
まず、Account 3 と青文字で表示されるのは、Metamask 内で保存されている名前をわかりやすく表示してくれているだけです。
アセットというところは、送金する対象のコインを確認しています。残高が、0.2 GoerliETH なのでそれが表示されています。
金額、というところはドル換算でレートを出してくれたりしますが、GoerliETH は金額に換算できないので換算レートがありませんと表示されます。
最後の一番下に、取引手数料であるガス代が表示されます。実際のガス代は最新の値が使われるのであくまで見積もりになります。これを見ると、0.00013199 GoerliETH がガス代になるので、送金する金額+ガス代がアカウントから減ることになります。送金する金額よりガス代の方が高いです。
送金する金額を「金額」というところに入力して「次へ」をクリックします。ここでは、0.0001 GoerliETH を送金することにしました。さらに確認画面が表示されるので、「確認」で送金を完了させます。
では、送金完了・・・っていう風にならないのが分散型ネットワークの特徴です。比較的高速に処理されますが、トランザクションが完了される前の「保留」という状態があります。この状態でできることは、二つで、「スピードアップ」と「キャンセル」です。スピードアップは、手数料を上乗せして優先的に処理されるようにすることで、キャンセルはそのなの通り、送金自体をキャンセルしてブロックチェーンに書き込まれません。
さて、完了すると、トランザクションが書き込まれます。
Metamask で確認すると、0.0001 GoerliETH が、Account 3 に入っています!
Etherscan で確認
Etherscan でも確認してみましょう。Metamask の下の方は、トランザクションを一覧しています。受領 0.0001 Goer… となっているレコードをクリックします。すると、トランザクションの詳細が出てきますので、これがトランザクションの内容が確認できます。ここからさらに「ブロックエクスプローラーで表示」というところをクリックすると Etherscan で確認できます。
Etherscan でも取引を確認することができました。
補足:Mumbai Testnet を Metamask に追加する
テストネットが非常に混み合ってきている印象がありますので、Mumbai Testnet も利用できるようにしましょう。ネットワークを追加するために必要な項目は、以下のとおりです。
項目 | 値 |
---|---|
ネットワーク名 | Mumbai Testnet (自由に名前はつけてOKです) |
新しい RPC URL | https://rpc-mumbai.maticvigil.com/ |
チェーンID | 80001 |
通貨記号 | Mumbai MATIC (MATICですが、わかりやすくMumbai MATIC と表示させています) |
ブロックエクスプローラーのURL | https://mumbai.polygonscan.com/ |
この情報をあとで使います。
まず、Metamask でネットワークを追加をクリックします。
追加できるネットワーク一覧にも Mumbai は、ないので、「ネットワークを手動で追加」をクリックします。
必要項目を入力して、「保存」すればネットワーク追加が完了です。
追加されました(筆者は、すでに Mumbai Faucet で、Mumbai MATIC を取得しています)。
これで、Mumbai Testnet も同様に利用できるようになりました。
Goerli Testnet に ERC20 スマートコントラクト(暗号通貨)をデプロイ
ERC20とは?
Ethereum 上に、ETH以外の独自コインを展開することができます。その独自コインを展開するための標準仕様が、ERC20で定められています。繰り返しになりますが、ERC(Ethereum Request for Comments)は、標準規格について定められています。ERC20 は、こちらのページに記載があります。そこに暗号通貨のスマートコントラクトが備えるべき機能とインターフェースが記載されています。プログラマーでない人にはわかりにくいと思いますが、こういう機能を持たせてくださいということが定義されているもので、標準仕様です。機能がちゃんと動くことは、プログラマーが責任を持つことになります。
ERC20 で作ったコインは、ETH などのコインと異なっていて、マイニングしたり、ガス代をERC20 トークンで支払ったりはできません。Ethereum ネットワークであれば、ガス代は、ETH を使って支払うことになります。ETH などのネットワークの大元となるコインと、ERC20 で作られたコインを区別するために、前者をコイン、後者をトークンと呼び分けることもあります。
独自暗号通貨をデプロイするまでの手順
オリジナルの ERC20 暗号通貨をデプロイしてみましょう!ここでは、次のステップで通貨を作っていきます。
- 開発環境 Ethereum Remix IDE を開く
- 現実に Ethereum メインネットにデプロイされている暗号通貨(ERC20)のソースコードを見てみる
- OpenZeppelinでERC20トークンのテンプレートを作成する
- Remix IDE で、コンパイル、デプロイしてみる
途中で、プログラムのコードが登場しますが、プログラマーでない方は、コピペでクリアしていきましょう。閉じたネットワーク環境である Remix VM や、テストネットでやる分には、失敗しても無害です。大胆にいきましょう。ただし、テストネットでもガス代は、かかるのでやり過ぎると一旦開発中断して明日になるのを待って、Faucet で通貨をもらう必要があります。
Ethereum Remix IDE を開いてみる
では、開発環境である Ethereum Remix IDE を開いてみましょう。
Remix IDE とは
さて、Remix IDE の IDE というのは、統合開発環境(Integrated Development Environment)のことで、開発するためのソースコード、ソースコードを機械が理解できるように変換するコンパイルとソフトウェアの不具合を修正したり検出するためのデバッグ機能、および試験的に実行する機能が含まれているものです。言い換えると、「これがあれば、開発に関係することはとりあえず全部できますよー」っていうソフトです。VS Code などを利用したことのある、開発者であれば特に説明することなく利用できるのではないかと思います。
ここでは、Remix IDE の構成や使い方の詳細に立ち入ることはなく、スマートコントラクトをコピペで作成する、スマートコントラクトをコンパイルする、スマートコントラクトをデプロイする、という3つの使い方だけ解説します。
他のリアルな ERC20 を見てみる(Shiba Coin を見てみる)
それでは、ERC20 スマートコントラクトを作成してみましょう。まずは、実際に取引所で取引されているERC20 トークンのソースコードを眺めてみましょう。
CoinMarketCap というサイトで、 Ethereum ネットワーク(プラットフォーム)上のトークンの時価総額ランキングを表示してみます。そうすると、Shiba Inu (SHIB) というトークンが、執筆時点で、8,460億円の時価総額があることがわかりました。とんでもない金額ですね。本当でしょうか。。。
Shiba Inu のスマートコントラクトを見てみましょう。Shiba Inu をクリックして、コントラクトのリンクを見ると、Etherscan のページが表示されます。
ソースコードを Etherscan でみることができます。こちらから閲覧可能です。ソースコードを読んでみると、10-20行読んだくらいで、ERC20 という規格を使っていることや、OpenZeppelin を使っていることもわかります。長いので以下に、Etherscan のリンクを貼っておきます。
https://etherscan.io/token/0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce#code
長いですね。ERC20 のインターフェース(こういう機能を持ちますという宣言)は、17行目から宣言されています。ここを読むと本体が、ERC20 の本体がどんな機能を実装されているのかがわかります。他にもOpenZeppelinのテンプレと思われるライブラリが宣言されていて、ERC20の本体は、227行目からです。さらに、441行目から、ERC20 を継承した、TokenMintERC20Token にトークンの形を決める大事なことが書いてあります。中身の、455行目に、constructor(コンストラクターと言います) から始まる関数が定義されていますが、ここで、トークンの名前や最大供給量などを定義することになっています。ここで与えられる値は、Etherscan のさらに下部の、Contract Creation Code というセクションで、確認することができます。その中に、 Decoded View
という文字がありますので、そこからの値を引用します。
-----Decoded View---------------
Arg [0] : name (string): SHIBA INU
Arg [1] : symbol (string): SHIB
Arg [2] : decimals (uint8): 18
Arg [3] : totalSupply (uint256): 1000000000000000000000000000000000
Arg [4] : feeReceiver (address): 0x6603cb70464ca51481d4edBb3B927F66F53F4f42
Arg [5] : tokenOwnerAddress (address): 0xB8f226dDb7bC672E27dffB67e4adAbFa8c0dFA08
Shiba Inu は、デプロイするときのコンストラクターに与える値で、名前を SHIBA INU、シンボルを SHIB、最大供給量などを決めています。コントラクトの所有者のアドレスが、0xB8f226dDb7bC672E27dffB67e4adAbFa8c0dFA08
ということもわかりますね。コントラクトの所有者は、コントラクトから簡単にわかるのですが、ここでも確認できます。
この所有者のアドレスを、Etherscan してみましょう。Token Holdings というところからトークンの所有状況を見ることができますが、SHIB は、現在保有していないようです。SHIB のコントラクトから見てみましょう。こちらが SHIB のコントラクトになります。 こちらの Holders というところから、保有者のアドレスを見てみます。 0xdEAD000000000000000042069420694206942069
というアドレスに、41%の Shiba Inu が入っていて、 $4,550,668,262 程度の価値になっているようです(えぇ、すごい。。。)。この記事ではあくまで、技術的な要素に限定して、こう言ったところの経緯や解釈などは、他の方にお任せします。
さて、Shiba Inu が、実際に ERC20 で作られていて、 OpenZeppelin も活用されていることがわかりましたので、次は、自分で OpenZeppelin のコードを作成してみましょう。
OpenZeppelin でソースコードを作成してみる
この章では、OpenZeppelin というライブラリを使ってコードを作成していきます。OpenZeppelin は、Solidity で使える便利ライブラリをたくさん用意してくれている便利なサービスです。
OpenZeppelin の Products から、Contructs を開きましょう(URL)。ページの中ほどに、エディターのような画面が出てきます。その中で、ERC20、ERC721、ERC1155、Governor、Custom とタブが表示されます。今回作るのは、ERC20なので、ERC20が強調されている状態にしてください。初めから ERC20 が強調されていると思いますが、されていない場合は、クリックしてタブを選択状態にしてください。
右側の黒いところをみると、スッカスカですが、すでに ERC20 で求められるインターフェースが実装されています。どこで実装されているのかというと、上の import "@poenzeppelin/contracts/token/ERC20/ERC20.sol";
という部分で実装済みの ERC20 スマートコントラクトを読み込んでいるのです。 .sol
というのは、solidily という Ethereum ネットワークのスマートコントラクトで使われるプログラミング言語を示す拡張子です。
このままデプロイしても ERC20 として機能するのですが、皆さんが思っているようには機能しません。例えば、このコインの残高は 0 で誰もコインを持っていませんし、増やすこともできません。。。なので、取引に使うことができません。次の章で、決めることを決めていきましょう。
自分だけのオリジナルコインの名前と発行の方針を決める
例えば、コインを次のようにしてみました。読者の皆さんも好きなようにつけてみてください。
- 名前:Okojo Coin
- シンボル:OKJC
- 初期発行額:1,000,000,000,000(1兆)
- 追加発行:可能
コイン(トークン)の名前を、Okojo Coin として、シンボル(USDとかJPYみたいなもの)を OKJCとしました。Okojo Coin も OKJC は、ユニークではありません。つまり、全く別の同じ名前とシンボルを持つ ERC20 コインを作成することは可能です。ちょっと気持ち悪い気もしますが、そういうものだと思っていてください。同じ名前で同じニックネームの人だっていますよね。でも両者は、区別されます。Ethereum の場合、コントラクトアドレスというものがあり、スマートコントラクトは、一意になりますので、矛盾するようなことは起こりません。
上記の設定は、適当にやっているので、読者で試したいことがあれば、どんどん試してみましょう。あくまで、テストネットにデプロイするので無害です。
オリジナルコインのコードを OpenZeppelin で作成する
上記の設定で、作成したコードは以下のようになります。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract OkojoCoin is ERC20, Ownable {
constructor() ERC20("Okojo Coin", "OKJC") {
_mint(msg.sender, 1000000000000 * 10 ** decimals());
}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
}
pragma とあるところの solidity 0.8.9 というのは、このコードを開発した時点での solidity のバージョンを示しています。中身を見てみましょう。
contract OkojoCoin is ERC20, Ownable
この部分は、OkojoCoin というスマートコントラクトは、ERC20 と Ownable を継承したコントラクトであることを示しています。ERC20 には、トークンの残高を見る機能や誰かにトークンを送金する機能などが備えられています。Ownable は、このトークン所有者を必須にする onlyOwner という機能が備えられています。(参照:ソースコード)
constructor() ERC20("Okojo Coin", "OKJC") {
_mint(msg.sender, 1000000000000 * 10 ** decimals());
}
ここは、コンストラクタと呼ばれ、スマートコントラクトをはじめにデプロイしたときに実行されます。Okojo Coin という名前、OKJC というシンボルが引数として渡され、コンストラクタの具体的な処理の中で、1兆コインをミントしています。decimalsと言うのは、細かい単位で取引できるように0が後ろに18個つきます。
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
ここは、後からミントする場合の処理にアクセスできるように書かれています。 プログラマー的には、プライベートな関数をコントラクトの所有者だけにパブリックな関数に変換していると言えます。
Mint というのは、造幣局を示しています。日本では、造幣局は、硬貨(コイン)の発行をしております。造幣局のホームページのアドレスは、https://www.mint.go.jp/ です。ここに mint とありますね。ミントは、造幣局そのものですが、硬貨を作成する的な意味合いで使われています。NFT(ERC721)でも同様にミントという言葉が使われています。
Remix IDE で、コントラクトを Remix VM にデプロイ
さて、すごく短いコードですが、作成できました。これを Remix IDE にコピペしましょう。
細かいですが、Remix IDE 上にファイルアイコンが表示されているので、これをクリックするとファイルが作成できます。無題のファイルが作成されるので、今回筆者の場合は、 OkojoCoin.sol
という名前でファイルを作成して、OpenZeppelin で作成されたコード(前述)をコピペします。
コピペすると、「あなた大丈夫ですか?騙されてないですか?」っていう警告文が表示されますが、テストネットだけでしかやらないという意思で、この警告をとりあえず無視しましょう。
そうしましたら、まずは、コンパイルです。左側の細い縦長のバーで、虫眼鏡の下の、ちょっと鈍角のカッコがそっぽを向きつついい塩梅でバランスをとっているアイコンをクリックしてください。そうするとコンパイルモードの画面になります。そのままコンパイル実行しましょう。
問題なくコンパイルできると、アイコンに✅がつきます。そしたら、その下のデプロイアイコンをクリックしてデプロイします。まずは、Remix VM (Merge) というところで実験しましょう。お金はかからないので、チャチャっとやっちゃいましょう。
そうしますと、Deployed Contracts っていうところにデプロイできたスマートコントラクトが表示されるので、ここを展開すると、実行可能なコントラクトの機能が一覧されます。この出てくる実行可能なコントラクトの一覧がインターフェースになっています。
例えば、 balanceOf を今デプロイに使ったアカウントで試してみましょう。まず、今は、Remix VM という架空のネットワーク上にデプロイしたので、その際に使われたアドレスをコピーしましょう。
コピーアイコンをクリックすればコピーされるので、これを balanceOf に入れるようにしてみましょう。
Remix VM 上で、ERC20コインが発行できたことが確認できました。さらに、ミントできるか確認してみましょう。
まずは、Remix VM でアカウントを切り替えます。
切り替えたアカウントの balanceOf
が 0 になることを確認してください。
この状態で、このアドレスに対して、mint を実行します。今回は、10コインだけミントしましょう。
私の環境では、こんな感じになります。残高 0 が 10 になれば成功です。早速 transact ボタンをクリックして、再度、balanceOf を実行します。ミントは、コントラクトのオーナーしか実行できないので、アカウントは、コントラクトをデプロイしたときのアカウントに戻してから実行しないと権限エラーになります。
transact 実行後の値です。確かに、残高が 10 になっているのがわかりました。
Remix VM は、ネットワークではありませんので、Metamask で接続して確認することができません。次に、オリジナルコインを Metamask でみられるようにしてみましょう。
ネットワーク上にスマートコントラクトをデプロイする
さて、ガス代を支払って今の ERC20 コインをネットワークにデプロイしてみましょう。どこにデプロイすれば良いかというと、先ほど、Remix VM (Merge) となっていたところを、Injected Provider – MetaMask します。そうすると、Metamask で選択されているネットワークにデプロイすることになります。
いろんなネットワークでガス代をみてみましょう!
例えば、本家本元のイーサリアムメインネットを選びます。
そうすると、Remix IDE の中では、main (1) network と表示されます。Metamask に加えここでも、実際に接続するネットワークを確認できますし、実際にガス代を求められる時にも確認できます。
徐に、デプロイボタンをクリックしてみましょう。Remix IDE でも親切なことに警告を表示してくれます。これを思い切って無視しましょう。そうすると、Metamask で確認画面が表示され、ガス代の見積もりが出ます。この段階では、拒否できますし、何しろ「このアカウントにETHは 0 」なので、無敵です。ガンガンいきましょう。
Metamask に表示された確認画面では、この ERC20 コインを Ethereum メインネットにデプロイするには、0.0375…ETH が必要で、それは、ドル換算では、68.38ドルということがわかりました。日本円で、大体9,000円です。遊びでコインをデプロイするにしては高すぎますので、そっと確認画面を閉じます(その前に残高不足で確認できないことも見ておいてください)
次に、Ethereum メインネットではなく、Polygon Mainnet も試してみましょう。Metamask に Polygon Mainnet が表示されていなければ、ネットワークを追加から、Polygon を追加してみてください。そうすると。。。
ガス代が、ETHではなく、MATIC という単位になっていますが、これのドル換算が、なんと 0.13 ドルです。。。ネットワークが違うとこんなにも価格が違うのですね。
では、次に、本命の Goerli Testnet にしてみましょう。しっかり、Goerli と表示されますね。
今度は、ドル換算はもちろん出ませんが、0.048 Goerli ETH がガス代であると出ました。このくらいであれば、支払えるのでデプロイしてみます。
実際にデプロイを実行すると、コントラクトの展開という名目でアクティビティが記録されます。しかし、まだ、ネットワークに承認されていないので、ブロックチェーンには乗ってきていません。
しばらくすると、承認されました。今回の取引は、ここに記録されました。ちょっとみてみましょう。
よくできました!1兆オコジョコインをミントすることができました!
オリジナルコインをメタマスクで確認
先ほど、1兆コインをPremint で発行したので、Metamask で確認してみましょう。テストネットでは、自作のERC20トークンは、Metamask にインポートの設定をしないと表示されません。
まずは、トークンが見当たりませんか?の中の、「トークンをインポート」をクリックしてください。トークンをコントラクトアドレスからインポートします。
そうしますと、いろんなフォームが出てきますが、コントラクトのアドレスを入力するのが確実です。
今回は、先ほどのスマートコントラクトのデプロイのアドレスを「トークンコントラクトアドレス」というところに入れれば他の値もロードされます。 0xCF0Bb6Bb510B4d8dF3c460705F3Dd2c95cFc1949
これが先ほどのコントラクトのアドレスになります。読者の皆さんが作られたコントラクトのアドレスで試してみてください。
そうすると、とんでもなく大量のオコジョコインの所有者が作成されました。これで、Metamask でもテストネットに作成したコントラクトにアクセスできることがわかりました。にしても、大量のコインを持ってますね笑。それが、Metamaskでアセットとして認識されると少し嬉しいですね。
今回は、テストネットを使っているので、ERC20トークンを手動で追加する必要がありますが、メジャーなネットワークでは、Metamask で自動検出してくれるのでその必要はありません。詳しくは、こちらに記載があります。トークンのアイコンが設定されていないので、ブロークンな画像になっています。
ここでは、ERC20のスマートコントラクトをコピペで作成しました。OpenZeppelin からライブラリをインポートして、Remix IDE で、コンパイルからデプロイまでしています。また、ここでも Metamask を使いました。Metamask で選択肢、注入されたネットワークにデプロイし、ガス代も Metamask で支払います。Metamask が重要な役割を演じているのがわかります。もちろん、Metamask 以外にもウォレットアプリがありますので、同様にできるものと思います。
オリジナルコインを送り合う
以前に、Goerli ETH を送金しあったりした容量と同じ容量でやります。筆者の場合は、「Test Account 2」から「Test Account 1」に ERC20 を送金してみます。
Test Account 1 の方もトークンのインポートが必要なので、送金後にトークンをインポートしてみてください。
Test Account 2 の方から、1000 OKJC を送金してみます。
続いて、ガス代の確認があるので、確認します。
送金が完了したら、Test Account 1 の方で、OKJCをインポートして、確認すると、1000 OKJC の入金が確認できます。
コインの送金履歴を Etherscan で確認
Metamask のアクティビティでも送金履歴が確認できますが、アクティビティから、ブロックエクスプローラーで表示をクリックして、Etherscan でもみてみましょう。ここでも、確かに送金の履歴を確認することができました。
これで、ERC20 の概要がわかりました。トークンの追加発行機能(mint)は、試していませんが、Remix IDE から試してみてください。
次に、すでにデプロイしたコントラクトを Remix IDE から呼び出す方法について補足しておきます。
Remix IDE ですでにデプロイしたコントラクトを呼び出す
まず、すでにデプロイしているコントラクトファイル(*.sol)を変更していないことを確認してください。変更されていると別のコントラクトになりますので、うまいことできないです。
次に、前にデプロイした状態を引き出したいファイル、筆者の場合は、OkojoCoin.sol になりますが、これをコンパイルします。既に経験済みですので、ここまでは簡単にできると思います。
次が注意です。デプロイのタブに移動するのですが、デプロイすると新しいコントラクトとして認識されてしまいます。デプロイ済みのコントラクトアドレスを指定してください。
これで、デプロイ済みの様々な機能にアクセスできます。試しに自分のアドレスに mint してみましょう。コントラクトの所有者である Test Account 2 で接続して、Test Account 1 に 10,000 OKJC をミントしようと思ったのですが、0を18個入れないといけないのを忘れていました。。。これだと、0.00000000000001をミントすることになってしまいますが、これでいきましょう。
確認して、transact してみましょう。
ガス代の確認をして進めます。
Etherscan でも確認してみましょう。
ちゃんとできていますね。(ここで確認した際に、0 を 18個入れるの忘れたことに気がつきました。。。)
Metamask でみてみましょう。
できています!
このように、Remix IDE では、既にデプロイしたスマートコントラクトを呼び出して実行することもできます。この仕組みについて簡単に説明します。コントラクトのアドレスとABI(Application Binary Interface)と呼ばれるコントラクトのインターフェース(使い方)が両方あればコントラクトを呼びだすことができます。Remix IDE で、コンパイルするとABIが自動的に設定されます。あとは、コントラクトのアドレスを教えてあげれば良いと言うわけです。
Goerli Testnet に ERC721 スマートコントラクト(NFT)をデプロイ
2021年から2022年にかけて話題となった、NFTをデプロイしてみましょう。一つのNFTコレクションは、一つのスマートコントラクトになっており、ERC721で標準化されています。EIPは、こちらで確認できます。
ERC721 の概要
ERC721 では、ERC20 と異なり、トークンを送付する時に量ではなくトークンを一意に特定するトークンIDを指定します。トークンIDが付与されることで、代替不可能としています。また、このトークンと画像ファイルのURIや名前、そのほかの属性などを規定したメタデータを紐づけることで、デジタル資産の一意性を担保する仕組みに使われます。ここでは、概念の詳細に踏み込むことなく、ERC721トークンをデプロイしてみましょう。
試しに、筆者は、オコジョコレクション(Okojo Collection)という画像のコレクションをERC721としてデプロイしてみます。このERC721は、次のようにします。
- トークンIDは、連番で自動発番される(0, 1, 2, 3, … と自動で発番される)
- コレクション名は、Okojo Collection、コレクションのシンボルは、OKOJOとする
- コレクションの所有者は、後からでもミントできる(コレクションに新しい作品を追加できる)
- ミントの際は、メタデータのJSONファイルが保存されているURIを指定する
- メタデータの保存には、IPFS(分散型ストレージ)を使う
まずは、既に公開されているERC721をみてみましょう
OpenSea で、トレンドに表示されているこちらの NFT をみてみましょう。
詳細のセクションに欲しい情報がまとまっています。
さて、一つずつ見ていきましょう。Azukiというコレクションは、次のようになっています。
項目 | 中身 |
---|---|
コントラクトアドレス | 0xED5AF388653567Af2F388E6224dC7C4b3241C544 |
トークンID | 1375 |
トークン標準 | ERC721 |
コントラクトアドレスが、分かれば Etherscan で調べることができます。このERC721コントラクトは、クリエーター自身である Azuki さんがデプロイしているように見えますね。Contract のタブをひらけば、ソースコードを見ることもできます。中身を見ていると、OpenZeppelin が登場しますね。
TOKEN TRACKER というところに、AZUKI と記載があります。これが、Azukiトークンになりますので、暗号通貨の通貨単位に当たるものになります。ERC721 は、NFTになるので、一つ一つのトークンが区別されています。
試しに、AZUKIトークンがどれほどトレードされているか見てみましょう。TOKEN TRACKER をクリックします。
ざっとみてみると、15 ETH 程度で、高いものは、143 ETH で取引されていますね。円換算だと、300万円〜3,000万円。すごい金額ですね、、、筆者の計算あってますかね。。。で取引されているようです。
次にメタデータを見てみましょう。 OpenSea のトークンIDをクリックします。
{
"name": "Azuki #1357",
"image": "ipfs://QmYDvPAXtiJg7s8JdRBSLWdgSphQdac8j1YuQNNxcGE1hg/1357.png",
"attributes": [
{
"trait_type": "Type",
"value": "Human"
},
{
"trait_type": "Hair",
"value": "Powder Blue Swept Back"
},
{
"trait_type": "Headgear",
"value": "Ayaigasa"
},
{
"trait_type": "Clothing",
"value": "Blue Kimono"
},
{
"trait_type": "Eyes",
"value": "Closed"
},
{
"trait_type": "Mouth",
"value": "Growl"
},
{
"trait_type": "Offhand",
"value": "Talisman"
},
{
"trait_type": "Background",
"value": "Off White C"
}
]
}
ここで、画像のURLが指定されています。 ipfs://QmYDvPAXtiJg7s8JdRBSLWdgSphQdac8j1YuQNNxcGE1hg/1357.png
となっておりますね。ipfs というのは、先ほど簡単に記述しましたが、分散型のストレージのことです。ブラウザから直接みることはできませんが、 ipfs://
以下の値が分かれば、ゲートウェイという仕組みで IPFS に保存されているファイルにブラウザからアクセスできます。
https://ipfs.io/ipfs/{ipfs://以下の値}
これでアクセスできます。今の場合 https://ipfs.io/ipfs/QmYDvPAXtiJg7s8JdRBSLWdgSphQdac8j1YuQNNxcGE1hg/1357.png になります。このアドレスにアクセスすると表示されました。
name は、作品名、image は、画像のURL、attributes は、作品のタイプがわかるような情報を入れます。attributes は、任意です。このメタデータの標準は、OpenSea に対応しているメタデータを入れると良いでしょう。
OpenSea のメタデータの標準
OpenSea で対応している、メタデータの標準は、下のリンクから確認できます。
https://docs.opensea.io/docs/metadata-standards#metadata-structure
{
"description": "Friendly OpenSea Creature that enjoys long swims in the ocean.",
"external_url": "https://openseacreatures.io/3",
"image": "https://storage.googleapis.com/opensea-prod.appspot.com/puffs/3.png",
"name": "Dave Starbelly",
"attributes": [ ... ]
}
これをみると、
- description: 作品の説明
- external_url: OpenSea に表示されるURL
- image: 画像のURL、非推奨ですが、image_dataに直接埋め込むこともできます
- name: 作品名
- attributes: OpenSea で表示される「属性」セクションを表示させるもの
などがあります。いろいろ試しましたが、最小構成で、name, image だけでも問題なさそうです。
分散型ストレージIPFS
NFTを画像に紐づけるには、画像をアップロードする必要があります。aws s3 などにアップロードしても良いのですが、いつまでも保存されているかわかりません。分散型のネットワーク上にファイルを保存することで、不変でネットワークが生き続ける限り保存されるストレージを利用することができます。(ただし、使われないファイルは自動削除されていきます)
これを提供する仕組みが、IPFSです。プロトコルは、 https://
ではなく ipfs://
になります。前述したように、ipsf プロトコルは、Chromeなど標準ブラウザがサポートしていないので、ゲートウェイを介して、インターネットのプロトコルでアクセスする必要があります。
nft.storage を使ってデジタル資産をアップロードする
IPFSを使う最も簡単な方法は、現在のところ NFT Storage というサービスな気がしています。もちろん、Pinata なども使えますのでここはお好みで選ぶのが良いと思います。
NFT Storage のアカウントを作成する
NFT Storage のアカウントは、こちらから作成できます。
現在のところ、GitHub あるいは、Email でサインアップできるので、アカウントを作ってみてください。
ログインするとこのような画面が表示されます。筆者のスクショは、テストであげたものが表示されていますが、何もファイルをアップロードしていない場合は、空の画面が表示されるかと思います。
早速、アップロードしてみましょう。おすすめのアップロード方法は、 NFTUp というアプリを使ってアップロードすることです。
このボタンをクリックするとインストールできるので、インストールしましょう。ダウンロードしている間に、API Keys というところから、API Key を作成しておいてください。
NFTUp をインストールして、起動すると、API Key を入れるように言われますので、今し方作成したAPI Key を入力してアカウントを連携してください。
NFTUp の使い方は、簡単です。アップロードしたいファイル、フォルダを「Drag and Drop files」という領域にドロップしてください。しばらくすると、ファイルが発行されてます。
アップロードするファイルを作成する
アップロードするファイルを作成してみましょう。写真でもイラストでもOKなんですが、今回は、イラストを作成してみます。OKOJOなので、オコジョをモチーフにした絵をアップロードしてみます。
これをアップロードしてみます。
そうしますと、CIDというものが発行され、CIDに基づいたIPFS URLが発行されます。ブラウザで見られるようにするために、Gateway URL も発行されます。ゲートウェイを見てみましょう。
https://bafkreihfhpwdfkrykmfcmlxisdpqecwnde5ghpyi5aoqfibgfskcndjve4.ipfs.nftstorage.link/
表示されますので、ちゃんとアップロードされていそうです。これで、image として指定するファイルを作ることができました。次にメタデータもファイルとしてアップロードしましょう。
メタデータは、こんな感じで作りました。
{
"name": "Okojo Collection #1",
"image": "ipfs://bafkreihfhpwdfkrykmfcmlxisdpqecwnde5ghpyi5aoqfibgfskcndjve4",
"attributes": [
{
"display_type": "date",
"trait_type": "Birthday",
"value": 1679294638
},
{
"trait_type": "Nose Color",
"value": "Azuki"
},
{
"trait_type": "Base Color",
"value": "White"
},
{
"trait_type": "Age Group",
"value": "Young Generation"
}
]
}
先ほどの Azuki さんのメタデータを参考に作っています。Birthday は、OpenSea のサンプルにあったので入れてみました。他のは、適当に入れています。これを、okojo.json としてアップロードします。
こちらもCIDが生成されました。
CIDとは?
CIDは、Contents Identifier の略で、コンテンツ自体のIDです。フォルダにすると、フォルダの中身までCIDに入りますので、フォルダにアイテムを追加したものは、CID が変わります。コレクションをフォルダにして、フォルダにアイテムを追加していきたいのにCIDが変わってしまうと不便な気がしますね。筆者は試していませんが、この辺は、Ethereum 内でのアドレス取得などで解決できるのかもしれません。Ethereum Naming Service というもので、ドメイン取得に似たサービスです。
OpenZeppelin で作成した ERC721 コントラクトをデプロイする
コンテンツの方は、紐づける画像をアップロードし、メタデータもアップロードしたので、デプロイする準備が整いました。OpenZeppelin の ERC721 を作成しましょう。
ERC721 のタブにします。Base URI は、特に持ち合わせていないので空にしておきましょう。後からNFTをミントしたいので、Mintable をチェックします。トークンIDは、連番で自動発番するようにしたいので、Autor Increment Ids もチェックしておきます。さらに、メタデータをIPFSに保存しているので、URI Storage にもチェックを入れます。これで準備完了です。
コードのコピーを載せておきます。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract OkojoCollection is ERC721, ERC721URIStorage, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIdCounter;
constructor() ERC721("Okojo Collection", "OKOJO") {}
function safeMint(address to, string memory uri) public onlyOwner {
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
_safeMint(to, tokenId);
_setTokenURI(tokenId, uri);
}
// The following functions are overrides required by Solidity.
function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
}
それほど長くないですが、実際に使うのは、safeMint だけです。続いて、Remix IDE でファイルを作成しましょう。筆者は、 OkojoCollection.sol
としました。
ここまで、来た読者の皆さんであれば、コンパイルとデプロイは余裕ですね。一気にやっちゃいましょう。とはいえ、一度、Remix VM でテストしましょうね。テストは、次の順でやってみてください。
safeMint する
Remix VM のアドレスの一つに NFT をミントしましょう。NFT Storage にアップロードしたファイルのうち、メタデータの方をURIに指定します。なんで、safeMint に safe がつくのかよくわかりませんが、
まずは、デプロイセクションのAccount のところで、デプロイに使ったアカウントを選びます。balanceOf を呼び出すと、0 が帰ってくるので、何も持っていないことが確認できますね。
そのアドレスにsafeMint で、to に今 balanceOf で調べたアドレスにして、ミントしてみましょう。
Remix VM なので、一瞬で終わります。
再度、balanceOf を呼び出してみましょう。
では、Goerli Testnet にデプロイしておきましょう。ガス代、結構高い・・・夕方以降は高くなります。平日の夜より、週末の昼間にやるべきですね。
オリジナル ERC721 に NFT をミントする
Georli Testnet で balanceOf を確認しましょう。
0 となっていますね。
ミントしましょう。
ミントもガス代かかりますが、それほどでもないですね。ただ、たくさんのNFTコレクションをミントしようとすると、無視できないコストになります。こういうのを解決する意味でも、Polygonなどのレイヤー2ネットワークや、ERC1155など一度にたくさんのアイテムをミントできる仕組みの良さがわかりますね。
balanceOf で、所有しているNFTを確認しましょう。
Etherscan で NFT を確認する
この取引を Etherscan でみてみましょう。 URLはこちらです。
Okojo Collection にNFTがミントされました!ERC-721トークンと表示されています。Token ID は、連番で自動発番されるので、0になっています。
OpenSea で NFT を確認する
OpenSea でも NFT コレクションを確認してみましょう。こちらのURLに確かに存在していました。
ちゃんとオコジョのアイコンが表示されています。テストネット用のOpenSeaは、以下のURLから入れますので、検索フィールドに検索したいアドレスを入れて表示されたアカウントをクリックすれば確認できます。
https://testnets.opensea.io/ja
説明文(description)を追加するのを忘れていましたが、Attributes に記載されている値が属性のセクションにちゃんと表示されていますね。コントラクトアドレス、トークンID、ERC721であることもきっちり OpenSea が拾ってくれています。
これで、ERC721トークンをミントすることができました。お疲れ様でした。
ERC721トークンを送る
今までと同じように、Test Account 2 から、Test Account 1 へNFTを送ってみます。Test Account 2 は、OpenSea でみるとこんな感じで、コレクションを持っています。My Chan Eyes というコレクションは、テストで作ったものです。
余談になりますが、この目のコレクションを作る方法は、以下のリンクからどうぞ。
https://sug01.com/archives/7345
せっかく作ったOkojoですが、Test Account 1 に送ってみましょう。
Test Account 1 のページは、こんな感じで空になっています。
先ほどの、Remix IDE から safeTransferFrom を実行します。
ガス代の確認画面で、しっかり確認して、取引が完了したら、Etherscanで確認しましょう。
ちゃんとできていそうです。
OpenSea で Test Account 1 を確認
Okojo Collection #1 が、Test Account 1 に移っています。
OpenSea で Test Account 2 を確認
Test Account 2 は、Okojo Collection #1 を失っています。
これで、NFTの取引のところも実験できました。
ERC1155 スマートコントラクト
同じようにすればデプロイできるので、こちらは、読者にお任せするとしましょう。と言いつつ説明してしまうのが、筆者です。
まずは、ERC1155 のトークンを色々みてみましょう。
Masked Girls NFT Digital X Real のメタデータを見てみる
https://opensea.io/ja/collection/masked-girls-nft-digital-x-real
こちらの NFT コレクションですが、ERC1155でミントされています。ERC1155であることは、コレクションの一つのアイテムをクリックして、詳細から確認することができます。
メタデータを確認してみましょう、となるのですが、
この場合は、OpenSea の API を使ってみます。
GET https://api.opensea.io/asset/{contract_address}/{token_id}
この形式でリクエストします。
上記の場合は、
- コントラクトアドレス: 0x495f947276749ce646f68ac8c248420045cb7b5e
- トークンID: 103868195281469504095998172036907834673482052934876586150305183726585727942657
になりますので、
https://api.opensea.io/asset/0x495f947276749ce646f68ac8c248420045cb7b5e/103868195281469504095998172036907834673482052934876586150305183726585727942657
ここにリクエスト(ブラウザで表示でOK)すれば、みられます。
画像URLは、https://i.seadn.io/gae/K_yvd5xs6EXWL26mRm6-TORZeG_YTGVDh8h5Yok0RQdkKyOA8Mp1CKt2Y7QK3t-h6ZEGayO8HcVlWHHUj1K-tkaN_tI4p1e-YIMz?w=500&auto=format で指定されています。そのほかにも指定されていますが、属性ようなものは確認できませんでした。
理由がわかりませんでしたが、メタデータが見られませんでしたので、他の例をみてみましょう。コントラクト自体は、OpenSeaが作成したもののようです。理由がわかる方、ぜひ教えてください。
Deck of Time: Cruel Fate のメタデータを見てみる
丁度良さそうな例があったので、こちらを使ってみます。こちらは、Town Star というゲームのアイテムのようです。こちらは、トークンIDにリンクが貼ってあり、メタデータを確認できました。
{
"decimalPlaces": 0,
"description": "Fate has been cruel. But as swiftly as the darkness has come, light can penetrate through the clouds. (While the Wheel of Fate granted no reward, this mysterious card may hold hope for a future boon.)",
"image": "https://tokens.gala.games/images/sandbox-games/mirandus/ticket/deck-of-time-cruel-fate.png",
"name": "Deck of Time: Cruel Fate",
"properties": {
"category": "Ticket",
"game": "Mirandus",
"rarity": {
"hexcode": "#17D200",
"icon": "https://tokens.gala.games/images/sandbox-games/rarity/uncommon.png",
"label": "Uncommon",
"supplyLimit": 36050
},
"tokenRun": "ticket"
}
}
name, image, properties (attributes と同じ?)があって、OpenSea の属性にもしっかり表示されています。ERC1155 も ERC721 のようにミントできることがわかりました。
同じようにすれば良いということが大体わかりましたので、早速テストします。
ユースケースとメタデータを考える〜ERC1155の肩たたき券を作る
たとえば、父の日に肩たたき拳を発行して、ERC1155 でお父さんに配布するよくあるユースケースについて考えてみましょう。
次のようにしてみました。
- 肩たたき券は、コントラクト所有者は追加発行できる
- 初回に15枚発行する
- メタデータは全て同じ(全部、同じ名前、同じ画像)
- 券は、消費される(使ったら消える)
こんな感じでしょうか。動作に影響ないですが、一枚15分で、最大3枚利用可能というところは、attributes に入れておくだけにしておきましょう。
{
"name": "肩たたき券",
"description": "この肩たたき券、一枚につき15分の肩たたきを受けることができます。最大連続で3枚まで使用できます。",
"image": "https://path/to/image/ticket.png",
"attributes": [
{
"trait_type": "Duration (mins)",
"value": 15
},
{
"trait_type": "Max uses",
"value": 3
}
]
}
画像URLの path/to/image
のところは、確定後、記入することにします。
肩たたき券の画像は、こちらにしました。デザインに特に意味はないです。
メタデータと画像を NFT Storage にアップロードする
画像とメタデータを安全なストレージにアップロードする必要があります。NFTUp を使ってアップロードしましょう。
まずは、画像データをアップロードします。
ipfs://bafybeihi2vmpy2qbtrsfrlicu5kmnabtb3j6b6v6tytbu7hksst7zoo6ti/ticket.png
こちらにアップロードできました。
こちらのURLで確認してみます。 https://ipfs.io/ipfs/bafybeihi2vmpy2qbtrsfrlicu5kmnabtb3j6b6v6tytbu7hksst7zoo6ti/ticket.png
確認できました。
次にメタデータもアップロードします。この時、画像のURLを先ほどアップロードしたものに変えておくことを忘れないでください。 path/to/image
の部分を置き換えましょう。
ipfs://bafybeihfehrs37a3rqmhbyw2mx2pralpmuwnam3wdstz2dnj4fcyaifzcu/meta.json
こちらにアップロードできました。
https://ipfs.io/ipfs/bafybeihfehrs37a3rqmhbyw2mx2pralpmuwnam3wdstz2dnj4fcyaifzcu/meta.json
確認できました。
OpenZeppelin で ERC1155 コントラクトを作成する
お馴染みの OpenZeppelin でコントラクトを作成してみます。
- Name: Katatataki Ken
- URI → 先ほどのメタデータのURI
- あとで、追加できるように Mintable を ON
- チケットは消費されるので、Burnable を ON
この状態でできました。
Remix IDE で、ERC1155をデプロイ
さて、Remix IDE で、デプロイします。デプロイの前に、Remix VM で各々で動作確認しておいてください。やることは、Mint してみることと、Mint した後に balanceOf が変わっていることです。Burn もテストしてください。ここでは、同じことの繰り返しを避けるためその手順は省略します。
それでは、デプロイしたコントラクトで、Mint してみます。
次に、balanceOf を確認しましょう。
返却値が小さくてみにくいですが、15枚あるのが確認できました。
OpenSeaのテストネットでも確認しましょう。
属性値は、レベルというところに表示されました。ERC1155 では、Enjin Metadata Style が使われるようで、先ほどの例のように、properties に記載する方が正解のようです。こういうのも実際にやってみるとわかりますね。皆さんは、metadata を attributes ではなく properties にする方法でも試してみてください。
と言いつつ、ちゃんと説明するのが、筆者です。metadata の記載を properties でやってみましょう。
メタデータを次のようにします。
{
"name": "肩たたき券",
"description": "この肩たたき券、一枚につき15分の肩たたきを受けることができます。最大連続で3枚まで使用できます。",
"image": "ipfs://bafybeihi2vmpy2qbtrsfrlicu5kmnabtb3j6b6v6tytbu7hksst7zoo6ti/ticket.png",
"properties": {
"Category": "Ticket",
"Purpose": "肩たたき",
"Duration": "15分",
"Max use": "3枚"
}
}
全く同じプロセスで、肩たたき券をMintしてみます。
属性のところにちゃんと表示されましたね。
肩たたき券を消費する(Burn)
先ほどアップした、肩たたき券を利用してみましょう。利用する際は、コントラクトの所有者が、Burnしていくようにしましょう。
id=0 のトークンを1つバーンさせます。(参照:burnのソースコードをみると、burn できるのは、承認されたアカウントか、トークンの所有者となっています)
balanceOf で、残高を確認しましょう。
ちゃんとチケットの残高が減っています。OpenSeaでも確認します。
ちゃんと、残高が14になっています。
テストネットにアリガトウスマートコントラクトをデプロイ
ここから先は、デベロッパー向けの内容になります。できるだけ平易に記述するようにしますが、JavaScript や HTML などの専門的な内容も含まれることがあります。
この前に作った、ERC20コイン(筆者の場合は、Okojo Coin)でありがとうを送り合うスマートコントラクトを作成してみましょう。と、書き始めましたが相当記事が長くなってしまいましたので、別記事で説明いたします。
編集後記
ERC20、ERC721、ERC1155 をスマートコントラクトとしてテストネットにデプロイしました。このようにインフラを持っていなくてもコントラクトをデプロイできる便利な仕組みです。一方で、ガス代がかかるのでコストがバカにならない仕組みにも見えます。実際には、デプロイしたコントラクトは、デプロイした人=オーナーが中央管理していくことになるでしょう。こういった場合は、許容されて良いと思います。徐々に仲間が増えるにつれて DAO の仕組みを部分的に導入していけば良いと思いました。
また、ブロックチェーン上だけで管理しきれないことは、従来型のサーバーの力を借りることもあると思います。全てをブロックチェーンだけで実装しようとすると、アジャイルな開発がやりづらかったり、コントラクトの変更やアップグレードも初めから計算してやらないと難しいです。シンプルで透明性の高い仕組みを作るにはとても使い勝手の良い技術だと思いました。
興味のある方は、開発者向けの記事(未投稿)も読んでみてください。また、オートロ株式会社では、余裕のある社会を作るために自動化ロボット、オートロを開発しています。技術者の方も、そうでない方も少しでも興味を持っていただければ、絶賛採用中ですので、こちらから応募してみてください!または、@shr_f にメンション等ください。
本件に関連したり、しなかったりしてももっと話を聞きたいと思っていただいた方もお問い合わせもしくは、@shr_f までご連絡いただけると幸甚です。
最後までお付き合いいただきありがとうございました。