Skip to main content
このページは AI による自動翻訳です。すべての内容は英語版を正とします。英語版を表示 →
このページは products/clmm/accounts(アカウントとは何か)および products/clmm/math(数学とは何か)と対になっています。引数とアカウント順序については権威的です。具体的なバイト レイアウトは IDL から取得されます。 2026-09 プログラム アップグレードは CLMM を Anchor 1.0.2 / Solana 3.1.10 で再構築し、管理者インストラクション CollectExcessLamports を追加し、CreateAmmConfig が owner / fund_owner に書き込む内容を変更しました。ユーザー向けのインストラクションは、アカウント、引数、数学を変更していません。2026-09-30 チェンジログ エントリを参照してください。

インストラクション インベントリ

init-tick-array インストラクションはなく、必要ありません。 ティック配列は OpenPosition* / IncreaseLiquidity* 内の TickArrayState::get_or_create_tick_array によって作成され、payer によって支払われます。(初期化されていない可能性がある、システム所有の)ティック配列 PDA を tick_array_lower / tick_array_upper として渡し、プログラムが不足している場合はそれを割り当てます。OpenLimitOrder は単一の tick_array に対して同じことを行います。
ほとんどの管理者専用インストラクション(CreateAmmConfig、UpdateAmmConfig、UpdatePoolStatus、CreateOperationAccount、UpdateOperationAccount、CloseProtocolPosition)は、プログラムのハードコードされた admin 公開鍵によってゲートされています。CreatePermissionPda / ClosePermissionPda は admin 公開鍵または専用の permission_pda_admin キーを受け入れます。CreateSupportMintAssociated / CloseSupportMintAssociated は admin 公開鍵または専用のサポート ミント所有者キーを受け入れます。CollectExcessLamports は admin 公開鍵または専用の collect-lamports ウォレットを受け入れます。リワード ストリーム管理者インストラクション(TransferRewardOwner、CollectRemainingRewards)はプログラム管理者ではなくリワード ファンダーによってゲートされています。 V2 サフィックスは「ボルト/NFT で Token-2022 をサポート、ビットマップ拡張スロットが必要」を意味します。SDK は新しいプールに対してデフォルトで V2 を選択します。

CreatePool

引数
アカウント(要約)
スロット 10 と 11 はミントごとであり、「SPL Token その後 Token-2022」ではありません。各スロットは一致するミント上の mint::token_program によって制約されるため、token_mint_0 が Token-2022 で token_mint_1 が従来の SPL のプールの場合、スロット 10 に Token-2022 を、スロット 11 に SPL Token を渡す必要があります。CreateCustomizablePool と CreatePermissionedPool は同じ 2 つのスロットを使用します。
前提条件
  • token_mint_0 < token_mint_1(バイト順)。
  • amm_config.disable_create_pool == false。
  • ミントは Token-2022 拡張ホワイトリストによって拒否されません。
事後条件
  • pool_state.sqrt_price_x64 = sqrt_price_x64、tick_current = floor(log_{1.0001}(price))。
  • pool_state.liquidity = 0(ポジションなし)。
  • pool_state.fee_on = FromInput(レガシー デフォルト)。
  • pool_state.dynamic_fee_info はゼロ化されます(動的手数料は無効)。

CreateCustomizablePool

