ERC-7066 - Lockable Extension for ERC-721

Created 2023-05-25
Status Final
Category ERC
Type Standards Track
Authors
Requires

Abstract

An extension of ERC-721, this standard incorporates locking features into NFTs, allowing for various uses while preventing sale or transfer. The token's owner can lock it, setting up locker address (either an EOA or a contract) that exclusively holds the power to unlock the token. Owner can also provide approval for tokenId, enabling ability to lock asset while address holds the token approval. Token can also be locked by approved, assigning locker to itself. Upon token transfer, these rights get purged.

Motivation

ERC-721 has sparked an unprecedented surge in demand for NFTs. However, despite this tremendous success, the NFT economy suffers from secondary liquidity where it remains illiquid in owner’s wallet. There are projects which aim to address the liquidity challenge, but they entail the below mentioned inconveniences and risks for owners as they necessitate transferring the participating NFTs to the projects' contracts.

The aforementioned issues contribute to a poor user experience (UX), and we propose enhancing the ERC-721 standard by implementing a native locking mechanism: Rather than being transferred to a smart contract, an NFT remains securely stored in self-custody but is locked. During the lock period, the NFT's transfer is restricted while its other properties remain unchanged. NFT Owner retains the ability to use or distribute it’s utility.

NFTs have numerous use cases where the NFT must remain within the owner's wallet, even when it serves as collateral for a loan. Whether it's authorizing access to a Discord server, or utilizing NFT within a play-to-earn (P2E) game, owner should have the freedom to do so throughout the lending period. Just as real estate owner can continue living in their mortgaged house, take personal loan or keep tenants to generate passive income, these functionalities should be available to NFT owners to bring more investors in NFT economy.

Lockable NFTs enable the following use cases :

This proposal is different from other locking proposals in number of ways:

By extending the ERC-721 standard, the proposed standard enables secure and convenient management of underlying NFT assets. It natively supports prevalent NFTFi use cases such as staking, lending, and renting. We anticipate that this proposed standard will foster increased engagement of NFT owners in NFTFi projects, thereby enhancing the overall vitality of the NFT ecosystem.

Specification

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

Overview

ERC-721 compliant contracts MAY implement this EIP to provide standard methods of locking and unlocking the token at its current owner address.

Token owner MAY lock the token and assign locker to some address using lock(uint256 tokenId, address _locker) function, this MUST set locker to _locker. Token owner or approved MAY lock the token using lock(uint256 tokenId) function, this MUST set locker to msg.sender. Token MAY be unlocked by locker using unlock function. unlock function MUST delete locker mapping and default to address(0).

If the token is locked, the lockerOf function MUST return an address that is locker and can unlock the token. For tokens that are not locked, the lockerOf function MUST return address(0).

lock function MUST revert if token is already locked. unlock function MUST revert if token is not locked. ERC-721 approve function MUST revert if token is locked. ERC-721 functions that transfer ownership of a token MUST revert if token is locked, unless msg.sender is approved and locker both. After ERC-721 token transfer function call, values of locker and approved MUST be purged.

Token MAY be transferred and locked, also assign approval to locker using transferAndLock function. This is RECOMMENDED for use-cases where Token transfer and subsequent revocation is REQUIRED.

Interface

// SPDX-License-Identifier: CC0-1.0

pragma solidity >=0.7.0 <0.9.0;

/// @title Lockable Extension for ERC721
/// @dev Interface for the Lockable extension
/// @author StreamNFT 

interface IERC7066{

    /**
     * @dev Emitted when tokenId is locked
     */
    event Lock (uint256 indexed tokenId, address _locker);

    /**
     * @dev Emitted when tokenId is unlocked
     */
    event Unlock (uint256 indexed tokenId);

    /**
     * @dev Lock the tokenId if msg.sender is owner or approved and set locker to msg.sender
     */
    function lock(uint256 tokenId) external;

    /**
     * @dev Lock the tokenId if msg.sender is owner and set locker to _locker
     */
    function lock(uint256 tokenId, address _locker) external;

    /**
     * @dev Unlocks the tokenId if msg.sender is locker
     */
    function unlock(uint256 tokenId) external;

    /**
     * @dev Tranfer and lock the token if the msg.sender is owner or approved. 
     *      Lock the token and set locker to caller
     *      Optionally approve caller if bool setApprove flag is true
     */
    function transferAndLock(uint256 tokenId, address from, address to, bool setApprove) external;

    /**
     * @dev Returns the wallet, that is stated as unlocking wallet for the tokenId.
     *      If address(0) returned, that means token is not locked. Any other result means token is locked.
     */
    function lockerOf(uint256 tokenId) external view returns (address);
}

Rationale

This proposal set locker[tokenId] to address(0) when token is unlocked because we delete mapping on locker[tokenId] freeing up space. Also, this assertion helps our contract to validate if token is locked or unlocked for internal function calls.

This proposal exposes transferAndLock(uint256 tokenId, address from, address to, bool setApprove) which can be used to transfer token and lock at the receiver's address. This additionally accepts input bool setApprove which on true assign approval to locker, hence enabling locker to revoke the token (revocation conditions can be defined in contracts and approval provided to contract). This provides conditional ownership to receiver, without the privilege to transfer token.

Backwards Compatibility

This standard is compatible with ERC-721 standards.

Existing Upgradedable ERC-721 can upgrade to this standard, enabling locking capability inherently and unlock underlying liquidity features.

Test Cases

Test cases can be found here.

Reference Implementation

Reference Interface can be found here.

Reference Implementation can be found here.

Security Considerations

There are no security considerations related directly to the implementation of this standard for the contract that manages ERC-721.

Considerations for the contracts that work with lockable tokens

Copyright

Copyright and related rights waived via CC0.