From d421da5c093df5766c548cf03df0db0290b5d9f8 Mon Sep 17 00:00:00 2001 From: Andrew Westberg Date: Sat, 1 Apr 2023 14:33:33 +0000 Subject: [PATCH 1/5] CIP-0068: Add SFT Semi-fungible token support --- CIP-0067/registry.json | 5 ++ CIP-0068/README.md | 111 +++++++++++++++++++++++++++++++++++------ 2 files changed, 102 insertions(+), 14 deletions(-) diff --git a/CIP-0067/registry.json b/CIP-0067/registry.json index de6145e7e6..50ccb005be 100644 --- a/CIP-0067/registry.json +++ b/CIP-0067/registry.json @@ -13,5 +13,10 @@ "asset_name_label": 333, "class": "FT", "description": "CIP-0068 - Datum Metadata Standard (333 sub standard)" + }, + { + "asset_name_label": 444, + "class": "SFT", + "description": "CIP-0068 - Datum Metadata Standard (444 sub standard)" } ] diff --git a/CIP-0068/README.md b/CIP-0068/README.md index 4a5a60a1e6..b8c7d58c0f 100644 --- a/CIP-0068/README.md +++ b/CIP-0068/README.md @@ -93,7 +93,7 @@ extra = plutus_data datum = #6.121([metadata, version, extra]) ``` -## 222 NFT Standard +#### 222 NFT Standard Besides the necessary standard for the `reference NFT` we're introducing two specific token standards in this CIP. Note that the possibilities are endless here and more standards can be built on top of this CIP for FTs, other NFTs, semi fungible tokens, etc. The first is the `222` NFT standard with the registered `asset_name_label` prefix value @@ -102,11 +102,11 @@ Besides the necessary standard for the `reference NFT` we're introducing two spe | 222 | NFT | NFT hold by the user's wallet making use of CIP-0025 inner structure | -### Class +##### Class The `user token` represents an NFT (non-fungible token). -### Pattern +##### Pattern The `user token` and `reference NFT` **must** have an identical name, preceded by the `asset_name_label` prefix. @@ -115,7 +115,7 @@ Example:\ `reference NFT`: `(100)Test123` -### Metadata +##### Metadata This is a low-level representation of the metadata, following closely the structure of CIP-0025. All UTF-8 encoded keys and values need to be converted into their respective byte's representation when creating the datum on-chain. @@ -147,10 +147,10 @@ datum = #6.121([metadata, 1, extra]) ; version 1 ``` Example datum as JSON: ```json -{"constructor" : 0, "fields": [{"map": [{"k": "6E616D65", "v": "5370616365427564"}, {"k": "696D616765", "v": "697066733A2F2F74657374"}]}, {"int": 1}]} +{"constructor" : 0, "fields": [{"map": [{"k": {"bytes": "6E616D65"}, "v": {"bytes": "5370616365427564"}}, {"k": {"bytes": "696D616765"}, "v": {"bytes": "697066733A2F2F74657374"}}]}, {"int": 1}]} ``` -### Retrieve metadata as 3rd party +##### Retrieve metadata as 3rd party A third party has the following NFT `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(222)TestToken` they want to lookup. The steps are @@ -159,7 +159,7 @@ A third party has the following NFT `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5c 3. Get the datum from the output and lookup metadata by going into the first field of constructor 0. 4. Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex. -### Retrieve metadata from a Plutus validator +##### Retrieve metadata from a Plutus validator We want to bring the metadata of the NFT `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(222)TestToken` in the Plutus validator context. To do this we @@ -168,7 +168,7 @@ We want to bring the metadata of the NFT `d5e6bf0500378d4f0da4e8dde6becec7621cd8 3. Reference the output in the transaction. (off-chain) 4. Verify validity of datum of the referenced output by checking if policy ID of `reference NFT` and `user token` and their asset names without the `asset_name_label` prefix match. (on-chain) -## 333 FT Standard +#### 333 FT Standard The second introduced standard is the `333` FT standard with the registered `asset_name_label` prefix value @@ -177,12 +177,12 @@ The second introduced standard is the `333` FT standard with the registered `ass | 333 | FT | FT hold by the user's wallet making use of Cardano foundation off-chain registry inner structure | -### Class +##### Class The `user token` is an FT (fungible token). -### Pattern +##### Pattern The `user token` and `reference NFT` **must** have an identical name, preceded by the `asset_name_label` prefix. @@ -191,7 +191,7 @@ Example:\ `reference NFT`: `(100)Test123` -### Metadata +##### Metadata This is a low-level representation of the metadata, following closely the structure of the Cardano foundation off-chain metadata registry. All UTF-8 encoded keys and values need to be converted into their respective byte's representation when creating the datum on-chain. @@ -225,10 +225,10 @@ datum = #6.121([metadata, 1, extra]) ; version 1 ``` Example datum as JSON: ```json -{"constructor" : 0, "fields": [{"map": [{"k": "6E616D65", "v": "5370616365427564"}, {"k": "6465736372697074696F6E", "v": "54686973206973206D79207465737420746F6B656E"}]}, {"int": 1}]} +{"constructor" : 0, "fields": [{"map": [{"k": {"bytes": "6E616D65"}, "v": {"bytes": "5370616365427564"}}, {"k": {"bytes": "6465736372697074696F6E"}, "v": {"bytes": "54686973206973206D79207465737420746F6B656E"}}]}, {"int": 1}]} ``` -### Retrieve metadata as 3rd party +##### Retrieve metadata as 3rd party A third party has the following FT `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(333)TestToken` they want to lookup. The steps are @@ -237,7 +237,7 @@ A third party has the following FT `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cb 3. Get the datum from the output and lookup metadata by going into the first field of constructor 0. 4. Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex. -### Retrieve metadata from a Plutus validator +##### Retrieve metadata from a Plutus validator We want to bring the metadata of the FT `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(333)TestToken` in the Plutus validator context. To do this we @@ -246,6 +246,89 @@ We want to bring the metadata of the FT `d5e6bf0500378d4f0da4e8dde6becec7621cd8c 3. Reference the output in the transaction. (off-chain) 4. Verify validity of datum of the referenced output by checking if policy ID of `reference NFT` and `user token` and their asset names without the `asset_name_label` prefix match. (on-chain) +#### 444 SFT Standard + +The third introduced standard is the `444` Semi-FT standard with the registered `asset_name_label` prefix value + +| asset_name_label | class | description | +| --------------------------- | ------------ | -------------------------------------------------------------------- | +| 444 | SFT | SFT hold by the user's wallet making use of the union of CIP-0025 inner structure AND the Cardano foundation off-chain registry inner structure | + +Semi-Fungible tokens don't fit cleanly into the other two FT/NFT classes of tokens and thus need their own standard. An example of a SFT would be a fractionalized NFT. The single reference NFT `(100)` represents the NFT itself, and the many `(444)` tokens represent the fractionalized shares. Minting 100 tokens and setting decimals to 2 would represent a single NFT that is split into 100 fractions. + +##### Class + +The `user token` is an SFT (semi-fungible token). + +##### Pattern + +The `user token` and `reference NFT` **must** have an identical name, preceded by the `asset_name_label` prefix. + +Example:\ +`user token`: `(444)Test123`\ +`reference NFT`: `(100)Test123` + +##### Metadata + +This is a low-level representation of the metadata, following closely the structure of CIP-0025 with the optional decimals field added. All UTF-8 encoded keys and values need to be converted into their respective byte's representation when creating the datum on-chain. + +``` +files_details = + { + ? name : bounded_bytes, ; UTF-8 + mediaType : bounded_bytes, ; UTF-8 + src : bounded_bytes ; UTF-8 + ; ... Additional properties are allowed + } + +metadata = + { + name : bounded_bytes, ; UTF-8 + image : bounded_bytes, ; UTF-8 + ? mediaType : bounded_bytes, ; UTF-8 + ? description : bounded_bytes, ; UTF-8 + ? decimals: int, + ? files : [* files_details] + ; ... Additional properties are allowed + } + +; A URI as a UTF-8 encoded bytestring. +; The URI scheme must be one of `https`, `ipfs` or `data` +; Do not encode plain file payloads as URI. +; 'logo' does not follow the explanation of the token-registry, it needs to be a valid URI and not a plain bytestring. +; Only use the following media types: `image/png`, `image/jpeg`, `image/svg+xml` +uri = bounded_bytes + +; Custom user defined plutus data. +; Setting data is optional, but the field is required +; and needs to be at least Unit/Void: #6.121([]) +extra = plutus_data + +datum = #6.121([metadata, 1, extra]) ; version 1 +``` +Example datum as JSON: +```json +{"constructor" : 0, "fields": [{"map": [{"k": {"bytes": "6E616D65"}, "v": {"bytes":"5370616365427564"}}, {"k": {"bytes": "6465736372697074696F6E"}, "v": {"bytes":"54686973206973206D79207465737420746F6B656E"}}, {"k": {"bytes": "696D616765"}, "v": {"bytes": "697066733A2F2F74657374"}}, {"k": {"bytes": "646563696D616C73"}, "v": {"int": 2}}]}, {"int": 1}]} +``` + +##### Retrieve metadata as 3rd party + +A third party has the following SFT `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(444)TestToken` they want to lookup. The steps are + +1. Construct `reference NFT` from `user token`: `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(100)TestToken` +2. Look up `reference NFT` and find the output it's locked in. +3. Get the datum from the output and lookup metadata by going into the first field of constructor 0. +4. Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex. + +##### Retrieve metadata from a Plutus validator + +We want to bring the metadata of the SFT `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(444)TestToken` in the Plutus validator context. To do this we + +1. Construct `reference NFT` from `user token`: `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(100)TestToken` (off-chain) +2. Look up `reference NFT` and find the output it's locked in. (off-chain) +3. Reference the output in the transaction. (off-chain) +4. Verify validity of datum of the referenced output by checking if policy ID of `reference NFT` and `user token` and their asset names without the `asset_name_label` prefix match. (on-chain) + ## Rationale Without seperation of `reference NFT` and `user token` you lose all flexibility and moving the `user token` would be quite cumbersome as you would need to add the metadata everytime to the new output where the `user token` is sent to. Hence you separate metadata and `user token` and lock the metadata inside another UTxO, so you can freely move the `user token` around. From 143380bef0edf858ae40321a237867a8d68980fb Mon Sep 17 00:00:00 2001 From: Robert Phair Date: Fri, 7 Apr 2023 15:45:01 +0530 Subject: [PATCH 2/5] this "backward compatibility" facet is part of Rationale --- CIP-0068/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CIP-0068/README.md b/CIP-0068/README.md index b8c7d58c0f..a24692de9c 100644 --- a/CIP-0068/README.md +++ b/CIP-0068/README.md @@ -338,7 +338,7 @@ In order to reference the correct UTxO containing the metadata, it needs to be a The security for the link is derived from the minting policy itself, so it's important to write the validator with the right constraints and rules since this CIP solely defines the interface to keep flexibility as high as possible. -## Backward Compatibility +### Backward Compatibility To keep metadata compatibility with changes coming in the future, we introduce a `version` field in the datum. From 30b662de5263618bbb75b3cb62fdf5457188c71b Mon Sep 17 00:00:00 2001 From: Robert Phair Date: Thu, 13 Apr 2023 16:58:53 +0530 Subject: [PATCH 3/5] comma end last items works best for group editing --- CIP-0067/registry.json | 4 ++-- CIP-0068/README.md | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CIP-0067/registry.json b/CIP-0067/registry.json index 50ccb005be..f7716b1f4d 100644 --- a/CIP-0067/registry.json +++ b/CIP-0067/registry.json @@ -16,7 +16,7 @@ }, { "asset_name_label": 444, - "class": "SFT", + "class": "RFT", "description": "CIP-0068 - Datum Metadata Standard (444 sub standard)" - } + }, ] diff --git a/CIP-0068/README.md b/CIP-0068/README.md index a24692de9c..96cc2e2864 100644 --- a/CIP-0068/README.md +++ b/CIP-0068/README.md @@ -246,19 +246,19 @@ We want to bring the metadata of the FT `d5e6bf0500378d4f0da4e8dde6becec7621cd8c 3. Reference the output in the transaction. (off-chain) 4. Verify validity of datum of the referenced output by checking if policy ID of `reference NFT` and `user token` and their asset names without the `asset_name_label` prefix match. (on-chain) -#### 444 SFT Standard +#### 444 RFT Standard -The third introduced standard is the `444` Semi-FT standard with the registered `asset_name_label` prefix value +The third introduced standard is the `444` Rich-FT standard with the registered `asset_name_label` prefix value | asset_name_label | class | description | | --------------------------- | ------------ | -------------------------------------------------------------------- | -| 444 | SFT | SFT hold by the user's wallet making use of the union of CIP-0025 inner structure AND the Cardano foundation off-chain registry inner structure | +| 444 | RFT | RFT hold by the user's wallet making use of the union of CIP-0025 inner structure AND the Cardano foundation off-chain registry inner structure | -Semi-Fungible tokens don't fit cleanly into the other two FT/NFT classes of tokens and thus need their own standard. An example of a SFT would be a fractionalized NFT. The single reference NFT `(100)` represents the NFT itself, and the many `(444)` tokens represent the fractionalized shares. Minting 100 tokens and setting decimals to 2 would represent a single NFT that is split into 100 fractions. +Rich-Fungible tokens don't fit cleanly into the other two FT/NFT classes of tokens and thus need their own standard. An example of an RFT would be a fractionalized NFT. The single reference NFT `(100)` represents the NFT itself, and the many `(444)` tokens represent the fractionalized shares. Minting 100 tokens and setting decimals to 2 would represent a single NFT that is split into 100 fractions. ##### Class -The `user token` is an SFT (semi-fungible token). +The `user token` is an RFT (rich-fungible token). ##### Pattern @@ -313,7 +313,7 @@ Example datum as JSON: ##### Retrieve metadata as 3rd party -A third party has the following SFT `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(444)TestToken` they want to lookup. The steps are +A third party has the following RFT `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(444)TestToken` they want to lookup. The steps are 1. Construct `reference NFT` from `user token`: `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(100)TestToken` 2. Look up `reference NFT` and find the output it's locked in. @@ -322,7 +322,7 @@ A third party has the following SFT `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5c ##### Retrieve metadata from a Plutus validator -We want to bring the metadata of the SFT `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(444)TestToken` in the Plutus validator context. To do this we +We want to bring the metadata of the RFT `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(444)TestToken` in the Plutus validator context. To do this we 1. Construct `reference NFT` from `user token`: `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(100)TestToken` (off-chain) 2. Look up `reference NFT` and find the output it's locked in. (off-chain) From cb583af7b794bac751eb8af3628343dce61bb147 Mon Sep 17 00:00:00 2001 From: Matthias Benkort <5680256+KtorZ@users.noreply.github.com> Date: Tue, 2 May 2023 19:09:31 +0200 Subject: [PATCH 4/5] Update CIP-0068/README.md --- CIP-0068/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CIP-0068/README.md b/CIP-0068/README.md index 96cc2e2864..050861fec9 100644 --- a/CIP-0068/README.md +++ b/CIP-0068/README.md @@ -95,7 +95,7 @@ datum = #6.121([metadata, version, extra]) #### 222 NFT Standard -Besides the necessary standard for the `reference NFT` we're introducing two specific token standards in this CIP. Note that the possibilities are endless here and more standards can be built on top of this CIP for FTs, other NFTs, semi fungible tokens, etc. The first is the `222` NFT standard with the registered `asset_name_label` prefix value +Besides the necessary standard for the `reference NFT` we're introducing two specific token standards in this CIP. Note that the possibilities are endless here and more standards can be built on top of this CIP for FTs, other NFTs, rich fungible tokens, etc. The first is the `222` NFT standard with the registered `asset_name_label` prefix value | asset_name_label | class | description | | --------------------------- | ------------ | -------------------------------------------------------------------- | From 5465b5c1fcf439acd4271bd67c2807d30fb6b1e7 Mon Sep 17 00:00:00 2001 From: Matthias Benkort <5680256+KtorZ@users.noreply.github.com> Date: Tue, 2 May 2023 19:11:21 +0200 Subject: [PATCH 5/5] Update CIP-0068/README.md --- CIP-0068/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CIP-0068/README.md b/CIP-0068/README.md index 050861fec9..e6a059bb55 100644 --- a/CIP-0068/README.md +++ b/CIP-0068/README.md @@ -95,7 +95,7 @@ datum = #6.121([metadata, version, extra]) #### 222 NFT Standard -Besides the necessary standard for the `reference NFT` we're introducing two specific token standards in this CIP. Note that the possibilities are endless here and more standards can be built on top of this CIP for FTs, other NFTs, rich fungible tokens, etc. The first is the `222` NFT standard with the registered `asset_name_label` prefix value +Besides the necessary standard for the `reference NFT` we're introducing three specific token standards in this CIP. Note that the possibilities are endless here and more standards can be built on top of this CIP for FTs, other NFTs, rich fungible tokens, etc. The first is the `222` NFT standard with the registered `asset_name_label` prefix value | asset_name_label | class | description | | --------------------------- | ------------ | -------------------------------------------------------------------- |