diff --git a/CIP-0035/CIP-0035.md b/CIP-0035/CIP-0035.md new file mode 100644 index 0000000000..ab280f842d --- /dev/null +++ b/CIP-0035/CIP-0035.md @@ -0,0 +1,218 @@ +--- +CIP: 35 +Title: On-Chain Token Metadata Standard +Authors: Matt Ho +Comments-URI: https://github.com/cardano-foundation/CIPs/pull/137 +Status: Draft +Type: Standards +Created: 2020-10-12 +License: CC-BY-4.0 +--- + +# Abstract + +This specification defines a new transaction metadata label (i.e. `20`) and entry for [CIP-0031] to associate token metadata +during a minting transaction. Unlike CIP-28, this proposal is intended to define a specific schema to allow basic information +about fungible tokens to be provided On-Chain. + +`20` is proposed as the metadata label in homage to the `ERC20` standard on Ethereum. + +# Motivation + +The (Cardano Token Registry)[https://github.com/cardano-foundation/cardano-token-registry] is a centralized Off-Chain governance system to manage token +metadata. This proposal aims to provide an On-Chain solution to the same problems that will afford users a much higher degree of trust than the existing +system. + +Specifically, this proposal aims to solve for the following: + +* Provide a standardized way to associate an icon and a ticker with a token +* Provide a mechanism that allows the viewer to evaluate the trustworthiness and/or authenticity of a token + +# Specification + +Minters of tokens on the Cardano blockchain main optionally choose to associate the following transaction metadata to facilitate off-chain labeling of tokens. +When doing so, transaction metadata MUST be included in the same transaction that mints the asset id. + +> NOTE +> +> The following provides an example of the proposed on-chain metadata: +```json +{ + "20": { + "": { + "": { + "ticker": "SUNDAE", + "url": "https://dex.sundaeswap.finance/assets/{policy-id}.{asset-name}", + "desc": "SUNDAE", + "icon": "ipfs://ipfs/", + "icon-": "ipfs://ipfs/", + "decimals": 6, + "version": "1.0" + } + } + } +} +``` + +Field | | Description | +:--- | :---- | :---- | +policy-id | | token policy id | +asset-name | | hex encoded asset name | +ticker | OPTIONAL | when present, field and overrides default ticker which is the asset-name | +url | OPTIONAL | https only url that refers to metadata stored offchain. The URL SHOULD use the project domain and MUST return authenticity metadata in either html or json format (see below) | +desc | OPTIONAL | additional description that defines the usage of the token | +icon | REQUIRED | MUST be either https, ipfs, or data. icon MUST be a browser supported image format. +icon-<size> | OPTIONAL | allows teams to provide icon in different sizes. the recommended values of size are 16, 32, 64, 96, 128. icons are assumed to be square so that icon-64 would refer to a 64x64 icon +decimals | OPTIONAL | how many decimal places should the token support? For ADA, this would be 6 e.g. 1 ADA is 10^6 Lovelace +version | OPTIONAL | when not specified, version will default to `1.0` + +> NOTE +> +> The following provides an example of the alternate proposed on-chain metadata reference: + +```json +{ + "20": { + "": { + "": { + "ref": "https://assets.sundaeswap.finance", + } + } + } +} +``` + +In some cases, it is not practical or desirable to have embed the metadata on-chain. In these cases, this proposal allows the on-chain + + +Field | | Description | +:--- | :---- | :---- | +policy-id | | token policy id | +asset-name | | hex encoded asset name | +ref | REQUIRED | https only url that holds the metadata in the onchain format (see above). The URL SHOULD use the project domain and MUST return the token metadata as described above + + +### Authenticity Metadata + +To help prevent adversaries from creating fake tokens with the intent to defraud users, projects may authenticate tokens using domains they control. This +mechanism provides users a better understanding of where their tokens came from. + +The url provided in the token metadata should return content in either html or JSON format. + +* In JSON format, the url should return a JSON block of the same shape as the on-chain token metadata that includes both the policy-id and asset-name to be verified. +* In HTML format, the url should contain the a `meta` tag with `name` of `cip-31:authenticate` and a value of a comma separate list of tokens to declare as authenticate where tokens are formatted as `{policy id}{hex-encoded asset name}` with no space in between + +## Example 1 - On-Chain Metadata + +In this example, we describe a transaction that contains the first minting of an asset, `12345678901234567890123456789012345678901234567890123456.EXAMPLE/P`. +The metadata attached to this transaction is as follows: + +```json +{ + "20": { + "12345678901234567890123456789012345678901234567890123456": { + "4558414D504C452F50": { + "ticker": "EXP", + "url": "https://example.com/", + "desc": "Example Publisher Token", + "icon": "ipfs://ipfs/1234567890123456789012345678901234567890123456", + "icon-16": "ipfs://ipfs/1234567890123456789012345678901234567890123456", + "decimals": 4 + } + } + } +} +``` + +* `4558414D504C452F50` is the hex encoded form of `EXAMPLE/P` + +When I visit, the url, `https://example.com/`, I am returned HTML which includes the following tag: + +```html + +``` + +## Example 2 - On-Chain Reference + +In this example, we use the same data, but instead construct the metadata as an off-chain reference. + +```json +{ + "20": { + "12345678901234567890123456789012345678901234567890123456": { + "4558414D504C452F50": { + "ref": "https://assets.example.com/" + } + } + } +} +``` + +In this example, the `ref` url returns the following JSON encoded content. Note that this URL also contains data for other tokens, but because we know the policy id and the hex encoded asset name of the `EXP`, we can uniquely identify from this list. + +```json +{ + "20": { + "12345678901234567890123456789012345678901234567890123456": { + "4558414D504C452F50": { + "ticker": "EXP", + "url": "https://example.com/asset.json", + "desc": "Example Publisher Token", + "icon": "ipfs://ipfs/1234567890123456789012345678901234567890123456", + "icon-16": "ipfs://ipfs/1234567890123456789012345678901234567890123456", + "decimals": 4 + } + }, + "12345678901234567890123456789012345678901234567890123456": { + "123456789012345678": { + "ticker": "OTHER-TOKEN", + "url": "https://other-token.com/", + "desc": "other token included for example purposes", + "icon": "ipfs://ipfs/1234567890123456789012345678901234567890123457", + "decimals": 2 + } + } + } +} +``` + +Unlike the previous example, this example returns a JSON encoded authenticity data as follows: + +```json +{ + "20": { + "12345678901234567890123456789012345678901234567890123456": { + "4558414D504C452F50": { + "ticker": "EXP", + "url": "https://example.com/asset.json", + "desc": "Example Publisher Token", + "icon": "ipfs://ipfs/1234567890123456789012345678901234567890123456", + "icon-16": "ipfs://ipfs/1234567890123456789012345678901234567890123456", + "decimals": 4 + } + }, + "12345678901234567890123456789012345678901234567890123456": { + "123456789012345678": { + "ticker": "OTHER-TOKEN", + "url": "https://other-token.com/", + "desc": "other token included for example purposes", + "icon": "ipfs://ipfs/1234567890123456789012345678901234567890123457", + "decimals": 2 + } + } + } +} +``` + +Notice this data is the same data as returned by the `ref` for the on-chain reference. This is intentionally designed to reduce the amount of +boilerplate required to satisfy this CIP. + +## Notes + +This CIP is intended to handle the common use faced primarily by exchanges as wallets that need to display tokens to their users. +Other standards, like `CIP-25`, the NFT metadata standard, will be more appropriate for handling specialized use cases. + +It is not expected nor desired for all tokens to contain `CIP-31` metadata. + + +