本文档介绍了与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 ),并以他们喜欢的方式将它们公开为外部函数。 |
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
,则必须通过 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
来管理其所有资产时发出。
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
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
中完成。
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)
internalERC721OutOfBoundsIndex(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每当通过 operator
从 from
将 IERC721
tokenId
token 转移到此合约时,都会调用此函数。
它必须返回其 Solidity 选择器以确认 token 转移。 如果返回任何其他值,或者接收者未实现该接口,则转移将被恢复。
选择器可以在 Solidity 中使用 IERC721Receiver.onERC721Received.selector
获得。
ERC721Pausable
import "@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
。
要求:
ERC721Burnable
import "@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不支持批量销毁。
ERC721URIStorage
import "@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。
ERC721Votes
import "@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
publicERC721Wrapper
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)
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 无法包装。
ERC721Holder
import "@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
。
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 值以接受转移。
- 原文链接: docs.openzeppelin.com/co...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!