はじめに

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

今回は、異なるブロックチェーン間でスマートコントラクトが安全かつ共通の方法でメッセージを送受信できるようにする、クロスチェーン通信の標準インターフェース仕組みを提案しているERC7786についてまとめていきます!

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

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

概要

ERC7786では、スマートコントラクトがクロスチェーン・メッセージング・プロトコルを通じて任意のデータを送信するための共通インターフェースと、そのためのワークフローを定義しています。 最終的な目標は、あらゆるメッセージング・プロトコル(ブリッジ)をこのインターフェース経由で利用できるようにすることです。 これにより、異なるブロックチェーン間の相互運用性(interoperability)と組み合わせ可能性(composability)が大幅に向上します。

これが実現すると、複数のチェーンにまたがって動作する新しいタイプの「クロスチェーン・ネイティブ・スマートコントラクト」が登場します。 開発者は特定のブリッジに依存せずに、共通のインターフェース経由でメッセージを送信できるようになります。 結果として、ベンダーロックイン(特定のブリッジ依存)のリスクが減少し、ブリッジ間での移行も容易になります。

ERC7786の設計はモジュール構造であり、ブリッジ固有の機能を「属性(structured metadata)」として扱うことができます。 一方で、共通の最低限の機能——つまり「単純なメッセージを送る」という目的——に対しては統一されたインターフェースを提供します。 これにより、シンプルなユースケースから高度なカスタマイズまで幅広く対応できる柔軟な設計となっています。

動機

背景:クロスチェーン・メッセージングの多様性

現在、クロスチェーン・メッセージング・プロトコル(またはブリッジ)は、異なるブロックチェーン上のスマートコントラクト同士が通信するために使われています。 しかし、この領域には以下のような多様性があります。

観点 プロトコル間の違い
分散化の度合い 完全に分散されたものから、中央集権的な検証者に依存するものまで様々
アーキテクチャ メッセージの中継方法、認証方式、Transferルールがそれぞれ異なる
インターフェース メッセージ送信時のAPIや関数仕様がプロトコルごとに異なる
保証 メッセージの最終性(finality)や安全性、再送保証の有無などが異なる

このように、プロトコルごとにワークフローとインターフェースが異なるため、ブリッジ間でのポータビリティ(移植性)がほとんどありません。 結果として、開発者は特定のブリッジに依存したコードを書かざるを得ず、ブリッジを変更することがほぼ不可能になっています。

さらに、こうした非互換性が原因で、汎用的にクロスチェーン通信を扱えるスマートコントラクトの開発も難しくなっています。

提案の目的

ERC7786が目指すのは、異なるチェーン上のスマートコントラクト間で通信を行うための共通インターフェースとワークフローを標準化することです。

この標準を採用することで以下が実現できます。

  • 異なるクロスチェーン・メッセージング・プロトコル間で同じ関数呼び出しを使える
  • 開発者がブリッジ固有の処理を意識せずに利用できる
  • 複数のブリッジを統合したマルチブリッジ対応アプリケーションを構築できる

さらに、既存のプロトコルがこの新しい標準をネイティブに実装していなくても、「アダプター・ゲートウェイ・コントラクト」を利用することで、このインターフェースに対応できるように設計されています。

既存のERCとの比較

これまでにも、クロスチェーン通信に関するERCはいくつか存在しました。 しかし、それらは主にEthereumやEVM互換チェーンの範囲に限定されており、他のブロックチェーンとの連携には対応していませんでした。

この提案では以下の点で改良されています。

比較項目 従来のERC 本提案
対応範囲 Ethereum/EVMチェーンのみ 非EVMチェーンを含む全ブロックチェーン
機能拡張性 限定的(機能追加が難しい) メタデータ(属性)で柔軟に拡張可能
ブリッジ依存性 高い(特定ブリッジ専用設計) 低い(アダプター経由で統一利用可能)
相互運用性 部分的 高い(共通ワークフローによる統合)

このように、提案されているインターフェースは、単にEthereumエコシステムに閉じたものではなく、将来的に複数のブロックチェーンを横断するエコシステムのコアとなる可能性を持っています。

仕様

メッセージフィールドのエンコーディング

クロスチェーンメッセージは、以下の要素で構成されます。

フィールド名 説明
Sender 送信元アドレス(送信チェーン上のコントラクトやアカウント)
Recipient 受信先アドレス(受信チェーン上のコントラクトやアカウント)
Payload メッセージの内容(バイナリデータ)
Value メッセージと一緒に送信されるネイティブトークンの値
Attributes 追加情報を含む属性のリスト

送信者と受信者

