ERC 721

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

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

The EIP consists of three interfaces, found here as IERC721, IERC721Metadata, and IERC721Enumerable. Only the first one is required in a contract to be ERC721 compliant. However, all three are implemented in ERC721.

Additionally, IERC721Receiver can be used to prevent tokens from becoming forever locked in contracts. Imagine sending an in-game item to an exchange address that can’t send it back!. When using safeTransferFrom, the token contract checks to see that the receiver is an IERC721Receiver, which implies that it knows how to handle ERC721 tokens. If you’re writing a contract that needs to receive ERC721 tokens, you’ll want to include this interface.

Finally, some custom extensions are also included:

Additionally there are multiple custom extensions, including:

Core

IERC721

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) 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, to cannot be zero.

  • tokenId token must exist and be owned by from.

  • If the caller is not from, it must be have been allowed to move this token by either approve or setApprovalForAll.

  • If to refers to a smart contract, it must implement IERC721Receiver.onERC721Received, which is called upon a safe transfer.

Emits a Transfer event.

transferFrom(address from, address to, uint256 tokenId) external

Transfers tokenId token from from to to.

Usage of this method is discouraged, use safeTransferFrom whenever possible.

Requirements:

  • from, to cannot be zero.

  • tokenId token must be owned by from.

  • If the caller is not from, it must be approved to move this token by either approve or setApprovalForAll.

Emits a 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 Approval event.

getApproved(uint256 tokenId) → address operator external

Returns the account approved for tokenId token.

Requirements:

  • tokenId must exist.

setApprovalForAll(address operator, bool _approved) external

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

Requirements:

  • The operator cannot be the caller.

Emits an ApprovalForAll event.

isApprovedForAll(address owner, address operator) → bool external

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

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

Safely transfers tokenId token from from to to.

Requirements:

  • from, to cannot be zero.

  • 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 approve or setApprovalForAll.

  • If to refers to a smart contract, it must implement IERC721Receiver.onERC721Received, which is called upon a safe transfer.

Emits a Transfer event.

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

Emitted when tokenId token is transfered from from to to.

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

Emitted when owner enables approved to manage the tokenId token.

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

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

IERC721Metadata

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.

IERC721Enumerable

totalSupply() → uint256 external

Returns the total amount of tokens stored by the contract.

tokenOfOwnerByIndex(address owner, uint256 index) → uint256 tokenId external

Returns a token ID owned by owner at a given index of its token list. Use along with 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 totalSupply to enumerate all tokens.

ERC721

constructor(string name, string symbol) public

balanceOf(address owner) → uint256 public

Gets the balance of the specified address.

ownerOf(uint256 tokenId) → address public

Gets the owner of the specified token ID.

name() → string public

Gets the token name.

symbol() → string public

Gets the token symbol.

tokenURI(uint256 tokenId) → string public

Returns the URI for a given token ID. May return an empty string.

If a base URI is set (via _setBaseURI), it is added as a prefix to the token’s own URI (via _setTokenURI).

If there is a base URI but no token URI, the token’s ID will be used as its URI when appending it to the base URI. This pattern for autogenerated token URIs can lead to large gas savings.

Table 1. Examples

_setBaseURI()

_setTokenURI()

tokenURI()

""

""

""

""

"token.uri/123"

"token.uri/123"

"token.uri/"

"123"

"token.uri/123"

"token.uri/"

""

"token.uri/<tokenId>"

Requirements:

  • tokenId must exist.

baseURI() → string public

Returns the base URI set via _setBaseURI. This will be automatically added as a prefix in tokenURI to each token’s URI, or to the token ID if no specific URI is set for that token ID.

tokenOfOwnerByIndex(address owner, uint256 index) → uint256 public

Gets the token ID at a given index of the tokens list of the requested owner.

totalSupply() → uint256 public

Gets the total amount of tokens stored by the contract.

tokenByIndex(uint256 index) → uint256 public

Gets the token ID at a given index of all the tokens in this contract Reverts if the index is greater or equal to the total number of tokens.

approve(address to, uint256 tokenId) public

