ERC-721 Product Extension

------------------------------------------  DRAFT ----------------------------------------

ERC-721 PRODUCT Extension 

This Product Asset NFT specification supports a Web3.0 Composable Commerce Marketplace.


ERC-721 Product Extension works in conjunction with ERC-721 Catalog Extension to create a standard for Web3.0 Commerce.  The two specifications work together to support catalog categories, NFT categorization, search, filtering, and detailed Product Asset NFT trait discovery and display. 


These two specifications are required to construct a truly decentralized marketplace.


Authors Richard Pedersen (@rpedersen)

Created 2023-05-15

Requires EIP-721, EIP-165, EIP-6059,
Ownable, ERC6059, ERC721URIStorage, ERC721CollectionMetadata


Github project


Table of Contents



Abstract

This standard is an essential ingredient to support Web3.0 composable commerce where Ethereum blockchain becomes a component of an overall ecommerce eco-system.  Without this standard, centralized solutions like OpenSea will be required to manage Catalog NFT categorization and Catalog wide NFT trait metadata



Motivation

Current Web3.0 marketplace solutions, like OpenSea, centralize the management and access of catalog and product level metadata forcing applications to build on their propriety API's.   Projects like Decentraland Marketplace (https://market.decentraland.org), also wall off this catalog information within their own marketplace.

A truly decentralized NFT marketplace that support third party providers, sellers and affiliates will required standards like ERC-721 Catalog Extension and ERC-721 Product Extension. 

Solutions like Web3.0 Product Asset Service (PAS) leverage this standard.  PAS dynamically discovers blockchain ERC-721 collections (products) and presents those assets to third party storefronts via a GraphQL Service API.  This is an example of a Web3.0 Composable Commerce Component Service.


Specification

abstract contract ERC721ProductExtension is Ownable, ERC6059, IERC721CollectionMetadata, IERC721ProductExtension { ... }

ERC6059:  enables Product Asset NFT's to be bundled into Catalog Category NFT's described by ERC-721 Catalog Collection
IERC721CollectionMetadata: enables Product Collection to contain metadata
IERC721Metadata: enables Product Asset NFT's to contain asset trait metadata


This specification leverages IERC721CollectionMetadata to incorporate Product Collection metadata.



Collection Metadata Schema referenced by collectionUri

{

    "$schema": "http://json-schema.org/draft-07/schema#",

    "title": "Metadata Schema",

    "type": "object",

    "version": "0.0.1",

    "properties": {

        "name": {

            "type": "string",

            "description": "Identifies the asset to which this token represents."

        },

        "description": {

            "type": "string",

            "description": "Description of the asset to which this token represents."

        },

        "image": {

            "type": "string",

            "description": "Header image for product"

        },

        "attributeTypes": {

            "type": "array",

            "items": {

                "type": "object",

                "properties": {

                    "name": {

                        "type": "string",

                        "description": "Name of trait."

                    },

                    "display_name": {

                        "type": "string",

                        "description": "Display name of trait."

                    },

                    "struct_type": {

                        "type": "string",

                        "description": "scalar, list, range, location, point, ..."

                    },

                    "scalar_type": {

                        "type": "string",

                        "description": "string, integer, boolean, number, ..."

                    },

                    "min": {

                        "type": [

                            "string",

                            "integer",

                            "number",

                            "boolean"

                        ],

                        "description": "min for trait."

                    },

                    "max": {

                        "type": [

                            "string",

                            "integer",

                            "number",

                            "boolean"

                        ],

                        "description": "min for trait."

                    },

                    "list": {

                        "type": "array",

                        "items": {

                            "type": [

                                "string",

                                "integer",

                                "number",

                                "boolean"

                            ],

                            "description": "list values"

                        }

                    }


                }

            },

            "required": [

                "name",

                "description"

            ]

        }

    },

    "required": [

        "name",

        "image",

        "description"

    ]

}



Example Collection metadata (describes Product)


