Fatskills
Practice. Master. Repeat.
Study Guide: Blockchain and Web3 Development: NFTs and Gaming NFT Standards ERC721 ERC1155 ERC4907
Source: https://www.fatskills.com/cryptocurrency-bitcoin-blockchain-and-more/chapter/blockchain-and-web3-development-blockchain-and-web3-development-nfts-and-gaming-nft-standards-erc721-erc1155-erc4907

Blockchain and Web3 Development: NFTs and Gaming NFT Standards ERC721 ERC1155 ERC4907

By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.

⏱️ ~5 min read

What This Is

NFT standards are the “blueprints” that tell the Ethereum Virtual Machine (EVM) how a non‑fungible token (NFT) should behave. By codifying metadata, ownership, and transfer rules, they let any wallet, marketplace, or game understand and move the same token type without custom logic. Real‑world example: A sneaker brand launches a limited‑edition shoe collection on OpenSea; each pair is an ERC‑721 token that buyers can view, trade, or use as an in‑game avatar accessory—all because the contract follows the same standard.


Key Terms & Code Snippets

  • ERC‑721: The original “single‑asset” NFT interface (functions like ownerOf, transferFrom).
    solidity contract MyArt is ERC721("MyArt", "ART") {
    function mint(address to, uint256 tokenId) external {
    _safeMint(to, tokenId);
    } }
  • ERC‑1155: A “multi‑token” standard that can hold both fungible (ERC‑20‑like) and non‑fungible items in one contract, saving gas on batch operations.
    solidity contract GameItems is ERC1155("ipfs://metadata/{id}.json") {
    function mint(address to, uint256 id, uint256 amount) external {
    _mint(to, id, amount, "");
    } }
  • ERC‑4907: Extension of ERC‑721 that adds user and expires fields, enabling rental or lease use‑cases without transferring ownership.
    solidity function setUser(uint256 tokenId, address user, uint64 expires) external onlyOwner {
    _setUser(tokenId, user, expires); }
  • _safeTransfer vs _transfer: _safeTransfer checks that the recipient implements the ERC‑721/1155 receiver interface, preventing tokens from being locked in contracts that can’t handle them.
  • IERC721Receiver.onERC721Received: The callback a contract must implement to accept ERC‑721 tokens safely.
    solidity function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) {
    return IERC721Receiver.onERC721Received.selector; }
  • Metadata URI (tokenURI / uri): A string (often an IPFS link) that points to JSON describing the NFT (name, image, attributes).
  • Batch Minting (_mintBatch): ERC‑1155 lets you mint many token IDs at once, cutting per‑mint gas from ~80k to ~15k.
  • Royalty Standard (ERC‑2981): Optional interface that tells marketplaces how much secondary‑sale royalty the creator receives.
    solidity function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address, uint256) {
    return (creator, salePrice * 5 / 100); // 5 % royalty }
  • supportsInterface(bytes4 interfaceId): ERC‑165 function that lets other contracts query which NFT interfaces a contract implements.
  • operator approvals (setApprovalForAll): Allows a marketplace contract to move any of a user’s tokens on their behalf, essential for gas‑efficient listings.


Step‑by‑Step / Process Flow

  1. Write the contract – Open Remix or VS Code, import OpenZeppelin’s ERC721.sol, ERC1155.sol, or ERC4907.sol and add your minting logic.
  2. Compile & test – Run npx hardhat compile (Solidity 0.8.20 recommended) and write unit tests with chai/ethers to verify ownerOf, balanceOf, and setUser (for ERC‑4907).
  3. Deploy – Use Hardhat + Infura/Alchemy:
    bash
    npx hardhat run scripts/deploy.js --network goerli
  4. Verify on Etherscan – Publish the source so wallets can read the ABI automatically.
  5. Interact from the front‑end – With Ethers.js:
    js
    const nft = new ethers.Contract(address, abi, signer);
    await nft.mint(walletAddress, 1);
    const uri = await nft.tokenURI(1);
  6. List on a marketplace – Call setApprovalForAll(marketplace, true) so the UI can transfer the token when a buyer clicks “Buy”.

Common Mistakes

  • Mistake: Using transferFrom instead of safeTransferFrom for ERC‑721.
    Correction: safeTransferFrom guarantees the receiver implements IERC721Receiver; otherwise the token could be forever stuck in a non‑compatible contract.

  • Mistake: Forgetting to override supportsInterface when mixing ERC‑721, ERC‑1155, and ERC‑4907.
    Correction: Call super.supportsInterface(interfaceId) for each parent contract so ERC‑165 queries return the correct bitmask.

  • Mistake: Storing large JSON metadata on‑chain (e.g., string public metadata).
    Correction: Keep metadata off‑chain (IPFS or Arweave) and only store the URI; this saves >90 % gas per mint.

  • Mistake: Approving the zero address (0x0) as an operator, which effectively revokes all approvals.
    Correction: Always pass a valid marketplace or escrow contract address to setApprovalForAll.

  • Mistake: Assuming ERC‑1155 batch minting is free of re‑entrancy risk.
    Correction: Even batch functions should follow the Checks‑Effects‑Interactions pattern; update state before external calls.


Blockchain Developer Interview / Practical Insights

  1. “Explain the difference between ERC‑721 and ERC‑1155 in terms of gas and use‑case.”

    Interviewers expect you to cite batch minting, single‑ID vs multi‑ID storage, and why games favor ERC‑1155 for inventory items.

  2. “How does ERC‑4907 enable a rental marketplace without transferring ownership?”

    Mention the user field, expiration timestamp, and that the original owner retains the ownerOf rights, allowing the contract to enforce time‑based access.

  3. “What security checks does _safeTransfer perform, and why are they important for composability?”

    Discuss the ERC‑721/1155 receiver interface check (onERC721Received/onERC1155Received) that prevents tokens from being locked in contracts that cannot handle them.

  4. “When auditing an NFT contract, what would you look for regarding royalty enforcement?”

    Verify that ERC‑2981 is correctly implemented, that the royalty fee is capped (e.g., ≤ 10 %), and that the contract does not allow the creator to change the royalty address after deployment (unless intended).


Quick Check Questions

  1. Scenario: A marketplace calls transferFrom to move a newly minted ERC‑721 token to a buyer, but the buyer’s address is a smart contract that does not implement onERC721Received.
    Answer: The transfer will succeed, but the token becomes locked because the contract cannot receive it safely. Use safeTransferFrom to avoid this.

  2. Scenario: An ERC‑1155 contract allows anyone to call mintBatch without access control.
    Answer: This is a critical vulnerability; anyone can create unlimited tokens, diluting scarcity and potentially draining gas from users. Always restrict minting to an admin role (onlyOwner or AccessControl).

  3. Scenario: A developer sets expires = block.timestamp + 30 days for an ERC‑4907 rental. After 30 days the user still has access.
    Answer: The contract likely compares expires with block.timestamp incorrectly (e.g., using > instead of <). Fix the logic so the user is cleared when block.timestamp >= expires.


Last‑Minute Cram Sheet (10 one‑liners)

  1. ⚠️ Never trust tx.origin for auth – it can be hijacked via phishing contracts.
  2. ERC‑721 = 0x80ac58cd, ERC‑1155 = 0xd9b67a26, ERC‑4907 = 0xad092b5c (ERC‑165 IDs).
  3. Batch minting (ERC‑1155) ≈ 15 k gas per token vs ≈ 80 k gas for ERC‑721.
  4. _safeTransfer = _transfer + interface check; always prefer the safe version.
  5. Metadata URI should be ipfs:// or ar://; on‑chain strings cost ~20 k gas per 32‑byte chunk.
  6. Royalty (ERC‑2981) is advisory – marketplaces may ignore it; enforce on‑chain if needed.
  7. setApprovalForAll is a single‑tx approval for any token ID; use it for marketplaces to reduce UI friction.
  8. Solidity 0.8.x auto‑reverts on overflow – no need for SafeMath unless you target <0.8.0.
  9. Gas‑opt: store uint256 counters in a single uint256 slot (bit‑packing) when you need many small counters.
  10. Testing tip: Use hardhat network reset between each test to avoid state bleed‑over that masks bugs.


ADVERTISEMENT