💪

ノンプログラマーでもできる!! フルオンチェーン NFTの作り方(初心者向け)

2023/01/15に公開約17,700字

フルオンチェーンNFTのスマートコントラクトを簡単に作成する方法を紹介します。

初めてブロックチェーンのプログラムを触るという方向けに、できるだけわかりやすく書きたいと思いますので、ここがよくわからん、などあればフィードバックいただけると嬉しいです。

0.はじめに

Ethereumに大きなデータを書き込むとガス代が大変なことになるので、ある程度綺麗な画像をフルオンチェーンにしようとすると、jpegやpngでなく、SVGという形式を使います。
そして、ブラウザで表示するときには、更にSVGをBase64という形式に変換しないといけません。
(SVG, Base64の詳細は各自でお調べください)

今回はSVGの作成、Base64の変換は別で実施し、作成するコントラクトでは変換したデータを書き込むようにします。

1.画像データの準備

SVG画像は、イラストレータで作成した画像の出力形式をSVGに指定して出力したり、巷の画像変換サービスを利用したりします。

  • googleで検索したら https://convertio.co/ja/ などが出てきました。このようなサービスを使ってSVG形式の画像ファイルを作成します。
  • こういったサービスで作成したSVGは余分なコードが多く含まれているため、これを削減するテクニックがあるそうです(ここでは割愛します)

SVGファイルができたら、今度はこのファイルをbase64形式に変換します。
これも巷に無料の変換サービスがあるので、使ってください。

2.作成するスマートコントラクトの概要

今回作成するスマートコントラクトは、3つのファイルで構成されています。

一つは、 ERC721SVG.sol というもので、これがフルオンチェーンNFTの中核をなします。トークンIDごとの画像データを保管します。

二つ目は、 SampleSVG.sol というERC721SVGを継承したものです。継承という専門用語を使いましたが、これは継承元に書かれているプログラムを簡単に使えるようにする仕組みです。
これを読んでいる皆さんが修正するのは、このファイルのみです。

三つ目は、Base64.solで、ERC721SVGから使用します。コントラクトからトークンIDの画像をリクエストされた際、ブラウザで解釈できるようにBase64形式に変換します。

3.実践

いよいよ実践です。
今回は、Ethereumのテスト用ネットワークである、Goerliチェーンにデプロイ(アップロード)します。
Goerliの設定は https://qiita.com/ItodaiCrypto/items/563214a28239c6f9cf0e を参考にどうぞ。
Goerliチェーンにデプロイするときには、Goerli専用のETHが必要となります。 ETHは https://goerlifaucet.com/ で無料取得することができますが、Alchemyというサービスにユーザ登録が必要だったりで、ちょっとめんどいです。難しい場合はお送りするのでTwitterDMでご連絡ください。

3-1.REMIXプロジェクトの作成

デプロイには、REMIXというオンラインの統合開発環境を使用します。
https://remix.ethereum.org/ へアクセスしてください。Chromeからの使用が安定しているようです。

アクセスしたら、WORKSPACE横の”+”ボタン

テンプレートに "Blank"を指定してOK

3-2.プログラムコードのコピペ

新規ファイル作成のボタンをクリックして、"ERC721SVG.sol"の空ファイルを作成します。
同様に、"SampleSVG.sol", "Base64.sol"も作成してください。

"ERC721SVG.sol"に以下のコードをコピーして貼り付けてください。

ERC721SVG.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.14;

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