送信者(sender)と受信者(recipient)のアドレスは、ERC7930で定義された「Interoperable Address(相互運用可能アドレス)」形式で入力される必要があります。 このアドレスは CAIP350に従ってシリアライズ(バイナリ化)されます。

ERC7930については以下の記事を参考にしてください。

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

受信者アドレスが省略またはゼロ値(全フィールドがゼロのアドレス)で入力された場合、そのメッセージは「ブロードキャストモード」を意味します。 このモードでは、最終的な受信者はブリッジプロトコル側で自動的に決定されます。

ペイロード

ペイロードは、ブリッジを通じて送信される任意のデータを格納する不透明なバイト列(opaque bytes)です。 つまり、ブリッジはその内容を解釈せず、単に転送します。

属性(Attributes)

属性はメッセージに追加情報を持たせるための「キーと値」のペアです。 キーは属性の種類やエンコーディング方法、ゲートウェイ内での意味を決定します。

属性の仕組みは拡張可能であり、標準化された属性は新たなERCとして提案・公開することが推奨されています。 ゲートウェイは標準的または独自の属性を任意にサポートできます。

要素 説明
属性キー 4バイトの値(bytes4)。Solidityの関数セレクターを使用して定義することが推奨されます。例:minGasLimit(uint256) → 0x39f87ba1
属性値 バイト配列(bytes)。キーで定義された型・意味に従う値。

属性リストは bytes[] 型でエンコードされ、各要素は「キー + 値」を連結したものになります。 abi.encodeWithSignature を使用してエンコード可能です。 属性が存在しない(空のリスト)場合でも、有効なメッセージとして扱われます。

送信手順

メッセージの送信は、Source Gatewayと呼ばれるコントラクトを通じて行われます。 このコントラクトは IERC7786GatewaySourceインターフェースを実装する必要があります。

IERC7786GatewaySource

javascript
interface IERC7786GatewaySource {
    event MessageSent(
        bytes32 indexed sendId,
        bytes sender,    // Binary Interoperable Address
        bytes recipient, // Binary Interoperable Address
        bytes payload,
        uint256 value,
        bytes[] attributes
    );

    error UnsupportedAttribute(bytes4 selector);

    function supportsAttribute(bytes4 selector) external view returns (bool);

    function sendMessage(
        bytes calldata recipient, // Binary Interoperable Address
        bytes calldata payload,
        bytes[] calldata attributes
    ) external payable returns (bytes32 sendId);
}

MessageSent

javascript
event MessageSent(
    bytes32 indexed sendId,
    bytes sender,
    bytes recipient,
    bytes payload,
    uint256 value,
    bytes[] attributes
);

メッセージ送信要求が行われたときに発行されるイベント。 このイベントは、送信元が別のチェーンにメッセージ送信を要求した時に発行されます。 sendId が存在する場合、メッセージを有効化するための「ポストプロセッシング」が必要な場合があります。

パラメータ

  • sendId
    • メッセージ送信の一意な識別子。
  • sender
    • 送信元アドレス(Interoperable Address形式)。
  • recipient
    • 受信先アドレス(Interoperable Address形式)。
  • payload
    • 送付されるデータ本体。
  • value
    • 一緒に送信されるネイティブトークンの量。
  • attributes
    • メッセージに付加される属性情報の配列。

UnsupportedAttribute

javascript
error UnsupportedAttribute(bytes4 selector);

サポートされていない属性を指定した場合に発生するエラー。 ゲートウェイが対応していない属性キー(セレクター)を使用したときに送出されます。

パラメータ

  • selector
    • サポート外の属性キー(bytes4形式)。

supportsAttribute

javascript
function supportsAttribute(bytes4 selector) external view returns (bool);

指定された属性がゲートウェイでサポートされているかを確認する関数。 引数で与えられた属性キーが、このゲートウェイで使用可能かどうかを返します。 ゲートウェイは将来的に新しい属性を追加サポートすることができますが、既存の属性を削除することは推奨されません(後方互換性維持のためです)。

引数

  • selector
    • 属性を識別するキー。

戻り値

  • bool
    • サポートされている場合は true、それ以外は false。

sendMessage

javascript
function sendMessage(
    bytes calldata recipient,
    bytes calldata payload,
    bytes[] calldata attributes
) external payable returns (bytes32 sendId);

メッセージ送信を開始する関数。 別チェーン上の受信者へメッセージを送るための処理を開始します。 ガス代の支払いなど、メッセージを有効化するための追加処理(ポストプロセッシング)が必要な場合があります。

