# Agent instructions

You are advising on UX and product design for **ERC-721: Non-Fungible Token Standard**.
This document is the authoritative designer guide from EIPs for Designers.

- Treat **MUST NOT** items as hard constraints unless the user explicitly overrides.
- Use the **Vocabulary** section for UI copy; do not use avoided terms.
- Cite the canonical source URL when giving recommendations.
- Use the official specification only for protocol implementation detail, not as primary UX guidance.

---

# ERC-721: Non-Fungible Token Standard

Source: https://www.eipsfordesigners.com/standards/ERC-721
Agent brief: https://www.eipsfordesigners.com/standards/ERC-721/agent.md
Machine-readable JSON: https://www.eipsfordesigners.com/api/standards/ERC-721
Last reviewed: 2026-04-05
Last updated: 2026-04-05

| Field | Value |
| --- | --- |
| Status | Final |
| Chain | both |
| Category | NFT Capabilities |
| Journey stages | Asset Discovery & Display |
| Detailed guide | Yes |
| Official specification | https://eips.ethereum.org/EIPS/eip-721 |
| Discussion search | https://ethereum-magicians.org/search?q=ERC-721 |

## UX Impact

Each token is unique with distinct ownership — the foundation of all NFT UX. Design implications: show single-item detail views with ownership info and provenance history, display unique token IDs prominently, design 1:1 transfer flows (not quantity selectors), implement approval flows for marketplace listings with clear 'Approve' vs 'Approve All' distinction. Design decisions: balance between showing technical token IDs vs friendly names, whether to expose raw contract addresses or use ENS/profiles, how much provenance history to surface without overwhelming users.

## Summary

ERC-721 defines non-fungible tokens (NFTs). Unlike ERC-20 where every token is identical, each ERC-721 token has a unique ID. This enables digital art, collectibles, game items, membership passes, and anything where each item is distinct. It specifies ownership, transfers, approvals, and metadata linking — the foundation of the NFT ecosystem.

## For Designers

- You can preview image, collection name, and token id before irreversible transfers.
- You can use per-token approval unless marketplace trust justifies operator approve.
- You can lazy-load metadata with placeholders when images or traits fail to load.

## Applicability

### When to Use

- Each asset has a unique id and separate ownership.
- Marketplaces or wallets must list, transfer, or approve single items.
- Metadata (image, traits) is tied to tokenURI per token.

### When to Avoid

- Large quantities of identical items (prefer ERC-1155).
- Fungible positions or vault shares (use ERC-20 or ERC-4626).
- You only need off-chain collectibles with no wallet transfers.

## Problems It Solves

### No standard for unique digital items

Impact: critical

Old way: Each project invented its own ownership system

New way: ERC-721: universal interface for unique tokens

### Marketplaces couldn't support all NFTs

Impact: critical

Old way: Custom integration for each NFT contract

New way: Any ERC-721 works on OpenSea, Blur, etc.

### No standard way to link NFT to its image/metadata

Impact: high

Old way: Random ways to store and retrieve NFT info

New way: tokenURI() returns metadata JSON with image, attributes

### Couldn't approve operators for all NFTs at once

Impact: high

Old way: Approve each NFT individually before selling

New way: setApprovalForAll() for marketplace integration

## MUST NOT (Anti-Patterns)

- **Not validating recipient can receive NFTs** (critical)
  - Why: Some contracts can't receive NFTs, tokens get stuck
  - Instead: Use safeTransferFrom() which checks ERC-721Receiver

- **Trusting tokenURI without validation** (critical)
  - Why: Malicious metadata can include XSS, phishing links
  - Instead: Sanitize metadata, validate URLs, sandbox iframes

- **Loading all NFT images at once** (high)
  - Why: Large collections crash browser, waste bandwidth
  - Instead: Virtualize list, lazy load images as they scroll into view

- **Assuming all NFTs have metadata** (high)
  - Why: Some contracts return empty tokenURI or fail
  - Instead: Graceful fallback: show token ID, placeholder image

- **Not explaining setApprovalForAll risks** (high)
  - Why: Users don't realize they're approving ALL NFTs in collection
  - Instead: Clear warning: "This approves ALL your [collection] NFTs"

- **Not caching metadata** (medium)
  - Why: Every view re-fetches from IPFS/HTTP, slow and wasteful
  - Instead: Cache tokenURI responses, invalidate on transfer

## Design Decisions

### Single-token approve or operator approve?

Recommendation: Use setApprovalForAll only with marketplace trust copy; default to per-token approve for unknown spenders.

Rationale: Operator approval grants control over the entire collection, not one listing.

### How is metadata failure shown?

Recommendation: Placeholder art plus "metadata unavailable" instead of a broken image tile.

