Staking Protocolerc721Facet

ERC721Facet

This core facet manages the ERC721 token functionality for staking position tokens within the staking platform (Staking Diamond).

_This contract is responsible for minting, transferring, and managing the staking position tokens represented by ERC721 NFTs. Each token uniquely identifies a user's position in a staking campaign, allowing them to manage the respective position and claim rewards based on their stake (see StakingSkeleton.sol).

The staking position tokens can be configured to be soulbound, meaning they cannot be transferred once minted. This ensures that ownership is retained by the user until they decide to exit the staking campaign. The soulbound property is not applied by default; it can be set during the initialization of the ERC721 facet._

OnlyAdminCanInitialize

error OnlyAdminCanInitialize(address nonAdminAccount)

Thrown when a non-admin account attempts to call restricted initialization functions.

AlreadyInitialized

error AlreadyInitialized()

Thrown when attempting to re-initialize.

TransferOperationNotSupported

error TransferOperationNotSupported()

Thrown when token is configured as non-transferable and a transfer operation is attempted.

OnlyDiamondCanMintInternally

error OnlyDiamondCanMintInternally(address caller)

Thrown when the mint function is called by an address other than the diamond contract itself.

OnlyDiamondCanBurnInternally

error OnlyDiamondCanBurnInternally(address caller)

Thrown when the burn function is called by an address other than the diamond contract itself.

ERC721FacetInitialized

event ERC721FacetInitialized(string name, string symbol, string baseURI, bool isTransferable)

Emitted at initErc721Facet().

initErc721Facet

function initErc721Facet(bytes initErc721FacetData) external

Initializes the ERC721 facet by setting the name, symbol, and baseURI for the staking position token collection.

_This function configures a dedicated storage slot within the Diamond’s storage structure (see ERC721FacetStorage.sol). It should only be called once to set up the initial configuration of the ERC721 facet. The baseURI_ should end with a / symbol for proper token URI generation.

This function can only be called by the Admin (see AccessControlStakingFacet.sol).

Emits an {ERC721FacetInitialized} event._

Parameters

NameTypeDescription
initErc721FacetDatabytesThe ABI-encoded data containing the following: - name_ The name (string) of the staking position token collection. - symbol_ The symbol (string) representing the staking position token collection. - baseURI_ The base URI (string) for token metadata, providing a common root for all token metadata URIs. - isTransferable_ A boolean flag indicating whether the staking position token collection is soulbound.

balanceOf

function balanceOf(address owner) public view returns (uint256)

See {IERC721-balanceOf}.

ownerOf

function ownerOf(uint256 tokenId) public view returns (address)

See {IERC721-ownerOf}.

name

function name() public view returns (string)

Retrieves the name of the ERC721 staking position token collection.

symbol

function symbol() public view returns (string)

Retrieves the symbol of the ERC721 staking position token collection.

tokenURI

function tokenURI(uint256 tokenId) public view returns (string)

Retrieves the Uniform Resource Identifier (URI) for the tokenId staking position token.

Returns the concatenation of baseURI and tokenId if baseURI is set; otherwise, returns an empty string.

Parameters

NameTypeDescription
tokenIduint256The ID of the staking position token.

Return Values

NameTypeDescription
[0]stringstring The URI of the specified token.

_baseURI

function _baseURI() internal view returns (string)

Returns the baseURI used for generating the Uniform Resource Identifiers (URIs) of the tokens.

Return Values

NameTypeDescription
[0]stringstring The base URI for token metadata.

approve

function approve(address to, uint256 tokenId) public payable

See {IERC721-approve}.

getApproved

function getApproved(uint256 tokenId) public view returns (address)

See {IERC721-getApproved}.

setApprovalForAll

function setApprovalForAll(address operator, bool approved) public

See {IERC721-setApprovalForAll}.

isApprovedForAll

function isApprovedForAll(address owner, address operator) public view returns (bool)

See {IERC721-isApprovedForAll}.

transferFrom

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

See {IERC721-transferFrom}. If the staking position token collection is soulbound (i.e., non-transferable), this operation is disabled.

safeTransferFrom

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

See {IERC721-safeTransferFrom}. If the staking position token collection is soulbound (i.e., non-transferable), this operation is disabled.

safeTransferFrom

function safeTransferFrom(address from, address to, uint256 tokenId, bytes data) public payable virtual

See {IERC721-safeTransferFrom}. If the staking position token collection is soulbound (i.e., non-transferable), this operation is disabled.

