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

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

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

【注意】 コード内に最低価格をハードコーディングしていますが、これを変更するメソッドが定義されている場合は最低価格は書き換えられてしまいます!

最低価格を保証するようなNFTプロジェクトがある場合、こういった悪意のあるコードが混じってないかチェックする必要があります。

    // こんなかんじのコード
    function setMintPrice(uint mintPrice) public onlyOwner {
        MINT_PRICE = mintPrice;
    }

コントラクトの作成

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);
    }
}

コンパイルする