新しいプールに推奨されます。CreatePool と同じ効果に加えて、プールごとの手数料回収モードとオプションの動的手数料オプトイン。 引数
アカウント — CreatePool の正確に 13 個の宣言されたアカウント。dynamic_fee_config は宣言されたアカウントではありません。
enable_dynamic_fee = true の場合、スナップショットする DynamicFeeConfig は最後の remaining_account として提供される必要があります。ハンドラーは ctx.remaining_accounts.last() を読み取ります。したがって、SupportMintAssociated バイパス PDA はそれの前に来る必要があります。そうしないと、プログラムは間違ったアカウントをスナップショットし、逆シリアル化に失敗します。フラグが設定されている間にそれを省略すると、AccountLack で失敗します。
前提条件 — CreatePool と同じ。enable_dynamic_fee = false の場合、remaining_account は不要で、渡されたものはサポート ミント レコードのみスキャンされます。 事後条件
  • pool_state.fee_on は選択された CollectFeeOn バリアントに設定されます。
  • 動的手数料が有効な場合:pool_state.dynamic_fee_info は提供された DynamicFeeConfig から初期化されます(5 つのキャリブレーション パラメータがコピーされ、状態フィールドはゼロ化されます)。
  • それ以外の場合:pool_state.dynamic_fee_info はゼロ化されます(= このプールでは動的手数料は永遠に非アクティブ)。
fee_on と動的手数料有効化ビットはプール作成時のみ設定されます。インプレース アップグレードはありません。レガシー CreatePool で作成されたプールは、動的手数料または片側手数料を遡及的に取得することはできません。新しいデプロイメントはこのインストラクションをデフォルトにする必要があります。

CreatePermissionedPool

CreatePool と CreateCustomizablePool は両方とも、プール PDA を ["pool", amm_config, token_mint_0, token_mint_1] から派生させるため、(config, mint0, mint1) トリプルごとに正確に1 つの正規プール アドレスが存在します。同じシードで 2 番目の init は失敗します。CreatePermissionedPool は、クライアント提供の seed_index: u16 をプール PDA シードに折り込むことでその制限を解除し、同じペアと手数料ティアの複数のプールを許可します。各プールは独自のアドレスにあります。任意のプール アドレスは特権機能であるため、支払者は Permission PDA を保持する必要があります。 プールに関するその他すべては CreateCustomizablePool と同じです。同じ CreateCustomizableParams を取り、片側手数料と動的手数料オプトインをサポートします。 引数
アカウント(要約) — CreateCustomizablePool と同じに加えて、前面に: pool_state PDA は ["pool", amm_config, token_mint_0, token_mint_1, seed_index.to_le_bytes()] から派生します。 前提条件
  • seed_index != 0。seed_index が 0 の場合はレガシー プール用に予約されており、ここで拒否されます。[0, 0] シード コンポーネントは、レガシー プール アドレスを従来の 4 シード形式に折りたたむものです。
  • payer の permission PDA が存在します(管理者が CreatePermissionPda を介して作成)。
  • CreatePool と同じミント/ホワイトリスト ルール。
事後条件
  • 新しい pool_state が seed_index 派生アドレスに存在し、pool_state.seed_index = seed_index。
  • その他すべての事後状態は CreateCustomizablePool と一致します(手数料モード、オプションの動的手数料)。
このインストラクションは一般的なプール作成アクセスを拡大しません。パーミッションレス作成は CreatePool / CreateCustomizablePool を通じて続行され、これらは 1 ペアあたり 1 プールのままです。CreatePermissionedPool は、ホワイトリストに登録されたオペレーターが同じペアの複数のプール(例:異なる初期価格またはローンチ コホート)が必要で、管理者によって付与された Permission PDA を保持する特定のケースのために存在します。

OpenPositionV2 / OpenPositionWithToken22Nft

