> 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/integrate-solana-program.md).

# Solana プログラムを統合する

SolanaプログラムをRome EVMと統合します — Solana署名者は誰か、資産がどうあなたのプログラムに届き、どう戻るか、1本の経路のルール、アトミックとイテレーティブの違い、そしてアカウントの準備。

このガイドは、Rome EVMユーザーに自分たちのプログラムを使ってほしいSolanaプログラムチーム向けです。対象は、EVMアカウント向けの価値を保持すべきプライバシー、レンディング、またはボールトプログラムです。これは次を基礎とします [EVMからSolanaを呼ぶ](/ja/gaido/call-solana-from-evm.md) （プリコンパイルの仕組み）を踏まえ、実際のプログラムが相手側にあるときに生じる疑問に答えます： *誰が* 署名するか、 *どのように* トークンが出入りするか、そして *どの* 制限が設計を形作るか。

本ガイド全体で使用するフロー：EVMアカウントがUSDCをあなたのプログラムへ移動し（「shield」または「deposit」）、あなたのプログラムがそのユーザーのために保持し、後で返却します（「unshield」または「withdraw」）。動詞は適宜ご自身のものに置き換えてください。

## 1. すべてのEVMアドレスには1つのSolanaアイデンティティがある

Romeは、ユーザーとコントラクトを問わず各EVMアドレスに対してSolanaアカウントを導出します。これは次のように呼ばれます **外部権限**:

```
external_auth(addr) = find_program_address(["EXTERNAL_AUTHORITY", addr_h160], rome_evm_program_id)
```

これはそのアドレスの関連トークンアカウントを所有します（つまり、 `wUSDC.balanceOf(addr)` が読み取る場所です）。また、そのアドレスの代理で行われるCPIに署名するキーでもあります。あなたのプログラムが見るのは32バイトのSolana公開鍵であり、H160を見ることはありません。

**誰が署名するかは、誰がプリコンパイルを呼び出すかで決まります：**

| プリコンパイルの呼び出し元                              | Solanaの署名者                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ひとつの **コントラクト**、通常の `CALL`                 | その **コントラクト自身の** 外部権限（`external_auth(contract)`）、および要求するコントラクトのsalt付きサブPDA                                                                                                                                                                                                                                                                                                                                                                    |
| ひとつの **ユーザー**、プリコンパイルアドレスへ直接送られたトランザクション内で | その **ユーザー自身の** 外部権限                                                                                                                                                                                                                                                                                                                                                                                                                           |
| 次を介するコントラクト `DELEGATECALL`                 | ベア権限は拒否されます（`DelegatecallOwnerAuthority`). `invoke` ）。署名者なしの場合、および `invoke_signed` salt付きサブPDAの場合は依然として実行されますが、それらのサブPDAは実行中のコントラクトのアドレスで名前空間化されます（`["EXTERNAL_AUTHORITY", caller, running_contract, salt]`）ので、 `pda_with_salt` では導出されません。HelperProgramでは、作成および資金供給用セレクタのみが通過します（`create_ata*`, `create_pda*`, `swap_gas_to_lamports`, `init_spl_mint`, `create_and_init_mint`）。これらが例外なのは、何にも署名しないからではなく、対象が呼び出し元に束縛されるかオペレーターによって資金供給されるためです |

その結果は、すでにご存じのERC-20のルールです： **コントラクトは、単独ではユーザーの資産を移動できません。** コントラクトは自身のアイデンティティとして動作し、ユーザーが先に権利を付与します。Solana側で移動する必要があるトークンの場合、その付与はユーザーのトークンアカウントに対するSPL委任です。ラッパーのERC-20 `approve` は、ラッパー自身の転送が尊重するEVM側の許可にすぎません。これがRome自身のトークンラッパーの動作方式であり、あなたのアダプターの動作方式でもあります（セクション3）。

salt付きサブPDA： `invoke_signed` 次のリストを受け取ります `bytes32` のsaltを受け取り、Romeは次で署名します `["EXTERNAL_AUTHORITY", caller_h160, salt]` 各項目について（bumpが追加されます。直接呼び出しではcallerはコントラクトです）。 `HelperProgram.pda_with_salt(addr, salt)` はSolidityからアドレスを返します。プログラムがポジションごとに別個の所有者アカウントを必要とする場合、ユーザーごとに1つのsalt（例：ユーザーのアドレス）を使用してください。

資金供給：外部権限PDAはATAを所有するために存在している必要はありません（`create_ata` は冪等で、トランザクションのSolana手数料支払者がrentを負担します）。そのPDAが存在しlamportsを保持する必要があるのは、あなたの命令が作成するアカウントに資金を供給するときだけです。 `HelperProgram.create_pda(addr)` は通常のSystem `CreateAccount`として作成するため、一度だけ呼び出してください。冪等ではありません。 `swap_gas_to_lamports(n)` はアドレスのPDAに `n` lamportsをトランザクションのSolana手数料支払者から入金します。呼び出し元はRomeガスでそれを支払います。すべてのlegacyトラックCPIによる手数料支払者残高への影響はトランザクション手数料に加算され、ガス価格でユーザーに請求されます。これはCPIが作成するアカウントのrentが請求されるのと同じです。Solanaレーンのプロビジョニング手順については、次で説明します [SolanaからEVMを呼ぶ](/ja/gaido/call-evm-from-solana.md)。コントラクトはコンストラクタまたは最初の呼び出し時に自身のPDAをプロビジョニングします。

## 2. ユーザーのポジションを保持する3つの方法

**A. アダプターコントラクト（再利用可能なアダプターに推奨）。** 1つのSolidityコントラクトがあなたのプログラムのフロントになります。ユーザーはアダプターの権限に対して自分のトークンアカウント上のSPL委任を付与します。アダプターはトークンを自身が所有するトークンアカウントに引き込み、自身としてあなたのプログラムを呼び出し、プログラム内のユーザーポジションをユーザーごとのサブPDAまたは命令データで渡す識別子でキー付けします。出金時には、ユーザー自身のトークンアカウントへ解放するようプログラムに指示します。あなたのプログラムが知る必要があるSolanaアイデンティティはアダプターだけです。この付与はERC-20ではなくSPL委任です `approve`。理由とユーザーのコストについてはセクション3で説明します。

**B. Solana署名者としてのユーザー。** フロントエンドはユーザーのEVMアカウントからトランザクションを送信します **CpiProgramプリコンパイルへ直接** (`to = 0xff…08`、calldata = ABIエンコードされた `invoke` または `invoke_signed`）。これによりユーザー自身の外部権限が署名し、あなたのプログラムはそれによってポジションをキー付けします。アダプターコントラクトも委任も不要ですが、各アクションはウォレット内の不透明なcalldataトランザクションになり、CPI以外にフローで必要なもの（ATA、事前転送）は別トランザクションになります。これは一回限りの付与（ユーザーの `approve_spl` をラッパーへ）および単純なプログラムには適していますが、複数ステップのフローには適していません。 [Cardo](https://github.com/rome-protocol/cardo) はこの形式を使用します。フロントエンドは次を送信します `invoke` をユーザーのウォレットから直接プリコンパイルへ送ります。

**C. カストディなしルーター。** ユーザーのトークンを一切保持しないコントラクトです。ユーザーはルーターの権限に対して自身のトークンアカウント上のSPL委任を付与します。ルーターはその権限を転送権限としてあなたのプログラムにCPIするため、トークンはユーザーのトークンアカウントからあなたのプログラムのアカウントへ（またはユーザーへ戻るように）移動し、ルーターは呼び出しの間に何も保持しません。ルーターはすべてのユーザー側アカウントを次から導出します `msg.sender`。これにより、一人のユーザーの付与を別のユーザーのアカウントに向けることはできません。また、汎用的な `invoke` パススルーとして動作するのではなく、固定された命令形式を持つ1つの固定プログラムを呼び出します。 `RomeDexRouter` で [rome-dex](https://github.com/rome-protocol/rome-dex) はこのように書かれています。rome-dexのEVMレーンは、生の直接 `invoke` もBの形で提供します。Aと同じ付与が必要で、同じ1デリゲートのコストがかかります（セクション3）。引き込みステップはありません。

このガイドの残りはAに従います。Cでも同じ付与と同じ署名ルールを使用します。

## 3. トークンの入出金

Rome上のUSDCは、2つの側面から見える1つのSPL mintです： `wUSDC` EVM側のERC-20ラッパーと、Solana側の外部権限のATAです。ユーザー自身のアドレスでは、この2つは同一の残高です： `wUSDC.balanceOf(user)` はユーザーのATAを読み取ります。中間にブリッジやラッピングのステップはありません。

**コントラクトのラッパー残高は、そのコントラクトが制御するトークンアカウントではありません。** ファクトリーは次をデプロイします `SPL_ERC20_cached` 通常のmint用に、またHadrianの `wUSDC` もその1つです。そのラッパーはコントラクトのために署名できないため、 `wUSDC.transferFrom(user, adapter, amount)` または `transfer` がトークンをコントラクトへ送ると、SPLトークンは次へ移動します **ラッパー自身のエスクロートークンアカウント** (`escrow_ata()`）。ラッパーはコントラクトごとの金額を自身のストレージに記録します。 `wUSDC.balanceOf(adapter)` はその記録、すなわちエスクロー台帳を返すのであり、次が所有するトークンアカウントの残高ではありません `external_auth(adapter)`。あなたのアダプターはCPIでこれらのトークンをプログラムに渡すことができません。それらは再びラッパーを通してのみ出せます。したがって、次で自身に資金供給するアダプターは `transferFrom` 、Solana側で使用できるものを何も持ちません。

機能する経路はSPL委任です：

* **付与。** ユーザーは次を送信します `approve_spl(adapter, amount, mint)` をトランザクションとして **HelperProgramへ直接** (`to = 0xff…09`）に送ります。ここで、 `トークンのラッパーを見つけるには、その` はラッパーの `mint_id()`です。ユーザー自身の権限が署名し、そのユーザーのトークンアカウントに設定されるデリゲートはアダプターの外部権限です。
* **入金。** アダプターの `deposit(amount)` はデリゲート用オーバーロードで引き込みます `HelperProgram.transfer_spl(srcAta, dstAta, amount, mint)`。ソースはユーザーのATA、宛先はアダプター自身のATA（`HelperProgram.ata(address(this), mint)`、一度だけ次で作成されます `create_ata`）です。アダプターの権限がデリゲートとして署名します。トークンは現在、次が所有するトークンアカウント内にあります `external_auth(adapter)`。これがあなたのCPIで指定するアカウントです。署名者とソースはアダプター自身のものであるため、追加の許可は不要です。これらは次には表示されません `wUSDC.balanceOf(adapter)`.
* **出金。** あなたのプログラムのwithdraw命令は次へ転送します **ユーザーの** ATA、 `HelperProgram.ata(user, mint)`。受け取りにユーザーの署名は不要で、残高は即座に次として表示されます `wUSDC.balanceOf(user)`。ATAがまだ存在しない可能性がある場合、先に次で作成してください `HelperProgram.create_ata(user, mint)` （冪等）。

**トークンアカウントにはデリゲートを1つだけ設定できます。** 上記の付与は、そのアカウントに対するラッパー自身の付与を置き換えます。ユーザーが再度ラッパーに付与するまで、そのアドレスからのすべての `wUSDC` `transfer` または `transferFrom` の出金は、SPLエラー `0x4`でrevertします。この付与を使用するフローの後は、次を呼び出してください `wUSDC.isEnabled(user)`。これが次を返したら `false`、ユーザーに次を送るよう求めてください `approve_spl(wrapper, 2^64-1, mint)` を再びHelperProgramへ送ります。これはラッパーが前提とする同じ最大付与です（次を参照 [一回限り：ラッパーに付与](/ja/gaido/dual-lane-app.md#one-time-grant-the-wrapper)）。上限付き付与は、残量が少なくなるとユーザーの通常の `wUSDC` 転送を再び壊します。また、 `isEnabled` は `true` のままです。残りが少しでもある間はアプリが再度要求すべきタイミングを知ることができません。

mintがどのラッパーを持つかを確認するには、ファクトリーの次を読み取ります `wrapper_kind_by_mint(mint)` （ファクトリーアドレスはチェーンの `contracts.json` 内にあります [registry](https://github.com/rome-protocol/rome-registry)). `1` は、このセクションで説明したキャッシュされたラッパーです。 `2` は、armed transfer hookを持つToken-2022 mint向けにファクトリーがデプロイする直接CPIラッパーです。このガイドでは扱いません。レジストリの `tokens.json` にはラッパーアドレスとmintが一覧表示されますが、その種類は表示されません。

## 4. コントラクトごと、トランザクションごとに1つのトラック

RomeにはSolanaの状態を変更するプリコンパイルのファミリーが2つあり、 **1つのトランザクションはそのうちちょうど1つを使用します** — ランタイムは、コントラクトをまたぐ場合も含め、両方の変更呼び出しを混在させるトランザクションを拒否します。

| トラック        | プリコンパイル                                                                                             | 効果の反映                                                          | 反復実行で動作                                                               |
| ----------- | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | --------------------------------------------------------------------- |
| **レガシー**    | `CpiProgram` `0xff…08` (`invoke`, `invoke_signed`), `HelperProgram` `0xff…09`, `Withdraw` `0x42…16` | EVMステップ内の実際のCPIとして即座に反映                                        | **いいえ** — 反復トランザクション内のlegacy CPIは次で失敗します `CpiProhibitedInIterativeTx` |
| **キャッシュ済み** | `SplCached` `0xff…05`, `ASplCached` `0xff…06`, `SystemCached` `0xff…04`, `WithdrawCached` `0xff…0b` | オーバーレイにステージングされ、トランザクションの終わりにCPIとしてコミットされます。EVM revertでは破棄されます | はい                                                                    |

これがプログラム統合で意味すること：

* **あなた自身のプログラムの命令を呼び出すのはlegacyトラックのみです。** キャッシュ済みトラックには汎用の `invoke`がありません。対象はSPL転送、ATA作成、system program操作、およびガス引き出しです。
* したがって、アダプターに資金を供給するステップがCPIと同じトランザクションで実行されるなら、それもlegacyトラックでなければなりません。キャッシュ済みラッパーの `transferFrom` はキャッシュ済みトラックの呼び出しであるため、あなたのCPIとトランザクションを共有できません（また、セクション3で示したとおり、エスクロー台帳にしか記録されません）。ユーザーがアダプターをSPLデリゲートにした後、代わりに次で引き込んでください `HelperProgram.transfer_spl(userAta, adapterAta, amount, mint)` 。これはユーザーからHelperProgramへ直接送られます（`approve_spl`、ユーザーがHelperProgramへ直接送信）。引き込みとCPIはいずれもlegacyトラックなので、1つのトランザクションで実行できます。
* **そのトランザクションにラッパーを含めないでください。** legacy CPIと同じトランザクション内で、アダプターからラッパーの状態変更関数（`wUSDC.transfer`, `transferFrom`）を呼び出さないでください。 `isEnabled(user)` と残高はフロントエンドから次を使って確認してください `eth_call`.
* **また、CPIトランザクションはアトミックでなければなりません。** これが設計の制約です。

読み取りはこのルールの対象外です： `account_info`, `account_data_at`, `account_u64_at`, `account_lamports`, `pdas_batch_derive` および `HelperProgram.user_balance` / `allowance_of` は事前ロード済みアカウントの読み取り（CPIなし）であり、どちらのトラックでも両方の実行モードで許可されます。事前チェックにはこれらを使用してください。順序に関するルールが1つあります：トランザクションでキャッシュ済み変更が一度実行されると、その後はlegacyトラックの読み取りがブロックされます。先に読み取り、その後に変更してください。

## 5. アトミックが予算

アトミックなRomeトランザクションは1つのSolanaトランザクションです：約 **140万コンピュートユニット**、 **64アドレス** のアカウントリスト、および **4 KB** のワイヤサイズ（Solana v1トランザクション）です。RomeプログラムとあなたのCPIはこの予算を共有します。ラッパー転送はHadrianで約170K CUを使用し、あなたの命令も独自の分を加えます。Solanaレシートの次で測定してください `computeUnitsConsumed`であり、EVMではありません `gasUsed`.

エミュレーションがトランザクションが収まらないと判断すると、Romeはそれを **反復的に** 複数のSolanaトランザクションにまたがって実行し、その中のlegacy CPIは失敗します。depositとwithdrawはそれぞれ1回のトークン移動と1回のプログラムへのCPIにとどめ、周囲のSolidityも小さく保ってください。より大きな処理は2つのユーザートランザクションに分割してください。

CPI深度：Solanaでは4レベルが許可され、Romeが1つ使用するため、あなたの命令はレベル2で実行され、その下に2レベル残ります（あなたのプログラム → SPL Tokenでは1レベル残ります）。

## 6. アカウントのプロビジョニング

あなたのプログラムは実行時にSolidityからアカウントを受け取りません。プロキシは **エミュレート** してから各トランザクションを送信し、CPIが触れたすべてのSolanaアカウントを記録して、Solanaトランザクションに配置します。あなたのアダプターは次でアカウントを指定します `invoke_signed` アカウントリスト内で指定し、エミュレーションがそれらが解決できることを証明します。ここから3つのことが導かれます：

* あなたの命令が触れるすべてのアカウントは、アダプターが持つ入力（自身のPDAとサブPDA、あなたのプログラムID、mint、ユーザーのアドレス）から導出可能でなければなりません。 `SystemProgram.find_program_address` および `CpiProgram.pdas_batch_derive` はSolidity内で導出を行います。
* まだ存在しないアカウント（新しいポジション、新しいATA）も、アカウントリスト内で指定する必要があります。そのアドレスがSolanaトランザクションに到達します。
* ユーザー、アダプター、ラッパーに対するRome自身のアカウントを含め、トランザクションが触れるものすべてが64アドレス以内に収まらなければなりません。1回の呼び出しで10市場に触れる設計は収まりません。

Solanaウォレットレーンでは、 `rome_emulateCallAccounts` がクライアントに同じ検出機能を公開します。SDKがこれを使用します。

CPIが決して指定できないアカウントが2つあります：トランザクションを送信するSolana手数料支払者（通常のSystem転送命令内を除く）とRomeプログラム自身です。RomeプログラムへのCPIは拒否されます。

## 7. Solidityでのdepositとwithdraw

legacyトラック上のアダプターの最小スケッチです。ユーザーはすでに次を送信しています `approve_spl(adapter, amount, mint)` をHelperProgramへ（セクション3）。 `PRIVACY_PROGRAM` はあなたのプログラムIDです； `encodeDeposit` / `encodeWithdraw` は命令データを構築します（Borsh、リトルエンディアン）。アカウントメタはあなたの命令のレイアウトに従います。

```solidity
import {ICrossProgramInvocation, IHelperProgram}
    from "@rome-protocol/rome-solidity/contracts/interface.sol";

contract PrivacyAdapter {
    ICrossProgramInvocation constant Cpi    = ICrossProgramInvocation(0xFF00000000000000000000000000000000000008);
    IHelperProgram          constant Helper = IHelperProgram(0xFF00000000000000000000000000000000000009);
    bytes32 constant SPL_TOKEN = 0x06ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a9; // TokenkegQ...

    bytes32 immutable PRIVACY_PROGRAM;
    bytes32 immutable USDC_MINT;

    constructor(bytes32 program, bytes32 mint) {
        PRIVACY_PROGRAM = program; USDC_MINT = mint;
        Helper.create_pda(address(this));                 // アダプター自身のSolanaアイデンティティ
        Helper.create_ata(address(this), USDC_MINT);      // およびそれが所有するUSDCアカウント
    }

    function _salt(address user) internal pure returns (bytes32) { return bytes32(uint256(uint160(user))); }

    function deposit(uint64 amount) external {
        bytes32 self       = Helper.pda(address(this));                   // 署名者：アダプターの権限
        bytes32 adapterAta = Helper.ata(address(this), USDC_MINT);
        bytes32 position   = Helper.pda_with_salt(address(this), _salt(msg.sender)); // ユーザーごとのサブPDA。これも署名する

        // ユーザーのトークンアカウントから引き込む。アダプターの権限はSPLの
        // ユーザーが付与したデリゲートとして署名する。これは以下のCPIと同様にlegacyトラック呼び出しである。
        Helper.transfer_spl(Helper.ata(msg.sender, USDC_MINT), adapterAta, amount, USDC_MINT);

        ICrossProgramInvocation.AccountMeta[] memory accs = new ICrossProgramInvocation.AccountMeta[](5);
        accs[0] = ICrossProgramInvocation.AccountMeta(self,       true,  true);
        accs[1] = ICrossProgramInvocation.AccountMeta(position,   true,  true);
        accs[2] = ICrossProgramInvocation.AccountMeta(adapterAta, false, true);                          // ソース：アダプターの権限が所有
        accs[3] = ICrossProgramInvocation.AccountMeta(_vaultFor(position), false, true);                 // あなたのプログラムのボールト
        accs[4] = ICrossProgramInvocation.AccountMeta(SPL_TOKEN, false, false);

        bytes32[] memory salts = new bytes32[](1);
        salts[0] = _salt(msg.sender);
        Cpi.invoke_signed(PRIVACY_PROGRAM, accs, encodeDeposit(amount), salts);
    }

    function withdraw(uint64 amount) external {
        bytes32 position = Helper.pda_with_salt(address(this), _salt(msg.sender));
        bytes32 userAta  = Helper.ata(msg.sender, USDC_MINT);            // 宛先：ユーザー自身のアカウント
        // ... 同じ形式：あなたのプログラムは、`position`による署名でボールトからuserAtaへ`amount`を移動する
        Cpi.invoke_signed(PRIVACY_PROGRAM, accs, encodeWithdraw(amount), salts);
    }
}
```

アダプターは決して次を呼び出しません `wUSDC` コントラクト。引き込みはユーザーの委任を使用するHelperProgram呼び出しであり、トークンは次が `external_auth(adapter)` 所有するトークンアカウントに置かれるため、CPIはそれらを使用できます。

署名者に関する注意。Romeが署名するアカウントの種類は正確に2つです：呼び出し側コントラクトのベア権限（`Helper.pda(address(this))`）。これは `salts`に列挙されなくても署名します。もう1つは、次の各エントリにつき1つのsalt付きサブPDAです `salts`。列挙するすべてのsaltは、署名者としてアカウントリストに現れなければなりません。そうでない場合、呼び出しは次のエラーで失敗します `signer account calculated from the provided seed was not found`。ユーザー自身の権限を含む、署名者としてマークされたその他のアカウントにはRomeからseedが与えられず、SolanaランタイムがCPIを拒否します。ユーザーのトークンに対する権利は委任に由来し、アダプターがユーザーとして署名することには決して由来しません。

引き込みなしの委任：あなたのプログラムがユーザーのトークンアカウントから直接使用すべき場合、ユーザーは次を送信します `HelperProgram.approve_spl_raw_delegate(userAta, yourProgramPda, amount, mint, decimals)` をHelperProgramへ直接送り、あなたのプログラムのPDAをSPLデリゲートとして指定します。RomeブリッジはWormholeにこれを使用します。セクション3の1デリゲートルールはここにも適用されます：この付与はラッパーのものを置き換えます。

## 8. テスト

* 〜に対してデプロイする **Hadrian** (testnet、チェーン200010) を先に。アドレスと RPC は [Contract Addresses](/ja/rifarensu/contract-addresses.md) そして [registry](https://github.com/rome-protocol/rome-registry).
* `eth_call` および `eth_estimateGas` プロキシが送信時に使うのと同じエミュレーションを実行するため、そこで失敗する CPI は同じ理由でチェーン上でも失敗し、revert データには基になる Solana エラー（`非EVM呼び出しエラー: …` Solanaプログラムのログ内）。
* 着地した EVM トランザクションの Solana 側は `rome_solanaTxForEvmTx(hash)`；Solana レシートには CU とあなたのプログラムのログがある。
* 〜では動作する CPI `eth_call` しかし送信時に拒否される場合、通常はエミュレーションが報告する制限に引っかかっています: 64 アドレス上限、アトミック CU 予算（トランザクションが反復処理になった）、またはトラックルール。

## 9. 参照

* [プリコンパイル参照](/ja/rifarensu/precompiles.md) — すべてのプリコンパイルのすべてのセレクタを、そのディスパッチクラスと delegatecall ルール付きで。
* [制約](/ja/ji-ben-gai-nian/constraints.md) — 上記の制限を 1 つの表にまとめたもの。
* [Token Interop](/ja/ji-ben-gai-nian/token-interop.md) — ラッパー、正規のミント、預け入れと引き出し。
* 公開リポジトリ内の参考アプリ: [cardo](https://github.com/rome-protocol/cardo) （ユーザーが CPI プリコンパイルを直接呼び出す、形態 B）、 [rome-dex](https://github.com/rome-protocol/rome-dex) （直接 `invoke` に加えて、カストディ不要のルーター、形態 C）、および [aerarium](https://github.com/rome-protocol/aerarium) （1 つの共有市場上の Compound III 貸出アプリ。Solidity から Solana プログラムを呼び出さない（CPI なし）ため、アダプターの例ではない）。


---

# 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/integrate-solana-program.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.