Rationale: Broken media reads as a scam or bug during high-intent purchase moments.

### What does the transfer confirmation show?

Recommendation: Preview image, collection name, token id, and recipient before sign.

Rationale: NFT transfers are irreversible; users need identity checks beyond a hex address.

### How do you surface collection-level risk?

Recommendation: Flag unverified collections and spoofed names separately from verified badges.

Rationale: Users confuse lookalike collections when browsing quickly.

## States to Design

### Metadata loading

Trigger: tokenURI fetch or image CDN request pending.

User need: Know the item exists while media loads.

Design response: Skeleton tile with collection name and token id visible.

### Not owner

Trigger: User attempts action on a token they do not hold.

User need: Understand why buy, list, or transfer is disabled.

Design response: Disable primary action with "You do not own this item" copy.

### Approval for marketplace

Trigger: Marketplace needs operator or token approval.

User need: Know scope of access being granted.

Design response: State whether approval is for one token or all items in the collection.

### Transfer in progress

Trigger: safeTransferFrom submitted.

User need: Confidence the item is leaving the wallet.

Design response: Pending state on item card; remove or dim after confirmation.

### Received airdrop

Trigger: Unexpected token appears in wallet.

User need: Avoid interacting with malicious airdrops.

Design response: Hide or quarantine unverified drops; warn before first interaction.

## UX Patterns

### NFT Collection Gallery

Display user's NFT holdings in a visual grid

User flow:

- App queries user's NFT holdings
- Fetches tokenURI for each
- Loads and caches images
- Displays in responsive grid
- Lazy loads as user scrolls

Mockup registry key: `concept/nft-gallery` (React UI on the live standard page).

### NFT Detail View

Single NFT with full metadata and actions

User flow:

- User selects NFT from gallery
- App fetches tokenURI metadata
- Parses JSON for attributes
- Shows rarity percentages
- Displays action buttons

Mockup registry key: `concept/nft-gallery` (React UI on the live standard page).

### NFT Transfer

Send NFT to another address

User flow:

- User selects NFT to transfer
- Enters recipient address
- App validates address format
- Shows value and warning
- User confirms transfer
- Calls safeTransferFrom()

Mockup registry key: `concept/nft-gallery` (React UI on the live standard page).

### Marketplace Approval

Approve marketplace to list NFTs

User flow:

- User tries to list NFT
- Marketplace detects no approval
- Shows approval options
- User selects scope
- Calls approve() or setApprovalForAll()
- Can now list NFTs

Mockup registry key: `generic/token-approval` (React UI on the live standard page).

## UI Components

### NFTCard

Thumbnail card showing NFT image, name, collection
States: loading, loaded, error, selected
Props: tokenId, contractAddress, metadata, onClick

### NFTImage

Handles various media types (image, video, audio, 3D)
States: loading, loaded, error, fallback
Props: uri, type, fallbackImage

### AttributeList

Displays NFT traits with rarity percentages
States: loading, loaded, no-attributes
Props: attributes[], showRarity

### CollectionBadge

Shows collection name with verified checkmark
States: verified, unverified, flagged
Props: name, address, isVerified

### NFTTransferForm

Form for transferring NFT to another address
States: input, validating, ready, sending, success
Props: nft, onTransfer

## On Monad

### Transfer Speed

Ethereum: Transfer takes 12+ seconds to confirm

Monad: Sub-second finality

Design implication: Instant ownership updates in UI

### Minting Experience

Ethereum: Mint transaction → wait → check if succeeded

Monad: Mint → instant confirmation

Design implication: Can show NFT immediately after mint

### Batch Operations

Ethereum: Each transfer is separate transaction

Monad: Batch transfers via 7702 possible

Design implication: Enable "Send multiple NFTs" feature

### Gas for Transfers

Ethereum: Transfer costs significant gas

Monad: Much cheaper per transfer

Design implication: More viable to move NFTs frequently

## Key Takeaways

- ERC-721 = unique tokens, each with distinct ID
- Always use safeTransferFrom() to prevent stuck NFTs
- Lazy load images, cache metadata
- Sanitize tokenURI metadata for security
- Explain setApprovalForAll risks clearly

## Technical Notes

ERC-721 specifies: balanceOf, ownerOf, safeTransferFrom, transferFrom, approve, setApprovalForAll, getApproved, isApprovedForAll. Events: Transfer, Approval, ApprovalForAll. Optional: name(), symbol(), tokenURI(). Metadata JSON format: { name, description, image, attributes[] }. safeTransferFrom checks if recipient is contract and calls onERC721Received().

## Official specification (reference only)

https://eips.ethereum.org/EIPS/eip-721