既存のプール内に新しいポジションを作成します。 引数
アカウント — 2 つのバリアントは異なるアカウント リストを持ちます。OpenPositionV2 は 22 を宣言します。OpenPositionWithToken22Nft は 20 を宣言します。 OpenPositionV2(順序): OpenPositionWithToken22Nft は metadata_account(5)と metadata_program(19)が削除された同じリストです。代わりに NFT ミント上の Token-2022 メタデータ拡張を通じてポジションのメタデータを書き込みます。20 アカウントを与えます。その position_nft_mint は裸の Signer で、position_nft_account は UncheckedAccount です。
tick_array_bitmap_extension はどちらのバリアントでも宣言されたアカウントではありません。 ポジションの範囲がプールのインライン tick_array_bitmap(±512 ティック配列)の外に落ちる場合、シード ["pool_tick_array_bitmap_extension", pool_state] の TickArrayBitmapExtension PDA を remaining_accounts[0] として追加します。
数学 — products/clmm/math を参照してください。base_flag が与えられた場合、プログラムは liquidity または (amount_0_max, amount_1_max) のいずれかを実際の L と消費された実際のトークン金額に解決します。 前提条件
  • tick_lower < tick_upper、両方とも pool.tick_spacing の倍数、[MIN_TICK, MAX_TICK] 内。
  • 2 つのティック配列 PDA が渡されます。それらは既に存在する必要はありません。get_or_create_tick_array は、このインストラクション内で payer の費用で不足しているものを割り当てます。個別の init-tick-array インストラクションはありません。
  • ユーザーはソース ATA に少なくとも amount_0_max と amount_1_max を持っています。
事後条件
  • personal_position が存在し、liquidity が設定され、fee_growth_inside_last がスナップショットされます。
  • tick_lower と tick_upper のティック配列エントリが更新されます(liquidity_gross += L、liquidity_net ± L、手数料成長スナップショットが保持されます)。
  • ポジションが範囲内の場合(tick_lower ≤ tick_current < tick_upper)、pool_state.liquidity += L。
  • ポジション NFT ミントは pool_state をフリーズ権限として記録します。ミント権限は単一の NFT がミントされた後に削除されます。フリーズ権限を記録しても、NFT トークン アカウントの状態は変わりません。
  • NFT トークン アカウントは、インストラクションが OpenPositionV2 または OpenPositionWithToken22Nftで、かついずれかのボルト ミントのフリーズ権限が CLMM の制限付き発行者リストと一致する場合を除き、フリーズされたままです。その一致する V2 パスのみがアカウントをフリーズします。OpenPosition V1 はフリーズしません。
一般的なエラー — TickInvalidOrder(tick_lower >= tick_upper)、TickAndSpacingNotMatch(エンドポイントが tick_spacing の倍数ではない)、InvalidTickIndex([MIN_TICK, MAX_TICK] の外)、MissingTickArrayBitmapExtensionAccount(範囲がインライン ビットマップの外で拡張機能が追加されていない)、NotApproved(pool_state.status がオープンをブロック)、ZeroAmountSpecified。
ポジション フリーズは宣言されたインストラクション アカウントまたは引数を追加しません。クライアントは既存の V2 レイアウトでこれらのポジションを開くことができます。動作はオンチェーンから vault_0_mint と vault_1_mint で選択されます。

IncreaseLiquidityV2

既に開いているポジションにリクイディティを追加します。 引数
アカウント — 15、OpenPosition から派生できません。rent、system_program、associated_token_program、メタデータ アカウントはありません。 ポジションの範囲がインライン ビットマップの外にある場合、TickArrayBitmapExtension PDA を remaining_accounts[0] として前に付けます。 効果
  • ユーザー → ボルトから amount_0_actual / amount_1_actual を転送します。
  • personal_position.liquidity と pool_state.liquidity(範囲内の場合)をインクリメントし、エンドポイント ティックの liquidity_gross / liquidity_net をそれに応じて調整します。
  • 最後のタッチ以降に発生した手数料とリワードを回収し、token_fees_owed_{0,1} / reward_amount_owed にクレジットします。これらは DecreaseLiquidity / DecreaseLiquidityV2 でのみ支払われ、増加時には支払われません。スタンドアロン回収インストラクションはありません。

DecreaseLiquidityV2

