skka3134

skka3134

email
telegram

ERC721 (NFT)

  1. ウィザードを使って契約を開発
    https://docs.openzeppelin.com/contracts/4.x/wizard
    Mintable : NFT をミント
    Auto increment Ids : id 自動増加
    Burnable : NFT を焼却
    Pausable : NFT の転送を一時停止
    Enumerable : 総発行量を確認
    URI storage : NFT の URI
    Ownable: 所有権管理、1 人の管理者
    Roles: 所有権管理、複数の管理者
    Transparent: 透明なプロキシ
    UUPS: プロキシ契約の衝突問題を解決
    image
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/draft-ERC721VotesUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";

/// @custom:security-contact [email protected]
contract Dragon is Initializable, ERC721Upgradeable, ERC721EnumerableUpgradeable, ERC721URIStorageUpgradeable, PausableUpgradeable, OwnableUpgradeable, ERC721BurnableUpgradeable, EIP712Upgradeable, ERC721VotesUpgradeable {
    using CountersUpgradeable for CountersUpgradeable.Counter;

    CountersUpgradeable.Counter private _tokenIdCounter;

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }

    function initialize() initializer public {
        __ERC721_init("Dragon", "Drag");
        __ERC721Enumerable_init();
        __ERC721URIStorage_init();
        __Pausable_init();
        __Ownable_init();
        __ERC721Burnable_init();
        __EIP712_init("Dragon", "1");
        __ERC721Votes_init();
    }

    function pause() public onlyOwner {
        _pause();
    }

    function unpause() public onlyOwner {
        _unpause();
    }

    function safeMint(address to, string memory uri) public onlyOwner {
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }

    function _beforeTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize)
        internal
        whenNotPaused
        override(ERC721Upgradeable, ERC721EnumerableUpgradeable)
    {
        super._beforeTokenTransfer(from, to, tokenId, batchSize);
    }

    // 以下の関数はSolidityによって必要なオーバーライドです。

    function _afterTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize)
        internal
        override(ERC721Upgradeable, ERC721VotesUpgradeable)
    {
        super._afterTokenTransfer(from, to, tokenId, batchSize);
    }

    function _burn(uint256 tokenId)
        internal
        override(ERC721Upgradeable, ERC721URIStorageUpgradeable)
    {
        super._burn(tokenId);
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override(ERC721Upgradeable, ERC721URIStorageUpgradeable)
        returns (string memory)
    {
        return super.tokenURI(tokenId);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721Upgradeable, ERC721EnumerableUpgradeable, ERC721URIStorageUpgradeable)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}
  1. remix https://remix.ethereum.org/
    image
  2. safeMint の onlyOwner を削除し、誰でもミントできるようにする
    function safeMint(address to, string memory uri) public onlyOwner {
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }

    function safeMint(address to, string memory uri) public  {
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }
  1. 最大発行量を定義する
    uint256 MAX = 1000;
    function safeMint(address to, string memory uri) public  {
        require(_tokenIdCounter.current() <= MAX, "exceed");
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }

  1. メタデータを IPFS にアップロード
    https://console.filebase.com/
    image
  2. メタデータの形式は JSON
{
    "description": "ドラゴン", 
    "external_url": "https://openseacreatures.io/3", 
    "image": "https://ipfs.filebase.io/ipfs/QmewcWVm6zmnCEwDzZSanrzdFNdzCF8X4Tfo5Qi87Qdhrf", 
    "name": "ドラゴン",
    "attributes": [
      {
        "trait_type": "ベース", 
        "value": "ヒトデ"
      }, 
      {
        "trait_type": "目", 
        "value": "大きい"
      }, 
      {
        "trait_type": "口", 
        "value": "驚いた"
      }, 
      {
        "trait_type": "レベル", 
        "value": 5
      }   
    ]
  }

image
7. コードを修正

    string  uri="ipfs://QmPHcbAwnaGkGm939xRzhwXuYVe12iqCKezDccJcmqf8p5";
    function safeMint(address to) public {
        require(_tokenIdCounter.current() <= MAX, "exceed");
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }

  1. Alchemy アカウントを作成し、Sepolia テストネットを選択
    https://dashboard.alchemy.com/
    Sepolia ファ aucet https://sepoliafaucet.com/):
    image
  2. MetaMask に Alchemy ノードを追加
    image
  3. コンパイルして最適化を有効にする
    image
  4. デプロイ
    image
  5. テスト OpenSea で確認する https://testnets.opensea.io/
    image
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。