ERC721 是以太坊上的一种非同质化代币(NFT,Non-Fungible Token)标准,由 William Entriken、Dieter Shirley、Jacob Evans 和 Nastassia Sachs 在 2018 年提出。与 ERC20 代币不同,ERC721 代币是独一无二的,每个代币都有唯一的标识符(Token ID),因此适用于表示独一无二的资产,如数字艺术品、收藏品、游戏道具等。
ERC721__4">ERC721 标准的完整定义
ERC721 标准定义了 NFT 合约必须实现的最小接口,包括函数和事件。以下是 ERC721 标准的详细内容。
1. 必须实现的函数
ERC721 标准规定了以下 9 个必须实现的函数:
1.1 balanceOf
- 功能: 返回指定地址拥有的 NFT 数量。
- 函数签名:
solidity">function balanceOf(address owner) external view returns (uint256);
1.2 ownerOf
- 功能: 返回指定
tokenId
的所有者地址。 - 函数签名:
solidity">function ownerOf(uint256 tokenId) external view returns (address);
1.3 safeTransferFrom
- 功能: 将 NFT 从当前所有者转移到另一个地址。如果目标地址是合约,则必须实现
onERC721Received
函数。 - 函数签名:
solidity">function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
1.4 transferFrom
- 功能: 将 NFT 从当前所有者转移到另一个地址。不检查目标地址是否是合约。
- 函数签名:
solidity">function transferFrom(address from, address to, uint256 tokenId) external;
1.5 approve
- 功能: 授权另一个地址(
approved
)管理指定的tokenId
。 - 函数签名:
solidity">function approve(address approved, uint256 tokenId) external;
1.6 setApprovalForAll
- 功能: 授权或取消授权另一个地址(
operator
)管理调用者所有的 NFT。 - 函数签名:
solidity">function setApprovalForAll(address operator, bool approved) external;
1.7 getApproved
- 功能: 返回被授权管理指定
tokenId
的地址。 - 函数签名:
solidity">function getApproved(uint256 tokenId) external view returns (address);
1.8 isApprovedForAll
- 功能: 检查
operator
是否被授权管理owner
的所有 NFT。 - 函数签名:
solidity">function isApprovedForAll(address owner, address operator) external view returns (bool);
ERC721Received_70">1.9 onERC721Received
- 功能: 当 NFT 被转移到合约地址时,目标合约必须实现此函数以接收 NFT。
- 函数签名:
solidity">function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
2. 必须实现的事件
ERC721 标准规定了以下 3 个必须实现的事件:
2.1 Transfer
- 触发条件: 当 NFT 的所有权从一个地址转移到另一个地址时触发。
- 事件签名:
solidity">event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
2.2 Approval
- 触发条件: 当某个地址被授权管理指定的
tokenId
时触发。 - 事件签名:
solidity">event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
2.3 ApprovalForAll
- 触发条件: 当
owner
授权或取消授权operator
管理其所有 NFT 时触发。 - 事件签名:
solidity">event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
3. 可选的功能
除了必须实现的函数和事件外,ERC721 标准还建议实现以下 可选功能:
3.1 name
- 功能: 返回 NFT 集合的名称(例如 “MyNFT”)。
- 函数签名:
solidity">function name() external view returns (string memory);
3.2 symbol
- 功能: 返回 NFT 集合的符号(例如 “MNFT”)。
- 函数签名:
solidity">function symbol() external view returns (string memory);
3.3 tokenURI
- 功能: 返回指定
tokenId
的元数据 URI(通常是 JSON 文件链接)。 - 函数签名:
solidity">function tokenURI(uint256 tokenId) external view returns (string memory);
ERC721__133">4. 完整的 ERC721 实现示例
以下是一个简单的 ERC721 代币实现示例:
solidity">// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";contract MyNFT is ERC721 {using Counters for Counters.Counter;Counters.Counter private _tokenIds;constructor() ERC721("MyNFT", "MNFT") {}function mint(address to) public returns (uint256) {_tokenIds.increment();uint256 newTokenId = _tokenIds.current();_mint(to, newTokenId);return newTokenId;}function tokenURI(uint256 tokenId) public view override returns (string memory) {require(_exists(tokenId), "Token does not exist");return string(abi.encodePacked("https://mynft.com/token/", Strings.toString(tokenId)));}
}
ERC721__166">5. ERC721 的重要注意事项
-
唯一性:
- 每个
tokenId
必须是唯一的,不能重复。
- 每个
-
元数据:
tokenURI
返回的元数据通常是一个 JSON 文件链接,包含 NFT 的名称、描述、图像等信息。
-
安全转账:
- 使用
safeTransferFrom
时,如果目标地址是合约,则必须实现onERC721Received
函数,否则转账会失败。
- 使用
-
授权管理:
approve
用于授权单个 NFT,而setApprovalForAll
用于授权所有 NFT。
-
Gas 费用:
- NFT 的转账和授权操作可能会消耗较多的 Gas,尤其是在链上存储大量元数据时。
6. 总结
ERC721 标准是以太坊上用于非同质化代币(NFT)的核心标准,适用于表示独一无二的资产。通过实现 ERC721 标准,开发者可以创建与其他以太坊应用程序(如钱包、市场和游戏)兼容的 NFT。完整的 ERC721 实现不仅包括必须实现的函数和事件,还应遵循最佳实践,确保 NFT 的安全性和互操作性。