ERC721 NFT标准
在区块链和加密货币的世界中,ERC721 标准为非同质化代币(Non-Fungible Token, NFT)的发展提供了重要基础。与普通的可互换代币(如 ERC20 代币)不同,每一枚 ERC721 代币都是独一无二的,这使它们成为艺术品、收藏品以及其他独特数字资产的理想载体。理解这一标准,对于开发和发布自己的 NFT 项目来说至关重要。
在本章,我们将详细探讨 ERC721 标准的机制,并通过一个具体的实例来演示如何实现基本的 ERC721 代币合约。
什么是 ERC721
ERC721 是一个 Ethereum 智能合约开发的一个标准接口,用于创建、跟踪和转移 NFT。该标准允许每个代币拥有唯一的属性和元数据。
CryptoKitties 是最早的主流区块链游戏之一,每一只加密猫都是一个独特的 NFT,拥有不同的外观、属性和稀有度。它通过 ERC721 标准进行代币化。玩家可以买卖、繁殖和收集这些虚拟的猫.
ERC721 与 ERC20 的比较
对比最广为人知的 ERC20 代币标准,ERC20 代币是可互换的,意味着每个代币都是相同的,并且具有相同的价值。相反,ERC721 的每一个代币都是独特的,并可以拥有不同的价值。
ERC721 的关键特征:
- 非同质化:每个代币都有独特的属性
- 所有权追踪:智能合约能准确记录每个代币的所有者
- 元数据可选性:合约可以包含一个可选的 URL,指向代币的元数据,如图片、文本等
ERC721 核心方法和事件
在 ERC721 标准中,定义了一系列方法和事件,这些都是为了保证非同质化代币的独特性、可跟踪性和可交易性。以下是一些关键的方法和事件:
方法
balanceOf(address _owner)
- 描述:返回指定地址所拥有的代币数量
- 参数:
_owner
:代币拥有者的地址 - 返回值:该地址拥有的代币数量
ownerOf(uint256 _tokenId)
- 描述:查询某个代币的所有者
- 参数:
_tokenId
:代币的唯一识别 ID - 返回值:拥有此代币的地址
safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data)
- 描述:安全地将代币从一个地址转移到另一个地址,调用时会检查接收者地址是否具备处理 ERC721 代币的能力
- 参数:
_from
:当前代币的拥有者地址_to
:代币将要被转移至的目标地址_tokenId
:将要被转移的代币的 IDdata
:额外的数据,可能会在调用中使用
transferFrom(address _from, address _to, uint256 _tokenId)
- 描述:将代币从一个地址转移到另一个地址,不检查接收者地址是否能处理 ERC721 代币
- 参数:
_from
:当前代币的拥有者地址_to
:代币将要被转移至的目标地址_tokenId
:将要被转移的代币的 ID
approve(address _approved, uint256 _tokenId)
- 描述:授权某个地址管理特定的ERC721代币
- 参数:
_approved
:被授权的地址_tokenId
:代币的唯一识别 ID
getApproved(uint256 _tokenId)
- 描述:获取被授权管理特定代币的地址
- 参数:
_tokenId
:代币的唯一识别 ID - 返回值:被授权的管理该代币的地址
setApprovalForAll(address _operator, bool _approved)
- 描述:将一个操作者地址设置为被批准或取消批准管理所有代币的权利
- 参数:
_operator
:操作者的地址_approved
:批准或取消批准的标志
isApprovedForAll(address _owner, address _operator)
- 描述:查询一个操作者是否被批准管理某个所有者的所有代币
- 参数:
_owner
:代币拥有者的地址_operator
:操作者的地址
- 返回值:是否被授权的布尔值
ERC721Metadata
是 ERC721 标准的一个非常重要的扩展,它为 NFT 增加了“名字(name
)”、“符号(symbol
)”和“元数据(tokenURI
)”三个方法。这些方法引入了关于 NFT 的额外信息,这在市场上展示和交易NFT 时特别有用。
事件
Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId)
在代币被转移时触发Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId)
在一个地址被授权管理另一个地址的特定代币时触发ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved)
当一个操作者被授权或取消授权管理某个所有者的所有代币时触发
这些方法和事件构成了 ERC721 代币标准的核心,确保了代币的可追踪和独一无二的特性,以及安全的交易方式。
完整的技术标准详见 eip-721
ERC721 实现
我们将使用 OpenZeppelin 的库来实现一个基础的 ERC721 代币:
// 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 _tokenIdCounter = 0;
constructor() ERC721("MyNFT", "MNFT") {}
function safeMint(address to, string memory uri) public onlyOwner {
uint256 tokenId = _tokenIdCounter;
_tokenIdCounter++;
_safeMint(to, tokenId);
_setTokenURI(tokenId, uri);
}
}
在这个简单的示例中,MyNFT
合约继承了 ERC721URIStorage
(继承了 ERC721
) 和 Ownable
合约。
MyNFT
合约的构造函数设置了 NFT 的名称和符号。合约使用一个私有变量 _tokenIdCounter
来追踪发行的每个 NFT 的唯一编号。
safeMint
函数提供了方法来铸造新的 NFT。它接收一个地址和一个 URI 作为参数,铸造一个新的 NFT。内部调用了 OpenZeppelin 的 ERC721 合约提供的 _safeMint
函数 ,不仅创建一个新的 token,并将其分配给一个指定的地址,而且它还确保目标地址是可以接收 ERC721 token 的。通过 ERC721URIStorage 合约提供的 _setTokenURI
方法设置其 metadata URI。Ownable 合约的 onlyOwner
修饰器限制了只有合约的拥有者才可以调用 safeMint
函数。
总结
通过这一章,你应该对 ERC721 代币有了一个全面的了解,从它的基本原理到如何实现一个简单的代币合约。NFT 不仅仅可以代表艺术品和收藏品,随着技术的发展,其应用将变得更加广泛。