{

    "name": "Decentraland",

    "description": "....",

    "image": "https://....",

    "attributeTypes": [

        {

            "name": "type",

            "display_name": "type",

            "struct_type": "list",

            "scalar_type": "string",

            "list": [

                "parcel",

                "estate"

            ]

        },

        {

            "name": "status",

            "display_name": "status",

            "struct_type": "list",

            "scalar_type": "string",

            "list": [

                "buy",

                "rent"

            ]

        },

        {

            "name": "x",

            "display_name": "x",

            "struct_type": "scalar",

            "scalar_type": "integer",

            "min": -200,

            "max": 200

        },

        {

            "name": "y",

            "display_name": "y",

            "struct_type": "scalar",

            "scalar_type": "integer",

            "min": -200,

            "max": 200

        },

        {

            "name": "adjacent-to-road",

            "display_name": "adjacent to road",

            "struct_type": "scalar",

            "scalar_type": "boolean"

        },

        {

            "name": "near-a-district",

            "display_name": "near a district",

            "struct_type": "scalar",

            "scalar_type": "boolean"

        },

        {

            "name": "distance-to-road",

            "display_name": "distance to road",

            "struct_type": "scalar",

            "scalar_type": "integer",

            "max": 10

        },

        {

            "name": "distance-to-district",

            "display_name": "distance to district",

            "struct_type": "scalar",

            "scalar_type": "integer",

            "max": 10

        }

    ]

}



Token Schema referenced by tokenUri (describes NFT Asset Trait level data)


{

    "$schema": "http://json-schema.org/draft-07/schema#",

    "title": "Asset Metadata Schema",

    "type": "object",

    "version": "0.0.1",

    "properties": {

        "name": {

            "type": "string",

            "description": "Name of Asset"

        },

        "price": {

            "type": "number",

            "description": "Price of land"

        },

        "image": {

            "type": "string",

            "description": "Land Image"

        },

        "attributes": {

            "type": "array",

            "items": {

                "type": "object",

                "properties": {

                    "name": {

                        "type": "string",

                        "description": "Name of trait."

                    },

                    "display_type": {

                        "type": "string",

                        "description": "Sets the representation of the value of the trait."

                    },

                    "value": {

                        "type": [

                            "string",

                            "integer",

                            "number",

                            "boolean"

                        ],

                        "description": "Value for trait."

                    }

                }

            },

            "required": [

                "name",

                "value"

            ]

        }

    },

    "required": [

        "name"

    ]

}


Example of token metadata (NFT Asset)


{

    "name": "Parcel 127,88",

    "display_name": "Parcel 127,88",

    "image": "...,

    "price": 87.5,

    "attributes": [

        {

            "id": "43215860598959184859848575143834562855000-X",

            "type": "X",

            "display_name": "127",

            "display_type": "number",

            "value": 127

        },

        {

            "id": "43215860598959184859848575143834562855000-Y",

            "type": "Y",

            "display_name": "88",

            "display_type": "number",

            "value": 88

        },

        {

            "id": "43215860598959184859848575143834562855000-Type",

            "type": "Type",

            "display_name": "parcel",

            "display_type": "checkbox",

            "value": "parcel"

        }

    ]

}



Catalog Category bundling of NFT Assets.  ERC-6059 supports cross collection nested hierarchy needed to bundle Product Asset NFT's into Catalog Categories. 



Rationale

Many NFT projects represent products that are presented in eCommerce marketplaces.  Each of these products have associated NFT Assets that have unique attributes (traits).  

An example of this is the metaverses like Decentraland where they represent land with X/Y Cartesian Coordinates and Type of parcel or estate.  They also include distance values from a road or district.  The current blockchain implementation requires 3rd party applications to read all 100k plus land NFT's to get a complete understanding of metadata attributes.  There is currently no way to learn what type of scalar value or data structure these traits represent.

This current tokenUri approach to NFT metadata forces eCommerce solutions to retain a bunch of information in centralized data sources like OpenSea does.   The inclusion of collection level metadata that adhere to a standard schema allows third party application to discover and implicitly understand NFT trait data.

Web2.0 composable commerce solutions depend on product level metadata for display, facetted based filtering, attribute based pricing, and promotions.

This collection metadata standard includes an AttributeTypes section that defines each Attribute within the tokenUri metadata.  The AttributeType defines the Attribute data structure and scalar type.  It also defines the limits and candidate values for these Attributes.


 "attributeTypes": [

{

            "name": "x",

            "display_name": "x",

            "struct_type": "scalar",

            "scalar_type": "integer",

            "min": -200,

            "max": 200

        },

        {

            "name": "type",

            "display_name": "type",

            "struct_type": "list",

            "scalar_type": "string",

            "list": [

                "parcel",

                "estate"

            ]

        }

]


This standard leverages principles from:


Other interesting ERC specifications on composability




Backwards Compatibility



Security Considerations

The same security considerations as with EIP-721 apply related to using http gateways or IPFS for the collectionURI and  tokenURI method.


Copyright

Copyright and related rights waived via CC0.


Citation

Please cite this document as:

Richard Pedersen (@rpedersen), "ERC-721 Product Extension for NFTs," Ethereum Improvement Proposals, May 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-xxxx.