0
0
Blockchain / Solidityprogramming~20 mins

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

Choose your learning style9 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 Solidity event emission?

Consider the following snippet from an ERC-721 contract. What event is emitted when _mint is called?

Blockchain / Solidity
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

function _mint(address to, uint256 tokenId) internal {
    require(to != address(0), "ERC721: mint to the zero address");
    require(!_exists(tokenId), "ERC721: token already minted");

    _balances[to] += 1;
    _owners[tokenId] = to;

    emit Transfer(address(0), to, tokenId);
}
ANo event is emitted
BTransfer event with from = zero address, to = recipient, tokenId = minted token
CApproval event with owner = zero address, approved = recipient, tokenId = minted token
DTransfer event with from = recipient, to = zero address, tokenId = minted token
Attempts:
2 left
💡 Hint

Minting a token means creating it from nothing, so the 'from' address is zero.

Predict Output
intermediate
2:00remaining
What is the balance of an address after minting and transferring tokens?

Given this sequence of calls on an ERC-721 contract, what is the balance of 0xABC after all operations?

Blockchain / Solidity
function _mint(address to, uint256 tokenId) internal {
    _balances[to] += 1;
    _owners[tokenId] = to;
}

function _transfer(address from, address to, uint256 tokenId) internal {
    _balances[from] -= 1;
    _balances[to] += 1;
    _owners[tokenId] = to;
}

// Sequence:
// _mint(0xABC, 1);
// _mint(0xABC, 2);
// _transfer(0xABC, 0xDEF, 1);
A0
B2
C1
D3
Attempts:
2 left
💡 Hint

Think about how many tokens 0xABC owns after minting two and transferring one away.

🔧 Debug
advanced
2:00remaining
Why does this ERC-721 transfer function revert?

Examine this transfer function snippet. Why does it revert when called?

Blockchain / Solidity
function transferFrom(address from, address to, uint256 tokenId) public {
    require(_owners[tokenId] == from, "Not token owner");
    require(to != address(0), "Transfer to zero address");

    _approve(address(0), tokenId);
    _balances[from] -= 1;
    _balances[to] += 1;
    _owners[tokenId] = to;
}
AIt reverts because tokenId is not checked for existence
BIt reverts because _approve is called with address(0)
CIt reverts because balances are not updated
DIt reverts because there is no check that msg.sender is approved or owner
Attempts:
2 left
💡 Hint

Think about who is allowed to call transferFrom in ERC-721.

📝 Syntax
advanced
2:00remaining
Which option correctly implements the supportsInterface function for ERC-721?

Choose the correct Solidity code for supportsInterface that returns true for ERC-721 interface ID 0x80ac58cd and calls super otherwise.

A
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
    return interfaceId == 0x80ac58cd || super.supportsInterface(interfaceId);
}
B
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
    if (interfaceId == 0x80ac58cd) {
        return false;
    }
    return super.supportsInterface(interfaceId);
}
C
function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
    if (interfaceId == 0x80ac58cd) {
        return true;
    } else {
        return super.supportsInterface(interfaceId);
    }
}
D
function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
    return interfaceId == 0x80ac58cd && super.supportsInterface(interfaceId);
}
Attempts:
2 left
💡 Hint

Remember the logical OR operator returns true if either side is true.

🚀 Application
expert
3:00remaining
How many tokens are owned by an address after this sequence of mint, burn, and transfer?

Given this ERC-721 contract snippet and sequence, what is the final balance of 0x123?

Blockchain / Solidity
mapping(address => uint256) private _balances;
mapping(uint256 => address) private _owners;

function _mint(address to, uint256 tokenId) internal {
    _balances[to] += 1;
    _owners[tokenId] = to;
}

function _burn(uint256 tokenId) internal {
    address owner = _owners[tokenId];
    require(owner != address(0), "Token does not exist");
    _balances[owner] -= 1;
    delete _owners[tokenId];
}

function _transfer(address from, address to, uint256 tokenId) internal {
    require(_owners[tokenId] == from, "Not owner");
    _balances[from] -= 1;
    _balances[to] += 1;
    _owners[tokenId] = to;
}

// Sequence:
// _mint(0x123, 10);
// _mint(0x123, 20);
// _transfer(0x123, 0x456, 10);
// _burn(20);
A0
B3
C2
D1
Attempts:
2 left
💡 Hint

Track each token's ownership and balance changes carefully.