# [ERC7694] EthereumからSolanaにストレージを書き込む仕組みを理解しよう！

> ERC7694は、Ethereumにおけるクロスチェーン・ストレージルーティングの仕組みを拡張し、Solanaブロックチェーンをストレージ先として直接利用できるようにする標準です。

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

## はじめに

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

https://amzn.asia/d/gxvJ0Pw

今回は、EthereumのスマートコントラクトがSolanaを外部ストレージとして扱い、書き込みと読み取りをクロスチェーンで安全に行う仕組みを提案している**ERC7694**についてまとめていきます！

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

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

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

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

## 概要

**ERC7694**は、Ethereumにおけるクロスチェーン・ストレージルーティングの仕組みを拡張し、Solanaブロックチェーンをストレージ先として直接利用できるようにする標準です。

これまでEthereumのスマートコントラクトは、以下のような外部ストレージに処理を委譲できました。

* Ethereum L1 コントラクト
* Ethereum L2（レイヤー2）
* オフチェーンのデータベース

**ERC7694**は、ここにSolanaという別のL1ブロックチェーンを新たな保存先として追加します。

#### EthereumからSolanaへの処理委譲とは何か

**ERC7694**により、Ethereum L1上のスマートコントラクトは、「**自分自身のロジックの一部として、Solanaへの書き込み処理を遅延実行（defer）する**」という構成を取れるようになります。

ここで重要なのは以下の点です。

* Ethereumコントラクトが直接Solanaを実行するわけではない
* クライアント（ウォレットや実行環境）がSolanaトランザクションを扱えることが前提
* Ethereum側はSolanaに保存されるべき処理をルーティング指定するだけ

つまり、EthereumコントラクトはSolanaを「**外部ストレージ兼実行環境**」として扱います。

#### EIP3668との関係（Offchain Lookup）

Solanaに保存されたデータは、そのままではEthereumコントラクトから参照できません。
そこで**ERC3668**（Offchain Lookup）が利用されます。

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

[\[ERC3668\] オフチェーンデータ参照の仕組みを理解しよう！](/articles/6bd9a27a7353bd8147b2)

**ERC3668**とは、「**スマートコントラクトの実行中に、オフチェーンのHTTPサービスからデータを取得し、その結果を検証付きでコールバックさせる仕組み**」です。

**ERC7694**では以下の流れになります。

1. Solanaにデータを書き込む
2. HTTPゲートウェイがSolana上のデータを取得
3. そのデータを**ERC3668**に準拠したフォーマットに変換
4. EthereumコントラクトがOffchain Lookupを通じて参照

これにより、Ethereum側のコントラクトはSolanaを意識せずに、標準的な方法でデータを取得できます。

#### ERC7694が目指すもの

**ERC7694**は、Ethereumが利用できるブロックスペース（計算・保存の場）を、
Ethereumエコシステムの外側まで広げることを目的としています。

Ethereumを「**中心**」としつつも、以下の他チェーンの特性を、Ethereumコントラクトの設計に直接組み込めるようにする標準です。

* 実行コストが安い
* 独自の設計思想を持つ
* 異なるユーザー層を持つ

## 動機

#### 既存のCross-Chain Storage Router Protocolの限界

**EIP7700**で定義された Cross-Chain Storage Router Protocol（CCIP-Store）では、
以下の3種類の外部ストレージルーターが定義されていました。

| ストレージ先      | 特徴                |
| ----------- | ----------------- |
| Ethereum L1 | 完全にオンチェーンだが高コスト   |
| Ethereum L2 | 安価だが Ethereum に依存 |
| データベース      | 柔軟だが中央集権的         |

**ERC7694**は、ここにSolana向けの第4のストレージルーターを追加します。

#### 中央集権リスクの問題

L2やデータベースは、スケーラビリティの面では優れていますが、どちらも「**中央集権化の要因**」を内包しています。

##### L2 の中央集権要因

* Ethereum インネットとの共有セキュリティ
* シーケンサーやブリッジ設計への依存

つまり、L2 は「**Ethereumの延長**」であり、完全に独立した存在ではありません。

##### データベースの中央集権要因

* 単一または少数の物理サーバー
* 運営主体への信頼が必須

これはブロックチェーンの思想とは相反します。

