🔥

RemixでWallet Connectを使用してコントラクト開発しよう!

2024/05/21に公開

はじめに

初めまして。
CryptoGamesというブロックチェーンゲーム企業でエンジニアをしている cardene(かるでね) です!
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。

https://cryptogames.co.jp/

代表的なゲームはクリプトスペルズというブロックチェーンゲームです。

https://cryptospells.jp/

以下でも情報発信しているので、興味ある記事があればぜひ読んでみてください!

https://twitter.com/cardene777

https://chaldene.net/

https://qiita.com/cardene

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4

今回はRemixという、ブラウザ上でスマートコントラクトの開発を行うことができるツールで、WalletConnectを使用して開発を行う手順を紹介します。
できる限り噛み砕いて非エンジニアでも実行できるよう解説していきます。

Remixにアクセス

まずはRemixのページを開きましょう。

https://remix.ethereum.org/#lang=en&optimize=false&runs=200&evmVersion=null&version=soljson-v0.8.25+commit.b61c2a91.js

https://remix.ethereum.org/#lang=en&optimize=false&runs=200&evmVersion=null&version=soljson-v0.8.25+commit.b61c2a91.js

URLの末尾にコンパイラのバージョンなど含まれているので、上記のURLから開いてください。

開くと上記のようなページが表示されます。

ページの左側にあるサイドメニューに注目してください。
図の赤枠はそれぞれ以下のことができる場所です。

  1. スマートコントラクトを開発をする場所。
  2. コンピューターが読みやすい形式に変換する「コンパイル」を行うタブ。
  3. コントラクトを公開する「デプロイ」を行うタブ。

Solidityファイルの作成

では、次にSolidityのファイルを作成していきましょう。

上記の「contracts」という部分にカーソルを合わせるとファイルアイコンが出てくるのでクリックします。
そうするとファイルが作成されて、ファイル名を設定できるようになります。

ファイル名を設定でできたら、ファイルをクリックして開きましょう。
ファイルを開くと中身が空になっているので、以下のようにコードを書いていきましょう。

今回は1からかかず、以下に書かれているコードをコピペしてください。
1行目から最後の行までコピーして、先ほど作成したファイルにペーストしてください。

https://gist.github.com/cardene777/22cf12395c33a87fd96f585d9c41d621

これでSolidityでかかれた、スマートコントラクトの作成ができました。

スマートコントラクトの解説

コントラクトの作成ができたところで、コントラクトの中身を見ていきましょう。

ライセンスとバージョン

// SPDX-License-Identifier: MIT

この部分ではライセンスについて定義しています。

pragma solidity 0.8.25;

ここではSolidityのバージョンを定義しています。
今回は0.8.25というバージョンを使用しています。

ライブラリのインポート

import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import {ERC721Burnable} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Base64} from "@openzeppelin/contracts/utils/Base64.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";

様々なライブラリを読み込んでいます。

  • ERC721
    • Openzeppelinが開発をしているERC721コントラクトを読み込んでいます。
    • ERC721形式のNFTを作成するときは、基本的にこのコントラクトを読み込みます。
  • ERC721Burnable
    • ERC721形式のNFTをburnできる拡張機能です。
    • burnとは、NFTを削除して以降使えなくする機能です。
  • Ownable
    • コントラクトの所有権を管理するコントラクトです。
  • Base64
    • データを他の形式に変換するコントラクトです。

https://wa3.i-3-i.info/word11338.html

  • Strings
    • 特定のデータを文字列に変換するコントラクトです。

コントラクト定義

