OpenZeppelin ContractsPrevious Versionsv4API ReferenceToken

ERC721

Smart contract ERC721 utilities and implementations

Outdated Version

You're viewing an older version (v4.x) The latest documentation is available for the current version. Click here to visit latest version.

This set of interfaces, contracts, and utilities are all related to the ERC721 Non-Fungible Token Standard.

For a walk through on how to create an ERC721 token read our ERC721 guide.

The EIP specifies four interfaces:

  • IERC721: Core functionality required in all compliant implementation.
  • IERC721Metadata: Optional extension that adds name, symbol, and token URI, almost always included.
  • IERC721Enumerable: Optional extension that allows enumerating the tokens on chain, often not included since it requires large gas overhead.
  • IERC721Receiver: An interface that must be implemented by contracts if they want to accept tokens through safeTransferFrom.

OpenZeppelin Contracts provides implementations of all four interfaces:

  • ERC721: The core and metadata extensions, with a base URI mechanism.
  • ERC721Enumerable: The enumerable extension.
  • ERC721Holder: A bare bones implementation of the receiver interface.

Additionally there are a few of other extensions:

  • ERC721Consecutive: An implementation of ERC2309 for minting batchs of tokens during construction, in accordance with ERC721.
  • ERC721URIStorage: A more flexible but more expensive way of storing metadata.
  • ERC721Votes: Support for voting and vote delegation.
  • ERC721Royalty: A way to signal royalty information following ERC2981.
  • ERC721Pausable: A primitive to pause contract operation.
  • ERC721Burnable: A way for token holders to burn their own tokens.
  • ERC721Wrapper: Wrapper to create an ERC721 backed by another ERC721, with deposit and withdraw methods. Useful in conjunction with ERC721Votes.

This core set of contracts is designed to be unopinionated, allowing developers to access the internal functions in ERC721 (such as _mint) and expose them as external functions in the way they prefer. On the other hand, ERC721 Presets (such as ERC721PresetMinterPauserAutoId) are designed using opinionated patterns to provide developers with ready to use, deployable contracts.

Core

IERC721

IERC721Metadata

IERC721Enumerable

ERC721

ERC721Enumerable

IERC721Receiver

Extensions

ERC721Pausable

ERC721Burnable

ERC721Consecutive

ERC721URIStorage

ERC721Votes

ERC721Royalty

ERC721Wrapper

Presets

These contracts are preconfigured combinations of the above features. They can be used through inheritance or as models to copy and paste their source code.

ERC721PresetMinterPauserAutoId

Utilities

ERC721Holder

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

Implementation of ERC721 Non-Fungible Token Standard, including the Metadata extension, but not including the Enumerable extension, which is available separately as ERC721Enumerable.

constructor(string name_, string symbol_)

public

#

Initializes the contract by setting a name and a symbol to the token collection.

supportsInterface(bytes4 interfaceId) → bool

public

#

balanceOf(address owner) → uint256

public

#

ownerOf(uint256 tokenId) → address

public

#

name() → string

public

#

symbol() → string

public

#

tokenURI(uint256 tokenId) → string

public

#

_baseURI() → string

internal

#

Base URI for computing ERC721.tokenURI. If set, the resulting URI for each token will be the concatenation of the baseURI and the tokenId. Empty by default, can be overridden in child contracts.

approve(address to, uint256 tokenId)

public

#

getApproved(uint256 tokenId) → address

public

#

setApprovalForAll(address operator, bool approved)

public

#

isApprovedForAll(address owner, address operator) → bool

public

#

transferFrom(address from, address to, uint256 tokenId)

public

#

safeTransferFrom(address from, address to, uint256 tokenId)

public

#

safeTransferFrom(address from, address to, uint256 tokenId, bytes data)

public

#

_safeTransfer(address from, address to, uint256 tokenId, bytes data)

internal

#

Safely transfers tokenId token from from to to, checking first that contract recipients are aware of the ERC721 protocol to prevent tokens from being forever locked.

data is additional data, it has no specified format and it is sent in call to to.

