# [ERC7930] 複数チェーンのアドレスを1つの形式で扱う仕組みを理解しよう！

> Interoperable Addresses（インターオペラブル・アドレス）は、「ある特定のチェーン固有のアドレス」をバイナリ形式で表現するための提案です。

- URL: https://cardene.dev/articles/e280966bf2619d25d4c8
- 公開日: 2025-10-17
- 更新日: 2025-10-17
- トピック: Blockchain
- タグ: ethereum, solidity, smartcontract, ブロックチェーン

## はじめに

『DApps開発入門』という本や色々記事を書いているかるでねです。

https://amzn.asia/d/gxvJ0Pw

今回は、異なるブロックチェーンのアドレスを、チェーン情報やチェックサム付きで安全かつ統一的に表現できるようにする仕組みを提案している**ERC7930**についてまとめていきます！

:::message
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
:::

https://eips.ethereum.org/EIPS/eip-7930

他にも様々なEIP・BIP・SLIP・CAIP・ENSIP・RFC・ACPについてまとめています。

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4

## 概要

Interoperable Addresses（インターオペラブル・アドレス）は、「**ある特定のチェーン固有のアドレス**」をバイナリ形式で表現するための提案です。
人間にとって読みやすい表示のためには、対になる仕様である「**Interoperable Names**」を用います。
中核となるのは、**バージョン付き・長さプレフィックス付きのバイナリエンベロープ**で、任意長データを安全にまとめます。
エンベロープ内のデータ（具体的なアドレスやチェーン識別子など）の解釈ルールとシリアライズ規則は、各チェーンタイプに対応した別規格（プロファイル）が定義します。
これにより、EVM系・非EVM系を含む多様なチェーンを統一的かつ拡張可能に扱えます。

:::message
#### バージョン付き・長さプレフィックス付きのバイナリエンベロープとは？

「**バイナリエンベロープ**」というのは、データをひとつのまとまり（包み）として整理して格納する仕組みのことです。
ここでは、「**アドレスに関する情報（チェーンIDや実際のアドレス本体など）**」を1つの箱に入れて管理するイメージです。

* **バージョン付き**
    どの世代・形式のデータかを示す番号を最初に入れておくことで、将来フォーマットが変わっても互換性を保てます。
    例えば「**v1**」、「**v2**」といった感じです。

* **長さプレフィックス付き**
    データの前に「**この後に続くデータの長さ**」を書いておく方式のことです。
    こうすることで、コンピュータはどこまでが1つのデータなのかを正確に読み取ることができます。

つまり「**バージョン付き・長さプレフィックス付きのバイナリエンベロープ**」とは、

どんな形式のデータなのか（version）と、どこまでがそのデータなのか（length）を明示した、安全で拡張性のあるデータのまとめ方。

この仕組みによって、将来的にフォーマットを拡張したり、異なるチェーンのアドレスデータを扱ったりしても、古いバージョンとの互換性を保ちながら安全に解釈できるようになります。
:::

## 動機

いま一般的に使われている Ethereum のアドレス（**ERC55**）は、チェーン固有性を持たないうえにチェックサムが任意という性質があり、現場では次のような困りごとが起きています。

:::message
**ERC55**については以下の記事を参考にしてください。
:::

[\[EIP55\] Ethereumアドレスのチェックサムの仕組みを理解しよう！](/articles/985f03760df12929b5f9)

- チェックサムが任意のため、ユーザーがアドレスを打ち間違えてもアプリ側が気づけず、そのまま処理が通ってしまうリスクがある。
- チェーン情報が含まれていないため、「**このアドレスはどのチェーン向けか**」を外部情報で管理しなければならず、誤チェーンでの送付・実行（特にコントラクトアドレスで顕著）を招きやすい。
- 拡張の仕組みがないため、上記の課題を既存フォーマットの中で自然に解決する手段がない。

Interoperable Addressesは、これまでの議論や **CAIP10**, **CAIP50** の知見を踏まえつつ、以下を一体化します。

:::message
**CAIP10**については以下の記事を参考にしてください。
:::

[\[CAIP10\] 異なるブロックチェーンのアカウントを統一管理する仕組みを理解しよう！](/articles/c483d9a87a43c94a3db5)