contract JBANFT is ERC721, ERC721Burnable, Ownable {

上記でコントラクト名の定義と複数のコントラクトを継承しています。
継承とは、他のコントラクトの機能を引き継いで、継承先のコントラクトで使えるようにすることです。
今回でいえば、JBANFTというコントラクトを作成し、ERC721ERC721BurnableOwnableの3つのコントラクトを継承して、JBANFTからも3つのコントラクトの機能を使用できるようにしています。

変数

uint256 private _nextTokenId;

_nextTokenIdという変数を定義しています。
変数とは値が入る「」のようなものです。
今回は_nextTokenIdという名前の「」を用意して、ここに任意の値を格納できるようにしています。
uint256というのはデータの種類を表していてと呼ばれます。
uint2560から2^256 - 1までの値を定義できる型です。
値が入っていないように見えるのは定義しているだけだからです。
ただ、Solidityの場合は0という値が入っています。

constructor

constructor(address initialOwner)
    ERC721("JBANFT", "JBAN")
    Ownable(initialOwner)
{}

constructorと呼ばれる、コントラクトをデプロイ(公開)した時に一度だけ実行される関数(一連の処理を一まとめにしたもの)を定義しています。
initialOwnerというアドレスを引数(関数実行時に渡される値)で受け取り、Ownableコントラクトの機能を実行してコントラクトの所有者をinitialOwnerに設定しています。
initialOwnerには、0xabc123...というようなアドレスが渡されます。
ERC721("JBANFT", "JBAN")という部分では、継承しているERC721コントラクトの機能を使用して、NFTの名前とシンボル名を設定しています。

mint関数

function safeMint(address to) public {
    uint256 tokenId = _nextTokenId++;
    _safeMint(to, tokenId);
}

この関数では、NFTをmint(新規発行)する処理を定義しています。
関数名はsafeMintで、toというアドレスを引数で受け取っています。
publicというのは関数のアクセス範囲を定義しています。

アクセス範囲 説明
external コントラクトの外部からのみ実行可能。
public コントラクトの外部・内部から実行可能。
internal コントラクトの内部からのみ実行可能。

上記3つのパターンがあり、データを更新する関数ではいずれかのパターンで定義する必要があります。
externalの場合は、コントラクト内に定義されている他の関数から呼び出されることができないですが、フロントエンドアプリケーションなど外部から実行することはできます。
publicの場合は、コントラクト内に定義されている他の関数から呼び出すことができ、フロントエンドアプリケーションなど外部からも実行できます。
internalの場合は、コントラクト内に定義されている他の関数からのみ呼び出すことができ、フロントエンドアプリケーションなど外部から実行することはできません。

では次に処理の内容を見ていきましょう。
tokenIdという変数を定義して、_nextTokenId++という値を格納しています。
_nextTokenId++というのは、_nextTokenIdに格納されている値に1を足す処理(インクリメント)をしています。
_nextTokenIdが仮に2だった場合、tokenIdには3が格納されます。
そしてこのtokenIdこそ、NFTのユニーク性を示す要素の1つである値です。
NFTがmintされるたびに値が1ずつ増えるため、同じtokenIdを持つNFTは存在しません。

次に_safeMintという関数を実行して、引数で受け取っているtoというアドレスと先ほど定義したtokenIdという値を渡しています。
この_safeMintという関数は、継承しているERC721コントラクトに定義されています。

_safeMint関数

ではせっかくなので、_safeMintの中身を見ていきましょう。

上記の赤枠の部分を「commandキー」を押しながらクリックしてください。

そうすると、上記のようにERC721というコントラクトが開きます。
これが継承しているERC721のコントラクトです。

304行目あたりに先ほど呼び出した_safeMintという関数が定義されています。

function _safeMint(address to, uint256 tokenId) internal {
    _safeMint(to, tokenId, "");
}

さらに別の関数を呼んでいますね。
Solidityでは、同じ関数名でも渡される引数が異なると別の関数扱いになります。
関数内で呼んでいる_safeMintは引数が3つで、先ほど実行した_safeMintは引数が2つなので別の関数扱いになります。

function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
    _mint(to, tokenId);
    _checkOnERC721Received(address(0), to, tokenId, data);
}

上記が先ほど実行していた、引数が3つの方の_safeMint関数です。
_mintという関数を呼んでいるのが確認できます。

