This proposal builds on ERC-1155 and creates a standard for referring relationships and quantifiable attributes between non-isolated ERC-721 or ERC-1155 non-fungible tokens (NFTs). It enables users to build a graph of NFTs and set quantifiable attributes for each NFT, facilitating more complex NFT ecosystems. While a similar proposal exists for ERC-721 tokens, it does not provide a way to establish quantifiable relationships or object attributes.
Motivation
The current standard for NFTs lacks the ability to establish relationships and attributes between tokens. This limitation makes it difficult for users to build more complex NFT ecosystems that require referring relationships and quantifiable attributes between tokens. For example, a user may create a derivative NFT that refers to the original NFT and sets a quantifiable attribute for the relationship between the two NFTs, but without a standardized way to establish relationships and attributes between NFTs, managing these ecosystems becomes increasingly difficult and inefficient.
This proposal aims to address this issue by extending the ERC-721 and ERC-1155 standards to include the ability to establish referring relationships and quantifiable attributes between NFTs.
By enabling users to build more complex NFT ecosystems, this proposal will enhance the NFT ecosystem and open up new possibilities for NFT use cases. However, it’s important to consider potential drawbacks such as increased complexity and gas cost, and carefully design rules to mitigate these issues.
Specification
This EIP proposes the addition of five new functions to the ERC-721 and ERC-1155 standards: setRelationship, setAttribute, getRelationship, getAttribute, and getAttributeNames. These functions allow users to establish referring relationships and set quantifiable attributes between NFTs.
setRelationship
The setRelationship function establishes a referring relationship between two NFTs. It takes the following parameters:
_derivativeID: The ID of the derivative NFT that refers to the original NFT.
This function returns the value of the referring relationship between the two NFTs as a uint256 data type.
Example Usage
NFTGraphnftContract=NFTGraph(addressOfContract);// Retrieve the value of an attribute named "Color" for NFT with ID 123
bytes32colorValue=nftContract.getAttribute(123,"Color");// Retrieve the names of all attributes associated with NFT with ID 456
bytes32[]memoryattributeNames=nftContract.getAttributeNames(456);
By including these functions and methods in the specification, you establish a clear and standardized way for users and developers to read attributes associated with NFTs.
Rationale
In developing this EIP, some key design decisions were made. For example, we limited the complexity of the relationship graph that can be created by only allowing for one referring relationship between two NFTs. This helps to ensure that the graph remains manageable and does not become too complex to be useful. Additionally, we kept the gas cost of setting attributes to a minimum by only allowing for one attribute to be set at a time.
While there are currently no similar features in other blockchain languages or standards, we drew inspiration from the concept of Graph Theory, which is a branch of mathematics that studies the relationships between objects. By adding the ability to establish relationships between NFTs and set quantifiable attributes for those relationships, we believe that the extended NFT standard will become even more useful and versatile for NFT creators and users.
Backwards Compatibility
This EIP is designed to be fully backward-compatible with existing ERC-721 and ERC-1155 contracts and tokens. Existing NFT contracts and tokens will continue to function as they did before, and the new setRelationship and setAttribute functions will only be available to contracts that explicitly implement this EIP.
Reference Implementation
To assist in understanding and implementing this proposal, we provide a reference Solidity interface and contract that define the functions for establishing relationships and reading attributes. Developers can use this interface as a foundation for integrating the NFT Relationship Enhancement into their own contracts.
The NFT Relationship Enhancement contract implements the ERC-165 standard interface to allow for interface detection. This enables smart contracts and applications to check if a given contract supports the functions defined in this proposal before interacting with it.
INFTGraph Interface
// SPDX-License-Identifier: MIT
pragmasolidity^0.8.0;import"@openzeppelin/contracts/token/ERC165/IERC165.sol";// Import IERC165 for interface detection
interfaceINFTGraphisIERC165{// setRelationship: Establishes relationships between NFTs.
functionsetRelationship(uint256_originalID,uint256_derivativeID,uint256_attribute)external;// setAttribute: Sets quantifiable attributes for NFTs.
functionsetAttribute(uint256_id,stringcalldata_name,uint256_value)external;// getRelationship: Retrieves relationship values between NFTs.
functiongetRelationship(uint256_originalID,uint256_derivativeID)externalviewreturns(uint256);// getAttribute: Retrieves the value of specific attributes associated with NFTs.
functiongetAttribute(uint256_id,stringcalldata_name)externalviewreturns(bytes32);// getAttributeNames: Retrieves all attribute names associated with an NFT.
functiongetAttributeNames(uint256_id)externalviewreturns(bytes32[]memory);}
The INFTGraph interface specifies the functions for setting relationships and attributes, as well as retrieving attribute information and relationship values.
NFTGraph Contract
// SPDX-License-Identifier: MIT
pragmasolidity^0.8.0;import"@openzeppelin/contracts/introspection/ERC165.sol";// Import ERC165 for interface detection
import"./INFTGraph.sol";// Import INFTGraph interface
contractNFTGraphisINFTGraph{mapping(uint256=>mapping(uint256=>uint256))publicrelationship;mapping(uint256=>mapping(bytes32=>bytes32))publicattributes;// Implement the setRelationship and setAttribute functions as described in the EIP specification.
// Implement the supportsInterface function for ERC-165.
functionsupportsInterface(bytes4interfaceID)publicviewoverridereturns(bool){returninterfaceID==type(INFTGraph).interfaceId||super.supportsInterface(interfaceID);}// Additional implementation details...
functiongetRelationship(uint256_originalID,uint256_derivativeID)externalviewreturns(uint256){returnrelationship[_originalID][_derivativeID];}functiongetAttribute(uint256_id,stringcalldata_name)externalviewreturns(bytes32){returnbytes32(attributes[_id][_name]);}functiongetAttributeNames(uint256_id)externalviewreturns(bytes32[]memory){bytes32[]memorynames=newbytes32[](attributes[_id].length);for(uint256i=0;i<attributes[_id].length;i++){names[i]=bytes32(attributes[_id][i]);}returnnames;}functionsetRelationship(uint256originalNFT,uint256derivativeNFT,uint256relationshipValue)public{require(originalNFT!=derivativeNFT,"Original and derivative NFTs must be different");relationship[originalNFT][derivativeNFT]=relationshipValue;}functionsetAttribute(uint256nft,bytes32attributeName,bytes32attributeValue)public{attributes[nft][attributeName]=attributeValue;}}
The NFTGraph contract implements the functions specified in the INFTGraph interface and provides storage for relationships and attributes.
Developers can use this reference interface and contract as a starting point for integrating the NFT Relationship Enhancement functionality into their own projects.
The interface provides a clear and standardized way to interact with the contract, promoting consistency and ease of integration.
Security Considerations
When implementing this proposal, contract developers should consider the following security aspects:
Validation of Relationships: Contracts utilizing the setRelationship function must ensure that the relationships being established are valid and authorized by the relevant parties. Unauthorized or malicious relationships could lead to unintended consequences.
Attribute Validation: Contracts implementing the setAttribute function should carefully validate attributes to prevent malicious or harmful values. Invalid or unvalidated attributes could disrupt the functionality of the NFT ecosystem.
Access Control: Contracts should implement appropriate access control mechanisms to restrict who can call critical functions, especially those that modify relationships or attributes. Unauthorized access can lead to misuse or exploitation.
Reentrancy Protection: Consider adding reentrancy protection mechanisms to functions that modify relationships or attributes. Reentrancy attacks could otherwise be exploited to manipulate contract behavior.
By addressing these considerations, developers can enhance the security of their contracts and protect the integrity of the NFT ecosystem.