* チェーン識別子による明示的なチェーンバインディング（アドレスとチェーンの結び付け）
* コンパクトで正規化（canonical）されたバイナリ形式（クロスチェーンのメッセージパッシングやインテント宣言で効く）
* **チェックサム**（名前衝突の緩和やヒューマンエラーの防止）

さらに、エコシステムの周縁や非EVMチェーンとも仲良くするために、非EVMチェーンのアドレス表現もサポートします。
これにより、クロスチェーンの流動性移動やメッセージパッシングの実装で、同じ入出力の“通し番号（共通言語）”として扱えるようになります。

#### 仕様の要点

実際のビット配列や各フィールド長は、チェーンプロファイル側で厳密に決まります。

```
+---------------------+-----------------+-------------------+-----------------+-------------+
| version (u8)        | total_len (u16) | chain_id (varlen) | address (bytes) | checksum(n) |
+---------------------+-----------------+-------------------+-----------------+-------------+
```

* **version**
    フォーマットのバージョン。
    将来拡張しても互換性を保つ鍵。
* **total_len**
    以降の全体長。
    取り回しやパースの安全性を担保。
* **chain_id**
    チェーン識別子。
    CAIP系の定義に沿うプロファイルが決める。
* **address**
    そのチェーンの「**生のアドレス**」をバイナリで入れる。
* **checksum**
    短くても比較しやすいチェックサム。
    人間の目でも違いを判断しやすい。

人間が読みやすい表示のためには **Interoperable Names**を使い、バイナリとの相互変換を行います。

#### この規格が目指す保証

Interoperable Addresses は、使い手が不透明な識別子として安心して扱える土台を目指しています。
具体的には以下の保証を掲げます。

* **将来バージョンからv1への単純変換が常に可能**
    将来のInteroperable Addressでも、ここで定義するv1に自明にダウングレードできます。
    これにより、ツールやスマートコントラクトがとりあえずv1を理解していれば受け入れやすくなります。

* **同じ対象アドレスなら、正規化後はビット単位で一致**
    2つのInteroperable Addressをこの正規化（canonical）バージョンへ変換したとき、ビット単位で一致するのは同一の対象アドレスを表すときだけです。
    逆に一致しないなら別物だと判定できます。

* **チェックサムは人間にもやさしい**
    短くても見比べやすいチェックサムを備えることで、追加データの有無に左右されず、対象アドレスの取り違えを避けやすくします。

#### 他規格との比較

##### CAIP10との関係

**CAIP10** は、ここでいう「**対象アドレス（target address）**」をテキストで表すための標準です。
テキスト標準であるがゆえに、チェーン固有のアドレス表現の中身のバイナリには立ち入りません。
各チェーンが既に定めた文字列表記をそのまま使うため、新しいチェーンを足すのは簡単です。
一方で、Interoperable Addressesのようにシリアライズ規則（バイナリ定義）まで踏み込む場合は、チェーンごとのプロファイル設計が必要になります。

この設計方針の違いは、以下の性質の違いとして表れます。

| 観点 | Interoperable Addresses   | CAIP-10  |
| --------------- | ------------ | ----------------- |
| 形式 | バイナリ（長さ付き・バージョン付与）    | テキスト                           |
| 正規化（canonicity） | 保証される（同一対象はビット単位で一致）  | 保証されない（同じ対象でも複数の妥当表現がありうる） |
| データ効率  | 高い（メッセージパッシング・インテントに最適） | 低め（テキストゆえに冗長）    |
| チェーン識別 | エンベロープ内に明示 | テキストとして表現（柔軟だが厳密性は低め）  |
| 互換性  | Interoperable Names 経由でCAIP10へ変換可能 | そのまま既存生態系で広く利用可                |

要点として、CAIP10はテキストで広く緩やかにつなぐ規格であり、Interoperable Addressesはバイナリで厳密に統一する規格です。
クロスチェーンのメッセージパッシングや流動性移動のように、データ効率と正規性が重要な場面では、Interoperable Addressesのコンパクトさと正規化が効いてきます。