function _mint(address to, uint256 tokenId) internal {
    if (to == address(0)) {
        revert ERC721InvalidReceiver(address(0));
    }
    address previousOwner = _update(to, tokenId, address(0));
    if (previousOwner != address(0)) {
        revert ERC721InvalidSender(address(0));
    }
}

上記の関数が先ほど実行されていた_mint関数です。
処理の中身を見ていきましょう。

if (to == address(0)) {
    revert ERC721InvalidReceiver(address(0));
}

上記では条件分岐を行なっています。
条件分岐とは、条件によって別の処理をするということです。
今回はto == address(0)というのが条件です。
これは、mintしたNFTを渡すアドレスがaddress(0)かどうかを確認しています。
==は値が等しいかの記号です。
address(0)はゼロアドレスと呼ばれ、誰の所有でもないアドレスです。
よって、このゼロアドレスに送ってしまうと誰も取り出せなくなります。

もしこのゼロアドレスがtoとして引数で渡された場合は、ERC721InvalidReceiverというエラーを返して処理を中断します。

address previousOwner = _update(to, tokenId, address(0));

次に_updateという別の関数を実行しています。

function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {
    address from = _ownerOf(tokenId);

    // Perform (optional) operator check
    if (auth != address(0)) {
        _checkAuthorized(from, auth, tokenId);
    }

    // Execute the update
    if (from != address(0)) {
        // Clear approval. No need to re-authorize or emit the Approval event
        _approve(address(0), tokenId, address(0), false);

        unchecked {
            _balances[from] -= 1;
        }
    }

    if (to != address(0)) {
        unchecked {
            _balances[to] += 1;
        }
    }

    _owners[tokenId] = to;

    emit Transfer(from, to, tokenId);

    return from;
}

ちょっと長いですね...。
まず引数で「to(NFTを受け取るアドレス)」、「tokenId(mintするNFTのトークンID)」、「authtokenIdのNFTの操作権限を持つアドレス)」を渡しています。
authには、現在のNFTの保有者からNFTの操作権限を付与されたアドレスが渡されますが、今回は新規発行のためゼロアドレスが格納されています。

address from = _ownerOf(tokenId);

上記では、_ownerOfという関数を実行して、引数で渡されたtokenIdのNFTの保有者を取得しています。
今回は新規発行のためゼロアドレスが返ってきます。
このようにゼロアドレスは値がないときなどにも使用されます。

if (auth != address(0)) {
    _checkAuthorized(from, auth, tokenId);
}

ここではauthの値がゼロアドレス以外の場合に、本当に現在のNFTの保有者からNFTの操作権限を付与されているかをチェックしています。

if (from != address(0)) {
    // Clear approval. No need to re-authorize or emit the Approval event
    _approve(address(0), tokenId, address(0), false);

    unchecked {
        _balances[from] -= 1;
    }
}

上記では、NFTのtrasnfer(アドレスAからアドレスBへNFTを送るなど)の処理が行われます。

if (to != address(0)) {
    unchecked {
        _balances[to] += 1;
    }
}

今回は新規発行(mint)なので、上記がメインの処理になります。
引数で渡されたtoには、NFTを受け取るアドレスが渡されているため、address(0)とは異なります。
!=は値が同じではないことを示す記号です。
その後、_balances[to] += 1;toが保有しているNFTの数の合計数を1足しています。
+=は左側の値に右側の値を足す処理をします。

mapping(address owner => uint256) private _balances;

_balancesというのは、マッピング配列と言われ上記のように定義されていています。
簡単に説明すると、ownerというアドレスごとにuint256の値が管理されています。

  • 0x123abc... -> 2
  • 0x456def... -> 5
  • 0x789hij... -> 1

上記のようにアドレスごとに、現在保有しているNFTの数が管理されていて、_balances[to]toには0x456def...などのアドレスが格納されています)というようにすることで5などのデータが取得できます。

今回はNFTを新規発行(mint)しているため、保有しているNFTの数を1増やしています。

_owners[tokenId] = to;

上記では特定のtokenIdに紐づくNFTの保有アドレスを取得しています。

