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.