また、Interoperable Namesは**CAIP10**に直接変換可能です（バイナリに戻さずにテキスト化できる）。
つまり、**CAIP10**を期待する既存のコンポーネントとも後方互換でやっていけます。

最後に、インターオペラビリティのロードマップとしては、まずアドレスのバイナリ標準を固めることで、メッセージパッシングやインテントといった共通インタフェースが前に進みやすくなります。
そのうえで、名前解決（Interoperable Names）を上に重ね、人間にも開発者にも扱いやすい表示・解決レイヤを整えていく、という順序が現実的です。

#### 使いどころのイメージ

* **ウォレットやブリッジ**
    送信先が「**どのチェーンの、どのアドレスか**」をエンベロープが強制的に含むため誤チェーン送付の回避に役立つ。
* **クロスチェーン DEX / メッセージング**
    バイナリで正規化されているので、識別・比較・ルーティングがシンプル。
* **監査・可観測性**
    短いチェックサムを目視で比較しやすいため、現場のオペレーションでも有用。

## 仕様

### 概念

Interoperable Addressesを構成する主要な概念は以下の3つです。

| 名称 | 説明  |
| ------ | --------------- |
| **Interoperable Address（相互運用可能アドレス）** | バイナリ形式のデータ構造で、特定のターゲットアドレスを一意に識別できる。人間が読める形式（Interoperable Name）にも変換できる。 |
| **Interoperable Name（相互運用可能名）**  | Interoperable Address を人間向けに文字列として表現したもの。ウォレットやUIで表示される。 |
| **Target Address（ターゲットアドレス）**  | Interoperable Address が指し示す具体的な宛先。アドレス本体とチェーンIDの組み合わせで表現される。   |

つまり、Interoperable Addressは機械が使う正確な識別子であり、Interoperable Nameはそれを人間が扱うための読みやすい表記という関係です。

### Interoperable Address v1 のバイナリ形式

Interoperable Addressのバイナリ表現は、以下のような構造で定義されています。

```
┌─────────┬───────────┬──────────────────────┬────────────────┬───────────────┬─────────┐
│ Version │ ChainType │ ChainReferenceLength │ ChainReference │ AddressLength │ Address │
└─────────┴───────────┴──────────────────────┴────────────────┴───────────────┴─────────┘
```

| フィールド名  | サイズ  | 説明  |
| ------- | ---- | --------- |
| **Version**  | 2バイト | フォーマットのバージョン識別子。v1の場合は常に `0x0001`（ビッグエンディアン）。将来のバージョンは別の規格（ERC）として定義される予定。  |
| **ChainType**   | 2バイト | **CAIP350** に定義された値で、**CAIP2**の namespaceに対応。どのチェーンタイプ（例：Ethereum, Solana, Cosmosなど）なのかを表す。これにより、他のフィールド（ChainReferenceやAddress）の解釈ルールを特定できる。 |
| **ChainReferenceLength** | 1バイト | ChainReference の長さ（バイト数）。0の可能性もあり、その場合はChainReferenceが存在しない。   |
| **ChainReference**       | 可変長  | **CAIP2**のチェーン識別子（namespace + reference）をバイナリ化したもの。具体的なフォーマットはチェーンタイプごとの **CAIP350**プロファイルで定義される。  |
| **AddressLength**  | 1バイト | Addressフィールドの長さ（バイト数）。0の可能性もあるが、ChainReferenceLength も0の場合は許されない。つまり、どちらかは必ず存在しなければならない。             |
| **Address**  | 可変長  | アドレス本体をバイナリ形式で格納する部分。チェーンタイプによって表現方法は異なり、これも **CAIP350**プロファイルに準拠して定義される。  |

:::message
**CAIP350**については以下の記事を参考にしてください。
:::

[\[CAIP350\] マルチチェーン対応アドレス変換規格の仕組みを理解しよう！](/articles/514b7340056bbb9ac7b6)

:::message
**CAIP2**については以下の記事を参考にしてください。
:::

[\[CAIP2\] 複数のブロックチェーンを識別する仕組みを理解しよう！](/articles/ee2925039fa62b982101)

この構造により、異なるブロックチェーンのアドレスを同じ形式で扱えるようになります。

### バージョン互換性