ポジションからリクイディティを削除します。 引数
アカウント — 16、IncreaseLiquidityV2 と同じ形状または順序ではありません。personal_position と pool_state が入れ替わり、ボルトはティック配列の前に来て、ユーザー側のアカウントは recipient_token_account_* という名前で、追加の memo_program があります。 残りのアカウント — アクティブなリワードごとに 3 つ、順序 reward_token_vault(W)、recipient_token_account(W)、reward_vault_mint。ポジションの範囲がインライン ビットマップの外にある場合、TickArrayBitmapExtension PDA を前に付けます。
これは手数料とリワードを回収する唯一の方法です。ポジションを変更せずに回収するには、liquidity = 0、amount_0_min = 0、amount_1_min = 0 で呼び出します。
効果
  • 現在の sqrt_price_x64 が与えられた削除された L の (amount_0, amount_1) を計算します。
  • 最後のタッチ以降に発生した手数料/リワードを決済します(IncreaseLiquidity と同じ)。
  • ボルトから amount_0 + fees_owed_0 と amount_1 + fees_owed_1 をユーザーに転送します。
  • リクイディティ カウンターをデクリメントします。新しい personal_position.liquidity == 0 の場合、ポジションは ClosePosition の対象になります。
スリッページ — amount_0_min と amount_1_min は、出力側の Token-2022 転送手数料を差し引いた後、ユーザーが受け入れる最小値です。

ClosePosition

ポジション NFT をバーンし、PersonalPositionState を閉じます。 宣言されたアカウント 残りのアカウント
  • フリーズされていない NFT:不要。追加のプール アカウントはハンドラーが読み取らないため無害です。
  • フリーズされた NFT:最初の残りのアカウントとして personal_position.pool_id を追加します。プログラムはそれを PoolState として読み込み、その PDA シードを使用してシャーに署名します。
前提条件
  • personal_position.liquidity == 0。
  • tokens_fees_owed_{0,1} == 0。
  • すべてのリワード カウンター reward_amount_owed == 0。
(つまり、すべてを回収し、最初にゼロに減らします。) 効果
  • NFT トークン アカウントがフリーズされている場合、最初の残りのアカウントが personal_position.pool_id と等しいことを確認し、プール PDA でそれをシャーします。
  • NFT をバーンします。
  • NFT トークン アカウントと personal_position を閉じ、家賃を nft_owner に払い戻します。ポジション NFT が Token-2022 を使用する場合、NFT ミントも閉じます。従来の SPL Token ミントは閉じることができず、供給量ゼロのままです。
シャー、バーン、クローズはアトミックです。NFT はこれらのステップ間で転送可能になることはできません。 条件付きクライアント ブレーク — 宣言された IDL レイアウトは変更されていないため、レガシー クライアントは既存のフリーズされていないポジションを閉じ続けます。プール残りのアカウントを省略するレガシー ビルダーは、フリーズされたポジションを閉じるときに AccountLack で失敗します。すべてのクローズに対してプールを渡すことが最も単純な互換性のある戦略です。

SwapV2

リクイディティ曲線を歩きます。is_base_input に応じて正確な入力または正確な出力。 引数
アカウント(要約) 呼び出し元は、予想されるスワップ ウォークをカバーするティック配列のランク付きリストを渡します。プログラムは必要なだけ使用します。SDK は PoolUtils.computeAmountOutFormat または API のクォート エンドポイント経由でこのリストを計算します。 前提条件
  • pool_state.status はスワップを許可します。
  • now >= open_time。
  • sqrt_price_limit_x64 は方向に対して sqrt_price_x64 の正しい側にあります。
