ERC721
This module provides interfaces, presets, and utilities related to ERC721 contracts.
For an overview of ERC721, read our ERC721 guide.
Interfaces
The interfaces documented here are provided by the openzeppelin_interfaces package version 2.2.0.
use openzeppelin_interfaces::erc721::IERC721;Interface of the IERC721 standard as defined in EIP721.
0x33eb2f84c309543403fd69f0d0f363781ef06ef6faeb0131ff16ea3175bd943Functions
balance_of(account)owner_of(token_id)safe_transfer_from(from, to, token_id, data)transfer_from(from, to, token_id)approve(to, token_id)set_approval_for_all(operator, approved)get_approved(token_id)is_approved_for_all(owner, operator)
Events
Approval(owner, approved, token_id)ApprovalForAll(owner, operator, approved)Transfer(from, to, token_id)
Functions
balance_of(account: ContractAddress) → u256
external
#Returns the number of NFTs owned by account.
owner_of(token_id: u256) → ContractAddress
external
#Returns the owner address of token_id.
safe_transfer_from(from: ContractAddress, to: ContractAddress, token_id: u256, data: Span<felt252>)
external
#Transfer ownership of token_id from from to to, checking first that to is aware of the ERC721 protocol to prevent tokens being locked forever. For information regarding how contracts communicate their awareness of the ERC721 protocol, see Receiving Tokens.
Emits a Transfer event.
transfer_from(from: ContractAddress, to: ContractAddress, token_id: u256)
external
#Transfer ownership of token_id from from to to.
Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 transfers or else they may be permanently lost. Usage of IERC721::safe_transfer_from prevents loss, though the caller must understand this adds an external call which potentially creates a reentrancy vulnerability.
Emits a Transfer event.
set_approval_for_all(operator: ContractAddress, approved: bool)
external
#Enable or disable approval for operator to manage all of the caller's assets.
Emits an ApprovalForAll event.
get_approved(token_id: u256) -> u256
external
#Returns the address approved for token_id.
is_approved_for_all(owner: ContractAddress, operator: ContractAddress) -> bool
external
#Query if operator is an authorized operator for owner.
Events
Approval(owner: ContractAddress, approved: ContractAddress, token_id: u256)
event
#Emitted when owner enables approved to manage the token_id token.
ApprovalForAll(owner: ContractAddress, operator: ContractAddress, approved: bool)
event
#Emitted when owner enables or disables operator to manage the token_id token.
Transfer(from: ContractAddress, to: ContractAddress, token_id: u256)
event
#Emitted when token_id token is transferred from from to to.
use openzeppelin_interfaces::erc721::IERC721Metadata;Interface for the optional metadata functions in EIP721.
0xabbcd595a567dce909050a1038e055daccb3c42af06f0add544fa90ee91f25Functions
Functions
name() -> ByteArray
external
#Returns the NFT name.
symbol() -> ByteArray
external
#Returns the NFT ticker symbol.
token_uri(token_id: u256) -> ByteArray
external
#Returns the Uniform Resource Identifier (URI) for the token_id token. If the URI is not set for token_id, the return value will be an empty ByteArray.
use openzeppelin_interfaces::erc721::IERC721Receiver;Interface for contracts that support receiving safe_transfer_from transfers.
0x3a0dff5f70d80458ad14ae37bb182a728e3c8cdda0402a5daa86620bdf910bcFunctions
Functions
on_erc721_received(operator: ContractAddress, from: ContractAddress, token_id: u256, data: Span<felt252>) -> felt252
external
#Whenever an IERC721 token_id token is transferred to this non-account contract via IERC721::safe_transfer_from by operator from from, this function is called.
Interface for the optional enumerable functions in EIP721.
0x16bc0f502eeaf65ce0b3acb5eea656e2f26979ce6750e8502a82f377e538c87Functions
Functions
total_supply() -> u256
external
#Returns the total amount of tokens stored by the contract.
token_by_index(index: u256) -> u256
external
#Returns a token id at a given index of all the tokens stored by the contract. Use along with IERC721Enumerable::total_supply to enumerate all tokens.
token_of_owner_by_index(owner: ContractAddress, index: u256) -> u256
external
#Returns the token id owned by owner at a given index of its token list. Use along with IERC721::balance_of to enumerate all of owner's tokens.
use openzeppelin_interfaces::erc721::IERC721ReceiverMut;Receiver interface with the same external ABI as IERC721Receiver, but with mutable state access for implementations that need to update storage while accepting a token.
Functions
on_erc721_received(ref self: TState, operator: ContractAddress, from: ContractAddress, token_id: u256, data: Span<felt252>) → felt252
external
#Handles an ERC721 safe-transfer callback with mutable contract state. A successful implementation returns the IERC721Receiver interface ID.
use openzeppelin_interfaces::erc721::IERC721Wrapper;Interface for an ERC721 token whose token IDs are backed by matching token IDs in another ERC721 contract.
Functions
Functions
underlying() → ContractAddress
external
#Returns the address of the underlying ERC721 token.
deposit_for(receiver: ContractAddress, token_ids: Span<u256>) → bool
external
#Deposits the underlying token_ids and mints matching wrapped tokens to receiver.
withdraw_to(receiver: ContractAddress, token_ids: Span<u256>) → bool
external
#Burns the caller's wrapped token_ids and transfers the matching underlying tokens to receiver.
Core
use openzeppelin_token::erc721::ERC721Component;ERC721 component implementing IERC721 and IERC721Metadata.
Implementing SRC5Component is a requirement for this component to be implemented.
See Hooks to understand how are hooks used.
Ownership
Core ownership lookup delegates to ERC721TokenOwnerTrait. All ERC721 implementations must select an ownership implementation.
ERC721TokenOwnerTrait trait
trait
#use openzeppelin_token::erc721::ERC721Component::ERC721TokenOwnerTrait;Defines owner_of(self: @ComponentState, token_id: u256) → ContractAddress for internal ownership resolution.
Custom implementations must preserve the invariant that balance_of(account) equals the number of token IDs resolved to account. Use increase_balance when an extension establishes ownership outside the core ownership map. Avoid external calls from this trait because ownership checks occur throughout state-changing operations and external calls can introduce reentrancy.
ERC721OwnerOfDefaultImpl impl
impl
#use openzeppelin_token::erc721::ERC721OwnerOfDefaultImpl;Resolves ownership from the core ERC721_owners storage map. It returns the zero address when the token does not exist.
ConsecutiveERC721TokenOwnerImpl impl
impl
#use openzeppelin_token::erc721::ERC721Component::ConsecutiveERC721TokenOwnerImpl;Resolves ordinary ownership from core storage and unresolved consecutive token IDs from ERC721ConsecutiveComponent, excluding sequential tokens recorded as burned.
Token URI
The metadata implementation delegates token URI resolution to ERC721TokenURITrait.
ERC721TokenURITrait trait
trait
#use openzeppelin_token::erc721::ERC721Component::ERC721TokenURITrait;Defines token_uri(self: @ComponentState, token_id: u256) → ByteArray, which is used by ERC721MetadataImpl.
ERC721TokenURIDefaultImpl impl
impl
#use openzeppelin_token::erc721::ERC721TokenURIDefaultImpl;Requires token_id to exist. Returns an empty ByteArray when the base URI is empty; otherwise returns the base URI concatenated with the decimal token ID.
Hooks
ERC721HooksTrait
Embeddable Mixin Implementations
ERC721MixinImpl
Embeddable Implementations
ERC721Impl
balance_of(self, account)owner_of(self, token_id)safe_transfer_from(self, from, to, token_id, data)transfer_from(self, from, to, token_id)approve(self, to, token_id)set_approval_for_all(self, operator, approved)get_approved(self, token_id)is_approved_for_all(self, owner, operator)
ERC721MetadataImpl
ERC721CamelOnlyImpl
balanceOf(self, account)ownerOf(self, tokenId)safeTransferFrom(self, from, to, tokenId, data)transferFrom(self, from, to, tokenId)setApprovalForAll(self, operator, approved)getApproved(self, tokenId)isApprovedForAll(self, owner, operator)
ERC721MetadataCamelOnlyImpl
SRC5Impl
Internal functions
InternalImpl
initializer(self, name, symbol, base_uri)initializer_no_metadata(self)exists(self, token_id)transfer(self, from, to, token_id)mint(self, to, token_id)safe_transfer(self, from, to, token_id, data)safe_mint(self, to, token_id, data)burn(self, token_id)increase_balance(self, account, value)update(self, to, token_id, auth)_owner_of(self, token_id)_require_owned(self, token_id)_approve(self, to, token_id, auth)_approve_with_optional_event(self, to, token_id, auth, emit_event)_set_approval_for_all(self, owner, operator, approved)_set_base_uri(self, base_uri)_base_uri(self)_is_authorized(self, owner, spender, token_id)_check_authorized(self, owner, spender, token_id)
Events
IERC721
Approval(owner, approved, token_id)ApprovalForAll(owner, operator, approved)Transfer(from, to, token_id)
Hooks
Hooks are functions which implementations can extend the functionality of the component source code. Every contract using ERC721Component is expected to provide an implementation of the ERC721HooksTrait. For basic token contracts, an empty implementation with no logic must be provided.
You can use openzeppelin_token::erc721::ERC721HooksEmptyImpl which is already available as part of the library for this purpose.
Embeddable functions
balance_of(self: @ContractState, account: ContractAddress) → u256
external
#See IERC721::balance_of.
owner_of(self: @ContractState, token_id: u256) → ContractAddress
external
#safe_transfer_from(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256, data: Span<felt252>)
external
#See IERC721::safe_transfer_from.
Requirements:
- Caller is either approved or the
token_idowner. tois not the zero address.fromis not the zero address.token_idexists.tois either an account contract or supports the IERC721Receiver interface.
transfer_from(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256)
external
#Requirements:
- Caller either approved or the
token_idowner. tois not the zero address.fromis not the zero address.token_idexists.
approve(ref self: ContractState, to: ContractAddress, token_id: u256)
external
#See IERC721::approve.
Requirements:
- The caller is either an approved operator or the
token_idowner. tocannot be the token owner or the zero address.token_idexists.
set_approval_for_all(ref self: ContractState, operator: ContractAddress, approved: bool)
external
#get_approved(self: @ContractState, token_id: u256) -> u256
external
#is_approved_for_all(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool
external
#name(self: @ContractState) -> ByteArray
external
#symbol(self: @ContractState) -> ByteArray
external
#token_uri(self: @ContractState, token_id: u256) -> ByteArray
external
#Returns the Uniform Resource Identifier (URI) for the token_id token. If a base URI is set, the resulting URI for each token will be the concatenation of the base URI and the token ID. For example, the base URI https://token-cdn-domain/ would be returned as https://token-cdn-domain/123 for token ID 123.
If the URI is not set for token_id, the return value will be an empty ByteArray.
balanceOf(self: @ContractState, account: ContractAddress) -> u256
external
#ownerOf(self: @ContractState, tokenId: u256) -> ContractAddress
external
#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
#setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool)
external
#getApproved(self: @ContractState, tokenId: u256) -> ContractAddress
external
#isApprovedForAll(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool
external
#tokenURI(self: @ContractState, tokenId: u256) -> ByteArray
external
#Internal functions
initializer(ref self: ContractState, name: ByteArray, symbol: ByteArray, base_uri: ByteArray)
internal
#Initializes the contract by setting the token name and symbol. This should be used inside the contract's constructor.
Most ERC721 contracts expose the IERC721Metadata interface which is what this initializer is meant to support. If the contract DOES NOT expose the IERC721Metadata interface, meaning the token does not have a name, symbol, or URI, the contract must instead use initializer_no_metadata in the constructor. Failure to abide by these instructions can lead to unexpected issues especially with UIs.
initializer_no_metadata(ref self: ContractState)
internal
#Initializes the contract with no metadata by registering only the IERC721 interface.
This initializer should ONLY be used during construction in the very specific instance when the contract does NOT expose the IERC721Metadata interface. Initializing a contract with this initializer means that tokens will not have a name, symbol, or URI.
transfer(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256)
internal
#Transfers token_id from from to to.
Internal function without access restriction.
This method may lead to the loss of tokens if to is not aware of the ERC721 protocol.
Requirements:
tois not the zero address.fromis the token owner.token_idexists.
Emits a Transfer event.
mint(ref self: ContractState, to: ContractAddress, token_id: u256)
internal
#Mints token_id and transfers it to to. Internal function without access restriction.
This method may lead to the loss of tokens if to is not aware of the ERC721 protocol.
Requirements:
tois not the zero address.token_iddoes not exist.
Emits a Transfer event.
safe_transfer(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256, data: Span<felt252>)
internal
#Transfers ownership of token_id from from if to is either an account or IERC721Receiver.
data is additional data, it has no specified format and is forwarded in IERC721Receiver::on_erc721_received to to.
This method makes an external call to the recipient contract, which can lead to reentrancy vulnerabilities.
Requirements:
tocannot be the zero address.frommust be the token owner.token_idexists.tois either an account contract or supports theIERC721Receiverinterface.
Emits a Transfer event.
safe_mint(ref self: ContractState, to: ContractAddress, token_id: u256, data: Span<felt252>)
internal
#Mints token_id if to is either an account or IERC721Receiver.
data is additional data, it has no specified format and is forwarded in IERC721Receiver::on_erc721_received to to.
This method makes an external call to the recipient contract, which can lead to reentrancy vulnerabilities.
Requirements:
token_iddoes not exist.tois either an account contract or supports theIERC721Receiverinterface.
Emits a Transfer event.
increase_balance(ref self: ContractState, account: ContractAddress, value: u128)
internal
#Increases account's balance without writing token ownership. This unsafe primitive supports extensions whose ERC721TokenOwnerTrait implementation establishes ownership outside the core map.
The caller must keep the balance and ownership invariant consistent. value is limited to u128 to protect the u256 balance from overflow across increments.
update(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress) → ContractAddress
internal
#Transfers token_id from its current owner to to, or alternatively mints (or burns) if the current owner (or to) is the zero address. Returns the owner of the token_id before the update.
The auth argument is optional. If the value passed is non-zero, then this function will check that auth is either the owner of the token, or approved to operate on the token (by the owner).
Emits a Transfer event.
This function can be extended using the ERC721HooksTrait, to add functionality before and/or after the transfer, mint, or burn.
_owner_of(self: @ContractState, token_id: u256) → ContractAddress
internal
#Internal function that returns the owner address of token_id.
_approve(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress)
internal
#Approve to to operate on token_id
The auth argument is optional. If the value passed is non-zero, then this function will check that auth is either the owner of the token, or approved to operate on all tokens held by this owner.
Emits an Approval event.
_approve_with_optional_event(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress, emit_event: bool)
internal
#Variant of _approve with an optional flag to enable or disable the Approval event. The event is not emitted in the context of transfers.
If auth is zero and emit_event is false, this function will not check that the token exists.
Requirements:
- if
authis non-zero, it must be either the owner of the token or approved to operate on all of its tokens.
May emit an Approval event.
_set_base_uri(ref self: ContractState, base_uri: ByteArray)
internal
#Internal function that sets the base_uri.
Events
Approval(owner: ContractAddress, approved: ContractAddress, token_id: u256)
event
#See IERC721::Approval.
ApprovalForAll(owner: ContractAddress, operator: ContractAddress, approved: bool)
event
#Transfer(from: ContractAddress, to: ContractAddress, token_id: u256)
event
#See IERC721::Transfer.
use openzeppelin_token::erc721::ERC721ReceiverComponent;ERC721Receiver component implementing IERC721Receiver.
Implementing SRC5Component is a requirement for this component to be implemented.
Embeddable Mixin Implementations
ERCReceiverMixinImpl
Embeddable Implementations
ERC721ReceiverImpl
ERC721ReceiverCamelImpl
Internal Functions
InternalImpl
Embeddable functions
on_erc721_received(self: @ContractState, operator: ContractAddress, from: ContractAddress, token_id: u256, data Span<felt252>) -> felt252
external
#Returns the IERC721Receiver interface ID.
onERC721Received(self: @ContractState, operator: ContractAddress, from: ContractAddress, token_id: u256, data Span<felt252>) -> felt252
external
#Internal functions
initializer(ref self: ContractState)
internal
#Registers the IERC721Receiver interface ID as supported through introspection.
Extensions
use openzeppelin_token::erc721::extensions::ERC721EnumerableComponent;Extension of ERC721 as defined in the EIP that adds enumerability of all the token ids in the contract as well as all token ids owned by each account. This extension allows contracts to publish their entire list of NFTs and make them discoverable.
Implementing ERC721Component is a requirement for this component to be implemented.
To properly track token ids, this extension requires that the ERC721EnumerableComponent::before_update function is called before every transfer, mint, or burn operation. For this, the ERC721HooksTrait::before_update hook must be used. Here's how the hook should be implemented in a contract:
#[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);
}
}
}Embeddable Implementations
ERC721EnumerableImpl
Internal functions
InternalImpl
initializer(self)before_update(self, to, token_id)all_tokens_of_owner(self, owner)_add_token_to_owner_enumeration(self, to, token_id)_add_token_to_all_tokens_enumeration(self, token_id)_remove_token_from_owner_enumeration(self, from, token_id)_remove_token_from_all_tokens_enumeration(self, token_id)
Embeddable functions
total_supply(self: @ContractState) → u256
external
#Returns the total number of tokens tracked by the enumerable extension.
token_by_index(self: @ContractState, index: u256) → u256
external
#token_of_owner_by_index(self: @ContractState, owner: ContractAddress, index: u256) → u256
external
#See IERC721Enumerable::token_of_owner_by_index.
Requirements:
indexis less thanowner's token balance.owneris not the zero address.
Internal functions
initializer(ref self: ContractState)
internal
#Registers the IERC721Enumerable interface ID as supported through introspection.
before_update(ref self: ContractState, to: ContractAddress, token_id: u256)
internal
#Updates the ownership and token-tracking data structures.
When a token is minted (or burned), token_id is added to (or removed from) the token-tracking structures.
When a token is transferred, minted, or burned, the ownership-tracking data structures reflect the change in ownership of token_id.
This must be added to the implementing contract's ERC721HooksTrait::before_update hook.
all_tokens_of_owner(self: @ContractState, owner: ContractAddress) → Span<u256>
internal
#Returns a list of all token ids owned by the specified owner. This function provides a more efficient alternative to calling ERC721::balance_of and iterating through tokens with ERC721Enumerable::token_of_owner_by_index.
Requirements:
owneris not the zero address.
_add_token_to_owner_enumeration(ref self: ContractState, to: ContractAddress, token_id: u256)
internal
#Adds token to this extension's ownership-tracking data structures.
_add_token_to_all_tokens_enumeration(ref self: ContractState, token_id: u256)
internal
#Adds token to this extension's token-tracking data structures.
_remove_token_from_owner_enumeration(ref self: ContractState, from: ContractAddress, token_id: u256)
internal
#Removes a token from this extension's ownership-tracking data structures.
This has 0(1) time complexity but alters the indexed order of owned tokens by swapping token_id and the index thereof with the last token id and the index thereof e.g. removing 1 from [1, 2, 3, 4] results in [4, 2, 3].
_remove_token_from_all_tokens_enumeration(ref self: ContractState, token_id: u256)
internal
#Removes token_id from this extension's token-tracking data structures.
This has 0(1) time complexity but alters the indexed order by swapping token_id and the index thereof with the last token id and the index thereof e.g. removing 1 from [1, 2, 3, 4] results in [4, 2, 3].
use openzeppelin_token::erc721::extensions::{DefaultConfig, ERC721ConsecutiveComponent};Implementation of the ERC-2309 consecutive transfer extension for batch minting sequential token IDs during construction.
Use ConsecutiveERC721TokenOwnerImpl as the core ownership implementation, and forward both core ERC721 hooks to this component's before_update and after_update functions.
Consecutive batch mints do not call ERC721Component::update, the ERC721 hooks, receiver callbacks, or individual Transfer events. For that reason, this component is incompatible with ERC721EnumerableComponent, whose accounting depends on seeing each token through a hook.
Constants and Configuration
Functions
Internal Implementations
Events
Constants and Configuration
DEFAULT_MAX_BATCH_SIZE: u64
constant
#The default maximum consecutive mint batch size: 5000.
DEFAULT_FIRST_CONSECUTIVE_ID: u64
constant
#The default first consecutive token ID: 0.
ImmutableConfig trait
trait
#Defines MAX_BATCH_SIZE: u64 and FIRST_CONSECUTIVE_ID: u64. Increasing the maximum above 5000 can exceed the batch sizes supported by off-chain indexers and marketplaces.
DefaultConfig impl
impl
#Storage
ERC721Consecutive_sequential_ownership: Trace
storage
#Ownership checkpoints for consecutive token ranges.
ERC721Consecutive_sequential_burn: BitMap
storage
#Bitmap recording burned tokens from consecutive ranges.
Functions
is_constructor_scope() → bool
function
#Returns whether the current entry point selector is constructor.
InternalImpl
max_batch_size(self)first_consecutive_id(self)next_consecutive_id(self)is_sequentially_burned(self, token_id)sequential_owner_of(self, token_id)mint_consecutive(self, to, batch_size)before_update(self, to, token_id, auth)after_update(self, to, token_id, auth)
max_batch_size(self: @ContractState) → u64
internal
#Returns ImmutableConfig::MAX_BATCH_SIZE.
first_consecutive_id(self: @ContractState) → u64
internal
#Returns ImmutableConfig::FIRST_CONSECUTIVE_ID.
next_consecutive_id(self: @ContractState) → u64
internal
#Returns the next token ID available for mint_consecutive.
is_sequentially_burned(self: @ContractState, token_id: u256) → bool
internal
#Returns whether token_id from a consecutive range has been burned.
sequential_owner_of(self: @ContractState, token_id: u256) → ContractAddress
internal
#Returns the owner recorded by the first consecutive ownership checkpoint at or after token_id. The token ID must fit in u64, and the stored owner must fit in ContractAddress.
mint_consecutive(ref self: ContractState, to: ContractAddress, batch_size: u64) → u64
internal
#Mints batch_size consecutive token IDs to to and returns the first ID in the batch. A non-zero batch must run during construction, must not exceed max_batch_size, and must have a non-zero recipient.
When batch_size is zero, the function performs no mint and simply returns the next consecutive ID. A non-zero batch emits one ConsecutiveTransfer, increases the recipient balance, and does not emit individual Transfer events or call on_erc721_received.
before_update(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress)
internal
#Enforces the consecutive mint lifecycle. Core ERC721 minting is forbidden during construction; after construction, ordinary core minting is allowed and consecutive minting is not.
Forward the core ERC721HooksTrait::before_update hook to this function.
after_update(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress)
internal
#Marks a token from the consecutive range as burned when an update sends it to the zero address.
Forward the core ERC721HooksTrait::after_update hook to this function.
Events
ConsecutiveTransfer(from_token_id: u256, to_token_id: u256, from_address: ContractAddress, to_address: ContractAddress)
event
#Emitted for a consecutive token range. from_token_id, from_address, and to_address are event keys.
Errors
FORBIDDEN_BATCH_MINT: felt252
constant
#'ERC721: forbidden batch mint'
EXCEEDED_MAX_BATCH_MINT: felt252
constant
#'ERC721: max batch exceeded'
FORBIDDEN_MINT: felt252
constant
#'ERC721: forbidden mint'
TOKEN_ID_OVERFLOW: felt252
constant
#'ERC721: token id overflow'
ADDRESS_OVERFLOW: felt252
constant
#'ERC721: address overflow'
use openzeppelin_token::erc721::extensions::ERC721URIStorageComponent;Extension that supports a URI suffix for each token. Use ERC721TokenURIStorageImpl as the contract's ERC721TokenURITrait implementation instead of ERC721TokenURIDefaultImpl.
Forward the core ERC721HooksTrait::after_update hook to this component's after_update function so burning a token clears its stored URI.
Implementations
Internal Implementations
Events
Storage
ERC721URIStorage_token_uris: Map<u256, ByteArray>
storage
#Token-specific URI suffixes keyed by token ID.
ERC721TokenURIStorageImpl
token_uri(self: @ERC721Component::ComponentState, token_id: u256) → ByteArray
impl
#Requires token_id to exist and resolves its URI as follows:
- With no base URI, returns the stored token-specific suffix, which can be empty.
- With a base URI and a stored suffix, returns their concatenation.
- With a base URI and no stored suffix, returns the base URI concatenated with the decimal token ID.
InternalImpl
set_token_uri(ref self: ContractState, token_id: u256, token_uri: ByteArray)
internal
#Stores token_uri for an existing token and emits MetadataUpdate.
after_update(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress)
internal
#Clears the stored token-specific URI when to is the zero address. Forward the core ERC721HooksTrait::after_update hook to this function.
Events
use openzeppelin_token::erc721::extensions::ERC721WrapperComponent;Component for an ERC721 token backed by matching token IDs from an underlying ERC721 contract.
Embeddable Implementations
Internal Implementations
Storage
ERC721Wrapper_underlying: ContractAddress
storage
#The configured underlying ERC721 token address.
ERC721WrapperImpl
underlying(self: @ContractState) → ContractAddress
external
#Returns the address of the underlying ERC721 token.
deposit_for(ref self: ContractState, receiver: ContractAddress, token_ids: Span<u256>) → bool
external
#For each token ID, transfers the underlying token from the caller to the wrapper with transfer_from, then safe-mints the matching wrapped token to receiver. Returns true when every deposit succeeds.
The underlying transfer intentionally does not invoke a receiver callback on the wrapper; the wrapped safe mint can invoke a callback on receiver.
withdraw_to(ref self: ContractState, receiver: ContractAddress, token_ids: Span<u256>) → bool
external
#For each token ID, uses the caller as authorization to burn the wrapped token, then safely transfers the matching underlying token to receiver. Returns true when every withdrawal succeeds.
ERC721WrapperReceiverImpl
on_erc721_received(ref self: ContractState, operator: ContractAddress, from: ContractAddress, token_id: u256, data: Span<felt252>) → felt252
external
#Accepts a safe transfer only from the configured underlying token, safe-mints the matching wrapped token to from, and returns the IERC721Receiver interface ID.
InternalImpl
initializer(ref self: ContractState, underlying: ContractAddress)
internal
#Stores underlying and registers support for IERC721Receiver. The underlying address must be non-zero and must differ from the wrapper address.
recover(ref self: ContractState, account: ContractAddress, token_id: u256) → u256
internal
#Recovers an underlying token transferred to the wrapper without minting its wrapped counterpart. The wrapper must own the underlying token_id; the function safe-mints the corresponding wrapped token to account and returns token_id.
Expose this function with suitable access control when recovery is required.
Errors
INVALID_UNDERLYING_ADDRESS: felt252
constant
#'Wrapper: invalid underlying'
UNSUPPORTED_TOKEN: felt252
constant
#'Wrapper: unsupported token'
INCORRECT_OWNER: felt252
constant
#'Wrapper: incorrect owner'
Presets
use openzeppelin_presets::ERC721Upgradeable;Upgradeable ERC721 contract leveraging ERC721Component.
0x05f3d201fc5c9de757ca6c42ec753d514ab1ea011b60bd139b6167cd069109d2Constructor
Embedded Implementations
ERC721MixinImpl
OwnableMixinImpl
External Functions
Constructor
constructor(ref self: ContractState, name: ByteArray, symbol: ByteArray, recipient: ContractAddress, token_ids: Span<u256>, base_uri: ByteArray, owner: ContractAddress)
constructor
#Sets the name and symbol. Mints token_ids tokens to recipient and sets the base_uri. Assigns owner as the contract owner with permissions to upgrade.
External functions
upgrade(ref self: ContractState, new_class_hash: ClassHash)
external
#Upgrades the contract to a new implementation given by new_class_hash.
Requirements:
- The caller is the contract owner.
new_class_hashcannot be zero.