Bird
Raised Fist0
Blockchain / Solidityprogramming~20 mins

ERC-721 NFT standard in Blockchain / Solidity - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
ERC-721 Mastery
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
What is the output of this ERC-721 token URI function call?
Consider the following simplified Solidity function from an ERC-721 contract. What will be the output of tokenURI(1) if the base URI is set to "https://example.com/token/" and token 1 exists?
Blockchain / Solidity
string private baseURI = "https://example.com/token/";

function tokenURI(uint256 tokenId) public view returns (string memory) {
    require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
    return string(abi.encodePacked(baseURI, Strings.toString(tokenId)));
}

function _exists(uint256 tokenId) internal view returns (bool) {
    return tokenId == 1;
}
ARevert with error "ERC721Metadata: URI query for nonexistent token"
B"https://example.com/token/"
C"https://example.com/token/1"
D"https://example.com/token/0"
Attempts:
2 left
💡 Hint
Think about how the base URI and token ID are combined and what the _exists function returns.
🧠 Conceptual
intermediate
1:30remaining
Which function is required by the ERC-721 standard to transfer ownership of a token?
In the ERC-721 standard, which function must be implemented to allow safe transfer of a token from one owner to another?
Amint(address to, uint256 tokenId)
BtransferFrom(address from, address to, uint256 tokenId)
Capprove(address to, uint256 tokenId)
DsafeTransferFrom(address from, address to, uint256 tokenId)
Attempts:
2 left
💡 Hint
The function should ensure the recipient can handle ERC-721 tokens safely.
🔧 Debug
advanced
2:00remaining
What error does this ERC-721 mint function produce?
Given this mint function snippet, what error will occur when calling mint(msg.sender, 0)?
Blockchain / Solidity
mapping(uint256 => address) private _owners;

function mint(address to, uint256 tokenId) public {
    require(to != address(0), "ERC721: mint to the zero address");
    require(!_exists(tokenId), "ERC721: token already minted");
    _owners[tokenId] = to;
}

function _exists(uint256 tokenId) internal view returns (bool) {
    return _owners[tokenId] != address(0);
}
AToken ID 0 is invalid and causes a runtime error
BNo error, token minted successfully
CRevert with "ERC721: token already minted"
DRevert with "ERC721: mint to the zero address"
Attempts:
2 left
💡 Hint
Check the conditions and what _exists returns for tokenId 0 initially.
📝 Syntax
advanced
2:00remaining
Which option correctly implements the supportsInterface function for ERC-721?
The ERC-721 standard requires implementing supportsInterface(bytes4 interfaceId). Which of the following implementations correctly returns true for the ERC-721 interface ID (0x80ac58cd) and false otherwise?
A
function supportsInterface(bytes4 interfaceId) public pure returns (bool) {
    if (interfaceId == 0x80ac58cd) {
        return true;
    } else {
        return false;
    }
}
B
function supportsInterface(bytes4 interfaceId) public pure returns (bool) {
    return interfaceId == 0x80ac58cd;
}
C
function supportsInterface(bytes4 interfaceId) public pure returns (bool) {
    return interfaceId != 0x80ac58cd;
}
D
function supportsInterface(bytes4 interfaceId) public pure returns (bool) {
    return interfaceId == 0x80ac58cd || interfaceId == 0x5b5e139f;
}
Attempts:
2 left
💡 Hint
Check which option returns true only for 0x80ac58cd and false for others.
🚀 Application
expert
3:00remaining
How many tokens are owned by address 0xABC after these operations?
Given the following sequence of ERC-721 operations, how many tokens does address 0xABC own at the end? 1. Mint token 1 to 0xABC 2. Mint token 2 to 0xDEF 3. Transfer token 2 from 0xDEF to 0xABC 4. Transfer token 1 from 0xABC to 0x123 5. Burn token 2 Assume all operations succeed and the burn function removes ownership.
A0
B3
C2
D1
Attempts:
2 left
💡 Hint
Track ownership changes and burning carefully.

Practice

(1/5)
1. What is the main purpose of the ERC-721 standard in blockchain?
easy
A. To define a standard for unique non-fungible tokens (NFTs)
B. To create fungible tokens like cryptocurrencies
C. To manage smart contract deployment
D. To encrypt blockchain transactions

Solution

  1. Step 1: Understand ERC-721's role

    ERC-721 is designed specifically for unique tokens, called NFTs, which are different from fungible tokens like cryptocurrencies.
  2. Step 2: Compare with other token standards

    ERC-20 is for fungible tokens, while ERC-721 is for unique, non-fungible tokens.
  3. Final Answer:

    To define a standard for unique non-fungible tokens (NFTs) -> Option A
  4. Quick Check:

    ERC-721 = Unique NFTs [OK]