#### 独立した合意形成を持つストレージの必要性

この背景から、独自のコンセンサスアルゴリズムを持つブロックチェーンをストレージとして使う方が望ましいという考え方が出てきます。

Solanaは以下の特徴を持っています。

* Ethereumとは独立したL1ブロックチェーン
* 高スループットかつ低コスト
* 実運用されている強力なエコシステム

**ERC7694**は、こうしたSolanaの特性を「**Ethereumの外部ストレージとして正式に扱う**」ためのルールを定義します。

#### クライアントに求められる振る舞い

**ERC7694**では、Ethereumクライアントやウォレットが、以下を行うことを前提としています。

* Solana向けのトランザクション生成
* 署名および送信
* 必要に応じたキー管理

これにより、Ethereumユーザーは追加の専用ツールなしでSolanaを利用できます。

#### ユースケース：ENS のようなチェーン非依存プロトコル

例えば ENS（Ethereum Name Service）のようなチェーン非依存プロトコルでは、

* 名前解決ロジックはEthereum側で管理
* 実データはSolanaに保存
* Solanaユーザーにもネイティブに対応

といった設計が可能になります。

これにより、以下の利点があります。

* EthereumとSolanaのユーザーを同時に取り込める
* 高コストなEthereumストレージを節約できる
* それでも検証可能性は維持できる

![image.png](/images/qiita-47fe2792-d018-4622-9ed7-80e05d4aa749.webp)
https://eips.ethereum.org/EIPS/eip-7694

## 仕様

**ERC7694**は、Ethereumコントラクトがストレージ書き込み処理をSolanaに委譲するための具体的な実装ルールを定義しています。
この仕様は大きく分けて次の流れで構成されています。

1. Ethereum側でSolanaへのストレージルーティングを宣言する方法
2. EVMとSVM間でのデータ型変換ルール
3. Solana側での書き込み処理の前提
4. Solanaに保存されたデータをEthereumから読み取る方法

#### Solanaストレージルーターの基本構造

##### `StorageRoutedToSolana` エラー

**ERC7694**では、Solanaへのストレージ書き込みは「**エラーによるルーティング**」として表現されます。
これは**EIP-7700**で定義されたストレージルーティングの設計を踏襲したものです。

##### `StorageRoutedToSolana`

```javascript
error StorageRoutedToSolana(
    bytes32 programId,
    bytes32 account
);
```

Solanaへのストレージ書き込みをクライアントに通知するために発生させるエラー。
Ethereumコントラクトは、Solanaに直接書き込みを行いません。
代わりにこのエラーを `revert` することで、「**Solanaに対してこの内容を書き込んでほしい**」という意図をクライアントに伝えます。
`programId` はSolanaにおけるプログラム（Ethereum のコントラクトに相当）を示し、`account` は書き込みを実行する管理用ウォレットを示します。

**パラメータ**

* `programId`
  * Solana上のプログラムIDを `bytes32` で表現した値。
* `account`
  * Solana上で書き込みを行う管理アカウントを `bytes32` で表現した値。

#### Ethereumコントラクト側の実装例

##### `setValue`

```javascript
function setValue(
    bytes32 node,
    bytes32 key,
    bytes32 value
) external {
    (
        bytes32 programId,
        bytes32 account
    ) = getMetadata(node);

    revert StorageRoutedToSolana(
        programId,
        account
    );
}
```

Solanaへのストレージ書き込みを要求する関数。
この関数は Ethereum上では実際の書き込み処理を行いません。
`getMetadata` によって、対象となるSolanaプログラム IDと管理アカウントを取得し、その情報を `StorageRoutedToSolana` エラーとして `revert` します。
この `revert` を検知したクライアントが、Solanaトランザクションを実行します。

**引数**

* `node`
  * ストレージの名前空間や対象ノードを表す識別子。
* `key`
  * ノード内のキーを表す識別子。
* `value`
  * 保存する値を表す識別子。

#### EVMとSVMのエンコーディング差異

Solanaの仮想マシン（SVM）では、アドレスや識別子に `base58` エンコーディングが使われます。
一方、EVMでは `hex` エンコーディングが標準です。

そのため**ERC7694**では、以下の処理が必須になります。

