Skip to content
Open
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
164 changes: 142 additions & 22 deletions CIP-0068/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,20 @@ The `user token` represents an NFT (non-fungible token).

##### Pattern

The `user token` and `reference NFT` MUST have an identical name, preceded by the `asset_name_label` prefix.
The `user token` and `reference NFT` MUST have an identical name (heretofore entitled `asset_name`), preceded by the `asset_name_label` prefix.

Example:\
`user token`: `(222)Test123`\
`reference NFT`: `(100)Test123`

##### 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.
This is either:

1. A low-level direct representation of the metadata, following closely the structure of CIP-0025
2. A 721-ERC-style token mapping exactly matching the structure of CIP-0025
Copy link
Contributor

@SmaugPool SmaugPool Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is confusing. Why referencing 721-ERC-style here? What does this mean? This is an Ethereum standard and it is not referenced anywhere. The only link with CIP25 is the 721 metadata label.

Also "mapping exactly matching the structure of CIP-0025" is also confusing. I think you are only talking about the policy_id -> asset_name mapping? The rest is different (222/333/444, bytes instead of strings, etc.). Also only CIP25v2 use bytes as keys in the mapping.

Note that "following closely the structure of CIP-0025" was about the individual asset metadata (name, image, files, etc.). Whereas you seem to talk about its encapsulation in policy_id -> asset_name maps.


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 =
Expand All @@ -188,6 +192,26 @@ metadata =
; ... Additional properties are allowed
}

