This proposal introduces a lockable interface for ERC-721 tokens that optimizes gas usage by eliminating unnecessary events. This interface forms the foundation for the creation and management of lockable ERC-721 tokens. It provides a gas-efficient approach by emitting a DefaultLocked(bool locked) event upon deployment, setting the initial lock status for all tokens, while individual Locked(uint256 indexed tokenId, bool locked) events handle subsequent status changes for specific tokens. The interface also includes a view function locked(uint256 tokenId) to return the current lock status of a token, and a view function defaultLocked() to query the default status of a newly minted token.


Existing lockable token proposals often mandate the emission of an event each time a token is minted. This results in unnecessary gas consumption, especially in cases where tokens are permanently locked from inception to destruction (e.g., soulbounds or non-transferable badges). This proposal offers a more gas-efficient solution that only emits events upon contract deployment and status changes of individual tokens.


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.

The interface is defined as follows:

// ERC165 interfaceId 0x6b61a747
interface IERC6982 {
   * @dev MUST be emitted when the contract is deployed to establish the default lock status 
   *      for all tokens. Also, MUST be emitted again if the default lock status changes, 
   *      to ensure the default status for all tokens (without a specific `Locked` event) is updated.
  event DefaultLocked(bool locked);

   * @dev MUST be emitted when the lock status of a specific token changes.
   *      This status overrides the default lock status for that specific token.
  event Locked(uint256 indexed tokenId, bool locked);

   * @dev Returns the current default lock status for tokens. 
   *      The returned value MUST reflect the status indicated by the most recent `DefaultLocked` event.
  function defaultLocked() external view returns (bool);

   * @dev Returns the lock status of a specific token. 
   *      If no `Locked` event has been emitted for the token, it MUST return the current default lock status. 
   *      The function MUST revert if the token does not exist.
  function locked(uint256 tokenId) external view returns (bool);

The ERC-165 interfaceId is 0x6b61a747.


This standard seeks to optimize gas consumption by minimizing the frequency of event emission. The DefaultLocked event is designed to establish the lock status for all tokens, thereby circumventing the need to emit an event each time a new token is minted. It’s crucial to note that the DefaultLocked event can be emitted at any point in time, and is not restricted to only before the Locked events are emitted.

Tokens may alter their behavior under certain circumstances (such as after a reveal), prompting the re-emission of the DefaultLocked event to reflect the new default status. The primary objective here is to economize on gas usage by avoiding the need to emit a Locked event for each token when the default status changes.

The Locked event is utilized to document changes in the lock status of individual tokens.

The defaultLocked function returns the prevailing default lock status of a token. This function is beneficial as it fosters interaction with other contracts and averts potential conflicts with ERC-5192, which is in its final stage.

The locked function gives the current lock status of a particular token, further facilitating interaction with other contracts. If no changes have been made to a specific token ID, this function should return the value provided by the defaultLocked function.

Bear in mind that a token being designated as “locked” doesn’t necessarily imply that it is entirely non-transferable. There might be certain conditions under which a token can still be transferred despite its locked status. Primarily, the locked status relates to a token’s transferability on marketplaces and external exchanges.

To illustrate, let’s consider the Cruna protocol. In this system, an NFT owner has the ability to activate what is termed an ‘protector’. This is essentially a secondary wallet with the unique privilege of initiating key transactions. Upon setting an initiator, the token’s status is rendered ‘locked’. However, this does not impede the token’s transferability if the initiation for the transfer comes from the designated protector.

Backwards Compatibility

This standard is fully backwards compatible with existing ERC-721 contracts. It can be easily integrated into existing contracts and will not cause any conflicts or disruptions.

Reference Implementation

An example implementation is located in the assets directory.

It solves a specific use case: token’s owners losing the ownership when staking the asset in a pool. The implementation allow the pool to lock the asset, leaving the ownership to the owner. In the README you can find more details about how to compile and test the contracts.

Security Considerations

This EIP does not introduce any known security considerations. However, as with any smart contract standard, it is crucial to employ rigorous security measures in the implementation of this interface.

Copyright and related rights waived via CC0.