๐จ ERC721 NFTs
ERC721 is the standard for non-fungible tokens (NFTs) on the EVM: each token has a unique ID and is not interchangeable. Defined by EIP-721ย .
๐ฏ Why ERC721
- Uniqueness โ Each token ID maps to one owner; ideal for art, collectibles, in-game items
- Ecosystem โ OpenSeaย , Raribleย , and wallets treat ERC721 as the default NFT standard
- Extensions โ ERC721Enumerableย , metadata (name, symbol,
tokenURI)
๐ Core Interface
// Minimal interface (EIP-721)
interface IERC721 {
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;
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
}Metadata is usually provided via ERC721Metadata: name(), symbol(), tokenURI(tokenId) (returns a URL to JSON with name, description, image).
๐ Minimal ERC721 Example
Using OpenZeppelinย :
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
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") {}
function mint(address to) public onlyOwner returns (uint256) {
uint256 tokenId = _nextTokenId++;
_safeMint(to, tokenId);
return tokenId;
}
}๐ง Reading NFT Data (ethers.js v6)
import { ethers } from 'ethers';
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const nftAddress = '0x...';
const abi = [
'function ownerOf(uint256 tokenId) view returns (address)',
'function tokenURI(uint256 tokenId) view returns (string)',
'function balanceOf(address owner) view returns (uint256)'
];
const nft = new ethers.Contract(nftAddress, abi, provider);
const tokenId = 1n;
const owner = await nft.ownerOf(tokenId);
const tokenURI = await nft.tokenURI(tokenId);
// tokenURI often points to IPFS or HTTP JSON (name, description, image)
const meta = await fetch(tokenURI).then(r => r.json());
console.log(meta.name, meta.image);๐ Resources
Last updated on