ERC721 Explained in Detail
ERC721 defines a token model where each tokenId is distinct. The core security surface is ownership: who can mint, transfer, approve, burn, and query each token.
Unlike ERC20 balances, ERC721 state is usually tracked per token ID. That makes edge cases around nonexistent tokens, burned tokens, approvals, and receiver callbacks important during review.
Smart contract example
function transferFrom(address from, address to, uint256 tokenId) public;
function ownerOf(uint256 tokenId) public view returns (address);
After a transfer, token-specific approval should not silently remain valid for the old owner.
ERC721 in Auditing
ERC721 bugs can break ownership, allow unauthorized transfers, bypass mint limits, or lock tokens in contracts. Auditors trace every path that changes ownership or approval state.
Safe transfers also call external receiver code, so ERC721 review often overlaps with reentrancy and external call review.
Red flags in code
-
Minting functions have weak or missing access control.
-
Transfers do not clear token-specific approvals.
-
Burned or nonexistent token IDs return misleading ownership data.
-
Custom transfer logic skips receiver checks for contract recipients.
-
supportsInterfaceis wrong or incomplete.
How to test or review it
-
Test mint, transfer, approve, revoke, burn, and ownership queries.
-
Try transfers by owner, approved address, operator, and unauthorized caller.
-
Transfer to contracts that accept, reject, revert, and reenter from the receiver hook.
-
Check edge cases for burned tokens and nonexistent token IDs.
-
Verify approvals are cleared when ownership changes.