⚠️ This EIP is not recommended for general use or implementation as it is likely to change.

EIP-4973: Account-bound Tokens Source

A standard interface for non-transferrable NFTs binding to an Ethereum account like a legendary World of Warcraft item binds to a character.

AuthorTim Daubenschütz, Raphael Roullet
Discussions-Tohttps://ethereum-magicians.org/t/eip-4973-non-transferrable-non-fungible-tokens-soulbound-tokens-or-badges/8825
StatusDraft
TypeStandards Track
CategoryERC
Created2022-04-01
Requires 165, 721

Abstract

Proposes a standard API for account-bound Tokens (ABT) within smart contracts. An ABT is a non-fungible token bound to a single account. ABTs don’t implement a canonical interface for transfers. This EIP defines basic functionality to mint, assign, revoke and track ABTs.

Motivation

In the popular MMORPG World of Warcraft, its game designers intentionally took some items out of the world’s auction house market system to prevent them from having a publicly-discovered price and limit their accessibility.

Vanilla WoW’s “Thunderfury, Blessed Blade of the Windseeker” was one such legendary item, and it required a forty-person raid, among other sub-tasks, to slay the firelord “Ragnaros” to gain the “Essence of the Firelord,” a material needed to craft the sword once.

Upon voluntary pickup, the sword permanently binds to a character’s “soul,” making it impossible to trade, sell or even swap it between a player’s characters.

In other words, “Thunderfury”’s price was the aggregate of all social costs related to completing the difficult quest line with friends and guild members. Other players spotting Thunderfuries could be sure their owner had slain “Ragnaros,” the blistering firelord.

World of Warcraft players could trash legendary and soulbound items like the Thunderfury to permanently remove them from their account.

The Ethereum community has expressed a need for non-transferrable, non-fungible, and socially-priced tokens similar to WoW’s soulbound items. Popular contracts implicitly implement account-bound interaction rights today. A principled standardization helps interoperability and improves on-chain data indexing.

The purpose of this document is to make ABTs a reality on Ethereum by creating consensus around a maximally backward-compatible but otherwise minimal interface definition.

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.

EIP-4973 tokens must implement the interfaces:

  • EIP-165’s ERC165 (0x01ffc9a7)
  • EIP-721’s ERC721Metadata (0x5b5e139f)

EIP-4973 tokens must not implement the interfaces:

An ABT receiver must be able to always call function burn(address _tokenId) to disassociate themselves from an ABT publicly.

// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.6;

/// @title Account-bound tokens
/// @dev See https://eips.ethereum.org/EIPS/eip-4973
///  Note: the ERC-165 identifier for this interface is 0x5164cf47.
interface IERC4973 /* is ERC165, ERC721Metadata */ {
  /// @dev This emits when a new token is created and bound to an account by
  /// any mechanism.
  /// Note: For a reliable `from` parameter, retrieve the transaction's
  /// authenticated `from` field.
  event Attest(address indexed to, uint256 indexed tokenId);
  /// @dev This emits when an existing ABT is revoked from an account and
  /// destroyed by any mechanism.
  /// Note: For a reliable `from` parameter, retrieve the transaction's
  /// authenticated `from` field.
  event Revoke(address indexed to, uint256 indexed tokenId);
  /// @notice Count all ABTs assigned to an owner
  /// @dev ABTs assigned to the zero address are considered invalid, and this
  ///  function throws for queries about the zero address.
  /// @param owner An address for whom to query the balance
  /// @return The number of ABTs owned by `owner`, possibly zero
  function balanceOf(address owner) external view returns (uint256);
  /// @notice Find the address bound to an ERC4973 account-bound token
  /// @dev ABTs assigned to zero address are considered invalid, and queries
  ///  about them do throw.
  /// @param tokenId The identifier for an ABT
  /// @return The address of the owner bound to the ABT
  function ownerOf(uint256 tokenId) external view returns (address);
  /// @notice Destroys `tokenId`. At any time, an ABT receiver must be able to
  ///  disassociate themselves from an ABT publicly through calling this
  ///  function.
  /// @dev Must emit a `event Revoke` with the `address to` field pointing to
  ///  the zero address.
  /// @param tokenId The identifier for an ABT
  function burn(uint256 tokenId) external;
}

See EIP-721 for a definition of its metadata JSON Schema.

Rationale

Interface

EIP-4973 shall be maximally backward-compatible but still only expose a minimal and simple to implement interface definition.

As EIP-721 tokens have seen widespread adoption with wallet providers and marketplaces, using its ERC721Metadata interface with EIP-165 for feature-detection potentially allows implementers to support EIP-4973 tokens out of the box.

If an implementer of EIP-721 properly built EIP-165’s function supportsInterface(bytes4 interfaceID) function, already by recognizing that EIP-721’s track and transfer interface component with the identifier 0x80ac58cd is not implemented, transferring of a token should not be suggested as a user interface option.

Still, since EIP-4973 supports EIP-721’s ERC721Metadata extension, wallets and marketplaces should display an account-bound token with no changes needed.

Although other implementations of account-bound tokens are possible, e.g., by having all transfer functions revert, EIP-4973 is superior as it supports feature detection through EIP-165.

We expose function burn(address _tokenId) and require it to be callable at any time by an ABT’s owner as it ensures an owner’s right to publicly disassociate themselves from what has been issued towards their account.

Exception handling

Given the non-transferable between accounts property of ABTs, if a user’s keys to an account or a contract get compromised or rotated, a user may lose the ability to associate themselves with the token. In some cases, this can be the desired effect. Therefore, EIP-4973 implementers should build re-issuance and revocation processes to enable recourse. We recommend implementing strictly decentralized, permissionless, and censorship-resistant re-issuance processes.

But this document is deliberately abstaining from offering a standardized form of exception handling in cases where user keys are compromised or rotated.

In cases where implementers want to make account-bound tokens shareable among different accounts, e.g., to avoid losing access when keys get compromised, we suggest issuing the account-bound token towards a contract’s account that implements a multi-signature functionality.

Provenance Indexing

ABTs can be indexed by tracking the emission of event Attest and event Revoke. To guarantee reliable and implementation-independent indexable information, neither event Attest nor event Revoke include a from argument to depict the transaction sender. Instead, as a from property wouldn’t be authenticated and hence opens a security vector, we omit it and advise indexers to substitute it with the transaction-level from field which gets authenticated through Ethereum’s transaction signature validation prior to inclusion in a block.

Backwards Compatibility

We have adopted the EIP-165 and ERC721Metadata functions purposefully to create a high degree of backward compatibility with EIP-721. We have deliberately used EIP-721 terminology such as function ownerOf(...) or function balanceOf(...) to minimize the effort of familiarization for EIP-4973 implementers already familiar with, e.g., EIP-20 or EIP-721.

Reference Implementation

You can find an implementation of this standard in ../assets/eip-4973.

Copyright and related rights waived via CC0.

Citation

Please cite this document as:

Tim Daubenschütz, Raphael Roullet, "EIP-4973: Account-bound Tokens [DRAFT]," Ethereum Improvement Proposals, no. 4973, April 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-4973.