このページは 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
引数
前提条件
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 は宣言されたアカウントではありません。
前提条件 — 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のpermissionPDA が存在します(管理者がCreatePermissionPdaを介して作成)。CreatePoolと同じミント/ホワイトリスト ルール。
- 新しい
pool_stateがseed_index派生アドレスに存在し、pool_state.seed_index = seed_index。 - その他すべての事後状態は
CreateCustomizablePoolと一致します(手数料モード、オプションの動的手数料)。
このインストラクションは一般的なプール作成アクセスを拡大しません。パーミッションレス作成は
CreatePool / CreateCustomizablePool を通じて続行され、これらは 1 ペアあたり 1 プールのままです。CreatePermissionedPool は、ホワイトリストに登録されたオペレーターが同じペアの複数のプール(例:異なる初期価格またはローンチ コホート)が必要で、管理者によって付与された Permission PDA を保持する特定のケースのために存在します。OpenPositionV2 / OpenPositionWithToken22Nft
既存のプール内に新しいポジションを作成します。
引数
OpenPositionV2 は 22 を宣言します。OpenPositionWithToken22Nft は 20 を宣言します。
OpenPositionV2(順序):
OpenPositionWithToken22Nft は metadata_account(5)と metadata_program(19)が削除された同じリストです。代わりに NFT ミント上の Token-2022 メタデータ拡張を通じてポジションのメタデータを書き込みます。20 アカウントを与えます。その position_nft_mint は裸の Signer で、position_nft_account は UncheckedAccount です。
数学 — 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 パスのみがアカウントをフリーズします。OpenPositionV1 はフリーズしません。
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
既に開いているポジションにリクイディティを追加します。
引数
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
ポジションからリクイディティを削除します。
引数
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 ミントは閉じることができず、供給量ゼロのままです。
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 年リリース後):
- 動的手数料サーチャージ —
pool.dynamic_fee_infoがゼロ以外の場合、プログラムは最後のスワップ以降に走査されたティック距離を使用して揮発性アキュムレータを更新し(products/clmm/feesのフィルター/減衰ルール付き)、AmmConfig.trade_fee_rateの上にdynamic_fee_componentを追加します。総手数料は 10%(MAX_FEE_RATE_NUMERATOR / 1_000_000)でキャップされます。 - リミット オーダー マッチング — 価格ウォークがオープン リミット オーダーを保持するティックを横切る場合、プログラムは最初にそのティックで利用可能なリミット オーダー リクイディティを埋めます(
order_phaseによる FIFO)、次に LP リクイディティ曲線に沿って進みます。埋められた金額はtick.unfilled_ratio_x64とtick.part_filled_orders_remainingを後の決済用に更新します。オーダー自体は所有者がSettleLimitOrderを呼び出すまで未使用のままです。 - 片側手数料ルーティング —
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、開始インデックスがプールのインライン ビットマップの外に落ちるティック配列を初期化する場合にのみ必須。それ以外の場合は何も渡しません。
アカウント リスト変更(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 のみが呼び出し可能です。
引数
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 つのキャリブレーション フィールド
