Track 5 · Tokens · lesson 6
ERC-721 and NFTs
15 min
ERC-20 tracks how much you have. ERC-721 tracks which ones.
That single change — from a balance to an identity — is the whole difference between fungible and non-fungible.
mapping(address => uint256) public balanceOf; // ERC-20: an amount
mapping(uint256 => address) public ownerOf; // ERC-721: an owner per id
Build one.
Nudge
Show me the approach
Show me the code
Explain the solution
What changed, concretely
ownerOf(id)replaces amounts. Each token id has exactly one owner.balanceOfstill exists, but now counts how many tokens you hold, not a quantity of anything.- Transfers move a specific id, so there is no partial transfer. You cannot send half an NFT.
- Approvals work per token id, plus
setApprovalForAllfor an operator over your whole collection.
setApprovalForAll is the NFT version of the unlimited approval, and it is
worse: it grants control of every token in that collection, including ones
you have not bought yet.
Marketplaces require it, because they cannot know in advance which token you will list. Nearly every NFT theft that was not a private key leak went through an operator approval the victim granted and forgot.
Predict
Your minimal NFT has no `safeTransferFrom`. What does the real standard's version add?
What an NFT is not
It is a row in a mapping saying an address owns id 42, plus usually a URL.
It is not the image. It confers no copyright, no legal ownership, and no enforcement outside the chain. Where the picture lives is the next lesson, and the answer disappoints most people.
Check
In ERC-721, what does `balanceOf(alice)` return?
Worth remembering
- ERC-721 maps token id to owner, instead of address to amount.
- `balanceOf` counts tokens held, not a quantity.
- Transfers move a specific id — there are no partial transfers.
- `setApprovalForAll` grants an operator control of your entire collection, including future tokens.
- `safeTransferFrom` checks a contract recipient can handle NFTs, at the cost of an external call.