|
| 1 | +--- |
| 2 | +namespace-identifier: iota-caip10 |
| 3 | +title: IOTA - Account ID Specification |
| 4 | +author: Enrico Marconi (@UMR1352) |
| 5 | +status: Draft |
| 6 | +type: Informational |
| 7 | +created: 2025-07-28 |
| 8 | +requires: CAIP-2, CAIP-10 |
| 9 | +--- |
| 10 | + |
| 11 | +<!--You can leave these HTML comments in your merged CAIP and delete the |
| 12 | + visible duplicate text guides, they will not appear and may be helpful to |
| 13 | + refer to if you edit it again. This is the suggested template for new CAIPs. |
| 14 | + Note that an CAIP number will be assigned by an editor. When opening a pull |
| 15 | + request to submit your EIP, please use an abbreviated title in the |
| 16 | + filename, `caipX.md`, all lowercase, no `-` between the CAIP and its |
| 17 | + number.--> |
| 18 | + |
| 19 | +# CAIP-10 |
| 20 | + |
| 21 | +*For context, see the [CAIP-10] specification.* |
| 22 | + |
| 23 | +## Introduction |
| 24 | + |
| 25 | +This document defines how IOTA addresses can be encoded as [CAIP-10]'s account IDs. |
| 26 | + |
| 27 | +## Specification |
| 28 | + |
| 29 | +### Semantics |
| 30 | + |
| 31 | +<!-- Explain (and refer to/add links in the `## References` section) any inputs |
| 32 | +or namespace-specific constructs needed to generate or interpret the valid |
| 33 | +possible values of a CAIP-10 in this namespace. Assume your reader has already |
| 34 | +read the CAIP-2 profile and understands how to form a valid CAIP-2 segment. --> |
| 35 | + |
| 36 | +In IOTA's object-based model, account addresses are just a subset of the whole |
| 37 | +address namespace, which is shared among objects, packages, and accounts. |
| 38 | + |
| 39 | +Therefore, an IOTA address may refer to either an object, a package or a more |
| 40 | +traditional key-based account. Most importantly, it is impossible to distinguish |
| 41 | +what an IOTA address refers to without querying a node. |
| 42 | + |
| 43 | +Nonetheless, all IOTA addresses can own assets (i.e. other objects), with the |
| 44 | +only difference being that key-derived address are the only types of address that |
| 45 | +can execute transactions. |
| 46 | + |
| 47 | +### Syntax |
| 48 | + |
| 49 | +<!-- Explain the actual algorithm or transformation needed to transform inputs |
| 50 | +(sometimes just a native address, other times additional context is needed) into |
| 51 | +a conformant and unique CAIP-10 deterministically. Consider including a regular |
| 52 | +expression for validation as well, as some consumers or toolmakers may want to |
| 53 | +support this CAIP-10 scheme without a deep understanding of any specifications, |
| 54 | +devdocs, or improvement proposals on which this specification depends. If there |
| 55 | +are canonicalization guarantees, checksums, or other assumptions in the native |
| 56 | +format, explain how they exist (or can be made to exist) in the CAIP-10 |
| 57 | +equivalent as well. --> |
| 58 | + |
| 59 | +An IOTA [CAIP-10]'s account ID is a case-sensitive string that is computed by appending |
| 60 | +an IOTA address to an IOTA [CAIP-2 Profile]'s chain ID, interlieved by the `:` character. |
| 61 | + |
| 62 | +The syntax of an IOTA address matches the following regular expression: |
| 63 | + |
| 64 | +``` |
| 65 | +0x[0-9a-f]{64} |
| 66 | +``` |
| 67 | + |
| 68 | +Hence, the regular expression that matches the whole [CAIP-10]'s account ID is: |
| 69 | + |
| 70 | +``` |
| 71 | +iota:(mainnet|testnet|devnet|[0-9a-f]{8}):0x[0-9a-f]{64} |
| 72 | +``` |
| 73 | + |
| 74 | +### Resolution Mechanics |
| 75 | + |
| 76 | +<!-- Many blockchain systems allow for transactions, asset-states, etc. to be |
| 77 | +validated against the chain they are targeting or depending to to avoid replay |
| 78 | +attacks or other unintended outcomes. This is often done by an API or RPC call |
| 79 | +to a node to validate the targetted chain or network. Include a sample |
| 80 | +request/response and add the relevant documentation to the `## References` |
| 81 | +section below if possible, as well as an explanation of any steps needed to |
| 82 | +validate the results, calculate checksums, persist session metadata or nonces, |
| 83 | + etc. --> |
| 84 | + |
| 85 | +Any Account ID conforming to the aforementioned syntax is a valid IOTA Account ID, |
| 86 | +independently of whether it is already in use by a wallet or on-chain object. |
| 87 | + |
| 88 | +It is possible to check whether a given Account ID refers to a key-pair derived address, |
| 89 | +an object, or a smart contract package by invoking the `iota_getObject` JSON-RPC API. |
| 90 | + |
| 91 | +For instance, checking IOTA address `0x53e4567ccafa5f36ce84c80aa8bc9be64e0d5ae796884274aef3005ae6733809` with |
| 92 | + |
| 93 | +```json |
| 94 | +{ |
| 95 | + "jsonrpc": "2.0", |
| 96 | + "id": 1, |
| 97 | + "method": "iota_getObject", |
| 98 | + "params": [ |
| 99 | + "0x53e4567ccafa5f36ce84c80aa8bc9be64e0d5ae796884274aef3005ae6733809", |
| 100 | + { |
| 101 | + "showType": true, |
| 102 | + "showOwner": true, |
| 103 | + "showPreviousTransaction": false, |
| 104 | + "showDisplay": false, |
| 105 | + "showContent": false, |
| 106 | + "showBcs": false, |
| 107 | + "showStorageRebate": false, |
| 108 | + } |
| 109 | + ] |
| 110 | +} |
| 111 | +``` |
| 112 | + |
| 113 | +yields the following response: |
| 114 | + |
| 115 | +```json |
| 116 | +{ |
| 117 | + "jsonrpc": "2.0", |
| 118 | + "result": { |
| 119 | + "data": { |
| 120 | + "objectId": "0x53e4567ccafa5f36ce84c80aa8bc9be64e0d5ae796884274aef3005ae6733809", |
| 121 | + "version": "1", |
| 122 | + "digest": "33K5ZXJ3RyubvYaHuEnQ1QXmmbhgtrFwp199dnEbL4n7", |
| 123 | + "type": "0x2::coin::Coin<0x2::iota::IOTA>", |
| 124 | + "owner": { |
| 125 | + "AddressOwner": "0xc8ec1d5b84dd6289e193b9f88de4a994358c9f856135236c3e75a925e1c77ac3" |
| 126 | + } |
| 127 | + } |
| 128 | + }, |
| 129 | + "id": 1 |
| 130 | +} |
| 131 | +``` |
| 132 | + |
| 133 | +which shows that address `0x53e4567ccafa5f36ce84c80aa8bc9be64e0d5ae796884274aef3005ae6733809` is actually |
| 134 | +an IOTA object of type `0x2::coin::Coin<0x2::iota::IOTA>` - i.e. an IOTA Coin - owned by address |
| 135 | +`0xc8ec1d5b84dd6289e193b9f88de4a994358c9f856135236c3e75a925e1c77ac3`. |
| 136 | + |
| 137 | +If we were to do the same for the coin owner's address |
| 138 | +`0xc8ec1d5b84dd6289e193b9f88de4a994358c9f856135236c3e75a925e1c77ac3` we'd get the following response: |
| 139 | + |
| 140 | +```json |
| 141 | +{ |
| 142 | + "jsonrpc": "2.0", |
| 143 | + "id": 1, |
| 144 | + "result": { |
| 145 | + "error": { |
| 146 | + "code": "notExists", |
| 147 | + "object_id": "0xc8ec1d5b84dd6289e193b9f88de4a994358c9f856135236c3e75a925e1c77ac3" |
| 148 | + } |
| 149 | + } |
| 150 | +} |
| 151 | +``` |
| 152 | + |
| 153 | +Which hints at the fact that address `0xc8ec1d5b84dd6289e193b9f88de4a994358c9f856135236c3e75a925e1c77ac3` is not |
| 154 | +an object, but a key-derived address. |
| 155 | + |
| 156 | +## Rationale |
| 157 | + |
| 158 | +<!-- Explain here how the mapping or translation between native identifiers and |
| 159 | +CAIP-10 identifiers was arrived at, history and pre-history, etc.--> |
| 160 | + |
| 161 | +IOTA addresses are lowercase-hex encoded 32 bytes string, which in the case of key-pair derived addresses - i.e. |
| 162 | +traditional accounts - are computed by hashing with the `blake2b` algorithm a public key's bytes. If the signature scheme to be computed with those bytes is anything other than `Ed25519`, the public key bytes have a sigil prepended **before** hashing. |
| 163 | +IOTA address currently supports pure Ed25519, Secp256k1, Secp256r1, and MultiSig with corresponding flag bytes of 0x00 (not prepended), 0x01, 0x02, and 0x03, respectively. |
| 164 | + |
| 165 | +As already mentioned above, all IOTA addresses can own assets and funds. |
| 166 | + |
| 167 | +## Test Cases |
| 168 | + |
| 169 | +<!-- A list of manually-composed and validated examples is the **most important** |
| 170 | +section, and by far the most read! be sure to check often that this stays in sync |
| 171 | +with any changes or additions in the preceding sections. --> |
| 172 | + |
| 173 | +``` |
| 174 | +# IOTA Mainnet |
| 175 | +iota:mainnet:0x7b4a34f6a011794f0ecbe5e5beb96102d3eef6122eb929b9f50a8d757bfbdd67 |
| 176 | +
|
| 177 | +# IOTA Testnet |
| 178 | +iota:testnet:0x2d3eef6122eb929b9f50a8d757bfbdd677b4a34f6a011794f0ecbe5e5beb9610 |
| 179 | +
|
| 180 | +# IOTA Devnet |
| 181 | +iota:devnet:0x929b9f50a8d757bfbdd677b4a34f6a011794f0ecbe5e5beb96102d3eef6122eb |
| 182 | +
|
| 183 | +# IOTA custom network |
| 184 | +iota:f3aa51bd:0xe5e5beb96102d37b4a34f6a011794f0ecbeef6122eb929b9f50a8d757bfbdd67 |
| 185 | +``` |
| 186 | + |
| 187 | +## References |
| 188 | + |
| 189 | +<!-- Links to external resources that help understanding the namespace or the |
| 190 | +specification/applied-CAIP better in this context. This can also include links |
| 191 | +to existing implementations. |
| 192 | +
|
| 193 | +The preferred format, for browser-rendering and long-term maintenance, is a |
| 194 | +bulletted list of [Name][] links (rather than classical [Name](referent) links), |
| 195 | +followed by ` - ` and a summary or explanation of the content. In a separate |
| 196 | +section below, add the name-referent pairs in the `[Name]: https://{referent} ` |
| 197 | +format-- this will be invisible in any Github-flavored Markdown rendering |
| 198 | +(including jekyll/github pages, aka github.io, but also docusaurus and many |
| 199 | +dev-docs rendering engines). --> |
| 200 | + |
| 201 | +[CAIP-2 Profile]: ./caip2.md |
| 202 | +[CAIP-2]: https://chainagnostic.org/CAIPs/caip-2 |
| 203 | +[CAIP-10]: https://chainagnostic.org/CAIPs/caip-10 |
| 204 | +[IOTA Docs]: https://docs.iota.org |
| 205 | +[IOTA RPC API]: https://docs.iota.org/iota-api-ref |
| 206 | +[IOTA Object Model]: https://docs.iota.org/developer/iota-101/objects/object-model |
| 207 | + |
| 208 | +## Copyright |
| 209 | + |
| 210 | +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). |
0 commit comments