以下の条件が適用されます。

  • サポートされていない属性が含まれる場合、UnsupportedAttribute エラーを返してリバートします。
  • 無効な値が指定された場合もリバートすることがあります。
  • ネイティブトークン(value)を送信することが許可されていない場合、リバートします。
  • メッセージごとに一意の sendId を返す場合があります。
  • この sendId は後のイベント追跡やポストプロセス処理で利用できます。

引数

  • recipient
    • 受信先アドレス(Interoperable Address形式)。
  • payload
    • 送信するデータ。
  • attributes
    • 付随する属性情報の配列。

戻り値

  • sendId
    • 一意なメッセージ送信識別子。
    • 存在しない場合はゼロ値。

ポストプロセッシング

sendMessage が呼び出された後、メッセージを実際に有効化するための追加処理が必要な場合があります。 この処理をポストプロセッシングと呼びます。

例として、宛先チェーンでメッセージを実行するためのガス代の支払いなどがあります。 ただし、この具体的なインターフェースや手順はこのERC7786の範囲外です。

受信手順

受信側では、Destination Gatewayがメッセージを検証し、対応するコントラクトに送付します。 受信ゲートウェイの実装や呼び出し方法はこのERCの範囲外です。

ただし、メッセージは次のインターフェースを実装したコントラクトに渡される必要があります。

IERC7786Recipient

javascript
interface IERC7786Recipient {
    function receiveMessage(
        bytes32 receiveId,     // Unique identifier
        bytes calldata sender, // Binary Interoperable Address
        bytes calldata payload
    ) external payable returns (bytes4);
}

receiveMessage

javascript
function receiveMessage(
    bytes32 receiveId,
    bytes calldata sender,
    bytes calldata payload
) external payable returns (bytes4);

他のチェーンから送信されたメッセージを受信する関数。 この関数は、メッセージが安全に到達したときに呼び出されます。 受信側のコントラクトは、この呼び出し元が信頼できるゲートウェイであることを確認する必要があります。 また、正常に受信した場合は固定の戻り値 0x2432ef26(IERC7786Recipient.receiveMessage.selector)を返す必要があります。 誤った値を返した場合、ゲートウェイはリバートします。

引数

  • receiveId
    • メッセージの一意な識別子。
  • sender
    • 送信元のアドレス(Interoperable Address形式)。
  • payload
    • メッセージのデータ本体。

戻り値

  • bytes4
    • 正常な受信を示す識別子。
    • 固定値 0x2432ef26。

相互作用図

送信から受信までの流れをまとめると以下のようになります。

プロパティ

安全性

安全性とは、「送信されたメッセージだけが一度だけ正しく宛先に届けられること」を保証する性質です。 より具体的には、以下の条件を満たす必要があります。

要件 説明
メッセージ送信の正当性 メッセージは、送信元で実際に送信されたものでなければ宛先に届かない。つまり、送信記録が存在しないメッセージは決して配信されない。
一度限りの配信 メッセージは、同一内容のものでも「送信トランザクションごとに」一度だけ配信される。重複配信(再送)や偽造を防ぐ必要がある。
トランザクションの確定性 送信チェーン上でトランザクションが最終確定(finalized)されてからでなければ、受信側に配信してはならない。

この性質によって、クロスチェーン通信においてもオンチェーン取引と同様の信頼性が保たれます。 特に「一度送ったメッセージが再び実行されてしまう」ようなリプレイ攻撃を防ぐうえで重要です。

Liveness

Livenessとは、「送信されたメッセージが最終的に宛先に届く」ことを保証する性質です。 どんなに安全性が確保されていても、メッセージが届かないままでは意味がありません。 そのため、Livenessはクロスチェーン通信の実用性を左右する重要な要件です。

この性質を満たすために、以下の条件が前提とされます。

要件 説明
チェーンの稼働 送信元チェーンと受信先チェーンの両方が正常に稼働しており、検閲(censorship)されていないこと。
コストの支払い 必要なガス代やプロトコル手数料が支払われていること。
検証可能な伝達経路 メッセージが中継ノードやブリッジを通過する際に、検証可能であり、改ざんされないこと。

つまり、「ブロックチェーン同士が健全に動作しており、必要な手数料が支払われている限り、メッセージは必ず最終的に届く」ことが保証されます。 これにより、プロトコルの信頼性と継続性が確保されます。

迅速性(Timeliness)

迅速性とは、「送信されたメッセージが一定の時間内に宛先に届く」ことを保証する性質です。 これは「いつか届く」ではなく、「一定の時間制約のもとで確実に届く」という保証を与えるものです。

このプロパティは必須ではなく推奨ですが、実用的なクロスチェーン通信では非常に重要です。 なぜなら、金融取引やゲームなどのリアルタイム性を求めるユースケースでは、時間の保証がないとユーザー体験が大きく損なわれるためです。

