--- eip: 6785 title: ERC-721 Utilities Information Extension description: Provide easy access to information about the `utility` of an NFT via functions and the NFT's metadata author: Otniel Nicola (@OT-kthd), Bogdan Popa (@BogdanKTHD) discussions-to: https://ethereum-magicians.org/t/eip-6785-erc-721-utilities-extension/13568 status: Draft type: Standards Track category: ERC created: 2023-03-27 requires: 165, 721 --- ## Abstract This specification defines standard functions and an extension of the metadata schema that outlines what a token's utility entails and how the utility may be used and/or accessed. This specification is an optional extension of [ERC-721](./eip-721.md). ## Motivation This specification aims to clarify what the utility associated with an NFT is and how to access this utility. Relying on third-party platforms to obtain information regarding the utility of the NFT that one owns can lead to scams, phishing or other forms of fraud. Currently, utilities that are offered with NFTs are not captured on-chain. We want the utility of an NFT to be part of the metadata of an NFT. The metadata information would include: a) type of utility, b) description of utility, c) frequency and duration of utility, and d) expiration of utility. This will provide transparency as to the utility terms, and greater accountability on the creator to honor these utilities. As the instructions on how to access a given utility may change over time, there should be a historical record of these changes for transparency. ## Specification The keywords “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 contract compliant with [ERC-6785](./eip-6785.md) MUST implement the interface defined as follows: ### Contract Interface ```solidity // @title NFT Utility description /// Note: the EIP-165 identifier for this interface is ed231d73 interface IERC6785 { // Logged when the utility description URL of an NFT is changed /// @notice Emitted when the utilityURL of an NFT is changed /// The empty string for `utilityUri` indicates that there is no utility associated event UpdateUtility(uint256 indexed tokenId, string utilityUri); /// @notice set the new utilityUri - remember the date it was set on /// @dev The empty string indicates there is no utility /// Throws if `tokenId` is not valid NFT /// @param utilityUri The new utility description of the NFT /// 4a048176 function setUtilityUri(uint256 tokenId, string utilityUri) external; /// @notice Get the utilityUri of an NFT /// @dev The empty string for `utilityUri` indicates that there is no utility associated /// @param tokenId The NFT to get the user address for /// @return The utility uri for this NFT /// 5e470cbc function utilityUriOf(uint256 tokenId) external view returns (string memory); /// @notice Get the changes made to utilityUri /// @param tokenId The NFT to get the user address for /// @return The history of changes to `utilityUri` for this NFT /// f96090b9 function utilityHistoryOf(uint256 tokenId) external view returns (string[] memory); } ``` All functions defined as view MAY be implemented as pure or view Function `setUtilityUri` MAY be implemented as public or external. Also, the ability to set the `utilityUri` SHOULD be restricted to the one who's offering the utility, whether that's the NFT creator or someone else. The event `UpdateUtility` MUST be emitted when the `setUtilityUri` function is called or any other time that the utility of the token is changed, like in batch updates. The method `utilityHistoryOf` MUST reflect all changes made to the `utilityUri` of a tokenId, whether that's done through `setUtilityUri` or by any other means, such as bulk updates The `supportsInterface` method MUST return true when called with `ed231d73` The original metadata SHOULD conform to the “ERC-6785 Metadata with utilities JSON Schema” which is a compatible extension of the “ERC-721 Metadata JSON Schema” defined in ERC-721. “ERC-6785 Metadata with utilities JSON Schema” : ```json { "title": "Asset Metadata", "type": "object", "properties": { "name": { "type": "string", "description": "Identifies the asset to which this NFT represents" }, "description": { "type": "string", "description": "Describes the asset to which this NFT represents" }, "image": { "type": "string", "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." }, "utilities": { "type": "object", "required": [ "type", "description", "t&c" ], "properties": { "type": { "type": "string", "description": "Describes what type of utility this is" }, "description": { "type": "string", "description": "A brief description of the utility" }, "properties": { "type": "array", "description": "An array of possible properties describing the utility, defined as key-value pairs", "items": { "type": "object" } }, "expiry": { "type": "number", "description": "The period of time for the validity of the utility, since the minting of the NFT. Expressed in seconds" }, "t&c": { "type": "string", "description": "" } } } } } ``` ## Rationale Since the `utilityUri` could contain information that has to be restricted to some level and could be dependent on an off-chain tool for displaying said information, the creator needs the ability to modify it in the event the off-chain tool or platform becomes unavailable or inaccessible. For transparency purposes, having a `utilityHistoryOf` method will make it clear how the `utilityUri` has changed over time. For example, if a creator sells an NFT that gives holders a right to a video call with the creator, the metadata for this utility NFT would read as follows: ```json { "name": "...", "description": "...", "image": "...", "utilities": { "type": "Video call", "description": "I will enter a private video call with whoever owns the NFT", "properties": [ { "sessions": 2 }, { "duration": 30 }, { "time_unit": "minutes" } ], "expiry": 1.577e+7, "t&c": "https://...." } } ``` In order to get access to the details needed to enter the video call, the owner would access the URI returned by the `getUtilityUri` method for the NFT that they own. Additionally, access to the details could be conditioned by the authentication with the wallet that owns the NFT. The current status of the utility would also be included in the URI (eg: how many sessions are still available, etc.) ## Backwards Compatibility This standard is compatible with current ERC-721 standard. There are no other standards that define similar methods for NFTs and the method names are not used by other ERC-721 related standards. ## Test Cases Test cases are available [here](../assets/eip-6785/test/ERC6785.test.js) ## Reference Implementation The reference implementation can be found [here](../assets/eip-6785/contracts/ERC6785.sol). ## Security Considerations There are no security considerations related directly to the implementation of this standard. ## Copyright Copyright and related rights waived via [CC0-1.0](../LICENSE.md).