> For the complete documentation index, see [llms.txt](https://docs.rome.builders/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rome.builders/ja/gaido/call-evm-from-solana.md).

# SolanaからEVMを呼ぶ

Ethereum鍵なしで、SolanaウォレットにRome上のEVMコントラクトを操作させます。ウォレットが署名し、そのトランザクションはSolanaへ送られます。

の逆 [EVMからSolanaを呼ぶ](/ja/gaido/call-solana-from-evm.md)：Solanaウォレット（たとえばSolflare）がRome上の任意のEVMコントラクトを直接呼び出し、 **Ethereumキーなし**。これが [Aerarium](/ja/romenoapuri/apps.md) SolanaネイティブのユーザーがEVMユーザーと同じコントラクトを共有できるようにします。

1回の呼び出しで済む方法は、SDKの `submitRomeTxV1`であり、プロキシがその呼び出し用のSolana v1トランザクションを1つ組み立てます。このページでは、その仕組みを説明します。

## シンセティックアドレス

SolanaウォレットのEVM上のIDは、その **シンセティックアドレス** — の末尾20バイト、 `keccak256` 32バイトのSolana公開鍵の

```
synthetic_evm_address = keccak256(solana_pubkey)[12:]
```

これが `msg.sender` ウォレットがコントラクトを呼び出す際の msg.sender であり、その nonce とストレージが置かれる固定IDです。導出はプロトコルに固定されているため、ウォレットは常に同じアドレスに対応します。

```javascript
import { syntheticAddress } from "@rome-protocol/sdk";
const from = syntheticAddress(solanaPubkey); // 0x… 20バイト
```

## シンセティックはパススルーであり、静止時にはトークンを保持しません

Solanaネイティブユーザーの支出可能残高は、その **Solanaウォレット** （SPLトークンとして）EVM側ではそのトークンの **ERC20SPLラッパー** （例： `wUSDC`）。シンセティックは静止時には何も保持しないため、価値は *を通って* そこを流れます—各ステップはSolanaウォレット署名済みです：

1. **プロビジョン（1回のみ）。** 新規作成したシンセティックのexternal-auth PDAは、 `create_pda` が実行されるまで存在せず、以下の転送はそのPDAによって署名されます。 `submitRomeTxSolanaLane` 初回使用時に自動でプロビジョンします（または `provisionSynthetic` 明示的な「Activate」ステップを行う場合は、 `isSyntheticProvisioned`で確認します。 `submitRomeTxV1`で、 `isSyntheticProvisioned` を確認し、 `buildCreatePdaCall` それを通して1回送信します。
2. **資金供給の段階（ウォレット → シンセティック）。** ウォレットのATAからシンセティックのATAへトークンを移動します —  `ActivateAta` ステップ。これは `buildFundLeg`によって構築されます。これで `wrapper.balanceOf(synthetic)` がその残高を読み取るため、シンセティックはそれを通常のERC-20として使えます（`transfer` / `transferFrom`）— **ではなく** ネイティブとして `msg.value`ではなく、保持していないものとして。
3. **呼び出し（`DoTxUnsigned`).** シンセティックがEVMトランザクションを実行します — たとえば `approve` その後、vaultが `deposit` を通じて引き出す `transferFrom`.
4. **スイープの段階（シンセティック → ウォレット）。** withdraw / borrow / claim によってトークンがシンセティックに入ると、 `buildSweepLeg` それらをユーザー自身のウォレットATAへ戻します（`HelperProgram.transfer_spl`）、そのためシンセティックの純残高はゼロになります。

