Skip to main content

ERC-721 Enumerable Transfer Module

Internal ERC721 token transfer logic

Key Features
  • Internal functions for token transfers, designed for facet composition.
  • Utilizes diamond storage for token ownership tracking.
  • Includes safeTransferFrom for compatibility checks with ERC721Receiver interfaces.
  • No external dependencies, ensuring composability within a diamond.
Module Usage

This module provides internal functions for use in your custom facets. Import it to access shared logic and storage.

Overview

This module provides internal functions for managing ERC721 token transfers within a diamond. It leverages diamond storage to track token ownership and ensures safe transfers by checking receiver compatibility. Changes made through this module are immediately visible to all facets accessing the shared ERC721 storage.

Storage

ERC721EnumerableStorage

storage-location: erc8042:erc721.enumerable

Definition
struct ERC721EnumerableStorage {
mapping(address owner => mapping(uint256 index => uint256 tokenId)) ownerTokens;
mapping(uint256 tokenId => uint256 ownerTokensIndex) ownerTokensIndex;
uint256[] allTokens;
mapping(uint256 tokenId => uint256 allTokensIndex) allTokensIndex;
}

ERC721Storage

storage-location: erc8042:erc721

Definition
struct ERC721Storage {
mapping(uint256 tokenId => address owner) ownerOf;
mapping(address owner => uint256 balance) balanceOf;
mapping(address owner => mapping(address operator => bool approved)) isApprovedForAll;
mapping(uint256 tokenId => address approved) approved;
}

State Variables

PropertyTypeDescription
STORAGE_POSITIONbytes32Diamond storage slot position for this module (Value: keccak256("erc721.enumerable"))
ERC721_STORAGE_POSITIONbytes32Diamond storage slot position for this module (Value: keccak256("erc721"))

Functions

getERC721Storage

Returns a pointer to the ERC-721 storage struct. Uses inline assembly to access the storage slot defined by STORAGE_POSITION.

function getERC721Storage() pure returns (ERC721Storage storage s);

Returns:

PropertyTypeDescription
sERC721StorageThe ERC721Storage struct in storage.

getStorage

Returns the storage struct used by this facet.

function getStorage() pure returns (ERC721EnumerableStorage storage s);

Returns:

PropertyTypeDescription
sERC721EnumerableStorageThe ERC721Enumerable storage struct.

function safeTransferFrom

Safely transfers a token, checking for receiver contract compatibility. Safely transfers a token with additional data.

function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory _data) ;

Parameters:

PropertyTypeDescription
_fromaddress-
_toaddress-
_tokenIduint256-
_databytes memory-

transferFrom

Internal function to transfer ownership of a token ID.

function transferFrom(address _from, address _to, uint256 _tokenId) ;

Parameters:

PropertyTypeDescription
_fromaddressThe address sending the token.
_toaddressThe address receiving the token.
_tokenIduint256The token ID being transferred.

Events

Errors

Best Practices

Best Practice
  • Ensure caller owns the token and the token exists before calling transferFrom or safeTransferFrom.
  • Verify receiver contract compatibility before calling safeTransferFrom to prevent unexpected reverts.
  • Handle custom errors like ERC721IncorrectOwner, ERC721InvalidReceiver, and ERC721NonexistentToken in calling facets.

Integration Notes

Shared Storage

This module interacts with diamond storage via the STORAGE_POSITION slot, identified by keccak256(\"erc721.enumerable\"). It reads and writes to the ERC721EnumerableStorage struct. All state changes made through transferFrom and safeTransferFrom are immediately reflected in this shared storage, making them visible to any other facet that accesses the same storage slot.

Was this helpful?
Last updated:

Newsletter

Get notified about releases, feature announcements, and technical deep-dives on building smart contracts with Compose.

No spam. Unsubscribe anytime.