This internal function is equivalent to ERC1155.safeTransferFrom, and can be used to e.g. implement alternative mechanisms to perform token transfer, such as signature-based.

Requirements:

  • from cannot be the zero address.
  • to cannot be the zero address.
  • tokenId token must exist and be owned by from.
  • If to refers to a smart contract, it must implement IERC721Receiver.onERC721Received, which is called upon a safe transfer.

Emits a IERC20.Transfer event.

_ownerOf(uint256 tokenId) → address

internal

#

Returns the owner of the tokenId. Does NOT revert if token doesn't exist

_exists(uint256 tokenId) → bool

internal

#

Returns whether tokenId exists.

Tokens can be managed by their owner or approved accounts via ERC20.approve or ERC1155.setApprovalForAll.

Tokens start existing when they are minted (_mint), and stop existing when they are burned (_burn).

_isApprovedOrOwner(address spender, uint256 tokenId) → bool

internal

#

Returns whether spender is allowed to manage tokenId.

Requirements:

  • tokenId must exist.

_safeMint(address to, uint256 tokenId)

internal

#

Safely mints tokenId and transfers it to to.

Requirements:

Emits a IERC20.Transfer event.

_safeMint(address to, uint256 tokenId, bytes data)

internal

#

Same as _safeMint, with an additional data parameter which is forwarded in IERC721Receiver.onERC721Received to contract recipients.

_mint(address to, uint256 tokenId)

internal

#

Mints tokenId and transfers it to to.

Usage of this method is discouraged, use ERC721._safeMint whenever possible

Requirements:

  • tokenId must not exist.
  • to cannot be the zero address.

Emits a IERC20.Transfer event.

_burn(uint256 tokenId)

internal

#

Destroys tokenId. The approval is cleared when the token is burned. This is an internal function that does not check if the sender is authorized to operate on the token.

Requirements:

  • tokenId must exist.

Emits a IERC20.Transfer event.

_transfer(address from, address to, uint256 tokenId)

internal

#

Transfers tokenId from from to to. As opposed to ERC20.transferFrom, this imposes no restrictions on msg.sender.

Requirements:

  • to cannot be the zero address.
  • tokenId token must be owned by from.

Emits a IERC20.Transfer event.

_approve(address to, uint256 tokenId)

internal

#

Approve to to operate on tokenId

Emits an IERC20.Approval event.

_setApprovalForAll(address owner, address operator, bool approved)

internal

#

Approve operator to operate on all of owner tokens

Emits an IERC1155.ApprovalForAll event.

_requireMinted(uint256 tokenId)

internal

#

Reverts if the tokenId has not been minted yet.

_beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize)

internal

#

Hook that is called before any token transfer. This includes minting and burning. If ERC721Consecutive is used, the hook may be called as part of a consecutive (batch) mint, as indicated by batchSize greater than 1.

Calling conditions:

  • When from and to are both non-zero, from's tokens will be transferred to to.
  • When from is zero, the tokens will be minted for to.
  • When to is zero, from's tokens will be burned.
  • from and to are never both zero.
  • batchSize is non-zero.

To learn more about hooks, head to xref:ROOT:extending-contracts#using-hooks[Using Hooks].

_afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize)

internal

#

Hook that is called after any token transfer. This includes minting and burning. If ERC721Consecutive is used, the hook may be called as part of a consecutive (batch) mint, as indicated by batchSize greater than 1.

Calling conditions:

  • When from and to are both non-zero, from's tokens were transferred to to.
  • When from is zero, the tokens were minted for to.
  • When to is zero, from's tokens were burned.
  • from and to are never both zero.
  • batchSize is non-zero.

To learn more about hooks, head to xref:ROOT:extending-contracts#using-hooks[Using Hooks].

__unsafe_increaseBalance(address account, uint256 amount)

internal

#

Unsafe write access to the balances, used by extensions that "mint" tokens using an ERC721.ownerOf override.

Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant being that for any address a the value returned by balanceOf(a) must be equal to the number of tokens such that ownerOf(tokenId) is a.

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

Required interface of an ERC721 compliant contract.

