diff --git a/EIPS/eip-1238.md b/EIPS/eip-1238.md new file mode 100644 index 00000000000000..e64635a4aad2a1 --- /dev/null +++ b/EIPS/eip-1238.md @@ -0,0 +1,152 @@ +--- +eip: 1238 +title: Non-Transferrable Non-Fungible Tokens (Soulbound Tokens) +author: Nicola Greco, Tim Daubenschütz +discussions-to: https://github.com/ethereum/eips/issues/1238 +type: Standards Track +category: ERC +status: Draft +created: 2022-04-01 +requires: 165, 721 +--- + +## Simple Summary + +A standard interface for non-transferrable non-fungible tokens, also known as +"soulbound tokens" (short "SBT"). + +## Abstract + +The following standard allows for the implementation of a standard API for SBTs +within smart contracts. This standard provides basic functionality to gift, +mint and track SBTs. + +## Motivation + +`ERC1238` tokens inhert their metadata model from `ERC721`'s metadata. Wallets +can differentiate between `ERC1238` and transferrable `ERC721` tokens through +`ERC165`'s `supportsInterface(bytes4 interfaceID);` method. + +When a wallet detects support for `IERC721Metadata` (`interfaceID`: +`0x5b5e139f`), it can additonal check if transfer functionality via + +- `IERC721` (`interfaceID`: `0x80ac58cd`); or +- soulbound properties via `IERC1238` (`interfaceID`: `0xad5ec850`) + +are supported. + +Since `ERC1238` supports `ERC721Metadata`, if implemented correctly, `ERC721` wallets +should be able to display `ERC1238` tokens without the need for any modifications +from developers. `ERC721`'s transfer functionality could be hidden from the UI if +`interfaceID` `0x80ac58cd` isn't supported or `ERC1238`'s `interfaceID` is +detected. + +## 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. + +**Every `ERC1238` compliant contract must implement the `ERC1238`, +`ERC721Metadata` and `ERC165` interfaces** (subject to "caveats" below): + +```solidity +pragma solidity ^0.8.6; + +/// @title ERC-1238 Non-Transferrable Non-Fungible Token Standard +/// @dev See https://eips.ethereum.org/EIPS/eip-1238 +/// Note: the ERC-165 identifier for this interface is 0xad5ec850. +interface IERC1238 /* is ERC165, ERC721Metadata */ { + /// @dev This emits when bond of any SBT is established by any mechanism. + /// This event emits when SBTs are created (`from` == 0) and destroyed + /// (`to` == 0). Exception: during contract creation, any number of SBTs + /// may be created and assigned without emitting Bond. + event Bond(address indexed _from, address indexed _to, uint256 indexed _tokenId); + /// @notice Find the address bound to an ERC1238 soulbound token (short "SBT") + /// @dev SBTs assigned to zero address are considered invalid, and queries + /// about them do throw. + /// @param _tokenId The identifier for an SBT + /// @return The address of the owner bound to the SBT + function boundTo(uint256 _tokenId) external view returns (address); +} + +interface ERC165 { + /// @notice Query if a contract implements an interface + /// @param interfaceID The interface identifier, as specified in ERC-165 + /// @dev Interface identification is specified in ERC-165. This function + /// uses less than 30,000 gas. + /// @return `true` if the contract implements `interfaceID` and + /// `interfaceID` is not 0xffffffff, `false` otherwise + function supportsInterface(bytes4 interfaceID) external view returns (bool); +} + +/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension +/// @dev See https://eips.ethereum.org/EIPS/eip-721 +/// Note: the ERC-165 identifier for this interface is 0x5b5e139f. +interface ERC721Metadata /* is ERC721 */ { + /// @notice A descriptive name for a collection of NFTs in this contract + function name() external view returns (string _name); + + /// @notice An abbreviated name for NFTs in this contract + function symbol() external view returns (string _symbol); + + /// @notice A distinct Uniform Resource Identifier (URI) for a given asset. + /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC + /// 3986. The URI may point to a JSON file that conforms to the "ERC721 + /// Metadata JSON Schema". + function tokenURI(uint256 _tokenId) external view returns (string); +} +``` + +For "ERC721 Metadata JSON Schema", see `ERC721` document. + +### Caveats + +No caveats known for now. + +## Rationale + +Since 2018, the Ethereum community has been seeking consensus for a standard +for non-transferrable non-fungible token. + +For `ERC1238`, we propose: + +- `event Bond(address indexed _from, address indexed _to, uint256 indexed _tokenId)`, essentially `ERC721`'s Transfer event but renamed to "Bond". +- `function boundTo(uint256 _tokenId) external view returns (address)`, + essentially `ERC721`'s `ownerOf(uint256 _tokenId)` but renamed to `boundTo`. + +The benefit of using the `ERC721Metadata` interface is that implementers (e.g. +wallets) of `ERC1238` can identify transfer and tracking functionality using the +`ERC165` `supportsInterface(bytes4 interfaceID)` function. + +## Backwards Compatibility + +We have adopted the `ERC165` and `ERC721Metadata` functions. `ERC1238`'s +`boundTo` function is the pendant to `ERC721`'s `ownerOf` function. + +## Test Cases + +See "Implementations" section. + +## Implementations + +- [rugpullindex/ERC1238](https://github.com/rugpullindex/ERC1238) is a minimal + implementation using `burn` and `mint` and test cases released under GNU + General Public License v3.0. + +## References + +**Standards** + +1. [ERC-165](./eip-165.md) Standard Interface Detection. +1. [ERC-721](https://github.com/ethereum/EIPs/issues/721) Token Standard. +1. Soulbound. https://vitalik.ca/general/2022/01/26/soulbound.html +1. RFC 2119 Key words for use in RFCs to Indicate Requirement Levels. https://www.ietf.org/rfc/rfc2119.txt + +**Issues** + +1. The Original ERC-1238 Issue. https://github.com/ethereum/eips/issues/1238 + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).