From 70d7e37deb0f492700caae56fb5e552cce2952ff Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Thu, 25 Jan 2024 18:40:34 +0100 Subject: [PATCH 1/7] nep-393: add class metadata interface --- neps/nep-0393.md | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/neps/nep-0393.md b/neps/nep-0393.md index 9c10b0469..5a01e2eb4 100644 --- a/neps/nep-0393.md +++ b/neps/nep-0393.md @@ -290,6 +290,23 @@ pub struct ContractMetadata { pub reference_hash: Option, } +pub struct ClassMetadata { + /// Issuer class name. Required. + pub name: String, + /// If defined, should be used instead of `contract_metadata.symbol`. + pub symbol: Option, + /// An URL to an Icon. To protect fellow developers from unintentionally triggering any + /// SSRF vulnerabilities with URL parsers, we don't allow to set an image bytes here. + /// If it doesn't start with a scheme (eg: https://) + /// then `contract_metadata.base_uri` should be prepended. + pub icon: Option, + /// JSON or an URL to a JSON file with more info. If it doesn't start with a scheme + /// (eg: https://) then base_uri should be prepended. + pub reference: Option, + /// Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. + pub reference_hash: Option, +} + /// TokenMetadata defines attributes for each SBT token. pub struct TokenMetadata { pub class: ClassId, // token class. Required. Must be non zero. @@ -448,12 +465,18 @@ Example **Soul Transfer** interface: ### SBT Issuer interface -SBTContract is the minimum required interface to be implemented by issuer. Other methods, such as a mint function, which requests the registry to proceed with token minting, is specific to an Issuer implementation (similarly, mint is not part of the FT standard). +SBTIssuer is the minimum required interface to be implemented by issuer. Other methods, such as a mint function, which requests the registry to proceed with token minting, is specific to an Issuer implementation (similarly, mint is not part of the FT standard). + +The issuer must provide metadata object of the Issuer. Optionally, Issuer can also provide metadata object for each token class. +Issuer level (contract) metadata, must provide information common to all tokens and all classes defined by the issuer. Class level metadata, must provide information common to all tokens of a given class. Information should be deduplicated and denormalized whenever possible. +Example: if all tokens of a give class share the same symbol and icon, then both icon and symbol must be defined in the `ClassMetadata` and left empty (`None`) in the token metadata level. If a particular SBT (token) has to have unique icon, but we would like to keep a default icon for all tokens of a given issuer, then we can have default icon defined in the `ContractMetadata.icon` and each SBT, that has to have different icon, can have it specified in `TokenMetadata.icon`. ```rust -pub trait SBTContract { +pub trait SBTIssuer { /// returns contract metadata fn sbt_metadata(&self) -> ContractMetadata; + /// returns sbt class metadata, or None if class is not found. + fn sbt_class_metadata(&self, class: ClassId) -> Option; } ``` From 7e53ce1d55a0239546b5e94c1303a9f03d1a42d1 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Thu, 25 Jan 2024 18:48:08 +0100 Subject: [PATCH 2/7] add comment --- neps/nep-0393.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/neps/nep-0393.md b/neps/nep-0393.md index 5a01e2eb4..cb3e446dd 100644 --- a/neps/nep-0393.md +++ b/neps/nep-0393.md @@ -270,6 +270,7 @@ All time related attributes are defined in milliseconds (as per NEP-171). ```rust /// ContractMetadata defines contract wide attributes, which describes the whole contract. +/// Must be provided by the Issuer contract. See the `SBTIssuer` trait. pub struct ContractMetadata { /// Version with namespace, example: "sbt-1.0.0". Required. pub spec: String, @@ -290,6 +291,8 @@ pub struct ContractMetadata { pub reference_hash: Option, } +/// ClassMetadata defines SBT class wide attributes, which are shared and default to all SBTs of +/// the given class. Must be provided by the Issuer contract. See the `SBTIssuer` trait. pub struct ClassMetadata { /// Issuer class name. Required. pub name: String, From caaee3641687314671a0662e0defcc435ca21d42 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Thu, 25 Jan 2024 18:50:11 +0100 Subject: [PATCH 3/7] rename ContractMetadata --- neps/nep-0393.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/neps/nep-0393.md b/neps/nep-0393.md index cb3e446dd..f8e725af6 100644 --- a/neps/nep-0393.md +++ b/neps/nep-0393.md @@ -269,9 +269,9 @@ The Soulbound Token follows the NFT [NEP-171](/~https://github.com/near/NEPs/blob/ All time related attributes are defined in milliseconds (as per NEP-171). ```rust -/// ContractMetadata defines contract wide attributes, which describes the whole contract. +/// IssuerMetadata defines contract wide attributes, which describes the whole contract. /// Must be provided by the Issuer contract. See the `SBTIssuer` trait. -pub struct ContractMetadata { +pub struct IssuerMetadata { /// Version with namespace, example: "sbt-1.0.0". Required. pub spec: String, /// Issuer Name, required, ex. "Mosaics" @@ -472,12 +472,12 @@ SBTIssuer is the minimum required interface to be implemented by issuer. Other m The issuer must provide metadata object of the Issuer. Optionally, Issuer can also provide metadata object for each token class. Issuer level (contract) metadata, must provide information common to all tokens and all classes defined by the issuer. Class level metadata, must provide information common to all tokens of a given class. Information should be deduplicated and denormalized whenever possible. -Example: if all tokens of a give class share the same symbol and icon, then both icon and symbol must be defined in the `ClassMetadata` and left empty (`None`) in the token metadata level. If a particular SBT (token) has to have unique icon, but we would like to keep a default icon for all tokens of a given issuer, then we can have default icon defined in the `ContractMetadata.icon` and each SBT, that has to have different icon, can have it specified in `TokenMetadata.icon`. +Example: if all tokens of a give class share the same symbol and icon, then both icon and symbol must be defined in the `ClassMetadata` and left empty (`None`) in the token metadata level. If a particular SBT (token) has to have unique icon, but we would like to keep a default icon for all tokens of a given issuer, then we can have default icon defined in the `IssuerMetadata.icon` and each SBT, that has to have different icon, can have it specified in `TokenMetadata.icon`. ```rust pub trait SBTIssuer { /// returns contract metadata - fn sbt_metadata(&self) -> ContractMetadata; + fn sbt_metadata(&self) -> IssuerMetadata; /// returns sbt class metadata, or None if class is not found. fn sbt_class_metadata(&self, class: ClassId) -> Option; } From ae9570d9e634f75a6c3a75b35f429ae17b940bd9 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Mon, 29 Jan 2024 14:36:01 +0100 Subject: [PATCH 4/7] Apply suggestions from code review Co-authored-by: Alexander Fadeev --- neps/nep-0393.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/neps/nep-0393.md b/neps/nep-0393.md index f8e725af6..342d2fd65 100644 --- a/neps/nep-0393.md +++ b/neps/nep-0393.md @@ -294,14 +294,14 @@ pub struct IssuerMetadata { /// ClassMetadata defines SBT class wide attributes, which are shared and default to all SBTs of /// the given class. Must be provided by the Issuer contract. See the `SBTIssuer` trait. pub struct ClassMetadata { - /// Issuer class name. Required. + /// Issuer class name. Required to be not empty. pub name: String, - /// If defined, should be used instead of `contract_metadata.symbol`. + /// If defined, should be used instead of `IssuerMetadata::symbol`. pub symbol: Option, /// An URL to an Icon. To protect fellow developers from unintentionally triggering any /// SSRF vulnerabilities with URL parsers, we don't allow to set an image bytes here. /// If it doesn't start with a scheme (eg: https://) - /// then `contract_metadata.base_uri` should be prepended. + /// then `IssuerMetadata::base_uri` should be prepended. pub icon: Option, /// JSON or an URL to a JSON file with more info. If it doesn't start with a scheme /// (eg: https://) then base_uri should be prepended. @@ -472,13 +472,13 @@ SBTIssuer is the minimum required interface to be implemented by issuer. Other m The issuer must provide metadata object of the Issuer. Optionally, Issuer can also provide metadata object for each token class. Issuer level (contract) metadata, must provide information common to all tokens and all classes defined by the issuer. Class level metadata, must provide information common to all tokens of a given class. Information should be deduplicated and denormalized whenever possible. -Example: if all tokens of a give class share the same symbol and icon, then both icon and symbol must be defined in the `ClassMetadata` and left empty (`None`) in the token metadata level. If a particular SBT (token) has to have unique icon, but we would like to keep a default icon for all tokens of a given issuer, then we can have default icon defined in the `IssuerMetadata.icon` and each SBT, that has to have different icon, can have it specified in `TokenMetadata.icon`. +Example: The issuer can set a default icon for all tokens (SBT) using `IssuerMetadata::icon` and additionally it can customize an icon of a particular token via `TokenMetadata::icon`. ```rust pub trait SBTIssuer { - /// returns contract metadata + /// Returns contract metadata. fn sbt_metadata(&self) -> IssuerMetadata; - /// returns sbt class metadata, or None if class is not found. + /// Returns SBT class metadata, or `None` if the class is not found. fn sbt_class_metadata(&self, class: ClassId) -> Option; } ``` From 6dedb92c70ca693b6344877ec2b925c4284ae6b5 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Mon, 29 Jan 2024 15:14:34 +0100 Subject: [PATCH 5/7] fix link --- neps/nep-0393.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/neps/nep-0393.md b/neps/nep-0393.md index 342d2fd65..774d3b08d 100644 --- a/neps/nep-0393.md +++ b/neps/nep-0393.md @@ -300,8 +300,8 @@ pub struct ClassMetadata { pub symbol: Option, /// An URL to an Icon. To protect fellow developers from unintentionally triggering any /// SSRF vulnerabilities with URL parsers, we don't allow to set an image bytes here. - /// If it doesn't start with a scheme (eg: https://) - /// then `IssuerMetadata::base_uri` should be prepended. + /// If it doesn't start with a scheme (eg: https://) then `IssuerMetadata::base_uri` + /// should be prepended. pub icon: Option, /// JSON or an URL to a JSON file with more info. If it doesn't start with a scheme /// (eg: https://) then base_uri should be prepended. @@ -620,7 +620,7 @@ trait SBT { ## Reference Implementation -- Common [type definitions](/~https://github.com/near-ndc/i-am-human/tree/main/contracts/sbt) (events, traits). +- Common [type definitions](/~https://github.com/near-ndc/i-am-human/tree/master/contracts/sbt) (events, traits). - [I Am Human](/~https://github.com/near-ndc/i-am-human) registry and issuers. ## Consequences From 8d025c873dfd70adb17e49cccf16f83ea1836381 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Tue, 20 Feb 2024 19:13:57 +0100 Subject: [PATCH 6/7] changelog --- neps/nep-0393.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/neps/nep-0393.md b/neps/nep-0393.md index 774d3b08d..cfa5f455c 100644 --- a/neps/nep-0393.md +++ b/neps/nep-0393.md @@ -693,6 +693,25 @@ The Contract Standards Working Group members approved this NEP on June 30, 2023 | 9 | [Privacy](/~https://github.com/near/NEPs/pull/393/#issuecomment-1504309947) | Concerns have been addressed: [comment-1](/~https://github.com/near/NEPs/pull/393/#issuecomment-1504485420) and [comment2](/~https://github.com/near/NEPs/pull/393/#issuecomment-1505958549) | resolved | | 10 | @frol [suggested](/~https://github.com/near/NEPs/pull/393/#discussion_r1247879778) to use a struct in `sbt_recover` and `sbt_soul_transfer`. | Motivation to use pair `(number, bool)` rather than follow a common Iterator Pattern. Rust uses `Option` type for that, that works perfectly for languages with native Option type, but creates a "null" problem for anything else. Other common way to implement Iterator is the presented pair, which doesn't require extra type definition and reduces code size. | new | +## Changelog + +### v1.1.0 + + +In v1.0.0 we defined Issuer (an entity authorized to mint SBTs in the registry) and SBT Class. We also defined Issuer Metadata and Token Metadata, but we didn't provide interface for class metadata. This was implemented in the reference implementation (in one of the subsequent revisions), but was not backported to the NEP. This update: + +- Fixes the name of the issuer interface from `SBTContract` to `SBTIssuer`. The original name is wrong and we oversight it in reviews. We talk everywhere about the issuer entity and issuer contract (even the header is SBT Issuer interface). +- Renames `ContractMetadata` to `IssuerMetadata`. +- Adds `ClassMetadata` struct and `sbt_class_metadata` function to the `SBTIssuer` interface. + +Reference implementation: [ContractMetadata, ClassMetadata, TokenMetadata](/~https://github.com/near-ndc/i-am-human/blob/registry/v1.8.0/contracts/sbt/src/metadata.rs#L18) and [SBTIssuer interface](/~https://github.com/near-ndc/i-am-human/blob/registry/v1.8.0/contracts/sbt/src/lib.rs#L49). + +#### Benefits + +- Improves the documentation and meaning of the issuer entity. +- Adds missing `ClassMetadata`. +- Improves issuer, class and token metadata documentation. + ## Copyright [Creative Commons Attribution 4.0 International Public License (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/) From 0d2235b5ac243d102dda13ac761c2086806d9f4f Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Tue, 20 Feb 2024 19:15:09 +0100 Subject: [PATCH 7/7] lint --- neps/nep-0393.md | 1 - 1 file changed, 1 deletion(-) diff --git a/neps/nep-0393.md b/neps/nep-0393.md index cfa5f455c..567a3ebe6 100644 --- a/neps/nep-0393.md +++ b/neps/nep-0393.md @@ -693,7 +693,6 @@ The Contract Standards Working Group members approved this NEP on June 30, 2023 | 9 | [Privacy](/~https://github.com/near/NEPs/pull/393/#issuecomment-1504309947) | Concerns have been addressed: [comment-1](/~https://github.com/near/NEPs/pull/393/#issuecomment-1504485420) and [comment2](/~https://github.com/near/NEPs/pull/393/#issuecomment-1505958549) | resolved | | 10 | @frol [suggested](/~https://github.com/near/NEPs/pull/393/#discussion_r1247879778) to use a struct in `sbt_recover` and `sbt_soul_transfer`. | Motivation to use pair `(number, bool)` rather than follow a common Iterator Pattern. Rust uses `Option` type for that, that works perfectly for languages with native Option type, but creates a "null" problem for anything else. Other common way to implement Iterator is the presented pair, which doesn't require extra type definition and reduces code size. | new | -## Changelog ### v1.1.0