Interoperable Addressの将来バージョンでは、v1との互換性を保ちながら進化できるルールが設けられています。
これにより、過去のウォレットやスマートコントラクトが新しいフォーマットのアドレスを扱う際にも混乱しないようにしています。

| ルール | 説明  |
| ----- | --------------- |
| **v1と互換性がないフォーマットは、Versionフィールドの最上位ビット（MSB）を1にする** | これにより、古いシステムでもこのバージョンは理解できないと即座に判断できる。      |
| **すべてのバージョンでアドレスとチェーン情報の両方をサポートすること**    | チェーンIDを欠いたアドレスは存在してはならない。  |
| **チェックサム計算時はVersionフィールドを除外し、v1形式にシリアライズして行うこと**   | チェックサムがバージョン依存にならないようにするため。     |
| **特定のCAIP namespaceの一部しか表せない場合がある**  | 新しいバージョンは、特定のチェーン群に特化することもできる。                |
| **Interoperable Nameに追加の文法や意味を持たせてもよい**  | たとえばENS（Ethereum Name Service）などの名前レジストリ連携など。 |
| **追加フィールドを定義してもよい**   | 表示情報やメタデータを格納するための新しいフィールドを導入できる。   |

これらのルールによって、互換性と拡張性を両立した設計が実現されています。

### Interoperable Name の形式

Interoperable Nameは、人間が読みやすいように表現された文字列形式のアドレスです。
基本構文は以下です。

```
<human readable name> ::= <address> @ <chain> # <checksum>
<address>             ::= [.-:_%a-zA-Z0-9]*
<chain>               ::= [.-:_a-zA-Z0-9]*
<checksum>            ::= [0-9A-F]{8}
```

構造としては以下のようになります。

| 要素 | 例  | 説明  |
| ------ | ------ | ------- |
| `<address>`  | `0xAbC123...` | チェーン固有のアドレス部分。バイナリ形式から変換されたもの。  |
| `<chain>`    | `eip155:1`    | **CAIP2**のブロックチェーン識別子。ChainReferenceが空の場合はnamespace（例：`eip155`）のみを書く。reference だけを書くことはできない。 |
| `<checksum>` | `5A3C9F2B` | チェックサム（ハッシュの上位4バイトを16進数で表記）。アドレスの正しさや衝突防止に使う。   |

したがって、ひとつのInteroperable Nameは以下のような形になります。

```
0x1234abcd5678ef90 @ eip155:1 # 5A3C9F2B
```

### チェックサムの計算方法

チェックサムは、誤入力や衝突を防ぐための短い識別子です。
計算方法は次のように定義されています。

- **対象となるデータ**
    * `ChainType`
    * `ChainReferenceLength`
    * `ChainReference`
    * `AddressLength`
    * `Address`
     （※Versionフィールドは含めません）
- **ハッシュ計算**
    上記を連結し、`keccak256` ハッシュを計算します。
- **上位4バイトを抽出**
    出力の最初の4バイトだけを取り出します。
- **16進表記に変換**
    **RFC4648**の定義に基づき、大文字の16進数（Base16）文字列に変換します。

これにより、短くても十分に識別力を持ち、人間が目視でも比較しやすい8桁のチェックサムが得られます。

## 補足

#### チェーンとアドレスの構文をこの形にした理由

Interoperable Nameの構文では、次のように「`@`」記号を使ってチェーンを区切り、「`:`」記号を別用途のために空けておく形を採用しています。

```
<address> @ <chain> # <checksum>
```

この形は、**CAIP2**および**CAIP10**の考え方を自然に表現できるように設計されています。

| 構成要素 | 目的 |
| ---- | ------------ |
| `@`  | チェーン名の区切りとして使用。これにより、`:` は**CAIP2**の `namespace`（チェーン識別子内部）にそのまま使えるようになる。 |
| `:`  | **CAIP2**や**CAIP10**で既に使われている区切り文字を維持し、既存の仕様との整合性を保つ。  |
| `#`  | チェックサムの区切り。人間にも視覚的にわかりやすい形式。        |

この設計により、以下のようなメリットがあります。