要件 説明
時間の上限 メッセージが宛先に届くまでの最大時間(bounded delivery time)を定義し、その範囲内で配信を保証する。
ドキュメント化 プロトコル提供者は、この時間上限や遅延特性を明示的にドキュメント化し、ユーザーが把握できるようにする。

これにより、開発者や利用者は、特定のブリッジを使用する時の遅延特性や性能を比較・選択できるようになります。

非中央集権的な保証

上記のすべての性質(安全性・活性・迅速性)は、中央集権的な信頼に依存してはならないとされています。 つまり、特定の管理者や単一の運営者に依存する構造は避けるべきです。

安全性(Safety)は、例えば以下のような「信頼できない(trustless)仕組み」で保証されるべきです。

仕組み 説明
ライトクライアント(Light Client Proof) 宛先チェーンが送信元チェーンのブロックを直接検証する仕組み。中間者を介さず、暗号学的に正当性を保証する。
分散バリデータ(Decentralized Validator Set) 開かれた分散型の検証者ネットワークが、メッセージの真正性を署名や証明書で保証する。

一方で、Livenessを確保するためには、メッセージのリレー(転送)も分散的またはパーミッションレス(誰でも参加できる)である必要があります。 なぜなら、もし単一のリレーヤー(中継者)に依存してしまうと、そのノードが停止したり、恣意的に取引を拒否した場合に、プロトコル全体が停止してしまうためです。

補足

属性設計の狙い

ERC7786では「属性(Attributes)」を用いて、ブリッジ固有機能を専用インターフェースなしで公開できるようにしています。 メッセージ自体は共通フォーマットのまま、必要に応じて属性を付け替えるだけで機能を拡張できるため、コントラクトが利用するゲートウェイ(ブリッジ)を差し替えても同じ表現でメッセージを記述し続けられます。 結果として、アプリケーションは1つの実装に縛られず、将来的な乗り換えや多様な運用に耐える構造になります。

ポータビリティの利点

属性を軸にした共通化により、以下のような実運用上の利点が生まれます。

課題/状況 従来(専用IF依存) 本標準(属性+共通IF)
ゲートウェイの停止・廃止・障害 コントラクト修正や再デプロイが必要になりがち ストレージ内のゲートウェイ先アドレスを更新するだけで切り替え可能
新バージョンへの更新 メッセージ記述や呼び出し手順の変更が必要 同じメッセージ表現のまま移行可能(属性で差分を吸収)
実装ベンダーへのロックイン 高い 低い
複数ブリッジの併用 実装が煩雑化 共通IFの上でルーティング設計が容易

このポータビリティは、運用時の停止リスクを減らし、開発と保守の負担を軽減します。

ブリッジの多層化

本インターフェースは、複数の独立ブリッジを経由してメッセージを搬送するようなゲートウェイ設計も想定しています。 目的に応じて、配信要件を「どれか一つ成功で可(高い活性)」あるいは「複数の成功を要件化(高い安全性)」のように構成できます。 これにより、ユースケースごとに安全性(Safety)と活性(Liveness)のバランスをとるアーキテクチャが組みやすくなります。

追加パラメータとポストプロセッシング

一部のクロスチェーン・プロトコルは、宛先やペイロード以外に追加パラメータ(宛先ガス上限、宛先チェーン手数料など)を要求します。 送信時にそれらの詳細を知らなくてもメッセージを通せるように、ERC7786ではポストプロセッシング(sendMessage 呼び出し後、配信前に追加操作を行う段階)を許容しています。

追加パラメータは以下のいずれかで満たされます。

方式 説明 特徴
属性で指定 追加パラメータを属性として同梱 追加コール不要。自己完結。
追加コール 送信後にゲートウェイへ追加入力 REQUIRED(属性が無い場合)。第三者が手当も可能に設計するのが推奨されます。

特に重要なのは、誰でも配信を後押しできる設計にすることです。 たとえ悪意ある者が無効なパラメータを与えようとしても、他の正当な参加者が有効なパラメータを与えて配信を成立させられることが望ましいとされています。

任意の直接コールを許す設計とその注意点

一部プロトコル/ゲートウェイには、受信先に対して任意の直接呼び出し(arbitrary call)を行える機能があります。 この場合、受信側コントラクトは「ゲートウェイ経由のクロスチェーン呼び出し」であることを自力で識別する必要があり、ゲートウェイ側のゲッター(送信元チェーン・送信者アドレスの取得)などを参照します。