abstract contract ERC721SVG is ERC721URIStorage, Ownable {
    bytes32 public constant CONTRACT_ADMIN = keccak256("CONTRACT_ADMIN");
    uint256 public currentTokenId;

    function setTokenURI(
        uint256 tokenId,
        string memory _encodedData,
        string memory _name,
        string memory _description
    ) public virtual onlyOwner {
        string memory _tokenURI;

        _tokenURI = string(
            abi.encodePacked(
                "data:application/json;base64,",
                Base64.encode(
                    bytes(
                        abi.encodePacked(
                            '{"name": "',
                            _name,
                            '", "description": "',
                            _description,
                            '", "image": "data:image/svg+xml;base64,',
                            _encodedData,
                            '"}'
                        )
                    )
                )
            )
        );

        _setTokenURI(tokenId, _tokenURI);
    }

    function createToken(
        address _to,
        string memory _encodedData,
        string memory _name,
        string memory _description
    ) public virtual onlyOwner returns (uint256 _tokenId) {
        _tokenId = ++currentTokenId;
        _safeMint(_to, _tokenId);
        setTokenURI(_tokenId, _encodedData, _name, _description);
    }

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

ペーストすると本当にコピーして良いかの確認ダイアログが表示されます。
変なコードは仕込んでいませんが(笑)、自己責任でご確認ください。

同様に、"Base64.sol","SampleSVG.sol" にも以下のコードをコピーして貼り付けてください。

Base64.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// @title Base64
// @author Brecht Devos <brecht@loopring.org>
// @notice Provides a function for encoding some bytes in base64
library Base64 {
    string internal constant TABLE =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    function encode(bytes memory data) internal pure returns (string memory) {
        if (data.length == 0) return "";

        // load the table into memory
        string memory table = TABLE;

        // multiply by 4/3 rounded up
        uint256 encodedLen = 4 * ((data.length + 2) / 3);

        // add some extra buffer at the end required for the writing
        string memory result = new string(encodedLen + 32);

        assembly {
            // set the actual output length
            mstore(result, encodedLen)

            // prepare the lookup table
            let tablePtr := add(table, 1)

            // input ptr
            let dataPtr := data
            let endPtr := add(dataPtr, mload(data))

            // result ptr, jump over length
            let resultPtr := add(result, 32)

            // run over the input, 3 bytes at a time
            for {

            } lt(dataPtr, endPtr) {

            } {
                dataPtr := add(dataPtr, 3)

                // read 3 bytes
                let input := mload(dataPtr)

                // write 4 characters
                mstore(
                    resultPtr,
                    shl(248, mload(add(tablePtr, and(shr(18, input), 0x3F))))
                )
                resultPtr := add(resultPtr, 1)
                mstore(
                    resultPtr,
                    shl(248, mload(add(tablePtr, and(shr(12, input), 0x3F))))
                )
                resultPtr := add(resultPtr, 1)
                mstore(
                    resultPtr,
                    shl(248, mload(add(tablePtr, and(shr(6, input), 0x3F))))
                )
                resultPtr := add(resultPtr, 1)
                mstore(
                    resultPtr,
                    shl(248, mload(add(tablePtr, and(input, 0x3F))))
                )
                resultPtr := add(resultPtr, 1)
            }

            // padding with '='
            switch mod(mload(data), 3)
            case 1 {
                mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
            }
            case 2 {
                mstore(sub(resultPtr, 1), shl(248, 0x3d))
            }
        }

        return result;
    }
}
SampleSVG.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "./ERC721SVG.sol";

contract SampleSVG is ERC721SVG {
    constructor() ERC721("SampleSVG", "SSVG") {
    }
}

3-3.プログラムコードの修正

修正する箇所は、SampleSVG.solの2箇所のみです。

  • 6行目: contract SampleSVG is ERC721SVG {
    SampleSVGをご自分の発行するコントラクト名に変更してください。
    ※contact名とファイル名は原則一致させるため、ファイル名も6行目に合わせて修正してください。(修正しなくても続行可能)
  • 7行目: constructor() ERC721("SampleSVG", "SSVG") {
    SampleSVGとSSVGも同様にご自分の発行するものに書き換えてください。SSVGは任意の短縮名です。

3-4.コンパイル

通常、 SampleSVG.solを修正すると、プログラムは自動でコンパイルされます。
コンパイル結果は、左メニューのコンパイルマークをクリックして確認できます。 SampleSVG.solを選択した状態でクリックしてください。

3-5.デプロイ

Goerliチェーンにデプロイします。
左メニューからデプロイマークをクリック後、ENVIRONMENTに InjectProvider - MetaMaskを指定してください。

このとき、MetaMaskのネットワークに「Goerliテストネットワーク」が選択されていることを確認してください。

問題なければ、以下のようにENVIRONMENTの下に「Goerli(5) network」、Accountにご自分のMetamaskアドレス、Contractに「SampleSVG」が表示されているはずです。

これを確認後、Deployボタンをクリックすると、Metamaskの確認画面が立ち上がり、確認ボタンでデプロイのトランザクションが走ります。

トランザクションが通ると、左画面下側のDeployed Contractにコントラクトアドレスが表示されます。

右側のコピーマークをクリックして、コントラクトアドレスを控えておいてください。(後ほどOpenseaで確認します)

3-6.SVGデータの登録

「1.画像データの準備」で準備したデータを使用します。
ここにサンプルデータを貼り付けていますので、とりあえずお試しされる場合はこちらをご利用ください。

base64変換後のSVG
PHN2ZyB3aWR0aD0iMzIwIiBoZWlnaHQ9IjMyMCIgdmlld0JveD0iMCAwIDMyMCAzMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc2hhcGUtcmVuZGVyaW5nPSJjcmlzcEVkZ2VzIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZTFkN2Q1IiAvPjxyZWN0IHdpZHRoPSIxNDAiIGhlaWdodD0iMTAiIHg9IjkwIiB5PSIyMTAiIGZpbGw9IiMzNDMyMzUiIC8+PHJlY3Qgd2lkdGg9IjE0MCIgaGVpZ2h0PSIxMCIgeD0iOTAiIHk9IjIyMCIgZmlsbD0iIzM0MzIzNSIgLz48cmVjdCB3aWR0aD0iMTQwIiBoZWlnaHQ9IjEwIiB4PSI5MCIgeT0iMjMwIiBmaWxsPSIjMzQzMjM1IiAvPjxyZWN0IHdpZHRoPSIxNDAiIGhlaWdodD0iMTAiIHg9IjkwIiB5PSIyNDAiIGZpbGw9IiMzNDMyMzUiIC8+PHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjEwIiB4PSI5MCIgeT0iMjUwIiBmaWxsPSIjMzQzMjM1IiAvPjxyZWN0IHdpZHRoPSIxMTAiIGhlaWdodD0iMTAiIHg9IjEyMCIgeT0iMjUwIiBmaWxsPSIjMzQzMjM1IiAvPjxyZWN0IHdpZHRoPSIyMCIgaGVpZ2h0PSIxMCIgeD0iOTAiIHk9IjI2MCIgZmlsbD0iIzM0MzIzNSIgLz48cmVjdCB3aWR0aD0iMTEwIiBoZWlnaHQ9IjEwIiB4PSIxMjAiIHk9IjI2MCIgZmlsbD0iIzM0MzIzNSIgLz48cmVjdCB3aWR0aD0iMjAiIGhlaWdodD0iMTAiIHg9IjkwIiB5PSIyNzAiIGZpbGw9IiMzNDMyMzUiIC8+PHJlY3Qgd2lkdGg9IjExMCIgaGVpZ2h0PSIxMCIgeD0iMTIwIiB5PSIyNzAiIGZpbGw9IiMzNDMyMzUiIC8+PHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjEwIiB4PSI5MCIgeT0iMjgwIiBmaWxsPSIjMzQzMjM1IiAvPjxyZWN0IHdpZHRoPSIxMTAiIGhlaWdodD0iMTAiIHg9IjEyMCIgeT0iMjgwIiBmaWxsPSIjMzQzMjM1IiAvPjxyZWN0IHdpZHRoPSIyMCIgaGVpZ2h0PSIxMCIgeD0iOTAiIHk9IjI5MCIgZmlsbD0iIzM0MzIzNSIgLz48cmVjdCB3aWR0aD0iMTEwIiBoZWlnaHQ9IjEwIiB4PSIxMjAiIHk9IjI5MCIgZmlsbD0iIzM0MzIzNSIgLz48cmVjdCB3aWR0aD0iMjAiIGhlaWdodD0iMTAiIHg9IjkwIiB5PSIzMDAiIGZpbGw9IiMzNDMyMzUiIC8+PHJlY3Qgd2lkdGg9IjExMCIgaGVpZ2h0PSIxMCIgeD0iMTIwIiB5PSIzMDAiIGZpbGw9IiMzNDMyMzUiIC8+PHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjEwIiB4PSI5MCIgeT0iMzEwIiBmaWxsPSIjMzQzMjM1IiAvPjxyZWN0IHdpZHRoPSIxMTAiIGhlaWdodD0iMTAiIHg9IjEyMCIgeT0iMzEwIiBmaWxsPSIjMzQzMjM1IiAvPjxyZWN0IHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCIgeD0iMTIwIiB5PSIyMTAiIGZpbGw9IiNmZmMxMTAiIC8+PHJlY3Qgd2lkdGg9IjEwIiBoZWlnaHQ9IjEwIiB4PSIxOTAiIHk9IjIxMCIgZmlsbD0iI2ZmYzExMCIgLz48cmVjdCB3aWR0aD0iMTAiIGhlaWdodD0iMTAiIHg9IjEyMCIgeT0iMjIwIiBmaWxsPSIjZmZjMTEwIiAvPjxyZWN0IHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCIgeD0iMTkwIiB5PSIyMjAiIGZpbGw9IiNmZmMxMTAiIC8+PHJlY3Qgd2lkdGg9IjEwIiBoZWlnaHQ9IjEwIiB4PSIxMzAiIHk9IjIzMCIgZmlsbD0iI2ZmYzExMCIgLz48cmVjdCB3aWR0aD0iMTAiIGhlaWdodD0iMTAiIHg9IjE4MCIgeT0iMjMwIiBmaWxsPSIjZmZjMTEwIiAvPjxyZWN0IHdpZHRoPSI0MCIgaGVpZ2h0PSIxMCIgeD0iMTQwIiB5PSIyNDAiIGZpbGw9IiNmZmMxMTAiIC8+PHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjEwIiB4PSIxNTAiIHk9IjI1MCIgZmlsbD0iI2ZmYzExMCIgLz48cmVjdCB3aWR0aD0iNDAiIGhlaWdodD0iMTAiIHg9IjE0MCIgeT0iMjYwIiBmaWxsPSIjZmZjMTEwIiAvPjxyZWN0IHdpZHRoPSIyMCIgaGVpZ2h0PSIxMCIgeD0iMTQwIiB5PSIyNzAiIGZpbGw9IiNmZmMxMTAiIC8+PHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjEwIiB4PSIxNjAiIHk9IjI4MCIgZmlsbD0iI2ZmYzExMCIgLz48cmVjdCB3aWR0aD0iNDAiIGhlaWdodD0iMTAiIHg9IjE0MCIgeT0iMjkwIiBmaWxsPSIjZmZjMTEwIiAvPjxyZWN0IHdpZHRoPSIyMCIgaGVpZ2h0PSIxMCIgeD0iMTUwIiB5PSIzMDAiIGZpbGw9IiNmZmMxMTAiIC8+PHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjEwIiB4PSIxNTAiIHk9IjEwIiBmaWxsPSIjZmZjMTEwIiAvPjxyZWN0IHdpZHRoPSIyMCIgaGVpZ2h0PSIxMCIgeD0iMTUwIiB5PSIyMCIgZmlsbD0iI2ZmYzExMCIgLz48cmVjdCB3aWR0aD0iODAiIGhlaWdodD0iMTAiIHg9IjEyMCIgeT0iMzAiIGZpbGw9IiNmZmMxMTAiIC8+PHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjEwIiB4PSIxMTAiIHk9IjQwIiBmaWxsPSIjZmZjMTEwIiAvPjxyZWN0IHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCIgeD0iMTMwIiB5PSI0MCIgZmlsbD0iI2ZmZmZmZiIgLz48cmVjdCB3aWR0aD0iNzAiIGhlaWdodD0iMTAiIHg9IjE0MCIgeT0iNDAiIGZpbGw9IiNmZmMxMTAiIC8+PHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjEwIiB4PSIxMDAiIHk9IjUwIiBmaWxsPSIjZmZjMTEwIiAvPjxyZWN0IHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCIgeD0iMTIwIiB5PSI1MCIgZmlsbD0iI2ZmZmZmZiIgLz48cmVjdCB3aWR0aD0iOTAiIGhlaWdodD0iMTAiIHg9IjEzMCIgeT0iNTAiIGZpbGw9IiNmZmMxMTAiIC8+PHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjEwIiB4PSI5MCIgeT0iNjAiIGZpbGw9IiNmZmMxMTAiIC8+PHJlY3Qgd2lkdGg9IjEwIiBoZWlnaHQ9IjEwIiB4PSIxMTAiIHk9IjYwIiBmaWxsPSIjZmZmZmZmIiAvPjxyZWN0IHdpZHRoPSIxMTAiIGhlaWdodD0iMTAiIHg9IjEyMCIgeT0iNjAiIGZpbGw9IiNmZmMxMTAiIC8+PHJlY3Qgd2lkdGg9IjE0MCIgaGVpZ2h0PSIxMCIgeD0iOTAiIHk9IjcwIiBmaWxsPSIjZmZjMTEwIiAvPjxyZWN0IHdpZHRoPSIxNDAiIGhlaWdodD0iMTAiIHg9IjkwIiB5PSI4MCIgZmlsbD0iI2ZmYzExMCIgLz48cmVjdCB3aWR0aD0iMTYwIiBoZWlnaHQ9IjEwIiB4PSI4MCIgeT0iOTAiIGZpbGw9IiNmZmMxMTAiIC8+PHJlY3Qgd2lkdGg9IjE2MCIgaGVpZ2h0PSIxMCIgeD0iODAiIHk9IjEwMCIgZmlsbD0iI2ZmYzExMCIgLz48cmVjdCB3aWR0aD0iMTYwIiBoZWlnaHQ9IjEwIiB4PSI4MCIgeT0iMTEwIiBmaWxsPSIjZmZjMTEwIiAvPjxyZWN0IHdpZHRoPSIxNjAiIGhlaWdodD0iMTAiIHg9IjgwIiB5PSIxMjAiIGZpbGw9IiNmZmMxMTAiIC8+PHJlY3Qgd2lkdGg9IjE2MCIgaGVpZ2h0PSIxMCIgeD0iODAiIHk9IjEzMCIgZmlsbD0iI2ZmYzExMCIgLz48cmVjdCB3aWR0aD0iMTYwIiBoZWlnaHQ9IjEwIiB4PSI4MCIgeT0iMTQwIiBmaWxsPSIjZDA4YjExIiAvPjxyZWN0IHdpZHRoPSIxNjAiIGhlaWdodD0iMTAiIHg9IjgwIiB5PSIxNTAiIGZpbGw9IiNkMDhiMTEiIC8+PHJlY3Qgd2lkdGg9IjIwMCIgaGVpZ2h0PSIxMCIgeD0iNjAiIHk9IjE2MCIgZmlsbD0iI2ZmYzExMCIgLz48cmVjdCB3aWR0aD0iMTAiIGhlaWdodD0iMTAiIHg9IjYwIiB5PSIxNzAiIGZpbGw9IiNmZmMxMTAiIC8+PHJlY3Qgd2lkdGg9IjEwIiBoZWlnaHQ9IjEwIiB4PSI3MCIgeT0iMTcwIiBmaWxsPSIjZmZmZmZmIiAvPjxyZWN0IHdpZHRoPSIxODAiIGhlaWdodD0iMTAiIHg9IjgwIiB5PSIxNzAiIGZpbGw9IiNmZmMxMTAiIC8+PHJlY3Qgd2lkdGg9IjEyMCIgaGVpZ2h0PSIxMCIgeD0iNDAiIHk9IjE4MCIgZmlsbD0iI2ZmYzExMCIgLz48cmVjdCB3aWR0aD0iMzAiIGhlaWdodD0iMTAiIHg9IjE2MCIgeT0iMTgwIiBmaWxsPSIjZTg3MDViIiAvPjxyZWN0IHdpZHRoPSI5MCIgaGVpZ2h0PSIxMCIgeD0iMTkwIiB5PSIxODAiIGZpbGw9IiNmZmMxMTAiIC8+PHJlY3Qgd2lkdGg9IjI0MCIgaGVpZ2h0PSIxMCIgeD0iNDAiIHk9IjE5MCIgZmlsbD0iI2ZmYzExMCIgLz48cmVjdCB3aWR0aD0iMjIwIiBoZWlnaHQ9IjEwIiB4PSI1MCIgeT0iMjAwIiBmaWxsPSIjZmZjMTEwIiAvPjxyZWN0IHdpZHRoPSI2MCIgaGVpZ2h0PSIxMCIgeD0iMTAwIiB5PSIxMTAiIGZpbGw9IiMyYjgzZjYiIC8+PHJlY3Qgd2lkdGg9IjYwIiBoZWlnaHQ9IjEwIiB4PSIxNzAiIHk9IjExMCIgZmlsbD0iIzJiODNmNiIgLz48cmVjdCB3aWR0aD0iMTAiIGhlaWdodD0iMTAiIHg9IjEwMCIgeT0iMTIwIiBmaWxsPSIjMmI4M2Y2IiAvPjxyZWN0IHdpZHRoPSIyMCIgaGVpZ2h0PSIxMCIgeD0iMTEwIiB5PSIxMjAiIGZpbGw9IiNmZmZmZmYiIC8+PHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjEwIiB4PSIxMzAiIHk9IjEyMCIgZmlsbD0iIzAwMDAwMCIgLz48cmVjdCB3aWR0aD0iMTAiIGhlaWdodD0iMTAiIHg9IjE1MCIgeT0iMTIwIiBmaWxsPSIjMmI4M2Y2IiAvPjxyZWN0IHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCIgeD0iMTcwIiB5PSIxMjAiIGZpbGw9IiMyYjgzZjYiIC8+PHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjEwIiB4PSIxODAiIHk9IjEyMCIgZmlsbD0iI2ZmZmZmZiIgLz48cmVjdCB3aWR0aD0iMjAiIGhlaWdodD0iMTAiIHg9IjIwMCIgeT0iMTIwIiBmaWxsPSIjMDAwMDAwIiAvPjxyZWN0IHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCIgeD0iMjIwIiB5PSIxMjAiIGZpbGw9IiMyYjgzZjYiIC8+PHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjEwIiB4PSI3MCIgeT0iMTMwIiBmaWxsPSIjMmI4M2Y2IiAvPjxyZWN0IHdpZHRoPSIyMCIgaGVpZ2h0PSIxMCIgeD0iMTEwIiB5PSIxMzAiIGZpbGw9IiNmZmZmZmYiIC8+PHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjEwIiB4PSIxMzAiIHk9IjEzMCIgZmlsbD0iIzAwMDAwMCIgLz48cmVjdCB3aWR0aD0iMzAiIGhlaWdodD0iMTAiIHg9IjE1MCIgeT0iMTMwIiBmaWxsPSIjMmI4M2Y2IiAvPjxyZWN0IHdpZHRoPSIyMCIgaGVpZ2h0PSIxMCIgeD0iMTgwIiB5PSIxMzAiIGZpbGw9IiNmZmZmZmYiIC8+PHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjEwIiB4PSIyMDAiIHk9IjEzMCIgZmlsbD0iIzAwMDAwMCIgLz48cmVjdCB3aWR0aD0iMTAiIGhlaWdodD0iMTAiIHg9IjIyMCIgeT0iMTMwIiBmaWxsPSIjMmI4M2Y2IiAvPjxyZWN0IHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCIgeD0iNzAiIHk9IjE0MCIgZmlsbD0iIzJiODNmNiIgLz48cmVjdCB3aWR0aD0iMTAiIGhlaWdodD0iMTAiIHg9IjEwMCIgeT0iMTQwIiBmaWxsPSIjMmI4M2Y2IiAvPjxyZWN0IHdpZHRoPSIyMCIgaGVpZ2h0PSIxMCIgeD0iMTEwIiB5PSIxNDAiIGZpbGw9IiNmZmZmZmYiIC8+PHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjEwIiB4PSIxMzAiIHk9IjE0MCIgZmlsbD0iIzAwMDAwMCIgLz48cmVjdCB3aWR0aD0iMTAiIGhlaWdodD0iMTAiIHg9IjE1MCIgeT0iMTQwIiBmaWxsPSIjMmI4M2Y2IiAvPjxyZWN0IHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCIgeD0iMTcwIiB5PSIxNDAiIGZpbGw9IiMyYjgzZjYiIC8+PHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjEwIiB4PSIxODAiIHk9IjE0MCIgZmlsbD0iI2ZmZmZmZiIgLz48cmVjdCB3aWR0aD0iMjAiIGhlaWdodD0iMTAiIHg9IjIwMCIgeT0iMTQwIiBmaWxsPSIjMDAwMDAwIiAvPjxyZWN0IHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCIgeD0iMjIwIiB5PSIxNDAiIGZpbGw9IiMyYjgzZjYiIC8+PHJlY3Qgd2lkdGg9IjEwIiBoZWlnaHQ9IjEwIiB4PSI3MCIgeT0iMTUwIiBmaWxsPSIjMmI4M2Y2IiAvPjxyZWN0IHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCIgeD0iMTAwIiB5PSIxNTAiIGZpbGw9IiMyYjgzZjYiIC8+PHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjEwIiB4PSIxMTAiIHk9IjE1MCIgZmlsbD0iI2ZmZmZmZiIgLz48cmVjdCB3aWR0aD0iMjAiIGhlaWdodD0iMTAiIHg9IjEzMCIgeT0iMTUwIiBmaWxsPSIjMDAwMDAwIiAvPjxyZWN0IHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCIgeD0iMTUwIiB5PSIxNTAiIGZpbGw9IiMyYjgzZjYiIC8+PHJlY3Qgd2lkdGg9IjEwIiBoZWlnaHQ9IjEwIiB4PSIxNzAiIHk9IjE1MCIgZmlsbD0iIzJiODNmNiIgLz48cmVjdCB3aWR0aD0iMjAiIGhlaWdodD0iMTAiIHg9IjE4MCIgeT0iMTUwIiBmaWxsPSIjZmZmZmZmIiAvPjxyZWN0IHdpZHRoPSIyMCIgaGVpZ2h0PSIxMCIgeD0iMjAwIiB5PSIxNTAiIGZpbGw9IiMwMDAwMDAiIC8+PHJlY3Qgd2lkdGg9IjEwIiBoZWlnaHQ9IjEwIiB4PSIyMjAiIHk9IjE1MCIgZmlsbD0iIzJiODNmNiIgLz48cmVjdCB3aWR0aD0iNjAiIGhlaWdodD0iMTAiIHg9IjEwMCIgeT0iMTYwIiBmaWxsPSIjMmI4M2Y2IiAvPjxyZWN0IHdpZHRoPSI2MCIgaGVpZ2h0PSIxMCIgeD0iMTcwIiB5PSIxNjAiIGZpbGw9IiMyYjgzZjYiIC8+PC9zdmc+

Deployed ContractのSampleSVGを展開すると、以下のように関数が一覧されます。

この中のcreateTokenがSVG画像のトークンを作成する関数です。右側の展開マークをクリックしてください。

以下のパラメタを設定し、「transact」をクリック、MetaMaskで確認するとトランザクションが実行されます。

  • _to: このSVGトークンをミントするアドレス
  • _encodedData: base64変換後のSVG
  • _name: このトークンの名前
  • _description: このトークンの説明
    トランザクションが通ると右下に以下のようなメッセージが表示されます。

同じコレクションに複数のSVGを登録したい場合は、このcreateTokenで別画像を登録します。

4.Openseaで確認

以上でSVGのトークンが発行されたため、Openseaで閲覧できる状態になりました。
テストネット版Opensea (https://testnets.opensea.io/ja) にアクセスし、「3-5.デプロイ」で控えたコントラクトアドレスを検索してください。
無事、登録したSVG画像が表示されれば成功です!!

Openseaへの反映まで時間がかかる場合があります。検索できない場合は時間が経ってから確認してみてください。

5.まとめ

以上、フルオンチェーンNFTを作成するコントラクトのデプロイ手順でした。
今回はGoerliテストネットへのデプロイしていますが、この手順に慣れたらEthereumのメインネットへデプロイすることも、そう難しくないと思います。どうぞ、お試しください。

Discussion

ログインするとコメントできます