_ownerOf

function _ownerOf(uint256 tokenId) internal view virtual returns (address)

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

IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the core ERC-721 logic MUST be matched with the use of {_increaseBalance} to keep balances consistent with ownership. The invariant to preserve is 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._

_getApproved

function _getApproved(uint256 tokenId) internal view virtual returns (address)

Returns the approved address for tokenId. Returns 0 if tokenId is not minted.

_isAuthorized

function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool)

_Returns whether spender is allowed to manage owner's tokens, or tokenId in particular (ignoring whether it is owned by owner).

WARNING: This function assumes that owner is the actual owner of tokenId and does not verify this assumption._

_checkAuthorized

function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual

_Checks if spender can operate on tokenId, assuming the provided owner is the actual owner. Reverts if:

  • spender does not have approval from owner for tokenId.
  • spender does not have approval to manage all of owner's assets.

WARNING: This function assumes that owner is the actual owner of tokenId and does not verify this assumption._

_increaseBalance

function _increaseBalance(address account, uint128 value) internal virtual

_Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.

NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that a uint256 would ever overflow from increments when these increments are bounded to uint128 values.

WARNING: Increasing an account's balance using this function tends to be paired with an override of the {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership remain consistent with one another._

_update

function _update(address to, uint256 tokenId, address auth) internal virtual returns (address)

_Transfers tokenId 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 tokenId before the update.

The auth argument is optional. If the value passed is non 0, 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.

NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}._

mint

function mint(address to, uint256 tokenId) external

Mints a staking position token with the specified tokenId to the address to.

Only the Staking Diamond contract can mint staking position NFT tokens.

Parameters

NameTypeDescription
toaddressThe address that will receive the staking position token.
tokenIduint256The ID of the staking position token to mint.

_mint

function _mint(address to, uint256 tokenId) internal

_Mints tokenId and transfers it to to.

WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible

Requirements:

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

Emits a {Transfer} event._

_safeMint

function _safeMint(address to, uint256 tokenId) internal

_Mints tokenId, transfers it to to and checks for to acceptance.

Requirements:

  • tokenId must not exist.
  • If to refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.

Emits a {Transfer} event._

_safeMint

function _safeMint(address to, uint256 tokenId, bytes data) internal virtual

Same as {xref-ERC721-_safeMint-address-uint256-}[_safeMint], with an additional data parameter which is forwarded in {IERC721Receiver-onERC721Received} to contract recipients.

burn

function burn(uint256 tokenId) external

Burns tokenId token.

Only the Staking Diamond contract can burn staking position NFT tokens.

Parameters

NameTypeDescription
tokenIduint256The ID of the staking position token to be burned.

_burn

function _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 {Transfer} event._

_transfer

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

_Transfers tokenId from from to to. As opposed to {transferFrom}, this imposes no restrictions on msg.sender.

Requirements:

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

Emits a {Transfer} event._

_safeTransfer

function _safeTransfer(address from, address to, uint256 tokenId) internal

_Safely transfers tokenId token from from to to, checking that contract recipients are aware of the ERC-721 standard 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 like {safeTransferFrom} in the sense that it invokes {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g. implement alternative mechanisms to perform token transfer, such as signature-based.

Requirements:

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

Emits a {Transfer} event._

_safeTransfer

function _safeTransfer(address from, address to, uint256 tokenId, bytes data) internal virtual

Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[_safeTransfer], with an additional data parameter which is forwarded in {IERC721Receiver-onERC721Received} to contract recipients.

_approve

function _approve(address to, uint256 tokenId, address auth) internal

_Approve to to operate on tokenId

The auth argument is optional. If the value passed is non 0, 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.

Overrides to this logic should be done to the variant with an additional bool emitEvent argument._

_approve

function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual

Variant of _approve with an optional flag to enable or disable the {Approval} event. The event is not emitted in the context of transfers.

_setApprovalForAll

function _setApprovalForAll(address owner, address operator, bool approved) internal virtual

_Approve operator to operate on all of owner tokens

Requirements:

  • operator can't be the address zero.

Emits an {ApprovalForAll} event._

_requireOwned

function _requireOwned(uint256 tokenId) internal view returns (address)

_Reverts if the tokenId doesn't have a current owner (it hasn't been minted, or it has been burned). Returns the owner.

Overrides to ownership logic should be done to {_ownerOf}._