Abstract

The Minimalistic Transferable interface for Non-Fungible Tokens standard extends ERC-721 by introducing the ability to identify whether an NFT can be transferred or not.

This proposal introduces the ability to prevent a token from being transferred from their owner, making them bound to the externally owned account, abstracted account, smart contract or token that owns it.

Motivation

With NFTs being a widespread form of tokens in the Ethereum ecosystem and being used for a variety of use cases, it is time to standardize additional utility for them. Having the ability to prevent the tokens from being transferred introduces new possibilities of NFT utility and evolution.

This proposal is designed in a way to be as minimal as possible in order to be compatible with any usecases that wish to utilize this proposal.

This EIP introduces new utilities for ERC-721 based tokens in the following areas:

Verifiable attribution

Personal achievements can be represented by non-fungible tokens. These tokens can be used to represent a wide range of accomplishments, including scientific advancements, philanthropic endeavors, athletic achievements, and more. However, if these achievement-indicating NFTs can be easily transferred, their authenticity and trustworthiness can be called into question. By binding the NFT to a specific account, it can be ensured that the account owning the NFT is the one that actually achieved the corresponding accomplishment. This creates a secure and verifiable record of personal achievements that can be easily accessed and recognized by others in the network. The ability to verify attribution helps to establish the credibility and value of the achievement-indicating NFT, making it a valuable asset that can be used as a recognition of the holder’s accomplishments.

Immutable properties

NFT properties are a critical aspect of non-fungible tokens, serving to differentiate them from one another and establish their scarcity. Centralized control of NFT properties by the issuer, however, can undermine the uniqueness of these properties.

By tying NFTs to specific properties, the original owner is ensured that the NFT will always retain these properties and its uniqueness.

In a blockchain game that employs non-transferable NFTs to represent skills or abilities, each skill would be a unique and permanent asset tied to a specific player or token. This would ensure that players retain ownership of the skills they have earned and prevent them from being traded or sold to other players. This can increase the perceived value of these skills, enhancing the player experience by allowing for greater customization and personalization of characters.

Specification

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

/// @title EIP-6454 Minimalistic Non-Transferable interface for NFTs
/// @dev See https://eips.ethereum.org/EIPS/eip-6454
/// @dev Note: the ERC-165 identifier for this interface is 0x91a6262f.

pragma solidity ^0.8.16;

interface IERC6454 /* is IERC165 */ {
    /**
     * @notice Used to check whether the given token is transferable or not.
     * @dev If this function returns `false`, the transfer of the token MUST revert execution.
     * @dev If the tokenId does not exist, this method MUST revert execution, unless the token is being checked for
     *  minting.
     * @dev The `from` parameter MAY be used to also validate the approval of the token for transfer, but anyone
     *  interacting with this function SHOULD NOT rely on it as it is not mandated by the proposal.
     * @param tokenId ID of the token being checked
     * @param from Address from which the token is being transferred
     * @param to Address to which the token is being transferred
     * @return Boolean value indicating whether the given token is transferable
     */
    function isTransferable(uint256 tokenId, address from, address to) external view returns (bool);
}

In order to determine whether a token is transferable or not in general, the function SHOULD return the appropriate boolean value when passing the 0x0000000000000000000000000000000000000000 address as the to and from parameter.

The general transferability of a token should not be affected by the ability to mint the token (value of from parameter is 0x0000000000000000000000000000000000000000) and the ability to burn the token (value of to parameter is 0x0000000000000000000000000000000000000000).

If the general transferability of token is false, any kind of transfer of the token, save minting and burning, MUST revert execution.

In order to determine whether a token is mintable, the exception SHOULD be made to allow the tokenId parameter for a token that does not exist. Additionally the from parameter SHOULD be 0x0000000000000000000000000000000000000000 and the to parameter SHOULD NOT be 0x0000000000000000000000000000000000000000.

In order to determine whether a token is burnable, the from parameter SHOULD NOT be 0x0000000000000000000000000000000000000000 and the to parameter SHOULD be 0x0000000000000000000000000000000000000000.

Implementers MAY choose to validate the approval of the token for transfer by the from parameter, but anyone interacting with this function SHOULD NOT rely on it as it is not mandated by the proposal. This means that the from parameter in such implementations validates the initiator of the transaction rather than the owner from which the token is being transferred (which can either be the owner of the token or the operator allowed to transfer the token).

Rationale