* Ethereum側では `bytes32` として扱う
* Solana側では `PubKey` として扱う
* クライアントが両者を相互変換する

#### Solana書き込み処理の疑似コード

##### `setValue`（Solana 側呼び出し）

```javascript
const [programId, account, node, key, value] = E2SVM(
  [programId, account, node, key, value],
  ["bytes32", "bytes32", "bytes32", "bytes32", "bytes32"]
);

const program = new program(programId, rpcProvider);
const wallet = useWallet();

if (wallet.publicKey === account) {
  await program(wallet).setValue(node, key, value);
}
```

Ethereumから受け取ったデータをSolanaプログラムに書き込む処理。
EVMの `bytes32` 型はすべてSVMの `PubKey` 型へ変換されます。
Solanaプログラムの呼び出しは、あらかじめ指定された管理アカウントのみが実行可能です。
これにより、任意のユーザーによる不正な書き込みを防ぎます。

#### Solanaプログラム側の実装イメージ

##### `setValue`（Solana プログラム）

```javascript
pub fn setValue(
    ctx: Context,
    node: PubKey,
    key: PubKey,
    value: PubKey
) -> ProgramResult {
    ...
}
```

Solana上でデータを書き込む関数。
この関数では、プログラム IDの検証や `rent exemption`（口座維持に必要な残高）の確認を行います。
その後、アカウントデータをデシリアライズし、`node` と `key` の組み合わせで値を保存します。
保存されたデータは後からEthereum側で参照される前提です。

#### EVMとSVMのデータ型対応表

**ERC7694** では、EVMとSVM間の型変換を厳密に定義しています。

| EVM     | SVM      |
| ------- | -------- |
| uint8   | u8       |
| uint16  | u16      |
| uint32  | u32      |
| uint64  | u64      |
| uint128 | u128     |
| uint256 | u256     |
| bytes1  | [u8; 1]  |
| bytes2  | [u8; 2]  |
| bytes4  | [u8; 4]  |
| bytes8  | [u8; 8]  |
| bytes16 | [u8; 16] |
| bytes32 | PubKey   |
| bytes   | Vec<u8>  |
| string  | String   |
| address | [u8; 20] |

※ `u256` はSVMにネイティブ実装はありませんが、Rustのクレートで一般的に対応されています。

#### SolanaからEthereumへの読み取り

Solanaに保存されたデータは、Ethereumコントラクトから直接参照できません。
ここで**ERC3668** 準拠した HTTPゲートウェイが使われます。

#### ERC3668対応HTTP ートウェイ

##### Solanaデータ読み取り処理

```javascript
const [programId, node, key] = parseQuery(path);

const [programId, node, key] = E2SVM(
  [programId, node, key],
  ["bytes32", "bytes32", "bytes32"]
);

const program = new program(programId, rpcProvider);
const value = await program.getValue(node, key);

const data = abi.encode(["bytes"], [value]);
emitERC3668(data);
```

SolanaのデータをEthereum向けに変換して返す処理。
ゲートウェイはURLパスから引数を取得し、Solanaプログラムを呼び出します。
取得した値はSVMの型からEVMの `bytes32` に変換され、**ERC3668**形式でEthereumに返されます。
データが存在しない場合は `null` 相当の値が返されます。

#### Solana 側の読み取り関数

##### `getValue`

```javascript
pub fn getValue<'a>(
    ctx: Context,
    node: Pubkey,
    key: Pubkey,
    account: &AccountInfo<'a>,
) -> Result<Pubkey, ProgramError> {
    ...
}
```

Solana上に保存された値を取得する関数。
指定されたアカウントが正しいプログラムに属していることを検証し
シリアライズされたデータから `node` と `key` に対応する値を取得します。
値が存在しない場合はエラーを返します。

## 補足

**ERC7694**における `StorageRoutedToSolana()` の設計は、**EIP7700**で定義されているCCIP-Storeの `StorageRoutedToL2()` と非常によく似た思想を採用しています。

ここで重要なのは、「**Ethereumコントラクト自身が他チェーンを直接呼び出さない**」という点です。
Ethereumはあくまで意図を宣言するだけで、実行はクライアントに委ねます。

#### `revert` を使ったルーティングという設計

Ethereumのスマートコントラクトは、Solanaのような異なる実行環境（SVM）を直接呼び出すことができません。