balanceOf(address owner) → uint256 balance

external

#

Returns the number of tokens in owner's account.

ownerOf(uint256 tokenId) → address owner

external

#

Returns the owner of the tokenId token.

Requirements:

  • tokenId must exist.

safeTransferFrom(address from, address to, uint256 tokenId, bytes data)

external

#

Safely transfers tokenId token from from to to.

Requirements:

  • from cannot be the zero address.
  • to cannot be the zero address.
  • tokenId token must exist and be owned by from.
  • If the caller is not from, it must be approved to move this token by either ERC20.approve or ERC1155.setApprovalForAll.
  • If to refers to a smart contract, it must implement IERC721Receiver.onERC721Received, which is called upon a safe transfer.

Emits a IERC20.Transfer event.

safeTransferFrom(address from, address to, uint256 tokenId)

external

#

Safely transfers tokenId token from from to to, checking first that contract recipients are aware of the ERC721 protocol to prevent tokens from being forever locked.

Requirements:

  • from cannot be the zero address.
  • to cannot be the zero address.
  • tokenId token must exist and be owned by from.
  • If the caller is not from, it must have been allowed to move this token by either ERC20.approve or ERC1155.setApprovalForAll.
  • If to refers to a smart contract, it must implement IERC721Receiver.onERC721Received, which is called upon a safe transfer.

Emits a IERC20.Transfer event.

transferFrom(address from, address to, uint256 tokenId)

external

#

Transfers tokenId token from from to to.

Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 or else they may be permanently lost. Usage of ERC1155.safeTransferFrom prevents loss, though the caller must understand this adds an external call which potentially creates a reentrancy vulnerability.

Requirements:

  • from cannot be the zero address.
  • to cannot be the zero address.
  • tokenId token must be owned by from.
  • If the caller is not from, it must be approved to move this token by either ERC20.approve or ERC1155.setApprovalForAll.

Emits a IERC20.Transfer event.

approve(address to, uint256 tokenId)

external

#

Gives permission to to to transfer tokenId token to another account. The approval is cleared when the token is transferred.

Only a single account can be approved at a time, so approving the zero address clears previous approvals.

Requirements:

  • The caller must own the token or be an approved operator.
  • tokenId must exist.

Emits an IERC20.Approval event.

setApprovalForAll(address operator, bool approved)

external

#

Approve or remove operator as an operator for the caller. Operators can call ERC20.transferFrom or ERC1155.safeTransferFrom for any token owned by the caller.

Requirements:

  • The operator cannot be the caller.

Emits an IERC1155.ApprovalForAll event.

getApproved(uint256 tokenId) → address operator

external

#

Returns the account approved for tokenId token.

Requirements:

  • tokenId must exist.

isApprovedForAll(address owner, address operator) → bool

external

#

Returns if the operator is allowed to manage all of the assets of owner.

See ERC1155.setApprovalForAll

Transfer(address indexed from, address indexed to, uint256 indexed tokenId)

event

#

Emitted when tokenId token is transferred from from to to.

Approval(address indexed owner, address indexed approved, uint256 indexed tokenId)

event

#

Emitted when owner enables approved to manage the tokenId token.

ApprovalForAll(address indexed owner, address indexed operator, bool approved)

event

#

Emitted when owner enables or disables (approved) operator to manage all of its assets.

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

Interface for any contract that wants to support safeTransfers from ERC721 asset contracts.

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

external

#

Whenever an IERC721 tokenId token is transferred to this contract via IERC721.safeTransferFrom by operator from from, this function is called.

It must return its Solidity selector to confirm the token transfer. If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.

The selector can be obtained in Solidity with IERC721Receiver.onERC721Received.selector.

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

ERC721 Token that can be burned (destroyed).

burn(uint256 tokenId)

public

#

Burns tokenId. See ERC721._burn.

Requirements:

  • The caller must own tokenId or be an approved operator.
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Consecutive.sol";

Implementation of the ERC2309 "Consecutive Transfer Extension" as defined in EIP-2309.