* **CAIP2のネームスペースをそのまま表現できる**
  例として `eip155:1` や `cosmos:osmosis-1` など、既存のチェーン識別子の書き方をそのまま流用できます。

* **CAIP10のアカウントIDも自然に表現できる**
  例:

  ```
  0x1234abcd5678ef90 @ eip155:1 # A1B2C3D4
  ```

さらに、Interoperable Address では長さ制限を設けていないため、256ビットのEVMチェーンIDなどより長い識別子も扱えるようになっています。
これにより、将来登場する大規模または特殊なチェーンに対しても、同じフォーマットで柔軟に対応できます。

#### アドレスに `%` 記号を含める理由

アドレス部分の構文では、`%` 記号も有効文字として認められています。
これは、**URLエンコード（パーセントエンコーディング）**を使って特殊文字を表現できるようにするためです。

例えば、もし将来のチェーンや非EVMアドレスで、通常の英数字以外の文字（例：記号やバイナリ文字列）を含むアドレス形式が登場した場合でも、`%xx` 形式で安全に表せるようになります。

例：

```
addr%20example @ chainx:100 # 9F3C0A2B
```

このように `%` を使えるようにしておくことで、どんなチェーンやプロトコルでも共通の文字ベース表記に変換でき、統一的なテキスト形式を維持できます。

#### 新しいエンコーディング方式を採用しなかった理由

Interoperable Addressの設計チームは、テキスト表現に**base58** や **base64** などの情報効率の高いエンコーディング方式を採用することも検討しました。
これらの方式を使えば、文字数を減らしてよりコンパクトに表記できます。

しかし、最終的には以下の理由からより馴染みのある表記を優先しました。

| 理由   | 説明   |
| ----- | ------ |
| **ユーザーにとって直感的であることを優先** | Interoperable Address と「**元の生アドレス**」の関係を見ただけで理解できるようにした。例えば「**0xで始まるEthereumアドレスだ**」とユーザーがすぐ認識できる。    |
| **既存ウォレットやDAppとの橋渡しを容易にするため**   | まだInteroperable Addressを完全にサポートしていないアプリやハードウェアウォレットでも、「**アドレス部分は同じで、チェーンとチェックサムが付いているだけ**」と判断しやすい。 |
| **人間に読みやすく、当面の暫定的な標準としても使いやすい** | 将来、チェーン名やアドレス名に特化した正式な標準（ネームサービス）ができるまでのつなぎとして、開発者とユーザーが扱いやすい構文にする。  |

つまり、技術的にはもっと効率化できたとしても、「**人間がすぐ理解でき、現場で使いやすい**」ことを重視して設計されたのです。

#### 長さゼロのアドレスやチェーンIDを許可した理由

**ERC7930**では、アドレスやチェーンIDの長さがゼロでもよいと明記されています。
一見すると「**空のアドレスを許すのは危険では？**」と思われるかもしれませんが、これには明確な意図があります。

- **異なる用途を1つの規格で扱うため**
    Interoperable Addressは、単にウォレット送金用の「**宛先**」を表すだけではなく、クロスチェーン通信のメッセージ送信元・送信先など、様々な文脈で使われることを想定しています。
- **共通フォーマットによる一貫性を保つため**
    例えば、以下のような状況を1つの仕様で表現できるようにするためです。

| 用途               | ChainID | Address | 意味                     |
| ---------------- | ------- | ------- | ---------------------- |
| クロスチェーンメッセージの宛先  | あり  | あり | 通常の宛先指定  |
| クロスチェーンメッセージの送信元 | あり | なし | チェーンのみ指定（送信元を特定） |
| 汎用的なアドレスのみ指定  | なし      | あり      | 単一チェーンに属さないアドレスやリソース指定 |

このように「**ゼロ長を許す**」ことで、1つのInteroperable Addressフォーマットが、外部チェーン向けの宛先から単なるアドレス指定まで幅広い用途に対応できるようになります。
これにより、開発者は用途に応じて別の仕様を作る必要がなくなり、実装も一貫性を保てます。

## セキュリティ

#### 抽象化の限界

Interoperable Address は、「**どのチェーンの**」、「**どのアドレスか**」を厳密に定義することで、アドレスの一意性と比較可能性を保証しようとしています。
しかし、この理想はチェーンごとの実装や仕様の違いによって部分的に崩れることがあります。

