This EIP proposes a new extension for NFTs (non-fungible token, aka EIP-721): nft-hyperlink-extention (hNFT), embedding NFTs with hyperlinks, referred to as “hNFTs”. As owners of hNFTs, users may authorize a URL slot to a specific address which can be either an externally-owned account (EOA) or a contract address and hNFT owners are entitled to revoke that authorization at any time. The address which has slot authorization can manage the URL of that slot.
Motivation
As NFTs attract more attention, they have the potential to become the primary medium of Web3. Currently, end users can’t attach rich texts, videos, or images to NFTs, and there’s no way to render these rich-content attachments. Many industries eagerly look forward to this kind of rich-content attachment ability. Attaching, editing, and displaying highly customized information can usefully be standardized.
This EIP uses hyperlinks as the aforementioned form of “highly customized attachment on NFT”, and also specifies how to attach, edit, and display these attachments on 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.
Interface
IERC5489
// SPDX-License-Identifier: CC0-1.0
pragmasolidity^0.8.0;interfaceIERC5489{/**
* @dev this event emits when the slot on `tokenId` is authorzized to `slotManagerAddr`
*/eventSlotAuthorizationCreated(uint256indexedtokenId,addressindexedslotManagerAddr);/**
* @dev this event emits when the authorization on slot `slotManagerAddr` of token `tokenId` is revoked.
* So, the corresponding DApp can handle this to stop on-going incentives or rights
*/eventSlotAuthorizationRevoked(uint256indexedtokenId,addressindexedslotManagerAddr);/**
* @dev this event emits when the uri on slot `slotManagerAddr` of token `tokenId` has been updated to `uri`.
*/eventSlotUriUpdated(uint256indexedtokenId,addressindexedslotManagerAddr,stringuri);/**
* @dev
* Authorize a hyperlink slot on `tokenId` to address `slotManagerAddr`.
* Indeed slot is an entry in a map whose key is address `slotManagerAddr`.
* Only the address `slotManagerAddr` can manage the specific slot.
* This method will emit SlotAuthorizationCreated event
*/functionauthorizeSlotTo(uint256tokenId,addressslotManagerAddr)external;/**
* @dev
* Revoke the authorization of the slot indicated by `slotManagerAddr` on token `tokenId`
* This method will emit SlotAuthorizationRevoked event
*/functionrevokeAuthorization(uint256tokenId,addressslotManagerAddr)external;/**
* @dev
* Revoke all authorizations of slot on token `tokenId`
* This method will emit SlotAuthorizationRevoked event for each slot
*/functionrevokeAllAuthorizations(uint256tokenId)external;/**
* @dev
* Set uri for a slot on a token, which is indicated by `tokenId` and `slotManagerAddr`
* Only the address with authorization through {authorizeSlotTo} can manipulate this slot.
* This method will emit SlotUriUpdated event
*/functionsetSlotUri(uint256tokenId,stringcalldatanewUri)external;/**
* @dev Throws if `tokenId` is not a valid NFT. URIs are defined in RFC 3986.
* The URI MUST point to a JSON file that conforms to the "EIP5489 Metadata JSON schema".
*
* returns the latest uri of an slot on a token, which is indicated by `tokenId`, `slotManagerAddr`
*/functiongetSlotUri(uint256tokenId,addressslotManagerAddr)externalviewreturns(stringmemory);}
The authorizeSlotTo(uint256 tokenId, address slotManagerAddr) function MAY be implemented as public or external.
The revokeAuthorization(uint256 tokenId, address slotManagerAddr) function MAY be implemented as public or external.
The revokeAllAuthorizations(uint256 tokenId) function MAY be implemented as public or external.
The setSlotUri(uint256 tokenId, string calldata newUri) function MAY be implemented as public or external.
The getSlotUri(uint256 tokenId, address slotManagerAddr) function MAY be implemented as pure or view.
The SlotAuthorizationCreated event MUST be emitted when a slot is authorized to an address.
The SlotAuthorizationRevoked event MUST be emitted when a slot authorization is revoked.
The SlotUriUpdated event MUSt be emitted when a slot’s URI is changed.
The supportInterface method MUST return true when called with 0x8f65987b.
Authentication
The authorizeSlotTo, revokeAuthorization, and revokeAllAuthorizations functions are authenticated if and only if the message sender is the owner of the token.
Metadata JSON schema
{"title":"AD Metadata","type":"object","properties":{"icon":{"type":"string","description":"A URI pointing to a resource with mime type image/* representing the slot's occupier. Consider making any images at a width between 48 and 1080 pixels and aspect ration between 1.91:1 and 4:5 inclusive. Suggest to show this as an thumbnail of the target resource"},"description":{"type":"string","description":"A paragraph which briefly introduce what is the target resource"},"target":{"type":"string","description":"A URI pointing to target resource, sugguest to follow 30X status code to support more redirections, the mime type and content rely on user's setting"}}}
Rationale
Extends NFT with hyperlinks
URIs are used to represent the value of slots to ensure enough flexibility to deal with different use cases.
Authorize slot to address
We use addresses to represent the key of slots to ensure enough flexibility to deal with all use cases.
Backwards Compatibility
As mentioned in the specifications section, this standard can be fully EIP-721 compatible by adding an extension function set.
In addition, new functions introduced in this standard have many similarities with the existing functions in EIP-721. This allows developers to easily adopt the standard quickly.
Reference Implementation
You can find an implementation of this standard in ERC5489.sol.