This extension allows the minting of large batches of tokens, during contract construction only. For upgradeable contracts this implies that batch minting is only available during proxy deployment, and not in subsequent upgrades. These batches are limited to 5000 tokens at a time by default to accommodate off-chain indexers.

Using this extension removes the ability to mint single tokens during contract construction. This ability is regained after construction. During construction, only batch minting is allowed.

This extension bypasses the hooks ERC1155._beforeTokenTransfer and ERC1155._afterTokenTransfer for tokens minted in batch. When using this extension, you should consider the _beforeConsecutiveTokenTransfer and _afterConsecutiveTokenTransfer hooks in addition to ERC1155._beforeTokenTransfer and ERC1155._afterTokenTransfer.

When overriding ERC1155._afterTokenTransfer, be careful about call ordering. ERC721.ownerOf may return invalid values during the ERC1155._afterTokenTransfer execution if the super call is not called first. To be safe, execute the super call before your custom logic.

Available since v4.8.

_maxBatchSize() → uint96

internal

#

Maximum size of a batch of consecutive tokens. This is designed to limit stress on off-chain indexing services that have to record one entry per token, and have protections against "unreasonably large" batches of tokens.

NOTE: Overriding the default value of 5000 will not cause on-chain issues, but may result in the asset not being correctly supported by off-chain indexing services (including marketplaces).

_ownerOf(uint256 tokenId) → address

internal

#

See ERC721._ownerOf. Override that checks the sequential ownership structure for tokens that have been minted as part of a batch, and not yet transferred.

_mintConsecutive(address to, uint96 batchSize) → uint96

internal

#

Mint a batch of tokens of length batchSize for to. Returns the token id of the first token minted in the batch; if batchSize is 0, returns the number of consecutive ids minted so far.

Requirements:

CAUTION: Does not emit a Transfer event. This is ERC721 compliant as long as it is done inside of the constructor, which is enforced by this function.

CAUTION: Does not invoke onERC721Received on the receiver.

Emits a IERC2309.ConsecutiveTransfer event.

_mint(address to, uint256 tokenId)

internal

#

See ERC721._mint. Override version that restricts normal minting to after construction.

Warning: Using ERC721Consecutive prevents using ERC1155._mint during construction in favor of ERC721Consecutive._mintConsecutive. After construction, ERC721Consecutive._mintConsecutive is no longer available and ERC1155._mint becomes available.

_afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize)

internal

#

See ERC721._afterTokenTransfer. Burning of tokens that have been sequentially minted must be explicit.

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

This implements an optional extension of ERC721 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.

supportsInterface(bytes4 interfaceId) → bool

public

#

tokenOfOwnerByIndex(address owner, uint256 index) → uint256

public

#

totalSupply() → uint256

public

#

tokenByIndex(uint256 index) → uint256

public

#

_beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize)

internal

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

ERC721 token with pausable token transfers, minting and burning.

Useful for scenarios such as preventing trades until the end of an evaluation period, or having an emergency switch for freezing all token transfers in the event of a large bug.

This contract does not include public pause and unpause functions. In addition to inheriting this contract, you must define both functions, invoking the Pausable._pause and Pausable._unpause internal functions, with appropriate access control, e.g. using AccessControl or Ownable. Not doing so will make the contract unpausable.

_beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize)

internal

#

See ERC721._beforeTokenTransfer.

Requirements:

  • the contract must not be paused.
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Royalty.sol";

Extension of ERC721 with the ERC2981 NFT Royalty Standard, a standardized way to retrieve royalty payment information.

Royalty information can be specified globally for all token ids via ERC2981._setDefaultRoyalty, and/or individually for specific token ids via ERC2981._setTokenRoyalty. The latter takes precedence over the first.

ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See Rationale in the EIP. Marketplaces are expected to voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.

Available since v4.5.

supportsInterface(bytes4 interfaceId) → bool

public

#

_burn(uint256 tokenId)

internal

#

See ERC721._burn. This override additionally clears the royalty information for the token.

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

ERC721 token with storage based token URI management.

supportsInterface(bytes4 interfaceId) → bool

public

#

