diff --git a/ERCS/erc-5521.md b/ERCS/erc-5521.md index 4bf16cae95..5336c5fbd3 100644 --- a/ERCS/erc-5521.md +++ b/ERCS/erc-5521.md @@ -4,7 +4,7 @@ title: Referable NFT description: An ERC-721 extension to construct reference relationships among NFTs author: Saber Yu (@OniReimu), Qin Wang , Shange Fu , Yilin Sai , Shiping Chen , Sherry Xu , Jiangshan Yu discussions-to: https://ethereum-magicians.org/t/eip-x-erc-721-referable-nft/10310 -status: Draft +status: Review type: Standards Track category: ERC created: 2022-08-10 @@ -13,7 +13,9 @@ requires: 165, 721 ## Abstract -This standard is an extension of [ERC-721](./eip-721.md). It proposes two referrable indicators, referring and referred, and a time-based indicator `createdTimestamp`. The relationship between each NFT forms a Directed acyclic graph (DAG). The standard allows users to query, track and analyze their relationships. +This standard is an extension of [ERC-721](./eip-721.md). It proposes two referable indicators, referring and referred, and a time-based indicator `createdTimestamp`. The relationship between each NFT forms a directed acyclic graph (DAG). The standard allows users to query, track and analyze their relationships. + +![System Architecture](../assets/eip-5521/system-arch.png) ## Motivation @@ -25,18 +27,78 @@ By adding the `referring` indicator, users can mint new NFTs (e.g., C, D, E) by 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. -`Relationship`: a structure that contains `referring`, `referred`, `createdTimestamp`, and other customized attributes such as `mapping (uint256 => address) privityOfAgreement` recording the ownerships of referred NFTs at the time the rNFTs were being created. -`referring`: an out-degree indicator, used to show the users this NFT refers to; -`referred`: an in-degree indicator, used to show the users who have refereed this NFT; -`createdTimestamp`: a time-based indicator, used to compare the timestamp of mint. +- `Relationship`: a structure that contains `referring`, `referred`, `createdTimestamp`, and other customized and **OPTIONAL** attributes (i.e., not necessarily included in the standard) such as `privityOfAgreement` recording the ownerships of referred NFTs at the time the rNFTs were being created or `profitSharing` recording the profit sharing of `referring`. +- `referring`: an out-degree indicator, used to show the users this NFT refers to; +- `referred`: an in-degree indicator, used to show the users who have refereed this NFT; +- `createdTimestamp`: a time-based indicator, used to compare the timestamp of mint, which **MUST NOT** be editable anyhow by callers; + +- `safeMint`: mint a new rNFT; +- `setNode`: set the referring list of an rNFT and update the referred list of each one in the referring list; + - `setNodeReferring`: set the referring list of an rNFT; + - `setNodeReferred`: set the referred list of the given rNFTs sourced from different contracts; + - `setNodeReferredExternal`: set the referred list of the given rNFTs sourced from external contracts; +- `referringOf`: get the referring list of an rNFT; +- `referredOf`: get the referred list of an rNFT. + +Implementers of this standard **MUST** have all of the following functions: + +```solidity + +pragma solidity ^0.8.4; + +interface IERC_5521 { + + /// Logged when a node in the rNFT gets referred and changed. + /// @notice Emitted when the `node` (i.e., an rNFT) is changed. + event UpdateNode(uint256 indexed tokenId, + address indexed owner, + address[] _address_referringList, + uint256[][] _tokenIds_referringList, + address[] _address_referredList, + uint256[][] _tokenIds_referredList + ); + + /// @notice set the referred list of an rNFT associated with different contract addresses and update the referring list of each one in the referred list. Checking the duplication of `addresses` and `tokenIds` is **RECOMMENDED**. + /// @param `tokenId` of rNFT being set. `addresses` of the contracts in which rNFTs with `tokenIds` being referred accordingly. + /// @requirement + /// - the size of `addresses` **MUST** be the same as that of `tokenIds`; + /// - once the size of `tokenIds` is non-zero, the inner size **MUST** also be non-zero; + /// - the `tokenId` **MUST** be unique within the same contract; + /// - the `tokenId` **MUST NOT** be the same as `tokenIds[i][j]` if `addresses[i]` is essentailly `address(this)`. + function setNode(uint256 tokenId, address[] memory addresses, uint256[][] memory tokenIds) external; + + /// @notice set the referring list of an rNFT associated with different contract addresses. + /// @param `tokenId` of rNFT being set, `addresses` of the contracts in which rNFTs with `_tokenIds` being referred accordingly. + function setNodeReferring(address[] memory addresses, uint256 tokenId, uint256[][] memory _tokenIds) private; + + /// @notice set the referred list of an rNFT associated with different contract addresses. + /// @param `_tokenIds` of rNFTs, associated with `addresses`, referred by the rNFT with `tokenId` in `this` contract. + function setNodeReferred(address[] memory addresses, uint256 tokenId, uint256[][] memory _tokenIds) private; + + /// @notice get the referring list of an rNFT. + /// @param `tokenId` of the rNFT being focused, `_address` of contract address associated with the focused rNFT. + /// @return the referring mapping of the rNFT. + function referringOf(address _address, uint256 tokenId) external view returns(address[] memory, uint256[][] memory); + + /// @notice get the referred list of an rNFT. + /// @param `tokenId` of the rNFT being focused, `_address` of contract address associated with the focused rNFT. + /// @return the referred mapping of the rNFT. + function referredOf(address _address, uint256 tokenId) external view returns(address[] memory, uint256[][] memory); +} + +interface TargetContract { + /// @notice set the referred list of an rNFT associated with external contract addresses. + /// @param `_tokenIds` of rNFTs associated with the contract address `_address` being referred by the rNFT with `tokenId`. + /// @requirement + /// - `_address` **MUST NOT** be the same as `address(this)` where `this` is executed by an external contract where `TargetContract` interface is implemented. + function setNodeReferredExternal(address _address, uint256 tokenId, uint256[] memory _tokenIds) external; -`safeMint`: mint a new rNFT; -`setNode`: set the referring list of an rNFT and update the referred list of each one in the referring list; -`setNodeReferring`: set the referring list of an rNFT; -`setNodeReferred`: set the referred list of the given rNFTs; -`setNodeReferredExternal`: set the referred list of the given rNFTs sourced from other contracts; -`referringOf`: Get the referring list of an rNFT; -`referredOf`: Get the referred list of an rNFT. + function referringOf(address _address, uint256 tokenId) external view returns(address[] memory, uint256[][] memory); + + function referredOf(address _address, uint256 tokenId) external view returns(address[] memory, uint256[][] memory); +} + +``` ## Rationale @@ -62,8 +124,6 @@ Test cases are included in [ERC_5521.test.js](../assets/eip-5521/ERC_5521.test.j ```solidity -// SPDX-License-Identifier: MIT - pragma solidity ^0.8.4; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; @@ -237,13 +297,21 @@ contract ERC_5521 is ERC721, IERC_5521, TargetContract { ## Security Considerations +### Timestamp + The `createdTimestamp` only covers the block-level timestamp (based on block headers), which does not support fine-grained comparisons such as transaction-level. +### Ownership and Reference + The change of ownership has nothing to do with the reference relationship. Normally, the distribution of profits complies to the aggreement when the NFT was being created regardless of the change of ownership unless specified in the agreement. Referring a token will not refer its descendants by default. In the case that only a specific child token gets referred, it means the privity of contract will involve nobody other than the owner of this specific child token. Alternatively, a chain-of-reference all the way from the root token to a specific very bottom child token (from root to leaf) can be constructured and recorded in the `referring` to explicitly define the distribution of profits. -The `safeMint` function has been deliberately designed to allow unrestricted minting and relationship setting, akin to the open referencing system seen in platforms like Google Scholar. This decision facilitates strong flexibility, enabling any user to create and define relationships between tokens without centralized control. While this design aligns with the intended openness of the system, it inherently carries certain risks. Unauthorized or incorrect references can be created, mirroring the challenges faced in traditional scholarly referencing where erroneous citations may occur. Additionally, the open nature may expose the system to potential abuse by malicious actors, who might manipulate relationships or inflate token supply. It is important to recognize that these risks are not considered design flaws but intentional trade-offs, balancing the system's flexibility against potential reliability concerns. Stakeholders should be aware that the on-chain data integrity guarantees extend only to what has been recorded on the blockchain and do not preclude the possibility of off-chain errors or manipulations. Thus, users and integrators should exercise caution and judgment in interpreting and using the relationships and other data provided by this system. +### Open Minting and Relationship Risks + +The `safeMint` function has been deliberately designed to allow unrestricted minting and relationship setting, akin to the open referencing system seen in platforms such as Google Scholar. This decision facilitates strong flexibility, enabling any user to create and define relationships between NFTs without centralized control. While this design aligns with the intended openness of the system, it inherently carries certain risks. Unauthorized or incorrect references can be created, mirroring the challenges faced in traditional scholarly referencing where erroneous citations may occur. Additionally, the open nature may expose the system to potential abuse by malicious actors, who might manipulate relationships or inflate token supply. It is important to recognize that these risks are not considered design flaws but intentional trade-offs, which balances the system's flexibility against potential reliability concerns. + +Stakeholders should be aware that the on-chain data integrity guarantees extend only to what has been recorded on the blockchain and do not preclude the possibility of off-chain errors or manipulations. Thus, users and integrators should exercise caution and judgment in interpreting and using the relationships and other data provided by this system. ## Copyright diff --git a/assets/erc-5521/system-arch.png b/assets/erc-5521/system-arch.png new file mode 100644 index 0000000000..04a66feecf Binary files /dev/null and b/assets/erc-5521/system-arch.png differ