Skip to content

Commit cb1f3b8

Browse files
authored
Merge pull request #390 from ldclabs/main
CAIP-390: Minimal Cross-Chain Asset Metadata Standard
2 parents ef324fa + aab1c18 commit cb1f3b8

File tree

1 file changed

+212
-0
lines changed

1 file changed

+212
-0
lines changed

CAIPs/caip-390.md

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
---
2+
caip: 390
3+
title: Minimal Cross-Chain Asset Metadata Standard
4+
status: Draft
5+
type: Standard
6+
category: Interface
7+
author: Yan (@xzensh)
8+
created: 2025-12-22
9+
requires: 2, 19
10+
---
11+
12+
## Simple Summary
13+
14+
A standardized JSON schema for retrieving and verifying off-chain metadata (profile, visual assets, and links) for crypto assets, with built-in support for cross-chain identity discovery.
15+
16+
## Abstract
17+
18+
This proposal defines a minimal, chain-agnostic JSON structure for asset metadata. It addresses the fragmentation of token information across Web3 by standardizing how wallets and dApps fetch essential data (logo, name, symbol, decimals) and extended data (links, cross-chain locations). The standard prioritizes URI-based resource referencing and introduces a "locations" field to map a single asset's existence across multiple blockchains using [CAIP-19] identifiers.
19+
20+
## Motivation
21+
22+
Currently, asset metadata is fragmented across various repositories (Coingecko, CoinMarketCap, TrustWallet Assets, Tokenlists.org), each using proprietary JSON structures.
23+
24+
1. **Inconsistency**: A developer must integrate multiple APIs to get a token's logo, website, and social links.
25+
2. **Cross-Chain Fragmentation**: Assets bridged across layers (e.g., L1 to L2) or chains are often treated as entirely separate entities by wallets, making portfolio views difficult to aggregate.
26+
3. **Ambiguity**: Link data is often unstructured (e.g., keys like `twitter`, `social_twitter`, `x_url`), requiring complex parsing logic.
27+
28+
We propose a unified schema that is compatible with existing NFT standards (ERC-721/OpenSea) while adding specific support for fungible token needs and cross-chain peer discovery.
29+
30+
## Specification
31+
32+
The metadata MUST be returned as a JSON object. The schema is defined as follows:
33+
34+
### Schema Definition
35+
36+
```json
37+
{
38+
"$schema": "http://json-schema.org/draft-07/schema#",
39+
"title": "CAIP Asset Metadata",
40+
"type": "object",
41+
"required": ["name", "symbol", "decimals", "image"],
42+
"properties": {
43+
"name": {
44+
"type": "string",
45+
"description": "Human-readable name of the asset."
46+
},
47+
"symbol": {
48+
"type": "string",
49+
"description": "Abbreviated symbol of the asset (ticker)."
50+
},
51+
"decimals": {
52+
"type": "integer",
53+
"minimum": 0,
54+
"description": "The number of decimals for the token balance. MUST be 0 for non-divisible assets (NFTs)."
55+
},
56+
"image": {
57+
"type": "string",
58+
"format": "uri",
59+
"description": "URI to the asset's logo or primary image. WebP, SVG or PNG formats are RECOMMENDED."
60+
},
61+
"description": {
62+
"type": "string",
63+
"maxLength": 1000,
64+
"description": "Brief description of the asset."
65+
},
66+
"external_url": {
67+
"type": "string",
68+
"format": "uri",
69+
"description": "URL to the official website or external resource of the asset. Compatible with ERC-721 metadata."
70+
},
71+
"links": {
72+
"type": "array",
73+
"description": "A list of auxiliary links related to the asset.",
74+
"items": {
75+
"type": "object",
76+
"required": ["name", "url", "rel"],
77+
"properties": {
78+
"name": {
79+
"type": "string",
80+
"description": "Display label for the link."
81+
},
82+
"url": {
83+
"type": "string",
84+
"format": "uri",
85+
"description": "The destination URL."
86+
},
87+
"rel": {
88+
"type": "string",
89+
"description": "Relationship type used for semantic classification.",
90+
"enum": [
91+
"homepage",
92+
"whitepaper",
93+
"documentation",
94+
"source_code",
95+
"governance",
96+
"audit",
97+
"social",
98+
"browser",
99+
"exchange",
100+
"bridge"
101+
]
102+
}
103+
}
104+
},
105+
"uniqueItems": true
106+
},
107+
"locations": {
108+
"type": "array",
109+
"description": "List of CAIP-19 identifiers representing this asset's peer contracts across different chains.",
110+
"items": {
111+
"type": "string",
112+
"pattern": "^[-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}/[-a-z0-9]{3,8}:[-.%a-zA-Z0-9]{1,128}$"
113+
},
114+
"uniqueItems": true
115+
}
116+
}
117+
}
118+
```
119+
120+
### Field Descriptions
121+
122+
#### Core Fields
123+
* **`decimals`**: This field is mandatory. For NFTs or non-divisible assets, it MUST be set to `0`. This eliminates ambiguity for consumers (wallets) regarding whether a value is missing or intentionally zero.
124+
* **`external_url`**: Used instead of "website" to maintain compatibility with existing NFT metadata standards (e.g., OpenSea).
125+
126+
#### `links` Object
127+
To prevent key-name fragmentation (e.g., `twitter_url` vs `socials.twitter`), links are defined as an array of objects containing a mandatory `rel` attribute.
128+
129+
Recommended values for `rel`:
130+
* `homepage`: Main project website.
131+
* `whitepaper`: Technical paper or economic model.
132+
* `documentation`: Developer docs or wikis.
133+
* `source_code`: Code repositories (GitHub, GitLab).
134+
* `governance`: Voting portals or forums.
135+
* `audit`: Security audit reports.
136+
* `social`: Social media profiles (X/Twitter, Discord, Telegram).
137+
* `browser`: Block explorer links.
138+
* `exchange`: Direct links to trading pairs on DEXs or CEXs (e.g., Uniswap Pool, Binance Spot).
139+
* `bridge`: Interfaces allowing users to bridge this asset across chains.
140+
141+
#### `locations` (Cross-Chain Discovery)
142+
This field allows an asset to declare its "peer" contracts on other networks. The value MUST be an array of valid [CAIP-19] strings.
143+
* Example: A `USDT` token on Ethereum mainnet can list its representations on BNB Chain and Solana in this field.
144+
* This enables wallets to aggregate balances of the "same" asset across chains without relying on centralized bridge mappings.
145+
146+
## Example
147+
148+
```json
149+
{
150+
"name": "ICPanda",
151+
"symbol": "PANDA",
152+
"decimals": 8,
153+
"image": "https://panda.fans/_assets/logo.svg",
154+
"description": "Building the open-source stack for AI agents to remember, transact, and evolve as first-class citizens in Web3.",
155+
"external_url": "https://panda.fans",
156+
"links": [
157+
{
158+
"name": "Twitter",
159+
"url": "https://x.com/ICPandaDAO",
160+
"rel": "social"
161+
},
162+
{
163+
"name": "Source Code",
164+
"url": "https://github.com/ldclabs/ic-panda",
165+
"rel": "source_code"
166+
},
167+
{
168+
"name": "ICPSwap",
169+
"url": "https://app.icpswap.com/swap/pro?input=ryjl3-tyaaa-aaaaa-aaaba-cai&output=druyg-tyaaa-aaaaq-aactq-cai",
170+
"rel": "exchange"
171+
},
172+
{
173+
"name": "Official Bridge",
174+
"url": "https://1bridge.app/?token=PANDA",
175+
"rel": "bridge"
176+
}
177+
],
178+
"locations": [
179+
"icp:1/token:druyg-tyaaa-aaaaq-aactq-cai",
180+
"eip155:56/bep20:0xe74583edaff618d88463554b84bc675196b36990",
181+
"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:PANDAvvWniWYKRbrCYQEAyeSJ5uUk1nc49eLqT6yQyL"
182+
]
183+
}
184+
```
185+
186+
## Rationale
187+
188+
### URI-First for Visuals
189+
We opted for a single `image` URI string rather than a complex object containing thumbnails or themes. Modern UI frameworks and CDNs handle image resizing and format negotiation efficiently. Sticking to a single string simplifies the parsing logic for wallets.
190+
191+
### Structured Links vs. Flat Keys
192+
Arbitrary keys in a JSON object (e.g., `"twitter": "..."`) lead to a chaotic ecosystem where consumers must maintain a mapping of thousands of non-standard keys. Using a structured array with a `rel` property enforces a controlled vocabulary while allowing flexibility for new types in the future.
193+
194+
### Peer-to-Peer Locations
195+
Existing token lists often treat bridged assets as separate entries. By including `locations`, we embed the "cross-chain graph" directly into the asset's metadata. We use [CAIP-19] because it is the standard for uniquely identifying asset instances in a multi-chain environment.
196+
197+
## Backwards Compatibility
198+
199+
* **ERC-721**: The usage of `name`, `description`, `image`, and `external_url` aligns with the widely adopted OpenSea metadata standard.
200+
* **Token Lists**: The structure implies that an array of these objects can easily be transformed into a Uniswap-style Token List.
201+
202+
## Security Considerations
203+
204+
1. **Phishing Risks**: Consuming applications (wallets) MUST exercise caution when rendering `external_url` or `links`. We recommend displaying the domain clearly to the user before redirection.
205+
2. **Image Validation**: Applications should sanitize SVG images referenced in the `image` field to prevent XSS attacks via embedded scripts.
206+
3. **Trust**: This standard defines the *format* of the data, not the *validity*. Consumers should verify the source of this JSON (e.g., ensuring it is served from a trusted domain or a verifiable on-chain registry).
207+
208+
## Copyright
209+
210+
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
211+
212+
[CAIP-19]: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-19.md

0 commit comments

Comments
 (0)