--- eip: 5516 title: Soulbound Multi-owner Tokens description: An interface for non-transferable, Multi-owner NFTs binding to Ethereum accounts author: Lucas Martín Grasso Ramos (@LucasGrasso), Matias Arazi (@MatiArazi) discussions-to: https://ethereum-magicians.org/t/EIP-5516-soulbound-multi-token-standard/10485 status: Review type: Standards Track category: ERC created: 2022-08-19 requires: 165, 1155 --- ## Abstract This EIP proposes a standard interface for non-fungible double signature Soulbound multi-tokens. Previous account-bound token standards face the issue of users losing their account keys or having them rotated, thereby losing their tokens in the process. This EIP provides a solution to this issue that allows for the recycling of SBTs. ## Motivation This EIP was inspired by the main characteristics of the [EIP-1155](./eip-1155.md) token and by articles in which benefits and potential use cases of Soulbound/Accountbound Tokens (SBTs) were presented. This design also allows for batch token transfers, saving on transaction costs. Trading of multiple tokens can be built on top of this standard and it removes the need to approve individual token contracts separately. It is also easy to describe and mix multiple fungible or non-fungible token types in a single contract. ### Characteristics - The NFT will be non-transferable after the initial transfer - Partially compatible with [EIP-1155](./eip-1155.md) - Double Signature - Multi-Token - Multi-Owner - Semi-Fungible ### Applications - Academic Degrees - Code audits - POAPs (Proof of Attendance Protocol NFTs) ## 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. **Smart contracts implementing this EIP MUST implement all of the functions in the `EIP-5516` interface.** **Smart contracts implementing this EIP MUST implement the [EIP-165](./eip-165.md) `supportsInterface` function and and MUST return the constant value `true` if `0x8314f22b` is passed through the `interfaceID` argument. They also MUST implement the [EIP-1155](./eip-1155.md) Interface and MUST return the constant value `true` if `0xd9b67a26` is passed through the `interfaceID` argument. Furthermore, they MUST implement the [EIP-1155](./eip-1155.md) Metadata interface, and MUST return the constant value `true` if `0x0e89341c` is passed through the `interfaceID` argument.** _See [EIP-1155](./eip-1155.md#specification)_ ```solidity // SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.4; /** @title Soulbound, Multi-Token standard. @notice Interface of the EIP-5516 Note: The ERC-165 identifier for this interface is 0x8314f22b. */ interface IERC5516 { /** * @dev Emitted when `account` claims or rejects pending tokens under `ids[]`. */ event TokenClaimed( address indexed operator, address indexed account, bool[] actions, uint256[] ids ); /** * @dev Emitted when `from` transfers token under `id` to every address at `to[]`. */ event TransferMulti( address indexed operator, address indexed from, address[] to, uint256 amount, uint256 id ); /** * @dev Get tokens owned by a given address. */ function tokensFrom(address from) external view returns (uint256[] memory); /** * @dev Get tokens awaiting to be claimed by a given address. */ function pendingFrom(address from) external view returns (uint256[] memory); /** * @dev Claims or Reject pending `id`. * * Requirements: * - `account` must have a pending token under `id` at the moment of call. * - `account` must not own a token under `id` at the moment of call. * * Emits a {TokenClaimed} event. * */ function claimOrReject( address account, uint256 id, bool action ) external; /** * @dev Claims or Reject pending tokens under `ids[]`. * * Requirements for each `id` `action` pair: * - `account` must have a pending token under `id` at the moment of call. * - `account` must not own a token under `id` at the moment of call. * * Emits a {TokenClaimed} event. * */ function claimOrRejectBatch( address account, uint256[] memory ids, bool[] memory actions ) external; /** * @dev Transfers `id` token from `from` to every address at `to[]`. * * Requirements: * * - `from` MUST be the creator(minter) of `id`. * - All addresses in `to[]` MUST be non-zero. * - All addresses in `to[]` MUST have the token `id` under `_pendings`. * - All addresses in `to[]` MUST not own a token type under `id`. * * Emits a {TransfersMulti} event. * */ function batchTransfer( address from, address[] memory to, uint256 id, uint256 amount, bytes memory data ) external; } ``` ## Rationale ### SBT as an extension of EIP-1155 We believe that Soulbound Tokens serve as a specialized subset of existing [EIP-1155](./eip-1155.md) tokens. The advantage of such a design is the seamless compatibility of SBTs with existing NFT services. Service providers can treat SBTs like NFTs and do not need to make drastic changes to their existing codebase. Making the standard mostly compatible with [EIP-1155](./eip-1155.md) also allows for SBTs to bind to multiple addresses and to Smart Contracts. ### Double-Signature The Double-Signature functionality was implemented to prevent the receipt of unwanted tokens. It symbolizes a handshake between the token receiver and sender, implying that **both** parties agree on the token transfer. ### Metadata. The [EIP-1155](./eip-1155.md#metadata) Metadata Interface was implemented for further compatibility with [EIP-1155](./eip-1155.md). ### Guaranteed log trace > As the Ethereum ecosystem continues to grow, many DApps are relying on traditional databases and explorer API services to retrieve and categorize data. The EIP-1155 standard guarantees that event logs emitted by the smart contract will provide enough data to create an accurate record of all current token balances. A database or explorer may listen to events and be able to provide indexed and categorized searches of every EIP-1155 token in the contract. _Quoted from [EIP-1155](./eip-1155.md#guaranteed-log-trace)_ This EIP extends this concept to the Double Signature functionality: The `{TokenClaimed}` event logs all the necessary information of a `ClaimOrReject(...)` or `ClaimOrRejectBatch(...)` function call, storing relevant information about the actions performed by the user. This also applies to the `batchTransfer(...)` function: It emits the `{TransferMulti}` event and logs necessary data. ### Exception handling Given the non-transferability property of SBTs, if a user's keys to an account get compromised or rotated, such user may lose the ability to associate themselves with the token. **Given the multi-owner characteristic of [EIP-1155](./eip-1155.md) compliant interfaces and contracts, SBTs will be able to bind to multiple accounts, providing a potential solution to the issue.** Multi-owner SBTs can also be issued to a contract account that implements a multi-signature functionality (As recommended in [EIP-4973](./eip-4973.md#exception-handling)); this can be achieved via the [EIP-1155](./eip-1155.md#erc-1155-token-receiver) Token Receiver interface. ### Multi-token The multi-token functionality permits the implementation of multiple token types in the same contract. Furthermore, all emitted tokens are stored in the same contract, preventing redundant bytecode from being deployed to the blockchain. It also facilitates transfer to token issuers, since all issued tokens are stored and can be accessed under the same contract address. ### The `batchTransfer` function This EIP supports transfers to multiple recipients. This eases token transfer to a large number of addresses, making it more gas-efficient and user-friendly. ## Backwards Compatibility This proposal is only partially compatible with EIP-1155, because it makes tokens non-transferable after the first transfer. ## Reference Implementation You can find an implementation of this standard in [../assets/EIP-5516](../assets/eip-5516/ERC5516.sol). ## Security Considerations Needs discussion. ## Copyright Copyright and related rights waived via [CC0](../LICENSE.md).