一般的なエラー — TooLittleOutputReceived(正確な入力スリッページ)、TooMuchInputPaid(正確な出力スリッページ)、SqrtPriceLimitOverflow、NotEnoughTickArrayAccount、InvalidFirstTickArrayAccount、MissingTickArrayBitmapExtensionAccount、LiquidityInsufficient、NotApproved(スワップ ビットが pool_state.status に設定)。CLMM には ExceededSlippage バリアントはありません。その名前は CPMM のものです。TickArrayNotFound もありません。 SwapV2 が呼び出し元が知るべきことを内部で行うこと(2025 年リリース後):
  1. 動的手数料サーチャージ — pool.dynamic_fee_info がゼロ以外の場合、プログラムは最後のスワップ以降に走査されたティック距離を使用して揮発性アキュムレータを更新し(products/clmm/fees のフィルター/減衰ルール付き)、AmmConfig.trade_fee_rate の上に dynamic_fee_component を追加します。総手数料は 10%(MAX_FEE_RATE_NUMERATOR / 1_000_000)でキャップされます。
  2. リミット オーダー マッチング — 価格ウォークがオープン リミット オーダーを保持するティックを横切る場合、プログラムは最初にそのティックで利用可能なリミット オーダー リクイディティを埋めます(order_phase による FIFO)、次に LP リクイディティ曲線に沿って進みます。埋められた金額は tick.unfilled_ratio_x64 と tick.part_filled_orders_remaining を後の決済用に更新します。オーダー自体は所有者が SettleLimitOrder を呼び出すまで未使用のままです。
  3. 片側手数料ルーティング — pool.fee_on = Token0Only または Token1Only の場合、スワップ ステップは同じ入力出力トレードを計算します。手数料はその後、設定された側にルーティングされます。設定された手数料側が出力である方向の場合、手数料はスワップ出力から差し引かれます(ユーザーは out − fee を受け取ります)。設定された手数料側が入力である方向の場合、動作は FromInput と一致します。PoolState の is_fee_on_input(zero_for_one) と is_fee_on_token0(zero_for_one) を参照してください。
Swap(V1)は SwapV2 と同じ動的手数料、片側手数料ルーティング、リミット オーダー マッチングを実装します。唯一欠けている機能は Token-2022 サポートです。両方のボルトが従来の SPL Token である必要があります。Token-2022 ミントを持つプールは SwapV2 を介してスワップする必要があります。アグリゲーターと SDK は既にすべての CLMM レッグに対して V2 を優先するため、呼び出し元はミント タイプで分岐する必要がありません。

OpenLimitOrder

特定のティックで売却注文を出します。オーダーはティックごとの FIFO コホートに留まり、価格が通過するときに埋まります。 引数
アカウント(要約) 残りのアカウント — [0] tick_array_bitmap_extension、開始インデックスがプールのインライン ビットマップの外に落ちるティック配列を初期化する場合にのみ必須。それ以外の場合は何も渡しません。
rent アカウントはありません。構造体は system_program で終わり、13 個の宣言されたアカウント。位置 14 の迷った rent は、オプションのビットマップ拡張機能が読み取られる場所に正確に着地するため、インライン ビットマップの外のティック配列を初めて作成する必要があるまで、オーダーは機能しているように見えます。その後、失敗します。
アカウント リスト変更(2026-07 リリース)。 OpenLimitOrder は入力側に加えて出力側アカウント — output_token_account、output_vault、output_vault_mint — も取得します。これらは検証にのみ使用されます。プログラムは所有者の入力または出力トークン アカウントがフリーズされている場合、オーダーを拒否します。これにより、埋めが実際に所有者の出力 ATA に決済できることが保証されます。これは、許可リスト/デフォルト フリーズ Token-2022 ミント(例:許可トークン)の場合に重要です。アカウントはまだシャーされていない可能性があります。古い片側アカウント リストに対して構築されたクライアントは、3 つの出力アカウントを追加する必要があります。
前提条件
  • input_token_account も output_token_account もフリーズされていません(そうでない場合は NotApproved)。
  • pool_state.status はスワップ(ビット 4)とリミット オーダー(ビット 5)操作の両方を許可します(そうでない場合は NotApproved)。
  • tick_index % pool.tick_spacing == 0 で [MIN_TICK, MAX_TICK] 内。
  • tick_index は選択された方向に対して pool.tick_current の右側にあります(token0 を売却 → ティックは現在より上である必要があり、その逆も同様)。既に交差したティックで売却すると、すぐに一致し、拒否されます。
事後条件
  • limit_order が存在し、オープン時に tick.order_phase と tick.unfilled_ratio_x64 をスナップショットします。
  • tick.orders_amount += amount(現在のコホート内)。
  • limit_order_nonce.order_nonce += 1。
  • OpenLimitOrderEvent が発行されます。
