The Lockable Extension for ERC-1155 introduces a robust locking mechanism for specific Non-Fungible Tokens (NFTs) within the ERC-1155 token standard, 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.
Inspired by the need for enhanced security and control over tokenized assets, this extension enables token owners to lock individual NFTs with tokenId
, ensuring that only approved users can withdraw predetermined amounts of locked tokens. Thus, offering a safer approach by allowing token owners to specify approved token IDs and amounts for withdrawal.
ERC-1155 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-1155 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 :
locker
, send token to user and lock the asset.This proposal is different from other locking proposals in number of ways:
lock
and unlock
and believes other conditions like time-bound are great ideas but can be achieved without creating a specific implementation. Locking and Unlocking can be based on any conditions (e.g. repayment, expiry). Therefore time-bound unlocks a relatively specific use case that can be achieved via smart-contracts themselves without that being a part of the token contract.transferAndLock
which can be used to transfer, lock and optionally approve token. Enabling the possibility of revocation after transfer.By extending the ERC-1155 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.
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.
ERC-1155 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 account, address _locker, uint256 amount)
function, this MUST set locker
to _locker
. Token owner or approved MAY lock
the token using lock(uint256 tokenId, address account, uint256 amount
function, this MUST set locker
to msg.sender
. Token MAY be unlocked
by locker
using unlock(uint256 tokenId, address account, uint256 amount)
function.
Token owner MAY approve
specific for specific tokenId
using setApprovalForId(uint256 tokenId, address operator, uint256 amount)
ensuring only approved tokenId could be spent by operator. getApprovalForId(uint256 tokenId, address account, address operator)
SHALL return amount
approved on account
by operator
.
If the token is locked
, the getLocked(uint256 tokenId, address account, address operator)
function MUST return an amount that is locked
by operator
on account
. For tokens that are not locked
, the getLocked(uint256 tokenId, address account, address operator)
function MUST return 0
.
lock
function MUST revert if account
has insufficient balance or not owner
or approved
of tokenId
. unlock
function MUST revert if provided amount
of tokenId
is not locked
. ERC-1155 safeTransferFrom
of a token MUST revert if account
transfer locked
amount, maximum transferable amount MUST be balance - getLocked
.
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.
// SPDX-License-Identifier: CC0-1.0
pragma solidity >=0.7.0 <0.9.0;
/// @title Lockable Extension for ERC1155
/// @dev Interface for the Lockable extension
/// @author piyush-chittara
interface IERCLockable1155 is IERC1155{
/**
* @dev Emitted when tokenId is locked
*/
event Lock(uint256 indexed tokenId, address account, address _locker, uint256 amount);
/**
* @dev Emitted when tokenId is unlocked
*/
event Unlock (uint256 indexed tokenId, address account, address _locker, uint256 amount);
/**
* @dev Lock the tokenId if msg.sender is owner or approved and set locker to msg.sender
*/
function lock(uint256 tokenId, address account, uint256 amount) external;
/**
* @dev Lock the tokenId if msg.sender is owner and set locker to _locker
*/
function lock(uint256 tokenId, address account, address _locker, uint256 amount) external;
/**
* @dev Unlocks the tokenId if msg.sender is locker
*/
function unlock(uint256 tokenId, address account, uint256 amount) 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(address from, address to, uint256 tokenId, uint256 amount, bool setApprove) external;
/**
* @dev Returns the wallet, that is stated as unlocking wallet for the tokenId.
* If (0) returned, that means token is not locked. Any other result means token is locked.
*/
function getLocked(uint256 tokenId, address account, address operator) external view returns (uint256);
function setApprovalForId(uint256 tokenId, address operator, uint256 amount) external;
}
This proposal exposes transferAndLock(address from, address to, uint256 tokenId, uint256 amount, 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.
This standard is compatible with ERC-1155 standards.
Existing Upgradeable ERC-1155 can upgrade to this standard, enabling locking capability inherently and unlock underlying liquidity features.
Reference Interface can be found here.
Reference Implementation can be found here.
There are no security considerations related directly to the implementation of this standard for the contract that manages ERC-1155.
amount
is locked
, specified amount
can not be transferred from locked account
.locked
and caller is locker
and approved
both, caller can transfer the token.locked
token with locker
as in-accesible account or un-verified contract address can lead to permanent lock of the token.Copyright and related rights waived via CC0.