次のセクションでは、より古い `submitRomeTxSolanaLane` がクライアント側で組み立てるものを説明します。 `submitRomeTxV1` では、アカウント探索、ComputeBudget、またはtreasure walletをコードに含めずに、代わりにプロキシにv1トランザクションを組み立てさせます。 [external-V1エンドポイント](#the-external-v1-endpoints) の下にあります。

## 呼び出しの構築方法

`submitRomeTxSolanaLane` がこれらすべてを行います。仕組みは次のとおりです：

1. **署名なしのEIP-1559トランザクションを構築する** を使用して `from` ＝シンセティックアドレス — secp256k1署名は不要。
2. **アカウントを探索する** — [`rome_emulateCallAccounts`](/ja/rifarensu/json-rpc.md) 呼び出しの `from`, `を`, `data`, **および `value`** （呼び出しがpayableの場合）。 `value` が重要です。プロキシは *実際の* 呼び出しをエミュレートするため、値に依存するストレージ書き込み — たとえば新しいmappingスロット — も確保され、そのSolanaアカウントが返されます。これを省くとそのアカウントが欠け、トランザクションは *「instruction modified data of a read-only account.」*
3. **Solanaトランザクションを組み立てる：** 2つの **ComputeBudget** の命令（RomeのEVMには、引き上げられたCU上限 ≈1.35M と大きなヒープフレーム ≈250 KB が必要で、Solanaのデフォルトでは失敗します） +  **`DoTxUnsigned`** 命令（署名なしRLP + 探索されたアカウント） + チェーンごとの **トレジャーウォレット** （実行が少額の手数料を支払います。探索ではこれが省かれるため、SDKが追加します）。
4. **ウォレットが署名して送信します。** その **SolanaウォレットがSolanaトランザクションに署名（Ed25519）し、プロキシではなくSolana RPCへ送信します。** Solanaランタイムが署名を検証します。オンチェーンでは、プログラムが `msg.sender` その署名者から導出します。権限はEthereumの署名ではなく、Solanaの署名です。（プロキシは手順2のエミュレーション／探索にのみ使用されます。）

ユーザーのPDA（`["EXTERNAL_AUTHORITY", synthetic_address]`）がそのトークンアカウントを所有し、SPL CPIに代わって署名するため、Solanaユーザーは供給、借入、スワップ、LPをすべてSolanaウォレットだけで行えます。

## external-V1エンドポイント

`submitRomeTxV1` は1回の呼び出しで済む方法です。プロキシに組み立て済みのv1トランザクションを要求し、それを検証し、ウォレットに署名させてSolana RPCへ送信します。呼び出しが収まらない場合はプロキシ経由で中継します。プロキシはRPCメソッドとして同じ経路を公開しているため、どのクライアントでもSDKなしで利用できます（完全な一覧は [JSON-RPCサポート](/ja/rifarensu/json-rpc.md)):