Hint: ERC-721 is for unique tokens, not fungible ones [OK]
Common Mistakes:
  • Confusing ERC-721 with ERC-20 fungible tokens
  • Thinking ERC-721 manages encryption
  • Assuming ERC-721 handles contract deployment
2. Which of the following is the correct function signature to get the owner of an NFT in ERC-721?
easy
A. function getOwner(address token) public returns (uint256);
B. function ownerOf(uint256 tokenId) external view returns (address);
C. function owner(uint256 id) external returns (address);
D. function tokenOwner(uint256 tokenId) public view returns (string);

Solution

  1. Step 1: Recall ERC-721 standard function names

    The standard defines ownerOf with a uint256 tokenId parameter returning an address.
  2. Step 2: Check function visibility and return type

    The function is external view and returns an address, matching function ownerOf(uint256 tokenId) external view returns (address); exactly.
  3. Final Answer:

    function ownerOf(uint256 tokenId) external view returns (address); -> Option B
  4. Quick Check:

    ownerOf(tokenId) returns owner address [OK]
Hint: Look for 'ownerOf' with tokenId returning address [OK]
Common Mistakes:
  • Using wrong function names like getOwner or tokenOwner
  • Incorrect return types like string instead of address
  • Missing view or external keywords
3. Given the following Solidity snippet, what will be the output of ownerOf(1) if token 1 is owned by address 0xABC...?
contract MyNFT is ERC721 {
    mapping(uint256 => address) private _owners;
    
    function ownerOf(uint256 tokenId) public view override returns (address) {
        return _owners[tokenId];
    }

    function mint(address to, uint256 tokenId) public {
        _owners[tokenId] = to;
    }
}
medium
A. 0x0000000000000000000000000000000000000000
B. Compilation error
C. 0xABC...
D. Function does not return anything

Solution

  1. Step 1: Understand the mint function effect

    The mint function sets the owner of tokenId to the given address in the _owners mapping.
  2. Step 2: Check ownerOf return value

    The ownerOf function returns the address stored in _owners[tokenId]. If token 1 was minted to 0xABC..., it returns that address.
  3. Final Answer:

    0xABC... -> Option C
  4. Quick Check:

    ownerOf(1) = minted owner address [OK]
Hint: ownerOf returns stored owner address from mapping [OK]
Common Mistakes:
  • Assuming default zero address if not minted
  • Thinking function has no return
  • Confusing compilation errors with runtime behavior
4. Identify the error in this ERC-721 transfer function snippet:
function transferFrom(address from, address to, uint256 tokenId) public override {
    require(ownerOf(tokenId) == msg.sender, "Not owner");
    _owners[tokenId] = to;
}
medium
A. The require should check if msg.sender is approved or owner, not just owner
B. The function should not override transferFrom
C. The _owners mapping should not be updated
D. The function is missing a return statement

Solution

  1. Step 1: Check transferFrom permission logic

    ERC-721 requires that the caller is either the owner or approved to transfer the token, not just the owner.
  2. Step 2: Identify missing approval check

    The code only checks if msg.sender is the owner, missing approval checks, which can block valid transfers.
  3. Final Answer:

    The require should check if msg.sender is approved or owner, not just owner -> Option A
  4. Quick Check:

    transferFrom needs owner or approved check [OK]
Hint: Check both owner and approved in transferFrom require [OK]
Common Mistakes:
  • Only checking owner without approval
  • Forgetting to override transferFrom
  • Not updating ownership mapping
5. You want to create an NFT contract that allows only the original minter to burn their token. Which ERC-721 function should you override and what check should you add?
hard
A. Override mint and check if msg.sender is approved
B. Override transferFrom and check if msg.sender is the owner
C. Override approve and check if msg.sender is the contract owner
D. Override _burn and check if msg.sender is the original minter

Solution

  1. Step 1: Identify burn function in ERC-721

    The _burn internal function handles token destruction in ERC-721 contracts.
  2. Step 2: Add ownership check for burning

    To restrict burning to original minters, override _burn and add a check that msg.sender matches the original minter address stored during minting.
  3. Final Answer:

    Override _burn and check if msg.sender is the original minter -> Option D
  4. Quick Check:

    Burn control = override _burn + minter check [OK]
Hint: Control burn by overriding _burn with minter check [OK]
Common Mistakes:
  • Trying to control burn in transferFrom or approve
  • Not storing original minter address
  • Checking approval instead of minter for burn
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard