ERC-7066 ERC-721 lock extension (Lockable Extension for ERC-721)
Final · NFTs & multi-token · created 2023-05-25
A standard that locks an NFT while it stays in the owner's wallet, blocking only sales and transfers. By designating an address with unlock authority (the locker), it enables financial uses such as lending and rental.
Why it is needed
Until now, using an NFT (a unique digital asset on a blockchain) for collateralized loans or rental required moving the NFT into the service's smart contract (a program that runs automatically on a blockchain) for safekeeping. This creates three problems. First, the NFT leaves your wallet, so you lose utility such as community access rights or in-game use. Second, combinations such as using one NFT for a loan and a rental at the same time are hard, which reduces market liquidity. Third, if the contract holding the NFT has a bug or vulnerability, the NFT can be stolen or lost. This standard proposes locking the NFT inside the owner's wallet instead of moving it. While locked, only transfer is restricted and its other properties are preserved, so the owner can keep enjoying the NFT's utility, much like continuing to live in a house pledged as collateral.
What to implement
event Lock (uint256 indexed tokenId, address _locker);: An event emitted when a token is locked. It reports the locked token ID and the address of the unlock authority.event Unlock (uint256 indexed tokenId);: An event emitted when a token's lock is released.function lock(uint256 tokenId) external;: If the caller is the owner or an approved address, locks the token and sets the caller as the unlock authority.function lock(uint256 tokenId, address _locker) external;: If the caller is the owner, locks the token and sets the specified _locker address as the unlock authority.function unlock(uint256 tokenId) external;: If the caller is the unlock authority, unlocks the token.function transferAndLock(uint256 tokenId, address from, address to, bool setApprove) external;: If the caller is the owner or an approved address, this transfers the token, then locks it and sets the caller as the locker. If setApprove is true, it also grants approval to the caller.function lockerOf(uint256 tokenId) external view returns (address);: Returns the locker address for the token. address(0) means the token is unlocked, and any other address means it is locked.
In depth
Basic rules for locking and unlocking
There are two lock functions. lock(uint256 tokenId, address _locker) can be called by the owner and MUST set the locker to _locker. lock(uint256 tokenId) can be called by the owner or an approved address and MUST set the locker to msg.sender. unlock can only be called by the locker and MUST delete the locker mapping, resetting it to address(0). Calling lock on a token that is already locked MUST revert, and calling unlock on a token that is not locked MUST also revert.
Checking lock status with lockerOf
If the token is locked, lockerOf MUST return the locker address that can unlock it, and if the token is not locked, it MUST return address(0). Deleting the mapping on unlock so that it resets to address(0) frees storage, and it also serves as the criterion a contract uses internally to determine whether a token is locked.
Transfer and approval restrictions on locked tokens
While a token is locked, the ERC-721 approve function MUST revert. The ERC-721 transfer functions that move ownership MUST also revert, with one exception: a transfer is allowed if msg.sender is both the approved address and the locker. After a transfer function executes, both the locker and approved values MUST be cleared. In other words, when the token passes to a new owner, all previous lock and approval rights disappear.
transferAndLock and setApprove
transferAndLock(uint256 tokenId, address from, address to, bool setApprove) transfers the token and then locks it at the receiving address. If setApprove is true, it also grants approval to the locker, so the locker can retrieve the token later. The conditions for retrieval can be defined by each contract. This gives the recipient conditional ownership without transfer rights, so it is RECOMMENDED for cases that require retrieval after transfer, such as buy now pay later (BNPL) purchases.
Differences from other locking proposals
This proposal contains only a minimal implementation of lock and unlock. It treats conditions such as time-limited locks as something that can be implemented in a separate smart contract rather than in the token contract, so any condition, such as repayment or expiry, can serve as the basis for locking and unlocking. It also separates the rights of the locker and the approver. If a token is locked together with approval, the approved address can unlock it and take the token, which enables lending, loans, and installment purchases. If a token is locked without retrieval rights and can only be unlocked when needed, an account-bound NFT can also be created.
Use cases
The use cases given in the original text include: NFT-collateralized loans, where the NFT is used as collateral while staying in the wallet; uncollateralized NFT rentals, where the borrower can use the NFT but cannot transfer it; buy now pay later (BNPL) purchases, where the NFT cannot be sold until the installments are fully paid; combined use of loans and rentals at the same time; primary sales where a buyer mints first with a partial payment; and soulbound (non-transferable) tokens, which an organization issues by designating itself as the locker. For security, if a cold wallet is designated as the locker, the NFT cannot be transferred without the cold wallet even if the everyday wallet is hacked.
Compatibility and status
This standard is compatible with ERC-721 and requires ERC-165 and ERC-721. Existing upgradeable ERC-721 contracts can be upgraded to this standard to add locking and make use of liquidity. This proposal has Final status.
Things to watch out for
- Locked tokens cannot be approved or transferred: Once a token is locked, it cannot be approved or transferred any further. Integrating contracts must be designed with this in mind.
- A locker that is also approved can transfer: Even while a token is locked, it can be transferred if the caller is both the locker and the approved address.
- Risk of permanent lock: If an inaccessible account or an unverified contract address is set as the locker, the token can be locked permanently.
- MEV considerations: Only authorized parties can lock and unlock, so lockable tokens have no MEV considerations.