tokenURI(uint256 tokenId) → string

public

#

_setTokenURI(uint256 tokenId, string _tokenURI)

internal

#

Sets _tokenURI as the tokenURI of tokenId.

Emits IERC4906.MetadataUpdate.

Requirements:

  • tokenId must exist.

_burn(uint256 tokenId)

internal

#

See ERC721._burn. This override additionally checks to see if a token-specific URI was set for the token, and if so, it deletes the token URI from the storage mapping.

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

Extension of ERC721 to support voting and delegation as implemented by Votes, where each individual NFT counts as 1 vote unit.

Tokens do not count as votes until they are delegated, because votes must be tracked which incurs an additional cost on every transfer. Token holders can either delegate to a trusted representative who will decide how to make use of the votes in governance decisions, or they can delegate to themselves to be their own representative.

Available since v4.5.

_afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize)

internal

#

See ERC721._afterTokenTransfer. Adjusts votes when tokens are transferred.

Emits a IVotes.DelegateVotesChanged event.

_getVotingUnits(address account) → uint256

internal

#

Returns the balance of account.

Overriding this function will likely result in incorrect vote tracking.

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

Extension of the ERC721 token contract to support token wrapping.

Users can deposit and withdraw an "underlying token" and receive a "wrapped token" with a matching tokenId. This is useful in conjunction with other modules. For example, combining this wrapping mechanism with ERC721Votes will allow the wrapping of an existing "basic" ERC721 into a governance token.

Available since v4.9.0

constructor(contract IERC721 underlyingToken)

internal

#

depositFor(address account, uint256[] tokenIds) → bool

public

#

Allow a user to deposit underlying tokens and mint the corresponding tokenIds.

withdrawTo(address account, uint256[] tokenIds) → bool

public

#

Allow a user to burn wrapped tokens and withdraw the corresponding tokenIds of the underlying tokens.

onERC721Received(address, address from, uint256 tokenId, bytes) → bytes4

public

#

Overrides IERC721Receiver.onERC721Received to allow minting on direct ERC721 transfers to this contract.

In case there's data attached, it validates that the operator is this contract, so only trusted data is accepted from ERC20Wrapper.depositFor.

Doesn't work with unsafe transfers (eg. IERC721.transferFrom). Use ERC721Wrapper._recover for recovering in that scenario.

_recover(address account, uint256 tokenId) → uint256

internal

#

Mint a wrapped token to cover any underlyingToken that would have been transferred by mistake. Internal function that can be exposed with access control if desired.

underlying() → contract IERC721

public

#

Returns the underlying token.

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

See https://eips.ethereum.org/EIPS/eip-721

totalSupply() → uint256

external

#

Returns the total amount of tokens stored by the contract.

tokenOfOwnerByIndex(address owner, uint256 index) → uint256

external

#

Returns a token ID owned by owner at a given index of its token list. Use along with ERC1155.balanceOf to enumerate all of owner's tokens.

tokenByIndex(uint256 index) → uint256

external

#

Returns a token ID at a given index of all the tokens stored by the contract. Use along with ERC1155Supply.totalSupply to enumerate all tokens.

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

See https://eips.ethereum.org/EIPS/eip-721

name() → string

external

#

Returns the token collection name.

symbol() → string

external

#

Returns the token collection symbol.

tokenURI(uint256 tokenId) → string

external

#

Returns the Uniform Resource Identifier (URI) for tokenId token.

import "@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol";

ERC721 token, including:

  • ability for holders to burn (destroy) their tokens
  • a minter role that allows for token minting (creation)
  • a pauser role that allows to stop all token transfers
  • token ID and URI autogeneration

This contract uses AccessControl to lock permissioned functions using the different roles - head to its documentation for details.

The account that deploys the contract will be granted the minter and pauser roles, as well as the default admin role, which will let it grant both minter and pauser roles to other accounts.

Deprecated in favor of Contracts Wizard.

Functions

ERC721Pausable

Pausable

ERC721Burnable

ERC721Enumerable

IERC721Enumerable

ERC721

IERC721Metadata

IERC721