Designing the proposal, we considered the following questions:

  1. Should we propose another (Non-)Transferable NFT proposal given the existence of existing ones, some even final, and how does this proposal compare to them?
    This proposal aims to provide the minimum necessary specification for the implementation of non-transferable NFTs, we feel none of the existing proposals have presented the minimal required interface. Unlike other proposals that address the same issue, this proposal requires fewer methods in its specification, providing a more streamlined solution.
  2. Why is there no event marking the token as Non-Transferable in this interface?
    The token can become non-transferable either at its creation, after being marked as non-transferable, or after a certain condition is met. This means that some cases of tokens becoming non-transferable cannot emit an event, such as if the token becoming non-transferable is determined by a block number. Requiring an event to be emitted upon the token becoming non-transferable is not feasible in such cases.
  3. Should the transferability state management function be included in this proposal?
    A function that marks a token as non-transferable or releases the binding is referred to as the transferability management function. To maintain the objective of designing an agnostic minimal transferable proposal, we have decided not to specify the transferability management function. This allows for a variety of custom implementations that require the tokens to be non-transferable.
  4. Why should this be an EIP if it only contains one method?
    One could argue that since the core of this proposal is to only prevent ERC-721 tokens to be transferred, this could be done by overriding the transfer function. While this is true, the only way to assure that the token is non-transferable before the smart contract execution, is for it to have the transferable interface.
    This also allows for smart contract to validate whether the token is not transferable and not attempt transferring it as this would result in failed transactions and wasted gas.
  5. Should we include the most straightforward method possible that only accepts a tokenId parameter?
    The initial version of the proposal contained a method that only accepted a tokenId parameter. This method would return a boolean value indicating whether the token is transferable. However, the fact that the token can be non-transferable for different reasons was brought up throughout the discussion. This is why the method was changed to accept additional parameters, allowing for a more flexible implementation. Additionally, we kept the original method’s functionality by specifying the methodology on how to achieve the same result (by passing the 0x0000000000000000000000000000000000000000 address as the to and from parameters).
  6. What is the best user experience for frontend?
    The best user experience for the front end is having a single method that checks whether the token is transferable. This method should handle both cases of transferability, general and conditional.
    The front end should also be able to handle the case where the token is not transferable and the transfer is attempted. This can be done by checking the return value of the transfer function, which will be false if the token is not transferable. If the token would just be set as non-transferable, without a standardized interface to check whether the token is transferable, the only way to validate transferability would be to attempt a gas calculation and check whether the transaction would revert. This is a bad user experience and should be avoided.
  7. Should we mandate that the isTransferable validates approvals as well?
    We considered specifying that the from parameter represents the initiator of the token transfer. This would mean that the from would validate whether the address is the owner of the token or approved to transfer it. While this might be beneficial, we ultimately decided to make it optional.
    As this proposal aims to be the minimal possible implementation and the approvals are already standardized, we feel that isTransferable can be used in conjunction with the approvals to validate whether the given address can initiate the transfer or not.
    Additionally, mandating the validation of approvals would incur higher gas consumption as additional checks would be required to validate the transferability.

Backwards Compatibility

The Minimalistic Non-Transferable token standard is fully compatible with ERC-721 and with the robust tooling available for implementations of ERC-721 as well as with the existing ERC-721 infrastructure.

Test Cases

Tests are included in transferable.ts.

To run them in terminal, you can use the following commands:

cd ../assets/eip-6454
npm install
npx hardhat test

Reference Implementation

See ERC721TransferableMock.sol.

Security Considerations

The same security considerations as with ERC-721 apply: hidden logic may be present in any of the functions, including burn, add asset, accept asset, and more.

A smart contract can implement the proposal interface but returns fraudulent values, i.e., returning false for isTransferable when the token is transferable. Such a contract would trick other contracts into thinking that the token is non-transferable when it is transferable. If such a contract exists, we suggest not interacting with it. Much like fraudulent ERC-20 or ERC-721 smart contracts, it is not possible to prevent such contracts from existing. We suggest that you verify all of the external smart contracts you interact with and not interact with contracts you do not trust.

Since the transferability state can change over time, verifying that the state of the token is transferable before interacting with it is essential. Therefore, a dApp, marketplace, or wallet implementing this interface should verify the state of the token every time the token is displayed.

Caution is advised when dealing with non-audited contracts.

Copyright and related rights waived via CC0.