ただし、この方式はゲートウェイが資産(例:ERC20)を保有している場合に危険です。 ゲートウェイから任意コントラクトへ任意呼び出しができる設計だと、何者かが不正な呼び出しを誘発し、資産や権限を奪うリスクがあります。 そのため、ERC7786は受信側に専用の receiveMessage 関数を設けることを推奨し、ゲートウェイの保有資産や権限を保護します。

任意コールの利便性をどうしても取り入れたい場合は、この標準を実装するゲートウェイの上にラッパーを実装し、receiveMessage 内で安全に検証したうえで任意コールに委譲する形が推奨されます。

javascript
// 擬似コード(Solidity風)。任意コールの安全なラッパー例。
interface IERC7786Recipient {
    function receiveMessage(bytes32 receiveId, bytes calldata sender, bytes calldata payload)
        external payable returns (bytes4);
}

contract SafeArbitraryCallWrapper is IERC7786Recipient {
    address public immutable trustedGateway;

    constructor(address _gateway) {
        trustedGateway = _gateway;
    }

    function receiveMessage(bytes32 receiveId, bytes calldata sender, bytes calldata payload)
        external payable override returns (bytes4)
    {
        // 1) ゲートウェイ検証
        require(msg.sender == trustedGateway, "unauthorized gateway");

        // 2) ペイロードの検証・デコード(例:dst, data, value等)
        (address dst, bytes memory data, uint256 callValue) = abi.decode(payload, (address, bytes, uint256));

        // 3) 任意コールの安全実行(reentrancy/戻り値チェック等は実装ポリシーに従う)
        (bool ok, ) = dst.call{value: callValue}(data);
        require(ok, "call failed");

        // 4) 規定のセレクタを返す
        return this.receiveMessage.selector; // 0x2432ef26 と同値
    }
}

上記のように、信頼するゲートウェイの呼び出しであることを厳密に検証し、ペイロードの構造と値を検査したうえで任意コールを行えば、安全性を維持しながら柔軟性を取り入れられます。

互換性

既存の多くのクロスチェーン・メッセージング・プロトコルは独自のインターフェースを実装しています。 ERC7786では、可能であれば標準インターフェースをネイティブ実装することを推奨します。 一方で、即座のネイティブ対応が難しい場合に備え、標準アダプターの整備を提案しています。

アダプターは以下の役割を担います。

コンポーネント 役割
既存プロトコル実装 従来のエンドポイント・手順を維持
アダプター(Gateway Adapter) 本標準のsendMessage/receiveMessage相当の入出力を受け取り、既存プロトコルの呼び出しにマッピング
利用コントラクト 本標準のIFにのみ依存し、背後のブリッジ差替え・多層化を透過化

この段階的アプローチにより、プロトコル側の導入コストを低減しつつ、エコシステム全体での共通化と相互運用性の向上が進みます。

セキュリティ

アドレス取り扱い

ERC7786で扱うInteroperable Address(ERC7930)は、CAIP350に基づくシリアライズを前提にしています。 ここで重要なのは、正規(canonical)エンコーディングを用いることです。 非正規の表現を受け付けると、異なる実装間で同一アドレスが別物として扱われるなどの齟齬が生じ、サイレントな配信失敗や誤配につながる可能性があります。

対策として、ゲートウェイは以下を満たすことが望まれます。

推奨事項 具体策
非正規エンコーディングの拒否 形式検証を行い、余分なゼロ、サイズ不一致、無効なネットワーク識別子などを検出したら明確に拒否する。
正規化処理の実施 軽微な表記ゆれ(例:大文字小文字、冗長な長さ表現)を正規形に正す。そのうえでイベント出力・内部保存する。
監査容易性の確保 正規化後の値でイベント(例:MessageSent)を発行し、ログの相互比較・運用監視を容易にする。

これらを徹底することで、チェーンや実装の違いをまたいだアドレス表現の不一致による不具合を未然に防ぎます。 最終的には、ユースケースに応じた厳格なバリデーションと、必要最小限の正規化方針を明文化(ドキュメント化)しておくことが望まれます。

引用

Francisco Giordano (@frangio), Hadrien Croubois (@Amxx), Ernesto Garcia (@ernestognw), CJ Cobb (@cjcobb23), Sergey Gorbunov (@sergeynog), joxes (@Joxess), "ERC-7786: Cross-Chain Messaging Gateway [DRAFT]," Ethereum Improvement Proposals, no. 7786, October 2024. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7786.

最後に

今回は「異なるブロックチェーン間でスマートコントラクトが安全かつ共通の方法でメッセージを送受信できるようにする、クロスチェーン通信の標準インターフェース仕組みを提案しているERC7786」についてまとめてきました! いかがだったでしょうか?

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

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