🔥

最低価格を絶対に保証するNFTの作り方 (Remix編)

2022/01/13に公開

概要

  • Remixを用いてNFTをmintできるコントラクトを作成・デプロイする
  • コントラクト作成→rinkebyテストネットにデプロイまで行う。
  • ブロックチェーン、Solidityの解説は省略

前提

  • Solidity v0.8.0系
  • Metamask利用
  • Remix
    • オンラインIDE。環境構築不要で簡単にコントラクトをコンパイル、作成、デプロイ、テスト、デバッグまでできるサービス
      https://remix.ethereum.org/

最低価格を絶対に保証する とは?

※仮にmint価格を0.1ETHとする
NFTをmint時(作成)に0.1ETHをプールし、burn時(焼却)にプールからユーザーの手元に0.1ETHを返す仕組みをコントラクトで定義する

コントラクトに定義した処理はデプロイ後二度と変更することができないので、
最低価格を 絶対に 保証できる

実装

コントラクトの作成

Remixを開き、 /contracts フォルダに Burnable.sol ファイルを作成する

下記のように実装します。重要な部分はコメントに記述しています。

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.4.2/contracts/token/ERC721/ERC721.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.4.2/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.4.2/contracts/utils/Counters.sol";

contract Burnable is ERC721URIStorage {

    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    // mint価格をここで定義
    // ここが最低価格になる。 0.01ETHではなく、1ETHでも可。
    uint MINT_PRICE = 0.01 ether;

    constructor () ERC721 ("Burnable", "BURN") {}

    // mint処理
    function mintBurnable(string memory tokenURI) public payable returns (uint256) { 
        // mint時に合わせて 0.01ether を送ってきているか確認
        require(msg.value == MINT_PRICE);

        _tokenIds.increment();
        uint256 newItemId = _tokenIds.current();

        // 実際のmint処理
        _mint(msg.sender, newItemId);
        _setTokenURI(newItemId, tokenURI);

        return newItemId;
    }

    // 換金burn処理
    function burn(uint256 _tokenId) public { 
        // そのNFT所有者かどうか確認
        require(ownerOf(_tokenId) == msg.sender);

        // そのNFTを無に転送する (burn)
        _transfer(msg.sender, 0x000000000000000000000000000000000000dEaD, _tokenId);

        // mint時に払った0.01etherを返す処理
        address payable receiver = payable(msg.sender);
        receiver.transfer(MINT_PRICE);
    }
}

コンパイルする

左側○印を選択し、下部の○印を押下しコンパイルする
下側にエラーがでなければ次のステップへ

デプロイする

Rinkebyテストネットにデプロイする
デプロイするためにはガス代を支払う必要があり、テストネット用のEthを多少持っておく必要があります。
https://nnnnn15z.hatenablog.jp/entry/feucet-rinkeby-eth

Rinkebyテストネットにデプロイするためには、下記画面にて以下の手順を踏んでください

  • RemixとMetamaskをconnect
  • ENVIRONMENTはInjected Web3を設定
    • Metamask側でRinkebyネットワークに切り替える
  • CONTRACTは先程コンパイルした Burnable - contracts/Burnable.sol を選択
  • Deployボタンを押す

デプロイに成功すると、 Deployed Contracts にデプロイしたコントラクトのアドレスとメソッド郡が表示されます。
試しに、rinkeby.etherscan.io でコントラクトを覗いてみましょう。

https://rinkeby.etherscan.io/address/コントラクトID
コントラクトIDは下記の画像箇所のコピーボタンからコピーできます

参考例は以下。(今回の記事を元に作ったサンプル)
https://rinkeby.etherscan.io/address/0x6aFBb902D64eEC7f15dad681012edE61dc0ffb13

0xa2e6b0fa... (私の開発用アドレス)からコントラクトが作られているということがログに出ていることがわかります。

動作確認

動きのおさらい

肝心のmintとburnをやっていきます。その前にコントラクトの全体的な動きをおさらいしておきます

  • コントラクトの動き
    • NFT mint時に0.01ETHをあわせて送る
    • mintした側の残高は0.01ETH+ガス代減っていて、コントラクト側には0.01ETHがプールされる
    • burn時にコントラクト側のプールから0.01ETH減り、burnした側に0.01ETHが送金される

mint

今回は呼び出し用のスクリプトやdApps等は作らず、Remixから該当メソッドを呼び出します。

  • VALUEに10、単位はFinneyを選択
    • 10Finney = 0.01ETH
  • mintBurnableのTokenURIに適当なmetadata.jsonのURLを指定する
  • mintBurnableボタンを押下する

成功したら、 rinkeby.etherscan.io に該当コントラクトのトランザクションと残高を覗きに行ってみましょう。

残高が0.01ETHになっていることがわかります。

mintしたNFTは testnet.opensea.io でも確認できるので見に行きます。

https://testnets.opensea.io/assets/コントラクトID/トークンID

参考例は以下。
https://testnets.opensea.io/assets/0x6aFBb902D64eEC7f15dad681012edE61dc0ffb13/1

burn

換金したい場合、用意した burn メソッドを呼ぶことでNFTのburnとmint時に支払ったETHが戻ってきます。
mint時と同じようにこちらもRemixから該当メソッドを呼び出します。

先程の mintBurnable の1つ上にある burn ボタンの横に換金したいトークンIDを入力し、ボタンを押します。

成功したら、同じく rinkeby.etherscan.io で覗きにいきましょう

0.01ETH分の残高がなくなっていることがわかります。これで動作確認ができました。

まとめ

  • Remixを使いコントラクトの作成、テストネットへのデプロイを行った
  • rinkeby.etherscan.io にてデプロイしたコントラクトの動きを確認した
  • testnet.opensea.io にてmintしたNFTを確認した

最後に

今回はrinkebyテストネットへのデプロイ方法を紹介しましたが、Metamaskの接続先ネットワークをMainnetに変更するだけでEthereumメインネットへのデプロイができます。

ただ、Ethereumメインネットの場合最低価格 0.01ETH ではガス代のほうが高くて全然回収できないじゃん!となってしまうのでmint価格を 1ETH 等にあげるか、 Polygonチェーン 等のガス代が安いネットワークへのデプロイにしたほうが良さそうです。

最低価格を保証するNFTは、単価が安いNFTではメリットは薄いと個人的には思っていますが、フェラーリが半永久的に利用可能なNFT会員権 のような単価が高いものであれば、購入のハードルが下がる意味でも向いてるかもしれないですね

参考リンク集

https://ethereumnavi.com/2021/12/04/burnables-nft/
この仕組みを採用しているNFTアート「Burnables」の解説記事。
Burnablesについての情報や、最低価格が保証されているということのメリット等について、丁寧に解説されています。必読!

https://docs.openzeppelin.com/contracts/4.x/erc721
ドキュメントって、大事だよね・・・。必読!

etc

Solidityについてワイワイ学ぶコミュニティ「solidity-jp」を作りました!
いまから学んでみたい/学習中だけどの日本語の情報が少ない/古くて時間がかかっているという方、一緒に学びましょう〜!!

https://solidity-jp.dev/

また、TwitterにてSolidityについて技術的な部分を発信しています。良ければフォローお願いします!

https://twitter.com/k0uhashi

Discussion