ERC-721 - OpenZeppelin 文档

本文档介绍了与ERC-721非同质化代币标准相关的一系列接口、合约和实用程序,包括核心功能接口IERC721、元数据扩展接口IERC721Metadata、枚举扩展接口IERC721Enumerable和接收器接口IERC721Receiver。

ERC-721

最好在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 提供了所有四个接口的实现:

此外,还有一些其他的扩展:

这组核心合约被设计为非主观的,允许开发人员访问 ERC-721 中的内部函数(例如 _mint),并以他们喜欢的方式将它们公开为外部函数。

核心

IERC721

import "@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,则必须通过 approvesetApprovalForAll 获得批准才能移动此 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,则必须通过 approvesetApprovalForAll 获得批准才能移动此 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,则必须通过 approvesetApprovalForAll 获得批准才能移动此 token。

发出 Transfer 事件。

approve(address to, uint256 tokenId) external

授予 to 权限,将 tokenId token 转移到另一个帐户。 当 token 被转移时,批准将被清除。

一次只能批准一个帐户,因此批准零地址会清除之前的批准。

要求:

  • 调用者必须拥有 token 或成为批准的操作员。

  • tokenId 必须存在。

发出 Approval 事件。

setApprovalForAll(address operator, bool approved) external

批准或删除 operator 作为调用者的操作员。 对于调用者拥有的任何 token,操作员都可以调用 transferFromsafeTransferFrom

要求:

  • operator 不能是零地址。

发出 ApprovalForAll 事件。

getApproved(uint256 tokenId) → address operator external

返回批准用于 tokenId token 的帐户。

要求:

  • tokenId 必须存在。
isApprovedForAll(address owner, address operator) → bool external

返回 operator 是否被允许管理 owner 的所有资产。

请参阅 setApprovalForAll

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 启用或禁用(approvedoperator 来管理其所有资产时发出。

IERC721Metadata

import "@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)。

IERC721Enumerable

import "@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。

ERC721

import "@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 public

请参阅 IERC721Metadata.symbol

tokenURI(uint256 tokenId) → string public

请参阅 IERC721Metadata.tokenURI

_baseURI() → string internal

用于计算 tokenURI 的基本 URI。如果设置,则每个 token 的结果 URI 将是 baseURItokenId 的串联。默认为空,可以在子合约中重写。

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

tokenIdfrom 转移到 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 中完成。

ERC721Enumerable

import "@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) internal
ERC721OutOfBoundsIndex(address owner, uint256 index) error

加粗owner 的 token 查询超出了 index 的范围。

所有者为 address(0) 表示全局超出范围的索引。
ERC721EnumerableForbiddenBatchMint() error

不允许批量铸造。

IERC721Receiver

import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";

任何想要支持来自 ERC-721 资产合约的安全转移的合约的接口。

函数

onERC721Received(address operator, address from, uint256 tokenId, bytes data) → bytes4 external

每当通过 operatorfromIERC721 tokenId token 转移到此合约时,都会调用此函数。

它必须返回其 Solidity 选择器以确认 token 转移。 如果返回任何其他值,或者接收者未实现该接口,则转移将被恢复。

选择器可以在 Solidity 中使用 IERC721Receiver.onERC721Received.selector 获得。

扩展

ERC721Pausable

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol";

具有可暂停 token 转移、铸造和销毁的 ERC-721 token。

适用于诸如在评估期结束之前阻止交易的场景,或者在发生重大错误时具有冻结所有 token 转移的紧急开关。

此合约不包括公共的暂停和取消暂停函数。除了继承此合约之外,你还必须定义这两个函数,调用Pausable._pausePausable._unpause 内部函数,并具有适当的访问控制,例如使用 AccessControlOwnable。如果不这样做,将使合约的暂停机制无法触及,因此无法使用。

函数

Pausable

ERC721

事件

Pausable

IERC721

错误

Pausable

IERC721Errors

_update(address to, uint256 tokenId, address auth) → address internal

请参阅 ERC721._update

要求:

  • 合约不得暂停。

ERC721Burnable

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";

可以销毁(销毁)的 ERC-721 token。

函数

ERC721

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

不支持批量销毁。

ERC721URIStorage

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

具有基于存储的 token URI 管理的 ERC-721 token。

函数

ERC721

Events

IERC4906

IERC721

Errors

IERC721Errors

supportsInterface(bytes4 interfaceId) → bool public

请参阅 IERC165.supportsInterface

tokenURI(uint256 tokenId) → string public

请参阅 IERC721Metadata.tokenURI

_setTokenURI(uint256 tokenId, string _tokenURI) internal

_tokenURI 设置为 tokenId 的 tokenURI。

发出 IERC4906.MetadataUpdate

ERC721Votes

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Votes.sol";

ERC-721 的扩展,用于支持由 Votes 实现的投票和委托,其中每个单独的 NFT 计为 1 个投票单元。

Token 在被委托之前不会计为选票,因为必须跟踪选票,这会在每次转移时产生额外的成本。 Token 持有者可以委托给受信任的代表,该代表将决定如何利用选票进行治理决策,或者他们可以委托给自己成为自己的代表。

函数

Votes

Nonces

EIP712

ERC721

ERC2981

Events

IERC721

Errors

IERC721Errors

ERC2981

supportsInterface(bytes4 interfaceId) → bool public

查看 IERC165.supportsInterface

ERC721Wrapper

import "@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) internal
depositFor(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 无法包装。

Utilities

ERC721Holder

import "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";

IERC721Receiver 接口的实现。

接受所有 token 转移。 确保合约能够将其 token 与 IERC721.safeTransferFromIERC721.approveIERC721.setApprovalForAll 一起使用。

功能

onERC721Received(address, address, uint256, bytes) → bytes4 public

查看 IERC721Receiver.onERC721Received

始终返回 IERC721Receiver.onERC721Received.selector

ERC721Utils

import "@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 值以接受转移。

← ERC 20

ERC 1155 →

  • 原文链接: docs.openzeppelin.com/co...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
OpenZeppelin
OpenZeppelin
江湖只有他的大名,没有他的介绍。