本文档介绍了与ERC-721非同质化代币标准相关的一系列接口、合约和实用程序,包括核心功能接口IERC721、元数据扩展接口IERC721Metadata、枚举扩展接口IERC721Enumerable和接收器接口IERC721Receiver。
| 最好在https://docs.openzeppelin.com/contracts/api/token/erc721 上查看此文档 |
这一组接口、合约和实用程序都与 ERC-721 Non-Fungible Token Standard 相关。
| 有关如何创建 ERC-721 token 的演练,请阅读我们的 ERC-721 指南。 |
ERC 指定了四个接口:
IERC721:所有合规实现中必须的核心功能。
IERC721Metadata:可选扩展,添加了名称、符号和 token URI,几乎总是包含在内。
IERC721Enumerable:可选扩展,允许在链上枚举 token,通常不包含,因为它需要大量的 gas 开销。
IERC721Receiver:如果合约希望通过 safeTransferFrom 接受 token,则合约必须实现的接口。
OpenZeppelin Contracts 提供了所有四个接口的实现:
ERC721:核心和元数据扩展,带有基本 URI 机制。
ERC721Enumerable:可枚举的扩展。
ERC721Holder:接收器接口的一个基本实现。
此外,还有一些其他的扩展:
ERC721Consecutive:ERC-2309 的实现,用于在构造期间按照 ERC-721 铸造批量的 token。
ERC721URIStorage:一种更灵活但更昂贵的存储元数据的方式。
ERC721Votes:支持投票和投票委托。
ERC721Royalty:一种遵循 ERC-2981 发出版税信息的方式。
ERC721Pausable:一个暂停合约操作的原语。
ERC721Burnable:token 持有者销毁他们自己的 token 的一种方式。
ERC721Wrapper:包装器,用于创建由另一个 ERC-721 支持的 ERC-721,带有存款和取款方法。与 ERC721Votes 结合使用很有用。
这组核心合约被设计为非主观的,允许开发人员访问 ERC-721 中的内部函数(例如 _mint),并以他们喜欢的方式将它们公开为外部函数。 |
IERC721import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
符合 ERC-721 标准的合约所需的接口。
函数
IERC165
事件
balanceOf(address owner) → uint256 balance external返回 owner 帐户中的 token 数量。
ownerOf(uint256 tokenId) → address owner external返回 tokenId token 的所有者。
要求:
tokenId 必须存在。safeTransferFrom(address from, address to, uint256 tokenId, bytes data) external将 tokenId token 从 from 安全地转移到 to。
要求:
from 不能是零地址。
to 不能是零地址。
tokenId token 必须存在并且属于 from。
如果调用者不是 from,则必须通过 approve 或 setApprovalForAll 获得批准才能移动此 token。
如果 to 指的是智能合约,则必须实现 IERC721Receiver.onERC721Received,该函数在安全转移时被调用。
发出 Transfer 事件。
safeTransferFrom(address from, address to, uint256 tokenId) external将 tokenId token 从 from 安全地转移到 to,首先检查合约接收者是否知道 ERC-721 协议,以防止 token 永远锁定。
要求:
from 不能是零地址。
to 不能是零地址。
tokenId token 必须存在并且属于 from。
如果调用者不是 from,则必须通过 approve 或
setApprovalForAll 获得批准才能移动此 token。
如果 to 指的是智能合约,则必须实现 IERC721Receiver.onERC721Received,该函数在安全转移时被调用。
发出 Transfer 事件。
transferFrom(address from, address to, uint256 tokenId) external将 tokenId token 从 from 转移到 to。
请注意,调用者有责任确认接收者能够接收 ERC-721<br>否则它们可能会永久丢失。使用 safeTransferFrom 可以防止丢失,但调用者必须<br>理解这会添加一个外部调用,这可能会导致重入漏洞。 |
要求:
from 不能是零地址。
to 不能是零地址。
tokenId token 必须属于 from。
如果调用者不是 from,则必须通过 approve 或 setApprovalForAll 获得批准才能移动此 token。
发出 Transfer 事件。
approve(address to, uint256 tokenId) external授予 to 权限,将 tokenId token 转移到另一个帐户。
当 token 被转移时,批准将被清除。
一次只能批准一个帐户,因此批准零地址会清除之前的批准。
要求:
调用者必须拥有 token 或成为批准的操作员。
tokenId 必须存在。
发出 Approval 事件。
setApprovalForAll(address operator, bool approved) external批准或删除 operator 作为调用者的操作员。
对于调用者拥有的任何 token,操作员都可以调用 transferFrom 或 safeTransferFrom。
要求:
operator 不能是零地址。发出 ApprovalForAll 事件。
getApproved(uint256 tokenId) → address operator external返回批准用于 tokenId token 的帐户。
要求:
tokenId 必须存在。isApprovedForAll(address owner, address operator) → bool external返回 operator 是否被允许管理 owner 的所有资产。
Transfer(address indexed from, address indexed to, uint256 indexed tokenId) event当 tokenId token 从 from 转移到 to 时发出。
Approval(address indexed owner, address indexed approved, uint256 indexed tokenId) event当 owner 启用 approved 来管理 tokenId token 时发出。
ApprovalForAll(address indexed owner, address indexed operator, bool approved) event当 owner 启用或禁用(approved)operator 来管理其所有资产时发出。
IERC721Metadataimport "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
请参阅 https://eips.ethereum.org/EIPS/eip-721
函数
IERC721
IERC165
事件
IERC721
name() → string external返回 token 集合名称。
symbol() → string external返回 token 集合符号。
tokenURI(uint256 tokenId) → string external返回 tokenId token 的统一资源标识符 (URI)。
IERC721Enumerableimport "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
请参阅 https://eips.ethereum.org/EIPS/eip-721
函数
IERC721
IERC165
事件
IERC721
totalSupply() → uint256 external返回合约存储的 token 总量。
tokenOfOwnerByIndex(address owner, uint256 index) → uint256 external返回 owner 的 token 列表中给定 index 处的 owner 拥有的 token ID。
与 balanceOf 一起使用以枚举 owner 的所有 token。
tokenByIndex(uint256 index) → uint256 external返回合约存储的所有 token 的给定 index 处的 token ID。
与 totalSupply 一起使用以枚举所有 token。
ERC721import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
ERC-721 非同质化 token 标准的实现,包括元数据扩展,但不包括可枚举扩展,该扩展可作为 ERC721Enumerable 单独提供。
函数
事件
IERC721
错误
IERC721Errors
constructor(string name_, string symbol_) internal通过为 token 集合设置一个 name 和一个 symbol 来初始化合约。
supportsInterface(bytes4 interfaceId) → bool public请参阅 IERC165.supportsInterface。
balanceOf(address owner) → uint256 public请参阅 IERC721.balanceOf。
ownerOf(uint256 tokenId) → address public请参阅 IERC721.ownerOf。
name() → string public请参阅 IERC721Metadata.name。
symbol() → string publictokenURI(uint256 tokenId) → string public_baseURI() → string internal用于计算 tokenURI 的基本 URI。如果设置,则每个 token 的结果 URI 将是 baseURI 和 tokenId 的串联。默认为空,可以在子合约中重写。
approve(address to, uint256 tokenId) public请参阅 [IERC721.approve](https://docs.openzeppelin.com/contracts/5.x/api/token/erc销毁 tokenId。
当 token 被销毁时,授权会被清除。
这是一个内部函数,不检查发送者是否有权操作该 token。
要求:
tokenId 必须存在。发出一个 Transfer 事件。
_transfer(address from, address to, uint256 tokenId) internal将 tokenId 从 from 转移到 to。
与 transferFrom 相比,这不对 msg.sender 施加任何限制。
要求:
to 不能是零地址。
tokenId token 必须由 from 拥有。
发出一个 Transfer 事件。
_safeTransfer(address from, address to, uint256 tokenId) internal安全地将 tokenId token 从 from 转移到 to,检查合约接收者
是否了解 ERC-721 标准,以防止 token 永远被锁定。
data 是附加数据,它没有指定的格式,并在调用 to 时发送。
这个内部函数类似于 safeTransferFrom,因为它会调用
IERC721Receiver.onERC721Received 在接收者上,并且可以用来例如
实现执行 token 转移的替代机制,例如基于签名的机制。
要求:
tokenId token 必须存在并且由 from 拥有。
to 不能是零地址。
from 不能是零地址。
如果 to 指的是智能合约,则它必须实现 IERC721Receiver.onERC721Received,该函数在安全转移时被调用。
发出一个 Transfer 事件。
_safeTransfer(address from, address to, uint256 tokenId, bytes data) internal与 _safeTransfer 相同,但带有一个额外的 data 参数,该参数是
在 IERC721Receiver.onERC721Received 中转发给合约接收者的。
_approve(address to, uint256 tokenId, address auth) internal授权 to 操作 tokenId
auth 参数是可选的。如果传递的值非 0,则此函数将检查 auth 是否为
token 的所有者,或被授权操作此所有者持有的所有 token。
发出一个 Approval 事件。
对此逻辑的重写应该对带有额外 bool emitEvent 参数的变体进行。
_approve(address to, uint256 tokenId, address auth, bool emitEvent) internal_approve 的变体,带有一个可选标志,用于启用或禁用 Approval 事件。该事件不是
在转移的上下文中发出的。
_setApprovalForAll(address owner, address operator, bool approved) internal授权 operator 操作所有 owner 的 token
要求: - operator 不能是零地址。
发出一个 ApprovalForAll 事件。
_requireOwned(uint256 tokenId) → address internal如果 tokenId 没有当前所有者(它尚未被铸造,或者已被销毁),则恢复。
返回所有者。
对所有权逻辑的重写应该在 _ownerOf 中完成。
ERC721Enumerableimport "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
这实现了在 ERC 中定义的 ERC721 的一个可选扩展,该扩展添加了可枚举性
合约中所有 token id 以及每个帐户拥有的所有 token id。
实现自定义 balanceOf 逻辑的 ERC721 扩展,例如 ERC721Consecutive,<br>会干扰可枚举性,不应与 ERC721Enumerable 一起使用。 |
函数
ERC721
事件
IERC721
错误
IERC721Errors
supportsInterface(bytes4 interfaceId) → bool public请参阅 IERC165.supportsInterface。
tokenOfOwnerByIndex(address owner, uint256 index) → uint256 public请参阅 IERC721Enumerable.tokenOfOwnerByIndex。
totalSupply() → uint256 public请参阅 IERC721Enumerable.totalSupply。
tokenByIndex(uint256 index) → uint256 public请参阅 IERC721Enumerable.tokenByIndex。
_update(address to, uint256 tokenId, address auth) → address internal请参阅 ERC721._update。
_increaseBalance(address account, uint128 amount) internalERC721OutOfBoundsIndex(address owner, uint256 index) error加粗owner 的 token 查询超出了 index 的范围。
所有者为 address(0) 表示全局超出范围的索引。 |
ERC721EnumerableForbiddenBatchMint() error不允许批量铸造。
IERC721Receiverimport "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
任何想要支持来自 ERC-721 资产合约的安全转移的合约的接口。
函数
onERC721Received(address operator, address from, uint256 tokenId, bytes data) → bytes4 external每当通过 operator 从 from 将 IERC721 tokenId token 转移到此合约时,都会调用此函数。
它必须返回其 Solidity 选择器以确认 token 转移。 如果返回任何其他值,或者接收者未实现该接口,则转移将被恢复。
选择器可以在 Solidity 中使用 IERC721Receiver.onERC721Received.selector 获得。
ERC721Pausableimport "@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol";
具有可暂停 token 转移、铸造和销毁的 ERC-721 token。
适用于诸如在评估期结束之前阻止交易的场景,或者在发生重大错误时具有冻结所有 token 转移的紧急开关。
此合约不包括公共的暂停和取消暂停函数。除了继承此合约之外,你还必须定义这两个函数,调用Pausable._pause 和 Pausable._unpause 内部函数,并具有适当的访问控制,例如使用 AccessControl 或 Ownable。如果不这样做,将使合约的暂停机制无法触及,因此无法使用。 |
函数
Pausable
ERC721
事件
Pausable
IERC721
错误
Pausable
IERC721Errors
_update(address to, uint256 tokenId, address auth) → address internal请参阅 ERC721._update。
要求:
ERC721Burnableimport "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
可以销毁(销毁)的 ERC-721 token。
函数
ERC721
[_isAuthorized(owner, spender, tokenId)](https://docs.openzeppelin.com/- **_maxBatchSize()**
ERC721
Events
IERC721
IERC2309
Errors
IERC721Errors
_maxBatchSize() → uint96 internal一批连续 token 的最大大小。这是为了限制链下索引服务的压力,这些服务必须记录每个 token 的一个条目,并且具有防止“非常大”的 token 批次的保护措施。
| 覆盖默认值 5000 不会引起链上问题,但可能导致链下索引服务(包括市场)无法正确支持该资产。 |
_ownerOf(uint256 tokenId) → address internal请参阅 ERC721._ownerOf。覆盖该函数以检查已作为批量的一部分铸造但尚未转移的 token 的顺序所有权结构。
_mintConsecutive(address to, uint96 batchSize) → uint96 internal为 to 批量铸造长度为 batchSize 的 token。 返回批量中铸造的第一个 token 的 token id;如果 batchSize 为 0,则返回到目前为止铸造的连续 id 的数量。
要求:
batchSize 不得大于 _maxBatchSize。
该函数在合约的构造函数中调用(直接或间接调用)。
不会发出 Transfer 事件。 只要它在构造函数内部完成, 这就符合 ERC-721 标准, 这是由该函数强制执行的。 |
不会在接收器上调用 onERC721Received。 |
发出 IERC2309.ConsecutiveTransfer 事件。
_update(address to, uint256 tokenId, address auth) → address internal请参阅 ERC721._update。 覆盖版本,将普通铸造限制在构造之后。
使用 ERC721Consecutive 可以防止在构造期间进行铸造, 而是支持 _mintConsecutive。<br>构造完成后,_mintConsecutive 不再可用, 通过 _update 进行铸造将变为可用。 |
_firstConsecutiveId() → uint96 internal用于在 _nextConsecutiveId 中偏移第一个 token id
ERC721ForbiddenBatchMint() error批量铸造仅限于构造函数。
任何在构造函数之外不发出 IERC721.Transfer 事件的批量铸造都不符合 ERC-721 标准。
ERC721ExceededMaxBatchMint(uint256 batchSize, uint256 maxBatch) error超过了每次批量铸造的最大数量。
ERC721ForbiddenMint() error不允许单独铸造。
ERC721ForbiddenBatchBurn() error不支持批量销毁。
ERC721URIStorageimport "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
具有基于存储的 token URI 管理的 ERC-721 token。
函数
ERC721
Events
IERC4906
IERC721
Errors
IERC721Errors
supportsInterface(bytes4 interfaceId) → bool publictokenURI(uint256 tokenId) → string public_setTokenURI(uint256 tokenId, string _tokenURI) internal将 _tokenURI 设置为 tokenId 的 tokenURI。
ERC721Votesimport "@openzeppelin/contracts/token/ERC721/extensions/ERC721Votes.sol";
ERC-721 的扩展,用于支持由 Votes 实现的投票和委托,其中每个单独的 NFT 计为 1 个投票单元。
Token 在被委托之前不会计为选票,因为必须跟踪选票,这会在每次转移时产生额外的成本。 Token 持有者可以委托给受信任的代表,该代表将决定如何利用选票进行治理决策,或者他们可以委托给自己成为自己的代表。
函数
Votes
Nonces
EIP712
ERC721
[_safeMint(to, tokenId)](https://docs.openzeppelin.com/contracts/5.- name()
ERC2981
Events
IERC721
Errors
IERC721Errors
ERC2981
supportsInterface(bytes4 interfaceId) → bool publicERC721Wrapperimport "@openzeppelin/contracts/token/ERC721/extensions/ERC721Wrapper.sol";
ERC-721 token 合约的扩展,用于支持 token 包装。
用户可以存入和提取“底层 token”,并接收具有匹配 tokenId 的“包装 token”。这与其他模块结合使用非常有用。例如,将此包装机制与 ERC721Votes 结合使用,可以将现有的“基本”ERC-721 包装成治理 token。
功能
ERC721
Events
IERC721
Errors
IERC721Errors
constructor(contract IERC721 underlyingToken) internaldepositFor(address account, uint256[] tokenIds) → bool public允许用户存入底层 token 并铸造相应的 tokenIds。
withdrawTo(address account, uint256[] tokenIds) → bool public允许用户销毁包装的 token 并提取底层 token 的相应 tokenIds。
onERC721Received(address, address from, uint256 tokenId, bytes) → bytes4 public覆盖 IERC721Receiver.onERC721Received 以允许在直接 ERC-721 转移到此合约时进行铸造。
如果附加了数据,它会验证 operator 是否为此合约,因此只有来自 depositFor的可信数据才会被接受。
不能与不安全的转移一起使用(例如 IERC721.transferFrom)。使用 ERC721Wrapper._recover<br>来在这种情况下进行恢复。 |
_recover(address account, uint256 tokenId) → uint256 internal铸造一个包装的 token,以覆盖任何可能被错误转移的 underlyingToken。 如果需要,可以使用访问控制公开的内部函数。
underlying() → contract IERC721 public返回底层 token。
ERC721UnsupportedToken(address token) error接收到的 ERC-721 token 无法包装。
ERC721Holderimport "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
IERC721Receiver 接口的实现。
接受所有 token 转移。
确保合约能够将其 token 与 IERC721.safeTransferFrom、IERC721.approve 或
IERC721.setApprovalForAll 一起使用。
功能
onERC721Received(address, address, uint256, bytes) → bytes4 public查看 IERC721Receiver.onERC721Received。
始终返回 IERC721Receiver.onERC721Received.selector。
ERC721Utilsimport "@openzeppelin/contracts/token/ERC721/utils/ERC721Utils.sol";
该库提供了通用的 ERC-721 实用函数。
查看 ERC-721。
加粗自 v5.1 起可用。
功能
checkOnERC721Received(address operator, address from, address to, uint256 tokenId, bytes data) internal通过在 to 地址上调用 IERC721Receiver.onERC721Received,对提供的 operator 执行接受检查。 operator 通常是启动 token 转移的地址(即 msg.sender)。
如果目标地址不包含代码(即 EOA),则不执行接受调用,并将其视为无操作。
否则,接收者必须实现 IERC721Receiver.onERC721Received 并返回接受 magic value 值以接受转移。
- 原文链接: docs.openzeppelin.com/co...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!