その代表的な例は以下のようなものです。

| 問題の種類  | 説明     |
| --------- | ---------------- |
| **シリアライズ方式の不整合**  | チェーンごとに定義される **CAIP350**プロファイルが、アドレスの変換（シリアライズ／デシリアライズ）で一意性を保証できない場合があります。つまり、同じアドレスが異なるバイナリ表現を持つ可能性があります。      |
| **CAIP2識別子の重複** | 1つのネットワークが、異なる**CAIP2**のID（namespace:reference）で表されてしまうことがあります。例えば、同一のチェーンを指していても、歴史的な経緯や運用上の都合で複数のIDが存在するケースです。 |

これらの問題があると、「**同じチェーン・同じアドレスなのに、Interoperable Address のバイナリ表現が異なる**」という事態が発生する可能性があります。
これを「**canonicity（正規性）**」の崩れと呼びます。

#### 実装者への注意点

Interoperable Addressをアプリケーションやスマートコントラクトで使う時、「**アドレスをキーとして扱う**」ようなケースでは、特に注意が必要です。
例えば、スマートコントラクトのマッピング（`mapping(address => value)`）や、
オンチェーン／オフチェーンでのキー・バリュー型データベースなどです。

こうした場合、同じアドレスを指しているのに、異なるバイナリ表現が登録されてしまうと、重複データやアクセス不整合を引き起こす可能性があります。

このため、実装者は以下の点を必ず確認することが推奨されています。

| チェック項目 | 説明 |
| --------- | ------------- |
| **CAIP350プロファイルの確認**  | 使用するチェーンの**CAIP350**のプロファイルをよく確認し、アドレスのシリアライズ方式が一意性（canonicity）を保証しているかどうかを確認すること。                                   |
| **Extra Considerations の内容** | 各**CAIP350**のプロファイルには「**Extra Considerations（追加の考慮事項）**」というセクションがあり、そこに正規性が保証されない可能性や名前衝突の懸念が記載されている場合があります。これを確認する必要があります。 |
| **他のネームスペースとの衝突チェック**  | 既にサポートされている別の `namespace` と衝突する可能性がないかを検証すること。異なるチェーン識別子が同じ実ネットワークを指していないか確認する。  |

この確認を怠ると、システム上では「**異なるキー**」として扱われてしまい、ユーザー資産やデータ参照に誤りが生じるおそれがあります。

#### 実際のリスクと対応の考え方

Interoperable Addressの設計は高い抽象度を持ち、「**どのチェーンのアドレスも統一的に扱う**」という大きな利点を提供します。
しかし、抽象化の下にあるチェーン固有の設計（アドレス構造、識別子体系、エンコード方式）はバラバラです。

つまり、Interoperable Address は「**標準化された表面上の形式**」を提供しますが、その中身の正確性や一意性は各チェーンのプロファイル定義に依存するということです。
そのため、実装時に必ず確認して必要に応じてアプリケーション側で追加の正規化処理を行うことが推奨されます。

* チェーンごとにプロファイルがどのように定義されているか
* その定義が他のチェーンやネットワークと衝突する恐れがないか

## 引用

Teddy (@0xteddybear), Joxes (@0xJoxess), Nick Johnson (@Arachnid), Francisco Giordano (@frangio), Skeletor Spaceman (@skeletor-spaceman), Racu (@0xRacoon), TiTi (@0xtiti), Gori (@0xGorilla), Ardy (@0xArdy), Onizuka (@onizuka-wl), Sam Kaufman (@SampkaML), Marco Stronati (@paracetamolo), Yuliya Alexiev (@yuliyaalexiev), Jeff Lau (@jefflau), Sam Wilson (@samwilsn), Vitalik Buterin (@vbuterin), "ERC-7930: Interoperable Addresses [DRAFT]," Ethereum Improvement Proposals, no. 7930, February 2025. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7930.

## 最後に

今回は「」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください！

[Twitter @cardene777](https://twitter.com/cardene777)

他の媒体でも情報発信しているのでぜひ他も見ていってください！

https://chaldene.net/

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4