metadata_map =
{
__RESERVE_KEYWORD_721_V4__ : bool, ; Long name to avoid conflict

"721":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the point of having __RESERVE_KEYWORD_721_V4__ bool here? Wouldn't the presence of "721" key be enough?

{
; As many of the below as needed based on which reference tokens are added
"<policy_id>":
{
"<asset_name_1>" : metadata,
; ...
"<asset_name_n>" : metadata,
}
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not some valid CDDL. It looks like you are confusing CDDL with JSON.
More importantly, this does not tell how the policy_id and asset_name keys are encoded (I guess byte encoding like CIP25v2 and all CIP68 fields?).

Overall we should avoid talking about JSON as metadata and datum are CBOR encoded and CBOR -> JSON is not directly bijective. This only leads to confusion.

Note that JSON in CIP68 is only discussed in examples and even this is slightly questionable in my opinion.

metadata_field =
metadata ; For backwards-compatibility in v4 onward, a map itself is valid metadata
/ metadata_map ; Multi-metadata is now supported as in CIP-0025

; A valid Uniform Resource Identifier (URI) as a UTF-8 encoded bytestring.
; The URI scheme must be one of `https` (HTTP), `ipfs` (IPFS), `ar` (Arweave) or `data` (on-chain).
; Data URLs (on-chain data) must comply to RFC2397.
Expand All @@ -198,12 +222,12 @@ uri = bounded_bytes / [ * bounded_bytes ] ; UTF-8
; and needs to be at least Unit/Void: #6.121([])
extra = plutus_data

datum = #6.121([metadata, version, extra])
datum = #6.121([metadata_field, version, extra])

version = 1 / 2 / 3
version = 1 / 2 / 3 / 4
```

Example datum as JSON:
Example datum as JSON (direct metadata):

```json
{
Expand Down Expand Up @@ -236,6 +260,45 @@ Example datum as JSON:
}
```

Example datum as JSON (721-style):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again what "721-style" means?


```json
{
"constructor": 0,
"fields": [
{
"map": [
{
"k": { "bytes": "373231" },
"v": {
"map": [
{
"k": { "bytes": "5370616365427564204131" },
"v": {
"map": [
{
"k": { "bytes": "6E616D65" },
"v": { "bytes": "5370616365427564" }
},
{
"k": { "bytes": "696D616765" },
"v": { "bytes": "697066733A2F2F74657374" }
}
]
}
}
]
}
}
]
},
{
"int": 4
}
]
}
```

##### Retrieve metadata as 3rd party

A third party has the following NFT `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(222)TestToken` they want
Expand All @@ -244,7 +307,9 @@ 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.
4. Determine whether this is a direct metadata or the CIP-0025 map style using the `__RESERVE_KEYWORD_721_V4__` map value (if present, default false)
5. Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex.
6. For multi-map style metadata, return only the JSON values inside the matching path: `721`->>`policy_id`->>`asset_name`

##### Retrieve metadata from a Plutus validator

Expand Down Expand Up @@ -274,17 +339,20 @@ The `user token` is an FT (fungible token).

##### Pattern

The `user token` and `reference NFT` MUST have an identical name, preceded by the `asset_name_label` prefix.
The `user token` and `reference NFT` MUST have an identical name (heretofore called `asset_name`), preceded by the `asset_name_label` prefix.

Example:\
`user token`: `(333)Test123`\
`reference NFT`: `(100)Test123`

##### 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.
This is either:

1. A low-level direct representation of the metadata, following closely the structure of the Cardano foundation off-chain metadata registry
2. A 721-ERC-style token mapping exactly matching 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.

```
; Explanation here: https://developers.cardano.org/docs/native-tokens/token-registry/cardano-token-registry/
Expand All @@ -304,6 +372,26 @@ metadata =
; ... Additional properties are allowed
}

metadata_map =
{
__RESERVE_KEYWORD_721_V4__ : bool, ; Long name to avoid conflict

"721":
{
; As many of the below as needed based on which reference tokens are added
"<policy_id>":
{
"<asset_name_1>" : metadata,
; ...
"<asset_name_n>" : metadata,
}
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again not valid CDDL

metadata_field =
metadata ; For backwards-compatibility in v4 onward, a map itself is valid metadata
/ metadata_map ; Multi-metadata is now supported as in CIP-0025

; A valid Uniform Resource Identifier (URI) as a UTF-8 encoded bytestring.
; The URI scheme must be one of `https` (HTTP), `ipfs` (IPFS), `ar` (Arweave) or `data` (on-chain).
; Data URLs (on-chain data) must comply to RFC2397.
Expand All @@ -314,9 +402,9 @@ uri = bounded_bytes / [ * bounded_bytes ] ; UTF-8
; and needs to be at least Unit/Void: #6.121([])
extra = plutus_data

datum = #6.121([metadata, version, extra])
datum = #6.121([metadata_field, version, extra])

version = 1 / 2 / 3
version = 1 / 2 / 3 / 4
```

Example datum as JSON:
Expand Down Expand Up @@ -360,7 +448,9 @@ 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.
4. Determine whether this is a direct metadata or the CIP-0025 map style using the `__RESERVE_KEYWORD_721_V4__` map value (if present, default false)
5. Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex.
6. For multi-map style metadata, return only the JSON values inside the matching path: `721`->>`policy_id`->>`asset_name`

##### Retrieve metadata from a Plutus validator

Expand Down Expand Up @@ -403,9 +493,12 @@ Example:\

##### 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.
This is either:

1. A low-level direct representation of the metadata, following closely the structure of CIP-0025 with the optional decimals field added
2. A 721-ERC-style token mapping exactly matching 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.

```
files_details =
Expand All @@ -430,19 +523,39 @@ metadata =
; ... Additional properties are allowed
}

metadata_map =
{
__RESERVE_KEYWORD_721_V4__ : bool, ; Long name to avoid conflict

"721":
{
; As many of the below as needed based on which reference tokens are added
"<policy_id>":
{
"<asset_name_1>" : metadata,
; ...
"<asset_name_n>" : metadata,
}
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again not valid CDDL

metadata_field =
metadata ; For backwards-compatibility in v4 onward, a map itself is valid metadata
/ metadata_map ; Multi-metadata is now supported as in CIP-0025

; A valid Uniform Resource Identifier (URI) as a UTF-8 encoded bytestring.
; The URI scheme must be one of `https` (HTTP), `ipfs` (IPFS), `ar` (Arweave) or `data` (on-chain).
; Data URLs (on-chain data) must comply to RFC2397.
uri = bounded_bytes ; UTF-8
uri = bounded_bytes / [ * bounded_bytes ] ; UTF-8

; 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, version, extra])
datum = #6.121([metadata_field, version, extra])

version = 3
version = 3 / 4
```

Example datum as JSON:
Expand Down Expand Up @@ -502,7 +615,9 @@ 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.
4. Determine whether this is a direct metadata or the CIP-0025 map style using the `__RESERVE_KEYWORD_721_V4__` map value (if present, default false)
5. Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex.
6. For multi-map style metadata, return only the JSON values inside the matching path: `721`->>`policy_id`->>`asset_name`

##### Retrieve metadata from a Plutus validator

Expand Down Expand Up @@ -551,7 +666,8 @@ version of these tokens from any point in time with the following format:
1. [6d897eb](https://github.com/cardano-foundation/CIPs/tree/6d897eb60805a58a3e54821fe61284d5c5903764/CIP-XXXX)
2. [45fa23b](https://github.com/cardano-foundation/CIPs/tree/45fa23b60806367a3e52231e552c4d7654237678/CIP-XXXX)
3. [bfc6fde](https://github.com/cardano-foundation/CIPs/tree/bfc6fde340280d8b51f5a7131b57f4cc6cc5f260/CIP-XXXX)
4. **Current**
4. [YYYYYYY](https://github.com/cardano-foundation/CIPs/tree/abcdefabcdefabcdefabcdefabcdefabcdefabcd/CIP-XXXX)
5. **Next Editor**
```

Each time a new version is introduced the previous version's link MUST be updated to match the last commit corresponding
Expand All @@ -578,6 +694,10 @@ versions of the affected tokens. `asset_name_labels` **MUST** only be marked obs

- Added [* bounded_bytes] support to the image and src tags on the metadata

#### version 4

- Add backwards-compatible support for multi-asset 721-ERC-style metadata mappings
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Backwards-compatible" with what exactly?
And again "721-ERC-style" is not clear. There is no ERC on Cardano.


## Rationale: how does this CIP achieve its goals?

Without separation of `reference NFT` and `user token` you lose all flexibility and moving the `user token` would be
Expand Down