一般的なエラー — NotApproved(入力または出力トークン アカウントがフリーズされているか、プールがスワップ/リミット オーダーを無効にしている)、ZeroAmountSpecified(入力側転送手数料後の amount == 0)、InvalidLimitOrderAmount(金額がそのティックで 1 ベース ユニット未満の出力を生成するか、u64 をオーバーフロー)、InvalidTickIndex([MIN_TICK, MAX_TICK] の外、または選択された方向に対して tick_current の間違った側)、TickAndSpacingNotMatch(tick_index % pool.tick_spacing != 0)、OrderPhaseSaturated。

IncreaseLimitOrder

既存のオープン オーダーに追加します。オーダーの owner のみが呼び出し可能です。 引数
アカウント — 8、入力側のみ。nonce アカウント、3 つすべての出力側アカウントおよび system_program をドロップします。 前提条件
  • limit_order.owner == signer。
  • オーダーはまだ同じコホート内にあります(tick.order_phase == limit_order.order_phase)。コホートが既に埋め始めている場合、オーダーは部分的に決済されます。呼び出し元は最初に DecreaseLimitOrder または SettleLimitOrder を呼び出して前に進める必要があります。
効果
  • 所有者 ATA から input_vault に amount を転送します。
  • limit_order.total_amount += amount。tick.orders_amount += amount。

DecreaseLimitOrder

オープン オーダーを削減または完全にキャンセルします。未約定の残りを所有者に払い戻し、過去の部分埋めによって既に決済された出力も払い戻します。 引数
アカウント — 入力と出力トークン側の両方: 効果
  • オープン以降のコホートの unfilled_ratio_x64 からオーダーの埋められた金額を再計算します。
  • 埋められた出力を output_token_account に送信します。
  • 未約定の入力の amount を input_token_account に送り返します。
  • limit_order をそれに応じて更新します。新しい未約定の残りがゼロの場合、プログラムはアカウントを閉じ、家賃を owner に払い戻します。

SettleLimitOrder

オーダーの未約定の残りを変更せずに、埋められた出力トークンを所有者にプッシュします。auto_withdraw キーパーが長時間実行される部分埋めをドリップペイしたい場合に便利です。 呼び出し元 — オーダーの owner、またはプログラムの limit_order_admin(自動キーパー ループを実行するオフチェーン操作ホット ウォレット)。キーパーは他の権限を持ちません。埋められた出力をオーダーの owner ATA にプッシュする以外に、ユーザー資金を移動することはできません。 アカウント 効果
  • (limit_order.unfilled_ratio_x64, tick.unfilled_ratio_x64) を使用して累積出力を計算します。
  • デルタを output_token_account に転送します。
  • limit_order.settled_output を更新します。
  • オーダーを閉じません。残りの入力に対してまだオープンです。

CloseLimitOrder

完全に消費されたオーダー アカウントを閉じます。家賃は誰が署名するかに関わらず常に limit_order.owner に返されます。 呼び出し元 — owner または limit_order_admin。 前提条件
  • オーダーの未約定の残りがゼロです(amount == total_amount が埋められて決済されたか、所有者が以前にオーダーをゼロに減らして閉じるのを忘れた)。
効果
  • limit_order を閉じます。家賃は limit_order.owner に送信されます。

CreateDynamicFeeConfig(管理者)

u16 インデックスの下で再利用可能なパラメータ セットを作成します。 引数
アカウント 一般的なエラー — InvalidDynamicFeeConfigParams(decay_period <= filter_period または 0 値フィールドが範囲外)。

UpdateDynamicFeeConfig(管理者)

既存の DynamicFeeConfig を変更します。作成時に既にコンフィグをスナップショットしたプールは遡及的に更新されません。このコンフィグを参照する新しく作成されたプールのみが新しい値を取得します。 引数 — CreateDynamicFeeConfig と同じ 5 つのキャリブレーション フィールド