mapping(uint256 tokenId => address) private _owners;

先ほどの_balances同様、上記のようにマッピング配列でデータが管理されています。

  • 1 -> 0x123abc...
  • 2 -> 0x456def...
  • 3 -> 0x789hij...
  • ...

上記のようにtokenIdに紐づくNFTの現在の保有者を管理しています。

今回はNFTを新規発行(mint)しているため、引数で渡されているtokenIdの保有者をtoのアドレスに設定しています。

emit Transfer(from, to, tokenId);

最後にTransferというイベントを発行して、フロントエンドアプリケーションなどにmint処理が成功したことを通知しています。

だいぶ長かったですが、これがmint処理の全貌です。

tokenURI

tokenURIという関数は、NFTのメタデータを返す関数です。

Openseaでいう上記データを管理しているのがメタデータです。

https://opensea.io/ja/assets/ethereum/0x524cab2ec69124574082676e6f654a18df49a048/20599

function tokenURI(uint256 tokenId)
        public
        view
        override
        returns (string memory)
    {

引数でtokenIdという値を受け取り、他に色々な値が設定されているのが確認できます。
publicmint関数でも説明したように、コントラクトの内外からアクセスできるということです。
viewは読み取り専用関数(データの更新をせずに、データを取得するだけの関数)を示しています。
overrideというのは、コントラクトを継承しているときに、継承元のコントラクト(今回の場合はERC721)に定義されている同じ名前の関数(今回の場合はtokenURI)を上書きすることを示しています。
上書きをすることで関数の処理を自分の好きなように書き換えられます。

returns (string memory)の部分では、この関数が返すデータの型を定義しています。
今回は文字列を返すため、stringという値が型として設定されています。
memoryというのは、関数実行時に一時的にデータを保存することを指します。
通常であればブロックチェーン上にデータを書き込みますが、memoryを使用すると一時的な保存場所にデータを保存するためガス代もかかりません。

require(
    tokenId <= _nextTokenId,
    "ERC721Metadata: URI query for nonexistent token"
);

ここでは、引数で渡されたtokenIdが既にmintされているものかチェックをしています。
もしまだmintされていないようであればエラーを返して処理を中断します。

// string memory uri = "https://ipfs.io/ipfs/QmXbBSeMWZd3wSxAKMhMSs5m5ZzJJDUHdSimnUmEx8BuEp?filename=JBAN.png";
        string memory uri = "https://arweave.net/pP9Rw4hx-Ki8m1R1A5EotbpZW2MAJlenmXbAtTa93Gc"; // ここに好きな画像を入れることも可能

ここではNFTの画像のURLを設定しています。
通常であればNFTの画像はtokenIdごとに異なりますが、今回は全部同じにしています。

return
            string(
                abi.encodePacked(
                    "data:application/json;base64,",
                    Base64.encode(
                        bytes(
                            abi.encodePacked(
                                '{"name": "JBANFT #',
                                Strings.toString(tokenId),
                                '", "description": "JBA NFT", "image": "',
                                uri,
                                '"}'
                            )
                        )
                    )
                )
            );

最後にメタデータを組み立てています。

{
	"name": "JBANFT #0",
	"description": "JBANFT NFT",
	"image": "https://arweave.net/pP9Rw4hx-Ki8m1R1A5EotbpZW2MAJlenmXbAtTa93Gc"
}

詳細は省きますが、上記のようなデータになるように組み立てて、最終的な出力はbase64形式で変換した以下の値になります。

data:application/json;base64,eyJuYW1lIjogIkpCQU5GVCAjMCIsICJkZXNjcmlwdGlvbiI6ICJKQkEgTkZUIiwgImltYWdlIjogImh0dHBzOi8vYXJ3ZWF2ZS5uZXQvcFA5Unc0aHgtS2k4bTFSMUE1RW90YnBaVzJNQUpsZW5tWGJBdFRhOTNHYyJ9

メタデータがなぜbase64形式で変換されるのがデフォルトなのかの理由は定かではないですが、以下のメリットがあるようです。

  • base64形式で変換した値をコントラクトに保存するときに効率よく保存される。
  • ほとんどのデータをbase64形式で変換できる。
  • 変換したデータだけをEtherum上でやり取りすれば良いため、無駄な処理をしなくて良い。

https://www.reddit.com/r/ethdev/comments/11ocw0s/why_is_base64_encoding_used_for_onchain_metadata/

これでコントラクト内に定義されている関数を一通り解説できました。
次にコントラクトをコンパイルしていきましょう。

コントラクトのコンパイル

次にコントラクトをコンパイルしていきます。
Solidityで書かれたコントラクトは人間が読みやすいように作られていますが、コンピューターからは読みにくい状態です。
コンパイルをすることで、コンピューターが読みやすいデータに変換することができます。

では早速そのコンパイルをしてみましょう。

サイドメニューの真ん中のアイコンをクリックして、「Compile Nft.sol」というボタンをクリックします。
サイドメニューのアイコンの右下がくるくるして、サイドチェックマークになればコンパイル成功です。
これだけの単純な処理でコンパイルができます。

コントラクトのデプロイ

では次にコントラクトのデプロイをしていきましょう。
デプロイとは、コントラクトを公開して他の人が実行したりできるようにすることです。
また、この章ではEthereumのメインネットやテストネットではなく、Remixが提供している環境にデプロイします。
そのため、他の人が触ったりはできませんが動作の確認などはできるため、作成したコントラクトの挙動を確認していきましょう。

  1. サイドメニューの下から2つ目のアイコンをクリック。
  2. アドレス横にあるコピーボタンをクリック。
    • ここにあるアドレスは仮のアドレスになります。
  3. 上記でコピーしたアドレスを貼り付けてください。
  4. Deploy」ボタンをクリックするとコントラクトがデプロイされます。

上記の手順に沿ってデプロイしていきましょう。

デプロイが成功すると、上記のようにデプロイしたコントラクトの関数などが見れるようになります。

一番上にコントラクトアドレスがあり、オレンジ色のボタンがデータを更新する関数、青色のボタンがデータを取得する関数です。

関数実行

ではデプロイしたコントラクトの関数を実行してみましょう!

前提

今回実行に使用するアドレスは、以下の部分でコピーしたものを使います。

NFT情報

まずはNFTの情報を取得してみましょう。

上記の3つの関数を実行してそれぞれ正しい情報が表示されているか確認してください。

  • name
    • NFTコントラクトの名前。
    • JBANFT
  • owner
    • デプロイボタンを押すときに設定したアドレス。
  • symbol
    • NFTのシンボル名。
    • JBAN

safeMint

次にNFTをmintしていきましょう。

上記の右の赤枠にコピーしたアドレスを貼り付けて、左の「safeMint」というボタンをクリックしてください。

実行後、上記の画像のように右下のコンソールと呼ばれる部分に出力がされていれば実行成功です。

balanceOf

では、次にbalanceOf関数を実行して、特定のアドレスが保有しているNFTの数を確認しましょう。

上記の右側に先ほどNFTを取得したアドレスを入力し、「balanceOf」というボタンをクリックしてください。
1」と出力されれば成功です。
再度safeMint関数を実行して、「balanceOf」というボタンをもう一度クリックしてみてください。
balanceOfはNFTの保有数を取得する関数であるため、「2」と出力されれば成功です。

ownerOf

では、次にownerOfを実行して、特定のtokenIdに紐づくNFTの保有アドレスを確認しましょう。

tokenIdを入力する部分に入れます。
まずは0を入れて「ownerOf」をクリックしてください。
先ほどsafeMintを実行してNFTを受け取ったアドレスが出力されていれば正しいです。
次に1を入れてみてください。
こちらも先ほど同様のアドレスが出力されるはずです。

2以降を入力して実行すると以下のようにエラーがコンソールに出力されます。

これは存在しないtokenIdにアクセスしたためです。

tokenURI

最後に、tokenURI関数を実行して、メタデータを取得しましょう。

0と入力して、上記のようにやたら長いランダムな文字が出力されていれば成功です。
これはbase64という形式に変換されたデータなので、元の形式に戻す必要があります。

https://www.en-pc.jp/tech/base64.php

上記にアクセスして、「data:application/json;base64,」以降のデータをコピーしてください。

上記のように入力して、「変換」をクリックしてください。
そうすると以下のように出力されます。

{
	"name": "JBANFT #0",
	"description": "JBANFT NFT",
	"image": "https://arweave.net/pP9Rw4hx-Ki8m1R1A5EotbpZW2MAJlenmXbAtTa93Gc"
}
  • name
    • JBANFT #0というNFTの名前が出力されます。
  • description
    • JBANFT NFTというNFTの説明が出力されます。
  • image
    • NFTの画像が出力されます。

imageの以下のURLにアクセスしてみてください。

https://arweave.net/pP9Rw4hx-Ki8m1R1A5EotbpZW2MAJlenmXbAtTa93Gc

上記のように画像が表示されるはずです。

これで一通りの実行は完了です。

WalletConnectでテストネットにデプロイ

では次のWalletConnectを使用してテストネットにコントラクトをデプロイしてみましょう。

WalletConnectとは、PCやスマートフォンのウォレットアプリケーションに接続することができるサービスです。
WalletConnectを使用することで、スマホしか使用できないユーザーでも簡単にDappsと接続することができるため非常に便利です。

前提

デプロイしたコントラクトの削除

まずは、先ほどデプロイしたコントラクトを削除しましょう。

上記のようにゴミ箱アイコンをクリックすることで、デプロイしたコントラクトを削除できます。

テストネットトークンの取得

今回はSepoliaテストネットを使用するため、Sepoliaテストネットトークンの取得が必要になります。

https://app.optimism.io/faucet

Sepoliaテストネットトークンを保有していない方は以下のサイトから取得してください。

Connect Wallet」からウォレットを接続し、Githubアカウントを保有している方はGithubアカウントを連携してください。

上記の「Ethereum Sepolia」がSepoliaテストネットトークンなので、「Claim your test ETH」に取得したいアドレスを入力し、「Ethereum Sepolia」右にあるボタンをクリックしてください。
しばらくするとウォレットにSepoliaテストネットトークンが入ってきます。

もし、Githubアカウントを持っていない場合は以下のサイトから0.05 ETHを取得することができます。

https://cloud.google.com/application/web3/faucet/ethereum/sepolia

WalletConnectでの接続

では、WalletConnectを使用してウォレットと接続していきましょう。

上記のように「ENVIRONMENT」の部分をクリックして「WalletConnect」を選択してください。

そうすると上記のように「Wallet Connect」というタブが開くので、「Connect Wallet」というボタンをクリックしてください。

ここで2つのパターンがあります。

PC

PCの場合は青枠の方の「Metamask」と「Browser Wallet」のどちらかを選択してください。

そうすると上記のように接続したいウォレットを選択して、ページ下部までスクロールして「Next」をクリックしてください。

その後、「Connect」をクリックしてください。

remixのページに戻るので、上記の赤枠部分に接続したアドレスが表示されていれば成功です。

スマホ

スマホの場合は赤枠の「WalletConnect」をクリックしてください。
今回はMetamaskアプリを使用していきます。

スマホのカメラアプリで上記のように表示されたQRコードを読み込んでください。
Metamaskアプリに誘導されるので移動してください。

上記のように表示されるので、右下の「接続」をクリックしてください。

接続が完了すると、上記のように赤枠部分に接続したアドレスが表示されます。

もし接続がうまくいかない場合は、上記のようにページ上部にあるネットワークの中から「Sepolia Test Network」を選択してください。
それでもうまくいかない場合はカメラアプリやMetamaskアプリの再起動やremixページのリロードなどをしてみてください。

ウォレットの資産確認

今回はSepoliaテストネットを使用します。
そのため、先ほど接続したウォレットにSepliaテストネットトークンがない場合は、トークンを接続したウォレットに送付してください。

送付した後ページをリロードすると上記の赤枠に、ウォレット内のSepoliaテストネットトークンの保有量が表示されます。

コントラクトのデプロイ

では、前章で試した手順で今後はSepoliaテストネットにコントラクトをデプロイしてみましょう。

上記のように接続したウォレットアドレスをコピーして、「Deploy」ボタンの右に貼り付けてください。
貼り付けるたら「Deploy」というボタンをクリックしてください。

スマホのMetamaskアプリに上記のように表示されるので、右下の「確定」を押してください。

上記のように赤枠部分が表示されていればデプロイ成功です。
view on etherscan」をクリックすると、Sepoliaテストネットにコントラクトをデプロイした時のトランザクションを確認できます。

https://sepolia.etherscan.io/tx/0x1155875d424d9b7a79e321e9eb795f384a7aedb078be768e3577b23eda60d47e

NFTのMint

では、次にNFTをMintしていきましょう。

上記のように接続したウォレットアドレスを入力して「safeMint」というボタンを押してください。

スマホのMetamaskで上記のように表示されるので、「確定」を押します。

その後上記のようにページ下部にトランザクションの状態が表示され、「トランザクション〇〇が完了しました」と出力されれば成功です。

remixでも上記のようにコンソールに出力されていれば成功を確認できます。

コンソール内の「view on etherscan」をクリックすることで、Mintのトランザクションを確認できます。

https://sepolia.etherscan.io/tx/0xc1d1d9d85053f049dac30824392cd3a4c75ab929ec127f3d691f3282bd738aae

わかりづらいのですが、上記にコントラクトアドレスが記載されています。
右側のコピーアイコンをクリックして、コントラクトアドレスをコピーしてください。

https://testnets.opensea.io/ja

コピーできたら上記のリンクを開いてください。
これはOpenseaといって、NFTのマーケットプレイスです。
NFTの売買ができる場所と覚えてもらえれば問題ないです。
今回はTestnetにコントラクトをデプロイしているため、Testnet用のOpenseaサイトを開いています。

上記の赤枠部分に、先ほどコピーしたコントラクトアドレスを貼り付けください。
そうすると「コレクション」という部分に、先ほどデプロイしたコントラクトが「JBANFT」と表示されているのでクリックします。

上記のような画面が開き、「JBANFT #0」という名前のNFTが表示されているのでクリックします。

そうすると上記のように表示されます。
これが先ほどMintしたNFTです。

NFTのチェック

では最後にbalanceOfownerOftokenURIの関数を実行してデータをチェックしましょう。

上記のように、balanceOfにはウォレットのアドレス、ownerOftokenURIには0という値を入れて実行してください。

  • balanceOf
    • 1
  • ownerOf
    • ウォレットのアドレス。
  • tokenURI
    • data:application/json;base64,eyJuYW1lIjogIkpCQU5GVCAjMCIsICJkZXNjcmlwdGlvbiI6ICJKQkEgTkZUIiwgImltYWdlIjogImh0dHBzOi8vaXBmcy5pby9pcGZzL1FtWGJCU2VNV1pkM3dTeEFLTWhNU3M1bTVaekpKRFVIZFNpbW5VbUV4OEJ1RXA/ZmlsZW5hbWU9SkJBTi5wbmcifQ==

上記のように出力されていれば成功です!

tokenURIの中身の確認方法は、以下のtokenURIの章を確認してください。

https://zenn.dev/cryptogames/articles/3903c469ffff87#tokenuri-1

最後に

今回はRemixでWallet Connectを使用してNFTコントラクトをデプロイする手順を紹介してきました。
できる限り噛み砕いて非エンジニアでもデプロイできるように解説してきましたがいかがだったでしょうか?

以下でも情報発信しているので、興味ある記事があればぜひ読んでみてください!

https://twitter.com/cardene777

https://chaldene.net/

https://qiita.com/cardene

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4

CryptoGames

Discussion