そのため**ERC7694**では、以下の方法を取ります。

* 書き込み処理を最後まで実行しようとしない
* 途中で `revert` する
* `revert` の中に「**どこに**」、「**何を**」実行すべきかを含める

この `revert` が、クロスチェーン実行のトリガーになります。

以下は、提示された図の流れをそのまま整理したものです。

```mermaid
sequenceDiagram
    participant Client
    participant L1 as Ethereum L1 Contract
    participant SOL as Solana Program

    Client->>L1: setValue(calldata)
    L1-->>Client: revert StorageRoutedToSolana(programId, account)
    Client->>SOL: Execute on Solana(programId, account, calldata)
    SOL-->>Client: response
```

![image.png](/images/qiita-c8c91bab-670f-4ce9-ac70-7d3bb5442023.webp)
https://eips.ethereum.org/EIPS/eip-7694

##### 1. クライアントがEthereumコントラクトを呼び出す

ユーザーやアプリケーションは、通常どおりEthereumのL1コントラクトに対して
`setValue` のような関数を呼び出します。

この時点では、呼び出し側はSolanaを意識する必要はありません。

##### 2. Ethereumコントラクトが `revert` でルーティングを宣言する

Ethereumコントラクトは処理を続行せず、`StorageRoutedToSolana(programId, account)` を含む `revert` を発生させます。

この `revert` はエラーではありますが失敗を意味しません。

ここで伝えられる情報は以下の2点です。

| 項目        | 意味                 |
| --------- | ------------------ |
| `programId` | Solana 側で呼び出すプログラム |
| `account`   | 実行を許可された管理アカウント    |

これにより、クライアントは「**この処理はSolanaで、このプログラムとアカウントを使って実行する**」という指示を正確に受け取ります。

##### 3. クライアントがSolana上で実行する

クライアントは `revert` 内容を解析し、以下を行った上で、Solanaプログラムを呼び出します。

* EVMの `calldata` をSVM用に変換
* `programId` を `base58` にデコード
* 指定された `account` を使って署名

ここで初めて実際のストレージ書き込みが行われます。

##### 4. Solana の実行結果がクライアントに返る

Solanaプログラムの実行結果は、クライアントに返却されます。
このレスポンスは、その後**ERC3668**を通じてEthereum側から参照される可能性があります。

#### StorageRoutedToL2 との共通点

**ERC7694**の `StorageRoutedToSolana()` は、**EIP7700**における `StorageRoutedToL2()` と以下の点で共通しています。

* `revert` を使って実行先を指定する
* 実行はクライアントが行う
* Ethereumコントラクトは実行環境を意識しない

つまり設計思想は完全に同一です。

#### 唯一の技術的な違い

両者の違いは実行環境の差に起因します。

| 項目     | L2               | Solana      |
| ------ | ---------------- | ----------- |
| 仮想マシン  | EVM              | SVM         |
| アドレス形式 | hex              | base58      |
| 基本型    | uint256, bytes32 | u64, PubKey |

このため**ERC7694**では、EVMとSVM間のデータ型キャストが明示的に定義されています。
それ以外の設計は、CCIP-Storeの延長線上にあります。

#### なぜこの設計が重要なのか

この設計により**ERC7694**は以下の特性を持ちます。

* Ethereumコントラクトは一切変更を強いられない
* クライアント実装で柔軟に対応できる
* 将来、他のL1を追加する際も同じパターンを使える

つまり、Solana専用の特別な仕組みではなく、汎用的なクロスチェーン実行モデル
として成立しています。

![image.png](/images/qiita-ff46f852-5305-4eaf-9d67-a67b1f392123.webp)
https://eips.ethereum.org/EIPS/eip-7694

## 引用

Avneet Singh (@sshmatrix), 0xc0de4c0ffee (@0xc0de4c0ffee), "ERC-7694: Solana Storage Router [DRAFT]," Ethereum Improvement Proposals, no. 7694, April 2024. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7694.

## 最後に

今回は「EthereumのスマートコントラクトがSolanaを外部ストレージとして扱い、書き込みと読み取りをクロスチェーンで安全に行う仕組みを提案している**ERC7694**」についてまとめてきました！
いかがだったでしょうか？

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

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

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

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

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