Approves another address to transfer the given token ID The zero address indicates there is no approved address. There can only be one approved address per token at a given time. Can only be called by the token owner or an approved operator.

getApproved(uint256 tokenId) → address public

Gets the approved address for a token ID, or zero if no address set Reverts if the token ID does not exist.

setApprovalForAll(address operator, bool approved) public

Sets or unsets the approval of a given operator An operator is allowed to transfer all tokens of the sender on their behalf.

isApprovedForAll(address owner, address operator) → bool public

Tells whether an operator is approved by a given owner.

transferFrom(address from, address to, uint256 tokenId) public

Transfers the ownership of a given token ID to another address. Usage of this method is discouraged, use safeTransferFrom whenever possible. Requires the msg.sender to be the owner, approved, or operator.

safeTransferFrom(address from, address to, uint256 tokenId) public

Safely transfers the ownership of a given token ID to another address If the target address is a contract, it must implement IERC721Receiver.onERC721Received, which is called upon a safe transfer, and return the magic value bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")); otherwise, the transfer is reverted. Requires the msg.sender to be the owner, approved, or operator

safeTransferFrom(address from, address to, uint256 tokenId, bytes _data) public

Safely transfers the ownership of a given token ID to another address If the target address is a contract, it must implement IERC721Receiver.onERC721Received, which is called upon a safe transfer, and return the magic value bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")); otherwise, the transfer is reverted. Requires the _msgSender() to be the owner, approved, or operator

_safeTransfer(address from, address to, uint256 tokenId, bytes _data) internal

Safely transfers the ownership of a given token ID to another address If the target address is a contract, it must implement onERC721Received, which is called upon a safe transfer, and return the magic value bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")); otherwise, the transfer is reverted. Requires the msg.sender to be the owner, approved, or operator

_exists(uint256 tokenId) → bool internal

Returns whether the specified token exists.

_isApprovedOrOwner(address spender, uint256 tokenId) → bool internal

Returns whether the given spender can transfer a given token ID.

_safeMint(address to, uint256 tokenId) internal

Internal function to safely mint a new token. Reverts if the given token ID already exists. If the target address is a contract, it must implement onERC721Received, which is called upon a safe transfer, and return the magic value bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")); otherwise, the transfer is reverted.

_safeMint(address to, uint256 tokenId, bytes _data) internal

Internal function to safely mint a new token. Reverts if the given token ID already exists. If the target address is a contract, it must implement onERC721Received, which is called upon a safe transfer, and return the magic value bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")); otherwise, the transfer is reverted.

_mint(address to, uint256 tokenId) internal

Internal function to mint a new token. Reverts if the given token ID already exists.

_burn(uint256 tokenId) internal

Internal function to burn a specific token. Reverts if the token does not exist.

_transfer(address from, address to, uint256 tokenId) internal

Internal function to transfer ownership of a given token ID to another address. As opposed to transferFrom, this imposes no restrictions on msg.sender.

_setTokenURI(uint256 tokenId, string _tokenURI) internal

Internal function to set the token URI for a given token.

Reverts if the token ID does not exist.

If all token IDs share a prefix (for example, if your URIs look like https://api.myproject.com/token/<id>;), use _setBaseURI to store it and save gas.

_setBaseURI(string baseURI_) internal

Internal function to set the base URI for all token IDs. It is automatically added as a prefix to the value returned in tokenURI, or to the token ID if tokenURI is empty.

_beforeTokenTransfer(address from, address to, uint256 tokenId) internal

Hook that is called before any token transfer. This includes minting and burning.

Calling conditions:

  • when from and to are both non-zero, from's tokenId will be transferred to to.

  • when from is zero, tokenId will be minted for to.

  • when to is zero, from's tokenId will be burned.

  • from and to are never both zero.

To learn more about hooks, head to Using Hooks.

IERC721Receiver

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

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

The ERC721 smart contract calls this function on the recipient after a IERC721.safeTransferFrom. This function MUST return the function selector, otherwise the caller will revert the transaction. The selector to be returned can be obtained as this.onERC721Received.selector. This function MAY throw to revert and reject the transfer. Note: the ERC721 contract address is always the message sender.

Extensions

Convenience

ERC721Holder

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