Skip to main content
このページは AI による自動翻訳です。すべての内容は英語版を正とします。英語版を表示 →
sdk-api/rust-cpi では、各 Raydium プログラムを呼び出すための低レベルの仕組みについて説明しています。このページはその上位レベルの補足です。Raydium をカスタムプログラムに組み込む 理由、ユースケースに適した パターン、そして端から端までの完全な実装方法について説明します。

CPI が適切なツールである場合

カスタムプログラムは、トレードがあなたのプログラムのみが実行できる他のオンチェーン状態変更と原子的に発生する必要がある場合に有効です。一般的なケースは以下の通りです。
  • エスクロー・リミットオーダープログラム — ユーザーがミントをエスクロー内に預け、プログラムが価格条件を監視し、トリガーされたときにプログラムが原子的に Raydium を通じてスワップし、ユーザーのアカウントにクレジットします。
  • アグリゲーター プロキシ — Raydium と 1 つ以上の他の DEX を通じてスワップをルーティングする単一の命令で、すべてのホップがプログラムが所有する単一のスリッページチェック下にあります。
  • 自動複利運用ヴォルト — LP またはファーム ステークをヴォルトに預け、ヴォルトがスケジュールに従ってリワードを収穫し、流動性を再供給し、シェアトークンを発行します。
  • ストラテジー ヴォルト — CLMM を通じてスワップして再バランスするレバレッジ LP ポジション、ポジションをクローズして 1 つのトランザクションで担保をスワップするリクイデーター。
  • カスタム ベスティング付きトークン起動プラットフォーム — プログラムがベスティング トークンを保有し、スケジュールに従って Raydium プールにリリースします。
オフチェーン コードからスワップを送信したいだけの場合、CPI は過剰です — SDK を使用してください。CPI が複雑さに見合う価値があるのは、独自の状態との原子性が要件である場合のみです。

構成パターン

パターン 1: シン プロキシ

プログラムは単一の命令を公開し、いくつかのポリシー(例:ホワイトリストに登録されたミント ペア、検証済みユーザーの手数料割引)を検証してから Raydium に転送します。
状態はユーザーの ATA に存在します。プログラムはトークンを所有しません。最小限の信頼フットプリント。

パターン 2: エスクロー

プログラムはユーザーの入力ミントを保有する PDA を所有しています。トリガー時に、PDA は Raydium へのスワップの CPI に署名します。
重要な詳細:PDA は CpiContext::new_with_signer を通じて署名します。PDA 署名者シードを参照してください。

パターン 3: 構成マルチホップ

プログラムは 1 つの命令で複数の CPI を発行し、すべてのホップ全体で単一のスリッページ境界を強制します。Raydium スワップ命令はそれぞれ独自の minimum_amount_out を持ちますが、それらを 0(または非常に緩い下限)に設定し、最後のホップの後に厳密な最終最小値を自分で強制します。
これにより、ルート全体に対して単一のリバート ゲートが得られます。すべてのホップがスリッページセーフであると信頼する場合にのみこのパターンを使用してください。そうでない場合は、各ホップに独自の最小値を強制させてください。

パターン 4: ヴォルト・ストラテジー

プログラムは PDA に LP トークンまたはファーム ステークを保有しています。キーパー(またはユーザー)が compound() を呼び出すと、以下が実行されます。
  1. ファームからリワードを収穫します。
  2. リワードをプール トークンにスワップします(CPMM または CLMM への CPI)。
  3. 収益を LP に戻します(別の CPI)。
  4. 新しい LP をステークします(別の CPI)。
すべて 1 つのトランザクションで実行されるため、ヴォルトの NAV は原子的に移動します。コンピュート予算は通常 600k~1M CU です。アドレス ルックアップ テーブルは必須です。

アカウント リスト構築

呼び出し元プログラムの Accounts 構造体は Raydium プログラムのアカウント順序を反映しますが、ほとんどの Raydium 側のアカウントは UncheckedAccount です。Raydium がそれ自体で検証するためです。あなたが所有するアカウントにのみ制約を追加します。
非対称性 — あなたのアカウントに対する厳密な検証、Raydium のアカウントに対する UncheckedAccount — は怠惰ではありません。受信者は独自に検証します。呼び出し元で二重検証するだけで CU が消費され、Raydium が新しい構造体レイアウト フィールドを出荷するときに同期がずれるリスクがあります。

CPI 呼び出し自体

PDA 署名者シード

CPI は、authority として渡された PDA が呼び出し元が主張する導出と一致する場合にのみ成功します。2 つは以下に同意する必要があります。
  1. シード バイト シーケンス(ここでは [b"escrow", user.key().as_ref()])。
  2. バンプ。
  3. 呼び出し元プログラム ID(Raydium ではなく、あなたのプログラム)。
PDA が何と一致しなければならないかに注意してください。CPMM の authority スロットは CPMM 自身の ボルト PDA です — プログラム全体で固定されたアカウントで、CPMM がそれを導出し自ら署名します。あなたのプログラムはこれを制御も差し替えもできません。あなたの PDA シードが一致しなければならないアカウントは payer です:チェックは CPMM 自身の transfer_from_user_to_pool_vault ヘルパー内で行われ、payer として渡されたアカウントが input_token_account の所有者であることを要求します。 一般的なバグ:escrow_input_ata がエスクロー PDA によって所有されているのに、userpayer として渡すことです。SPL Token プログラムは owner mismatch で拒否します。常に payer を ATA の所有者にしてください — そしてその所有者が PDA の場合は new_with_signer で署名してください。

残りのアカウント

いくつかの Raydium 命令は、固定されたアカウントの後に追加された可変長のアカウント リストを取ります — 残りのアカウント
  • CLMM SwapV2: スワップが走査する可能性のあるティック配列の 1~8 個の TickArrayState アカウント(スワップ方向)。
  • Farm v6 Deposit / Harvest / Withdraw: (reward_vault, user_reward_ata) ペア、ライブ リワード スロットごとに 1 ペア。
  • Token-2022 転送フック ミント: 転送フック プログラムと、フックが必要とするアカウント。
Anchor CPI ヘルパーは残りのアカウントを型チェックしません。それらを通す:
順序が重要です。 CLMM の場合:
Farm v6 ハーベストの場合:
呼び出し元プログラムは、クライアントから受け取った残りのアカウントを変更されずに通す必要があります。フィルタリングまたは並べ替えを試みないでください。

構成呼び出しのコンピュート予算

CPI は呼び出しフレーム自体に約 1,500 CU のコストがかかります。被呼び出し側の独自の CU 使用量がその上に積み重なります。 以下の被呼び出し側の数値は、2026-09-09 に高ボリュームのプールで実行されたライブのメインネット トランザクションから、Raydium プログラム自身の呼び出しに対する Program <id> consumed N of M compute units ログ行を読み取って測定したものです(したがって内部のトークン プログラム CPI も含まれます): 各 CPI フレームにつき約 1,500 と、あなた自身のプログラムのオーバーヘッドをその上に追加してください。CLMM のスワップ コストはティック交差の回数に応じて増えるため、その数値は下限として扱ってください。Token-2022 ミントは転送自体の拡張機能処理コストを追加します。一律の乗数を当てるのではなく、自分のミントで測定してください。
このページの以前の版には 5~7 倍高い見積もり(CPMM スワップ約 150,000 CU、CLMM 約 180,000)が 記載されていました。それらは一度も測定されたものではありません。ドキュメント化された数値ではなく、 自分自身の computeUnitsConsumed の読み取り値から予算を組んでください — また、ATA 作成、wSOL の ラッピング、compute-budget 命令を数えると、トランザクション全体は Raydium 命令単体よりも高くつく ことに注意してください。
常に明示的な ComputeBudgetProgram::set_compute_unit_limit を設定してください。
デフォルトの 200k CU 上限は、構成呼び出しが完了する前に静かに枯渇します。

エラー伝播

Raydium のプログラムは安定したエラー コードを持つ Anchor エラーを返します。呼び出し元プログラムはそれらを Err(ProgramError::Custom(code)) として見ます。デフォルトでバブルアップします。
または特定のコードをインターセプトします。
ERROR_CODE_OFFSET という項に注意してください:#[error_code] のバリアントは 6000 から始まる番号で発行されるため、素の enum 判別子と比較しても一致することはありません。(anchor-lang にも raydium_cp_swap にも is_err ヘルパーは存在しません — このページの以前のリビジョンでは、存在しないヘルパーを使用していました。) エラー コードから意味へのマッピングは IDL ポリシーごとに安定しています(sdk-api/anchor-idlを参照)。新しいコードは最後に追加され、既存のコードの意味は変わりません。

完全な実装例:リミットオーダー エスクロー

フロー:
  1. open_order — ユーザーが input_mintamount_in をエスクロー PDA に預け、ターゲット min_amount_out と有効期限を記録します。
  2. execute_order — 誰でも(キーパー)現在のプール アカウントで呼び出すことができます。プログラムは現在の見積もりが min_amount_out 以上であることを確認してから、Raydium スワップに CPI し、出力をエスクロー内に保持します。
  3. claim — ユーザーはエスクロー内から出力ミントを引き出します。
キーパーはトランザクション手数料を支払います(他の場所でキーパー手数料を取得します — 表示されていません)。order PDA はエスクローの入力 ATA を所有しているため、payer として CPI に署名します。したがって ExecuteOrder には、CPMM 自身のボルト PDA 用に pool_authority: UncheckedAccount<'info> フィールドも必要です。Raydium 側のスリッページ チェック エスクロー独自のデルタ チェックの両方が下限を強制します — 二重チェック。

テスト

Raydium プログラムをローカル バリデーターにプルして統合テストを実行します(Anchor.toml から)。
プール状態アカウントもクローンして、テストが実際にスワップを実行できるようにします。anchor test はスタートアップ時にメインネットからそれらをフェッチします。sdk-api/rust-cpi を参照してください。

構成に固有の落とし穴

リエントランシー

Solana には真のリエントランシーはありません — CPI は同じ呼び出しで元のプログラムに呼び戻すことはできません。しかし、論理的なリエントランシーに自分自身を構築することはできます。CPI があなたの状態を読み、その後あなたのコードが CPI がそれを変更しなかったと仮定して再度読みます。Raydium の場合、CPI はあなたの状態に触れないため、これはフラッシュ ローン コンテキストなどほど懸念事項ではありません。しかし、Raydium をレンディング プロトコルと構成する場合は注意してください。

アカウント可変性ドリフト

プログラムがアカウントを mut として渡すが、Raydium がそれを読み取り専用として期待する場合(またはその逆)、ランタイムは InvalidAccountData で呼び出しを拒否します。常に IDL で Raydium の命令の予期される可変性を確認してください。raydium_cp_swap::cpi::accounts::Swap は、CPMM 自身の Swap 構造体に付いた #[account(mut)] マーカーから、各アカウントの可変性を代わりに設定します — 生成されるフィールドはすべて素の AccountInfo<'info> なので、フラグを運ぶのはフィールド型ではなく、導出された ToAccountMetas の実装です。

Token-2022 プログラム フィールド

入力ミントと出力ミントは異なるトークン プログラムの下にある可能性があります — 1 つは SPL Token、1 つは Token-2022。CPI にはこの理由のために個別の input_token_programoutput_token_program フィールドがあります。常に各ミントの owner フィールドを確認し、正しいプログラムを各スロットにルーティングしてください。

バージョン管理されたトランザクション

2 つ以上の Raydium CPI と ATA 作成を実行する構成トランザクションは、レガシー(LUT なしの v0)トランザクションに収まることはめったにありません。V0 とアドレス ルックアップ テーブルを使用してください。raydium.getRaydiumLutAddresses() を通じて Raydium のパブリック LUT をプルしてください。

ポインター

ソース: