> For the complete documentation index, see [llms.txt](https://www.anandisheladiya.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.anandisheladiya.com/protocols/ercs-and-eips/erc-721-the-standard-for-non-fungible-tokens-nfts.md).

# ERC-721: The Standard for Non-Fungible Tokens (NFTs)

### **Introduction**

ERC-721 is the standard for **non-fungible tokens (NFTs)**, meaning **each token is unique** and cannot be replaced (e.g., CryptoKitties, Bored Apes).

### **Architecture**

An ERC-721 token smart contract includes:

* **Token Ownership Mapping:** Each token has a unique `tokenId` linked to an address.
* **Metadata Storage:** Stores information like name, image, and description.
* **Transfer Functions:** Allows ownership to be transferred.

### **Key Functions of ERC-721**

| Function                                    | Description                                    |
| ------------------------------------------- | ---------------------------------------------- |
| balanceOf(address)                          | Returns the number of NFTs owned by an address |
| ownerOf(uint256 tokenId)                    | Returns the owner of a specific NFT            |
| transferFrom(address, address, uint256)     | Transfers ownership of an NFT                  |
| approve(address, uint256)                   | Approves another address to manage an NFT      |
| safeTransferFrom(address, address, uint256) | Ensures safe NFT transfer                      |

### **Workflow of ERC-721 Transactions**

1. **Minting:** A unique `tokenId` is created and assigned to an owner.
2. **Transfer:** The NFT can be transferred using `transferFrom()`.
3. **Approval & Marketplace Integration:**
   * The owner approves a marketplace contract to manage their NFT using `approve()`.
   * The marketplace can then transfer the NFT on behalf of the owner.

### Example: ERC-721 Smart Contract

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract MyNFT is ERC721URIStorage, Ownable {
    uint256 private _nextTokenId;

    constructor() ERC721("MyNFT", "MNFT") {}

    function mintNFT(address recipient, string memory tokenURI) public onlyOwner {
        uint256 tokenId = _nextTokenId;
        _nextTokenId++;
        _mint(recipient, tokenId);
        _setTokenURI(tokenId, tokenURI);
    }
}

```

### ERC-721 NFT Flow

```scss
[ User A ]  ---> (mint tokenId #1) --->  [ NFT Contract ]
[ User A ]  ---> (transfer tokenId #1) --->  [ User B ]
[ Marketplace ] ---> (approve & transfer NFT) ---> [ Buyer ]

```
