Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update ERC-5521: Move to Review #14

Merged
merged 3 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 84 additions & 16 deletions ERCS/erc-5521.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: Referable NFT
description: An ERC-721 extension to construct reference relationships among NFTs
author: Saber Yu (@OniReimu), Qin Wang <[email protected]>, Shange Fu <[email protected]>, Yilin Sai <[email protected]>, Shiping Chen <[email protected]>, Sherry Xu <[email protected]>, Jiangshan Yu <[email protected]>
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
Expand All @@ -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

Expand All @@ -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

Expand All @@ -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";
Expand Down Expand Up @@ -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

Expand Down
Binary file added assets/erc-5521/system-arch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading