ERC721
此模块提供与 ERC721 合约相关的接口、预设和实用程序。
提示:有关 ERC721 的概述,请阅读我们的 ERC721 指南。
核心
IERC721
use openzeppelin_token::erc721::interface::IERC721;
如 EIP721 中定义的 IERC721 标准的接口。
0x33eb2f84c309543403fd69f0d0f363781ef06ef6faeb0131ff16ea3175bd943
safe_transfer_from(from: ContractAddress, to: ContractAddress, token_id: u256, data: Span<felt252>)
external
将 token_id
的所有权从 from
转移到 to
,首先检查 to
是否知道 ERC721 协议,以防止 Token 永远被锁定。
有关合约如何传递它们对 ERC721 协议的了解的信息,请参阅 接收 Token。
发出一个 Transfer 事件。
transfer_from(from: ContractAddress, to: ContractAddress, token_id: u256)
external
将 token_id
的所有权从 from
转移到 to
。
请注意,调用者有责任确认接收者有能力接收 ERC721 转移,否则它们可能会永久丢失。 使用 IERC721::safe_transfer_from 可以防止token丢失,但调用者必须理解这会增加一个外部调用,可能会产生重入漏洞。
发出一个 Transfer 事件。
set_approval_for_all(operator: ContractAddress, approved: bool)
external
启用或禁用对 operator
的授权,以管理调用者的所有资产。
发出一个 ApprovalForAll 事件。
is_approved_for_all(owner: ContractAddress, operator: ContractAddress) -> bool
external
查询 operator
是否为 owner
的授权operator。
Approval(owner: ContractAddress, approved: ContractAddress, token_id: u256)
event
当 owner
启用 approved
以管理 token_id
Token时发出。
IERC721Metadata
use openzeppelin_token::erc721::interface::IERC721Metadata;
EIP721 中可选元数据函数的接口。
0xabbcd595a567dce909050a1038e055daccb3c42af06f0add544fa90ee91f25
ERC721Component
use openzeppelin_token::erc721::ERC721Component;
实现了 IERC721 和 IERC721Metadata 的 ERC721 组件。
注意:实施 SRC5Component 是本组件需要实现的要求。
注意:请参阅 Hooks 以了解 Hook 的使用方式。
Hooks
Hooks 是一些函数,其实现可以扩展组件源代码的功能。每个 使用 ERC721Component 的合约都应提供 ERC721HooksTrait 的实现。对于基本 Token合约, 必须提供没有逻辑的空实现。
提示:您可以使用 openzeppelin_token::erc721::ERC721HooksEmptyImpl
,它已作为库的一部分提供
为此目的。
before_update(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress)
hook
在 update 函数的开头,在任何其他逻辑之前执行的函数。
after_update(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress)
hook
在 update 函数末尾执行的函数。
balance_of(self: @ContractState, account: ContractAddress) → u256
external
请参阅 IERC721::balance_of。
owner_of(self: @ContractState, token_id: u256) → ContractAddress
external
请参阅 IERC721::owner_of。
要求:
-
token_id
存在。
safe_transfer_from(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256, data: Span<felt252>)
external
要求:
-
调用者要么获得批准,要么是
token_id
的所有者。 -
to
不是零地址。 -
from
不是零地址。 -
token_id
存在。 -
to
要么是账户合约,要么支持 IERC721Receiver 接口。
transfer_from(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256)
external
要求:
-
调用者要么获得批准,要么是
token_id
的所有者。 -
to
不是零地址。 -
from
不是零地址。 -
token_id
存在。
approve(ref self: ContractState, to: ContractAddress, token_id: u256)
external
请参阅 IERC721::approve。
要求:
-
调用者要么是被批准的operator,要么是
token_id
的所有者。 -
to
不能是 Token所有者或零地址。 -
token_id
存在。
set_approval_for_all(ref self: ContractState, operator: ContractAddress, approved: bool)
external
要求:
-
operator
不是零地址。
is_approved_for_all(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool
external
token_uri(self: @ContractState, token_id: u256) -> ByteArray
external
返回 token_id
Token的 Uniform Resource Identifier (URI)。
如果设置了基本 URI,则每个 Token 的结果 URI 将是基本 URI 和 Token ID 的串联。
例如,基本 URI https://token-cdn-domain/
将作为 https://token-cdn-domain/123
返回 Token ID 123
。
如果未为 token_id
设置 URI,则返回值将为空 ByteArray
。
safeTransferFrom(ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenId: u256, data: Span<felt252>)
external
transferFrom(ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenId: u256)
external
isApprovedForAll(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool
external
initializer(ref self: ContractState, name: ByteArray, symbol: ByteArray, base_uri: ByteArray)
internal
通过设置 Token名称和符号来初始化合约。 这应该在合约的构造函数中使用。
警告:大多数 ERC721 合约都公开了 IERC721Metadata 接口, 这就是此初始化程序旨在支持的。 如果合约未公开 IERC721Metadata 接口, 意味着该 Token没有名称、符号或 URI, 则合约必须改用 initializer_no_metadata 在构造函数中。 不遵守这些说明可能会导致意外问题,尤其是在 用户界面。
initializer_no_metadata(ref self: ContractState)
internal
通过仅注册 IERC721 接口来初始化没有元数据的合约。
警告:此初始化程序应仅在非常特殊的情况下在构造期间使用,即合约未公开 IERC721Metadata 接口。 使用此初始化程序初始化合约意味着 Token将没有名称、符号或 URI。
transfer(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256)
internal
将 token_id
从 from
转移到 to
。
没有访问限制的内部函数。
警告:如果 to
不知道 ERC721 协议,则此方法可能会导致 Token丢失。
要求:
-
to
不是零地址。 -
from
是 Token所有者。 -
token_id
存在。
发出一个 Transfer 事件。
mint(ref self: ContractState, to: ContractAddress, token_id: u256)
internal
铸造 token_id
并将其转移到 to
。
没有访问限制的内部函数。
警告:如果 to
不知道 ERC721 协议,则此方法可能会导致 Token丢失。
要求:
-
to
不是零地址。 -
token_id
不存在。
发出一个 Transfer 事件。
safe_transfer(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256, data: Span<felt252>)
internal
如果 to
是账户或 IERC721Receiver
,则将 token_id
的所有权从 from
转移。
data
是附加数据,它没有指定的格式,并在 IERC721Receiver::on_erc721_received
中转发到 to
。
警告:此方法会向接收者合约发出外部调用,这可能导致重入漏洞。
要求:
-
to
不能是零地址。 -
from
必须是 Token所有者。 -
token_id
存在。 -
to
要么是账户合约,要么支持IERC721Receiver
接口。
发出一个 Transfer 事件。
safe_mint(ref self: ContractState, to: ContractAddress, token_id: u256, data: Span<felt252>)
internal
如果 to
是账户或 IERC721Receiver
,则铸造 token_id
。
data
是附加数据,它没有指定的格式,并在 IERC721Receiver::on_erc721_received
中转发到 to
。
警告:此方法会向接收者合约发出外部调用,这可能导致重入漏洞。
要求:
-
token_id
不存在。 -
to
要么是账户合约,要么支持IERC721Receiver
接口。
发出一个 Transfer 事件。
burn(ref self: ContractState, token_id: u256)
internal
销毁 token_id
。Token被烧毁时,批准被清除。
此内部函数不检查调用者是否被授权 操作 Token。
要求:
-
token_id
存在。
发出一个 Transfer 事件。
update(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress)
internal
将其当前所有者转移到 token_id
到 to
,或者,如果当前所有者
(或 to
)是零地址,则进行铸造(或销毁)。返回更新之前 token_id
的所有者。
auth
参数是可选的。如果传递的值为非零值,则此函数将检查
auth
是 Token的所有者,还是被批准操作 Token(由所有者)。
This function can be extended by using the |
发出一个 Transfer 事件。
注意:可以使用 ERC721HooksTrait
扩展功能,在转移、铸造或销毁前后添加功能。
_owner_of(self: @ContractState, token_id: felt252) -> ContractAddress
internal
返回 token_id
的所有者地址的内部函数。
IERC721Receiver
use openzeppelin_token::erc721::interface::IERC721Receiver;
支持接收 safe_transfer_from
transfers 的合约接口。
0x3a0dff5f70d80458ad14ae37bb182a728e3c8cdda0402a5daa86620bdf910bc
on_erc721_received(operator: ContractAddress, from: ContractAddress, token_id: u256, data: Span<felt252>) -> felt252
external
每当一个 IERC721 token_id
token 通过 IERC721::safe_transfer_from 由 operator
从 from
转移到这个非账户合约时,此函数被调用。
ERC721ReceiverComponent
use openzeppelin_token::erc721::ERC721ReceiverComponent;
实现 IERC721Receiver 的 ERC721Receiver 组件。
实施 SRC5Component 是本组件需要实现的要求。 |
on_erc721_received(self: @ContractState, operator: ContractAddress, from: ContractAddress, token_id: u256, data Span<felt252>) -> felt252
external
返回 IERC721Receiver
接口 ID。
Extensions
IERC721Enumerable
EIP721 中可选的可枚举函数接口。
0x16bc0f502eeaf65ce0b3acb5eea656e2f26979ce6750e8502a82f377e538c87
token_by_index(index: u256) -> u256
external
返回合约存储的所有 token 中给定 index
处的 token id。
与 IERC721Enumerable::total_supply 一起使用可以枚举所有 token。
token_of_owner_by_index(owner: ContractAddress, index: u256) -> u256
external
返回 owner
拥有的 token 列表中给定 index
处的 token id。
与 IERC721::balance_of 一起使用可以枚举所有 owner
的 token。
ERC721EnumerableComponent
use openzeppelin_token::erc721::extensions::ERC721EnumerableComponent;
EIP 中定义的 ERC721 扩展,它增加了合约中所有 token id 以及每个账户拥有的所有 token id 的可枚举性。 此扩展允许合约发布其整个 NFT 列表并使其可被发现。
实现 ERC721Component 是实现此组件的先决条件。 |
为了正确跟踪 token id,此扩展要求在每次转移、铸造或销毁操作之前调用 ERC721EnumerableComponent::before_update 函数。 为此,必须使用 ERC721HooksTrait::before_update hook。 以下是如何在合约中实现 hook:
#[starknet::contract]
mod ERC721EnumerableContract {
(...)
component!(path: ERC721Component, storage: erc721, event: ERC721Event);
component!(path: ERC721EnumerableComponent, storage: erc721_enumerable, event: ERC721EnumerableEvent);
component!(path: SRC5Component, storage: src5, event: SRC5Event);
impl ERC721HooksImpl of ERC721Component::ERC721HooksTrait<ContractState> {
fn before_update(
ref self: ERC721Component::ComponentState<ContractState>,
to: ContractAddress,
token_id: u256,
auth: ContractAddress
) {
let mut contract_state = self.get_contract_mut();
contract_state.erc721_enumerable.before_update(to, token_id);
}
}
}
token_of_owner_by_index(self: @ContractState, owner: ContractAddress, index: u256) → u256
external
要求:
-
index
小于owner
的 token 余额。 -
owner
不是零地址。
before_update(ref self: ContractState, to: ContractAddress, token_id: u256)
internal
更新所有权和 token 跟踪数据结构。
当 token 被铸造(或销毁)时,token_id
被添加到(或从)token 跟踪结构中。
当 token 被转移、铸造或销毁时,所有权跟踪数据结构会反映 token_id
所有权的变化。
这必须添加到实现合约的 ERC721HooksTrait::before_update hook 中。
all_tokens_of_owner(self: @ContractState, owner: ContractAddress) → Span<u256>
internal
返回指定 owner
拥有的所有 token id 的列表。
此函数提供了比调用 ERC721::balance_of
并使用 ERC721Enumerable::token_of_owner_by_index
迭代 token 更有效的替代方案。
要求:
-
owner
不是零地址。
_add_token_to_owner_enumeration(ref self: ContractState, to: ContractAddress, token_id: u256)
internal
将 token 添加到此扩展的所有权跟踪数据结构。
_add_token_to_all_tokens_enumeration(ref self: ContractState, token_id: u256)
internal
将 token 添加到此扩展的 token 跟踪数据结构。
Presets
ERC721Upgradeable
use openzeppelin_presets::ERC721Upgradeable;
利用 ERC721Component 的可升级 ERC721 合约。
0x06d1cd9d8c2008d36bd627e204c3e5f565d4e632de4e50b36d2388c7ba7a64ce