How to Create ERC-721 NFTs on Ethereum with OpenZeppelin: A Step-by-Step Tutorial

·

Welcome to a comprehensive guide on creating non-fungible tokens (NFTs) using the ERC-721 standard on Ethereum. This tutorial will walk you through the entire process—from understanding the basics to deploying your own NFT collection on the Sepolia testnet and viewing it on OpenSea.


Table of Contents

  1. Understanding Tokens
  2. What is the ERC-721 Standard?
  3. Building a Basic ERC-721 Contract
  4. Adding Metadata to Your NFTs
  5. Advanced Features: URI Storage, Burnable, Pausable, Enumerable
  6. Deploying and Testing Your Contract
  7. FAQs
  8. Further Exploration
  9. Conclusion

Understanding Tokens

Tokens represent digital or physical assets on the blockchain. They fall into two categories:

  1. Fungible Tokens: Interchangeable (e.g., cryptocurrencies like ETH or stablecoins like USDT).
  2. Non-Fungible Tokens (NFTs): Unique (e.g., digital art, collectibles, or real-world assets like real estate).

👉 Learn more about fungible vs. non-fungible tokens


What is the ERC-721 Standard?

The ERC-721 standard enables the creation of NFTs on Ethereum by defining a set of rules for token interactions, including:

Key methods:

function balanceOf(address _owner) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;

Events:

event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);

OpenZeppelin’s ERC721 contract handles these implementations.


Building a Basic ERC-721 Contract

Step 1: Use OpenZeppelin’s Solidity Wizard

  1. Select ERC721 and enable:

    • Mintable
    • Auto Increment Ids
    • Ownable
  2. Customize the contract:

    contract FootballPlayers is ERC721, Ownable {
     uint256 private _nextTokenId;
     constructor() ERC721("Football Players", "FTP") Ownable(msg.sender) {}
     function safeMint(address to) public onlyOwner {
         uint256 tokenId = _nextTokenId++;
         _safeMint(to, tokenId);
     }
    }

Step 2: Set Up a Hardhat Project

npm init -y
npm install -D hardhat @nomicfoundation/hardhat-ignition-ethers
npx hardhat init # Choose TypeScript

Configure hardhat.config.ts for Sepolia:

networks: {
    sepolia: {
        url: process.env.INFURA_SEPOLIA_ENDPOINT,
        accounts: [process.env.PRIVATE_KEY]
    }
}

Adding Metadata to Your NFTs

Store NFT metadata (name, image, description) off-chain using IPFS:

  1. Upload images and JSON files to NFT.Storage.
  2. Link metadata via tokenURI:

    function _baseURI() internal pure override returns (string memory) {
     return "ipfs://YOUR_FOLDER_CID/";
    }
    function tokenURI(uint256 tokenId) public view override returns (string memory) {
     return string(abi.encodePacked(_baseURI(), tokenId.toString(), ".json"));
    }

Example JSON:

{
    "name": "Football Players #0",
    "description": "Italian football player",
    "image": "ipfs://IMAGE_CID"
}

Advanced Features

Extend functionality with OpenZeppelin’s extensions:

  1. URI Storage: Store per-token metadata.
  2. Burnable: Allow token destruction (burn).
  3. Pausable: Freeze transfers (pause/unpause).
  4. Enumerable: Track all tokens (totalSupply).

Updated contract:

contract FootballPlayers is ERC721, ERC721Enumerable, ERC721URIStorage, Ownable {
    function safeMint(address to, string memory uri) public onlyOwner {
        uint256 tokenId = _nextTokenId++;
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }
    // Override required methods (e.g., _update, supportsInterface)
}

Deploying and Testing Your Contract

  1. Compile: npx hardhat compile
  2. Test:

    npx hardhat test test/FootballPlayers.ts --typecheck
  3. Deploy to Sepolia:

    npx hardhat ignition deploy ignition/modules/FootballPlayers.ts --network sepolia
  4. Verify on OpenSea.

FAQs

Q1: What’s the difference between ERC-721 and ERC-20?

Q2: How do I store NFT metadata cheaply?

Use IPFS for decentralized, cost-effective storage.

Q3: Can I update metadata after minting?

No, IPFS data is immutable. Plan metadata carefully before deployment.

👉 Explore more NFT use cases


Further Exploration


Conclusion

You’ve now learned how to:

Happy coding! For questions, reach out via GitHub.


This version:
- Follows SEO best practices (keyword integration, structured headings).
- Removes redundant/ads.
- Adds FAQs and engaging anchor texts.