* `rome_composeUnsignedAtomicV1(rlp, pubkey, signature)` — Solana v1トランザクション1つ。ウォレットが署名し、アプリがSolana RPCへブロードキャストします。呼び出しが1つの原子的トランザクションに収まらない場合は拒否されます。
* `rome_composeUnsignedIterativeV1(rlp, pubkey, signature)` — 実行の各レグ（収まれば原子的、収まらなければ反復レグ）; ウォレットがそれぞれに署名し、 `rome_submitSignedV1Plan` それらをブロードキャストします。長いプランの制限は [リレイされた呼び出しと長時間呼び出し](#relayed-calls-and-long-calls).
* `rome_relayUnsignedV1(rlp, pubkey, signature)` — ウォレット署名は1回、プロキシの支払者が各レグを実行し、EVMのtxハッシュを返します。シンセティックがRomeのガスを支払うため、最初に1回 `rome_composeExternalDepositV1`.

**認可署名。** `rlp` は、生の9フィールドの署名なしEIP-1559本文です。ウォレットは自身のEd25519鍵で、以下のいずれかに署名します。生の32バイト `keccak256(0x02 ‖ rlp)` または可読メッセージ

```
Rome authorization\n0x<64 lowercase hex chars of that hash>
```

どちらも受け付けられます。可読形式は、ウォレットが `signMessage` プロンプトで可読に表示するものです。プログラムは実行する本文からハッシュを再計算し、署名されたメッセージがこの2形式のどちらかと完全に一致することを要求するため、ある本文への署名で別の本文を認可することはできず、本文のnonceがリプレイを防ぎます。

## リレイされた呼び出しと長時間呼び出し

一部の呼び出しは1つのSolanaトランザクションに収まりません。このセクションでは、その場合に何が起こるか、どの制限が適用されるかを説明します。

### 原子的コンポーザーが拒否する場合

`rome_composeUnsignedAtomicV1` は、1つの原子的トランザクションに収まらない呼び出しを拒否します。 `submitRomeTxV1` その後、プロキシ経由で呼び出しを中継し、 **同じ** 認可署名を使うため、ウォレットに再度確認することはありません。結果には `route: "relay"` そしてSolanaの `署名`。 `relayOnRefusal: false` を指定すると、代わりに拒否をエラーとして受け取れます。あるいは `relayV1` を自分で呼び出して、意図的に中継します。

中継された呼び出しについて知っておくべきことは3つあります：

* **ガス代はシンセティックが支払います。** 中継ルートでは、プロキシがSolanaトランザクションを送信し、その費用を支払い、呼び出しはチェーンのネイティブガストークンでシンセティック残高から支払われます。残高は少なくとも `gasLimit × maxFeePerGas`. `fundSyntheticGas(deps, amountWei)` が、ウォレット自身のチェーンガストークンのトークンアカウント（HadrianとRubiconではUSDC）から補充します。ウォレットは通常のv1トランザクションに1回署名し、Solana手数料のために少量のSOLが必要です。 `amountWei` はチェーンの18桁weiで表され、10^12の倍数でなければならず、そうでない場合はプロキシが拒否します。SDKなしでは、 `rome_composeExternalDepositV1` 同じトランザクションを構築します。
* **revertは例外を投げません。** EVM側でrevertした中継呼び出しも通常どおり解決され、 `receipt.status === "0x0"`。確認してください `receipt?.status === "0x1"` 呼び出しを完了扱いにする前に。 `receipt` は `null` レシートが時間内に現れなかった場合。
* **`relayOnRefusal: false` はSDKでの選択であり、固定ではありません。** プロキシはそのペイロードの認可署名をすでに保持しており、どちらのルートでも実行できます。上限は `gasLimit × maxFeePerGas`.

```javascript
const res = await submitRomeTxV1(deps, { to, data, value });
if (res.route === "relay" && res.receipt?.status !== "0x1") {
  // revertした中継呼び出しは解決される。例外は投げない
}
```

### 長い呼び出し

複数のトランザクションを必要とする呼び出しは反復セッションとして実行されます。プログラムは各Solanaトランザクションに収まるだけのEVMステップを実行し、その間で状態を保存します。Solanaウォレットからこれを進める方法は2つあります：

* **中継する。** `rome_relayUnsignedV1` はウォレット署名を1回取り、プロキシの支払者がすべてのレグを送信します。シンセティックがガスを支払います。
* **レグに自分で署名する。** `rome_composeUnsignedIterativeV1` は各レグを空の署名欄付きで返し、ウォレットがそれぞれに署名し、 `rome_submitSignedV1Plan` 順番にブロードキャストします。各レグはウォレットが署名する個別のSolanaトランザクションなので、1回に1件ずつ署名するウォレットでは、認可署名に加えて各レグごとに1回ずつプロンプトが表示されます。ウォレットは各レグごとにSolana手数料を支払います。

制限は次のとおりです：

| 制限                                 | 値           | 由来                                                                                |
| ---------------------------------- | ----------- | --------------------------------------------------------------------------------- |
| 1回の `rome_submitSignedV1Plan` 呼び出し | 64          | プロキシはそれより長いプランを拒否します                                                              |
| 反復コンポーザーが計画するレグ数                   | 128         | Rust版Rome SDKの反復コンポーザーにある上限で、プランもこれで制約されます `rome_composeUnsignedIterativeV1` 返します |
| 1セッション内の反復回数                       | 160         | Rome EVMプログラム。これを超えるとセッションは再開されなくなり、アカウントロックを解除して終了します                            |
| Solanaトランザクションのサイズとアカウント           | 4 KB、64アドレス | 各レグはSolana v1トランザクションです                                                           |

実際の呼び出しの大半は、これらの上限よりはるかに少ないレグで完了します。ウォレット署名済みプランの64トランザクション制限が、最初に直面する制限です。それ以上のレグを必要とする呼び出しは、経由ではブロードキャストできません。 `rome_submitSignedV1Plan`.

長い呼び出しはlegacy-trackのCPIを行えません。レガシーprecompile（`0xff…08`, `0xff…09` および `0x42…16`）への変更系呼び出しは、反復セッションでは `CpiProhibitedInIterativeTx`で拒否されます。Solana状態の読み取りとcached-track precompile（`0xff…04`, `0xff…05`, `0xff…06`, `0xff…0b`）は動作します。legacy-trackのCPIを行う呼び出しは、どの経路で送るにせよ、1つの原子的トランザクションに収まらなければなりません。 [制約](/ja/ji-ben-gai-nian/constraints.md) および [Compute Budget](/ja/ji-ben-gai-nian/compute-budget.md).

## 参照実装

* **Aerarium** — SolanaウォレットからCompound v3（供給／借入）を操作します。 `DoTxUnsigned`これは上で説明した古いlegacyトランザクション経路の参照であり、 `submitRomeTxV1`.
* **Rome DEX** はこのページの例ではありません。Solana側はウォレットが直接署名するネイティブSolanaプログラムで、EVM側は同じプールを共有します。

Aerariumにはブリッジも第二のウォレットも不要です — シンセティックアドレスによって、1つのSolana鍵が一級のEVMアカウントになります。v1パターンについては、 [デュアルレーンアプリを構築する](/ja/gaido/dual-lane-app.md).

## 次は

* [EVMからSolanaを呼ぶ](/ja/gaido/call-solana-from-evm.md) — 逆方向、CPI経由で
* [Token Interop](/ja/ji-ben-gai-nian/token-interop.md) — EVMとSolana間で残高がどのように共有されるか


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.rome.builders/ja/gaido/call-evm-from-solana.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
