Nathaniel's blog
Back to posts

NFT Standards: ERC-721, ERC-1155, and Beyond

Nathaniel LinFebruary 9, 20267 min read0 views
NFT Standards: ERC-721, ERC-1155, and Beyond

Non-fungible tokens are unique digital assets on a blockchain. But "NFT" is an umbrella term — underneath, there are distinct standards with different capabilities. Understanding them is essential for building web3 applications.

ERC-721: The Original NFT Standard

ERC-721 defines a contract where each token has a unique ID and a single owner:

interface IERC721 {
    function balanceOf(address owner) external view returns (uint256);
    function ownerOf(uint256 tokenId) external view returns (address);
    function transferFrom(address from, address to, uint256 tokenId) external;
    function approve(address to, uint256 tokenId) external;
    function safeTransferFrom(address from, address to, uint256 tokenId) external;
}

Key characteristics:

  • Each token is distinct — token #1 and token #2 are different assets

  • Ownership is one-to-one: one address owns one token

  • Transfer moves the entire token — no fractions

  • Metadata (image, attributes) lives off-chain, linked via tokenURI()

Building with OpenZeppelin:

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

contract MyNFT is ERC721, Ownable {
    uint256 private _nextTokenId;

    constructor() ERC721("MyNFT", "MNFT") Ownable(msg.sender) {}

    function mint(address to) public onlyOwner returns (uint256) {
        uint256 tokenId = _nextTokenId++;
        _safeMint(to, tokenId);
        return tokenId;
    }
}

ERC-1155: Multi-Token Standard

ERC-1155 is the Swiss Army knife of token standards. A single contract can manage both fungible and non-fungible tokens:

interface IERC1155 {
    function balanceOf(address account, uint256 id) external view returns (uint256);
    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
        external view returns (uint256[] memory);
    function safeTransferFrom(
        address from, address to, uint256 id, uint256 amount, bytes calldata data
    ) external;
    function safeBatchTransferFrom(
        address from, address to, uint256[] calldata ids,
        uint256[] calldata amounts, bytes calldata data
    ) external;
}

The key difference: each token ID has a supply. Token #1 might have a supply of 1 (NFT), while token #2 has a supply of 1,000,000 (fungible).

Advantages over ERC-721:

  • Batch operations: Transfer multiple token types in one transaction

  • Gas efficiency: Shared storage for metadata and approvals

  • Flexibility: Mix fungible and non-fungible in one contract

Use cases: gaming items (weapons are NFTs, gold coins are fungible), event tickets (same event = fungible, different tiers = different IDs).

ERC-6551: Token-Bound Accounts

A newer standard that gives NFTs their own wallet addresses. Every ERC-721 token can own other assets:

  • An NFT character can own ERC-20 tokens, other NFTs, and even interact with DeFi protocols

  • Transfer the NFT → transfer everything it owns

  • Creates composable, portable digital identities

Metadata Standards

The visual part of NFTs — images, videos, attributes — follows a JSON metadata standard:

{
  "name": "Cool Cat #42",
  "description": "A very cool cat",
  "image": "ipfs://Qm.../42.png",
  "attributes": [
    { "trait_type": "Background", "value": "Blue" },
    { "trait_type": "Fur", "value": "Gold" },
    { "trait_type": "Coolness", "display_type": "number", "value": 99 }
  ]
}

Store this on IPFS or Arweave for permanence — not on a centralized server that can disappear.

Choosing the right standard depends on your use case. ERC-721 for unique 1-of-1 assets. ERC-1155 for games, memberships, or any scenario mixing fungible and non-fungible tokens. The ecosystem keeps evolving, but these foundations remain stable.

Share this post

Reactions