AccessControlEnumerable

AccessControl

ERC165

IERC165

IAccessControlEnumerable

IAccessControl

constructor(string name, string symbol, string baseTokenURI)

public

#

Grants DEFAULT_ADMIN_ROLE, MINTER_ROLE and PAUSER_ROLE to the account that deploys the contract.

Token URIs will be autogenerated based on baseURI and their token IDs. See ERC721.tokenURI.

_baseURI() → string

internal

#

Base URI for computing ERC721.tokenURI. If set, the resulting URI for each token will be the concatenation of the baseURI and the tokenId. Empty by default, can be overridden in child contracts.

mint(address to)

public

#

Creates a new token for to. Its token ID will be automatically assigned (and available on the emitted IERC721.Transfer event), and the token URI autogenerated based on the base URI passed at construction.

See ERC721._mint.

Requirements:

  • the caller must have the MINTER_ROLE.

pause()

public

#

Pauses all token transfers.

See ERC721Pausable and Pausable._pause.

Requirements:

  • the caller must have the PAUSER_ROLE.

unpause()

public

#

Unpauses all token transfers.

See ERC721Pausable and Pausable._unpause.

Requirements:

  • the caller must have the PAUSER_ROLE.

_beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize)

internal

#

supportsInterface(bytes4 interfaceId) → bool

public

#

MINTER_ROLE() → bytes32

public

#

PAUSER_ROLE() → bytes32

public

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

Implementation of the IERC721Receiver interface.

Accepts all token transfers. Make sure the contract is able to use its token with IERC721.safeTransferFrom, IERC721.approve or IERC721.setApprovalForAll.

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

public

#

See IERC721Receiver.onERC721Received.

Always returns IERC721Receiver.onERC721Received.selector.

On this page

CoreExtensionsPresetsUtilitiesERC721IERC721MetadataIERC721ERC165IERC165IERC721MetadataIERC721ERC165IERC165IERC721IERC165IERC165IERC721ReceiverERC721BurnableERC721IERC721MetadataIERC721ERC165IERC165ERC721IERC721MetadataIERC721ERC165IERC165ERC721ConsecutiveERC721IERC721MetadataIERC721ERC165IERC165IERC2309ERC721IERC721MetadataIERC721ERC165IERC165IERC2309ERC721EnumerableIERC721EnumerableERC721IERC721MetadataIERC721ERC165IERC165IERC721EnumerableERC721IERC721MetadataIERC721ERC165IERC165ERC721PausablePausableERC721IERC721MetadataIERC721ERC165IERC165PausableERC721IERC721MetadataIERC721ERC165IERC165ERC721RoyaltyERC721IERC721MetadataIERC721ERC2981ERC165IERC2981IERC165ERC721IERC721MetadataIERC721ERC2981ERC165IERC2981IERC165ERC721URIStorageERC721IERC721MetadataIERC4906IERC721ERC165IERC165ERC721IERC721MetadataIERC4906IERC721ERC165IERC165ERC721VotesVotesIERC5805IVotesIERC6372EIP712IERC5267ERC721IERC721MetadataIERC721ERC165IERC165VotesIERC5805IVotesIERC6372EIP712IERC5267ERC721IERC721MetadataIERC721ERC165IERC165ERC721WrapperIERC721ReceiverERC721IERC721MetadataIERC721ERC165IERC165IERC721ReceiverERC721IERC721MetadataIERC721ERC165IERC165IERC721EnumerableIERC721IERC165IERC721IERC165IERC721MetadataIERC721IERC165IERC721IERC165ERC721PresetMinterPauserAutoIdERC721PausablePausableERC721BurnableERC721EnumerableIERC721EnumerableERC721IERC721MetadataIERC721AccessControlEnumerableAccessControlERC165IERC165IAccessControlEnumerableIAccessControlERC721PausablePausableERC721BurnableERC721EnumerableIERC721EnumerableERC721IERC721MetadataIERC721AccessControlEnumerableAccessControlERC165IERC165IAccessControlEnumerableIAccessControlERC721HolderIERC721Receiver