Esta página foi traduzida automaticamente por IA. A versão em inglês é a fonte oficial.Ver versão em inglês →
Esta página funciona em conjunto com
products/clmm/accounts (o que são as contas) e products/clmm/math (o que é a matemática). É autoritativa para argumentos e ordenação de contas; layouts de bytes específicos vêm do IDL.A atualização do programa 2026-09 reconstruiu CLMM no Anchor 1.0.2 / Solana 3.1.10, adicionou a instrução de admin CollectExcessLamports e alterou o que CreateAmmConfig escreve em owner / fund_owner. Nenhuma instrução voltada para o usuário alterou suas contas, argumentos ou matemática. Veja a entrada do changelog de 2026-09-30.Inventário de instruções
Não há instrução de inicialização de array de tick, e nenhuma é necessária. Um array de tick é criado dentro
de
OpenPosition* / IncreaseLiquidity* por TickArrayState::get_or_create_tick_array, pago por
payer. Passe o PDA do array de tick (possivelmente ainda não inicializado, de propriedade do sistema) como
tick_array_lower / tick_array_upper e o programa o aloca se estiver faltando.
OpenLimitOrder faz o mesmo para seu único tick_array.CreateAmmConfig, UpdateAmmConfig, UpdatePoolStatus, CreateOperationAccount, UpdateOperationAccount, CloseProtocolPosition) é controlada pela chave admin codificada do programa. CreatePermissionPda / ClosePermissionPda aceitam a chave admin ou uma chave permission_pda_admin dedicada; CreateSupportMintAssociated / CloseSupportMintAssociated aceitam a chave admin ou uma chave de proprietário de mint de suporte dedicada; CollectExcessLamports aceita a chave admin ou uma carteira de coleta de lamports dedicada. Instruções de admin de fluxo de recompensa (TransferRewardOwner, CollectRemainingRewards) são controladas pelo financiador de recompensa, não pelo admin do programa.
Sufixo V2 significa “suporta Token-2022 em cofres / NFT, requer slot de extensão de bitmap”. O SDK escolhe V2 por padrão para novos pools.
CreatePool
Argumentos
Pré-condições
token_mint_0 < token_mint_1por ordem de byte.amm_config.disable_create_pool == false.- Mints não são rejeitados pela lista de permissões de extensão Token-2022.
pool_state.sqrt_price_x64 = sqrt_price_x64,tick_current = floor(log_{1.0001}(price)).pool_state.liquidity = 0(sem posições ainda).pool_state.fee_on = FromInput(padrão legado).pool_state.dynamic_fee_infoé zerado (taxa dinâmica desabilitada).
CreateCustomizablePool
Recomendado para novos pools. Mesmo efeito que CreatePool mais modo de coleta de taxa por pool e um opt-in de taxa dinâmica opcional.
Argumentos
CreatePool. dynamic_fee_config não é uma conta declarada.
Pré-condições — mesmas que CreatePool. Se enable_dynamic_fee = false, nenhuma remaining_account é necessária e qualquer uma que seja passada é apenas verificada para registros de mint de suporte.
Pós-condições
pool_state.fee_ondefinido para a varianteCollectFeeOnescolhida.- Se taxa dinâmica foi habilitada:
pool_state.dynamic_fee_infoé inicializado a partir doDynamicFeeConfigfornecido (cinco parâmetros de calibração copiados; campos de estado zerados). - Caso contrário:
pool_state.dynamic_fee_infoé zerado (= taxa dinâmica inativa para sempre para este pool).
fee_on e o bit de habilitação de taxa dinâmica são definidos apenas na criação do pool. Não há atualização in-place — pools criados via CreatePool legado não podem ganhar retroativamente taxa dinâmica ou taxa unilateral. Novas implantações devem usar como padrão esta instrução.
CreatePermissionedPool
Tanto CreatePool quanto CreateCustomizablePool derivam o PDA do pool de ["pool", amm_config, token_mint_0, token_mint_1], então há exatamente um endereço de pool canônico por tripla (config, mint0, mint1) — um segundo init nas mesmas sementes falha. CreatePermissionedPool remove essa restrição dobrando um seed_index: u16 fornecido pelo cliente nas sementes do PDA do pool, permitindo múltiplos pools para o mesmo par e nível de taxa — cada um em seu próprio endereço. Como um endereço de pool arbitrário é uma capacidade privilegiada, o pagador deve manter um PDA Permission que o autoriza.
Tudo mais sobre o pool é idêntico a CreateCustomizablePool: ele leva os mesmos CreateCustomizableParams e suporta taxa unilateral e opt-in de taxa dinâmica.
Argumentos
CreateCustomizablePool mais, na frente:
O PDA
pool_state é derivado de ["pool", amm_config, token_mint_0, token_mint_1, seed_index.to_le_bytes()].
Pré-condições
seed_index != 0. Umseed_indexde0é reservado para pools legados e é rejeitado aqui; o componente de semente[0, 0]é o que faz um endereço de pool legado colapsar para a forma clássica de quatro sementes.- O PDA
permissionparapayerexiste (criado por um admin viaCreatePermissionPda). - Mesmas regras de mint / lista de permissões que
CreatePool.
- Um novo
pool_stateexiste no endereço derivado deseed_index, compool_state.seed_index = seed_index. - Todo outro pós-estado corresponde a
CreateCustomizablePool(modo de taxa, taxa dinâmica opcional).
Esta instrução não amplia o acesso geral de criação de pool — a criação sem permissão continua através de
CreatePool / CreateCustomizablePool, que permanecem um-pool-por-par. CreatePermissionedPool existe para o caso específico em que um operador na lista de permissões precisa de vários pools para o mesmo par (por exemplo, preços iniciais ou coortes de lançamento diferentes) e mantém um PDA Permission concedido pelo admin.OpenPositionV2 / OpenPositionWithToken22Nft
Cria uma nova posição dentro de um pool existente.
Argumentos
OpenPositionV2 declara 22; OpenPositionWithToken22Nft declara 20.
OpenPositionV2, em ordem:
OpenPositionWithToken22Nft é a mesma lista com metadata_account (5) e metadata_program (19) removidos — escreve os metadados da posição através da extensão de metadados Token-2022 no mint do NFT em vez disso — dando 20 contas. Seu position_nft_mint é um Signer simples e position_nft_account um UncheckedAccount.
Matemática — veja products/clmm/math. Dado base_flag, o programa resolve liquidity ou (amount_0_max, amount_1_max) em L real e os valores de token reais consumidos.
Pré-condições
tick_lower < tick_upper, ambos múltiplos depool.tick_spacing, dentro de[MIN_TICK, MAX_TICK].- Os dois PDAs de array de tick são passados. Eles não precisam já existir —
get_or_create_tick_arrayaloca um faltante no custo depayerdentro desta instrução. Não há instrução separada de inicialização de array de tick. - O usuário tem pelo menos
amount_0_maxeamount_1_maxnas ATAs de origem.
personal_positionexiste,liquiditydefinido,fee_growth_inside_lastcapturado.- Entradas de array de tick em
tick_loweretick_upperatualizadas (liquidity_gross += L,liquidity_net ± L, snapshots de crescimento de taxa mantidos). pool_state.liquidity += Lse a posição está no intervalo (tick_lower ≤ tick_current < tick_upper).- O mint do NFT da posição registra
pool_statecomo autoridade de congelamento. A autoridade de mint é removida após o único NFT ser cunhado. Registrar a autoridade de congelamento não altera o estado da conta de token do NFT. - A conta de token do NFT permanece descongelada a menos que a instrução seja
OpenPositionV2ouOpenPositionWithToken22Nfte a autoridade de congelamento de qualquer mint de cofre corresponda à lista de emissores restritos do CLMM. Apenas esse caminho V2 correspondente congela a conta.OpenPositionV1 não congela.
TickInvalidOrder (tick_lower >= tick_upper), TickAndSpacingNotMatch (um endpoint não é múltiplo de tick_spacing), InvalidTickIndex (fora de [MIN_TICK, MAX_TICK]), MissingTickArrayBitmapExtensionAccount (intervalo fora do bitmap inline e a extensão não foi anexada), NotApproved (pool_state.status bloqueia abertura), ZeroAmountSpecified.
O congelamento de posição não adiciona contas de instrução declaradas ou argumentos. Os clientes podem abrir essas posições com os layouts V2 existentes. O comportamento é selecionado on-chain a partir de
vault_0_mint e vault_1_mint.IncreaseLiquidityV2
Adiciona liquidez a uma posição já aberta.
Argumentos
OpenPosition: não há rent, não há system_program, não há associated_token_program e nenhuma conta de metadados.
Anexe o PDA
TickArrayBitmapExtension como remaining_accounts[0] quando o intervalo da posição está fora do bitmap inline.
Efeito
- Transfere
amount_0_actual/amount_1_actualdo usuário → cofres. - Incrementa
personal_position.liquidityepool_state.liquidity(se no intervalo), e oliquidity_gross/liquidity_netdo tick de endpoint de acordo. - Coleta taxas e recompensas devidas desde o último toque e as credita a
token_fees_owed_{0,1}/reward_amount_owed. Esses são pagos apenas emDecreaseLiquidity/DecreaseLiquidityV2, não em aumento — não há instrução de coleta autônoma.
DecreaseLiquidityV2
Remove liquidez de uma posição.
Argumentos
IncreaseLiquidityV2: personal_position e pool_state são trocados, os cofres vêm antes dos arrays de tick, as contas do lado do usuário são nomeadas recipient_token_account_*, e há um memo_program extra.
Contas restantes — três por recompensa ativa sendo coletada, na ordem
reward_token_vault(W), recipient_token_account(W), reward_vault_mint. Anexe o PDA TickArrayBitmapExtension quando o intervalo da posição está fora do bitmap inline.
Esta é também a única forma de coletar taxas e recompensas. Para coletar sem alterar a
posição, chame-a com
liquidity = 0, amount_0_min = 0, amount_1_min = 0.- Computa
(amount_0, amount_1)para oLremovido dadosqrt_price_x64atual. - Liquida taxas/recompensas acumuladas desde o último toque, mesmo que
IncreaseLiquidity. - Transfere
amount_0 + fees_owed_0eamount_1 + fees_owed_1dos cofres para o usuário. - Decrementa contadores de liquidez; se o novo
personal_position.liquidity == 0, a posição é elegível paraClosePosition.
amount_0_min e amount_1_min são os mínimos que o usuário aceita líquido de taxas de transferência Token-2022 no lado de saída.
ClosePosition
Queima o NFT de posição e fecha PersonalPositionState.
Contas declaradas
Contas restantes
- NFT descongelado: nenhum necessário; uma conta de pool extra é inofensiva porque o manipulador não a lê.
- NFT congelado: anexe
personal_position.pool_idcomo a primeira conta restante. O programa a carrega comoPoolStatee usa suas sementes de PDA para assinar o descongelamento.
personal_position.liquidity == 0.tokens_fees_owed_{0,1} == 0.- Todos os contadores de recompensa
reward_amount_owed == 0.
- Se a conta de token do NFT estiver congelada, verifica se a primeira conta restante é igual a
personal_position.pool_id, depois a descongela com o PDA do pool. - Queima o NFT.
- Fecha a conta de token do NFT e
personal_position, reembolsando aluguel paranft_owner. Se o NFT de posição usar Token-2022, também fecha o mint do NFT; mints SPL Token clássicos não podem ser fechados e permanecem com fornecimento zero.
AccountLack ao fechar uma posição congelada. Passar o pool para cada fechamento é a estratégia compatível mais simples.
SwapV2
Caminha pela curva de liquidez; entrada exata ou saída exata dependendo de is_base_input.
Argumentos
Os chamadores passam uma lista classificada de arrays de tick cobrindo a caminhada de swap esperada; o programa usa quantos precisar. O SDK calcula esta lista via
PoolUtils.computeAmountOutFormat ou o endpoint de cotação da API.
Pré-condições
pool_state.statuspermite swap.now >= open_time.sqrt_price_limit_x64está no lado correto desqrt_price_x64para a direção.
TooLittleOutputReceived (slippage exato-em), TooMuchInputPaid (slippage exato-fora), SqrtPriceLimitOverflow, NotEnoughTickArrayAccount, InvalidFirstTickArrayAccount, MissingTickArrayBitmapExtensionAccount, LiquidityInsufficient, NotApproved (bit de swap definido em pool_state.status). CLMM não tem variante ExceededSlippage — esse nome é do CPMM — e não tem TickArrayNotFound.
O que SwapV2 faz internamente que os chamadores devem saber (pós-lançamento de 2025):
- Sobretaxa de taxa dinâmica — se
pool.dynamic_fee_infofor diferente de zero, o programa atualiza o acumulador de volatilidade usando a distância de tick percorrida desde o último swap (com as regras de filtro/decaimento deproducts/clmm/fees) e adiciona umdynamic_fee_componentem cima deAmmConfig.trade_fee_rate. A taxa total é limitada a 10% (MAX_FEE_RATE_NUMERATOR / 1_000_000). - Correspondência de ordem limitada — quando a caminhada de preço cruza um tick que contém ordens limitadas abertas, o programa primeiro preenche a liquidez de ordem limitada disponível naquele tick (FIFO por
order_phase), depois prossegue ao longo da curva de liquidez LP. Os valores preenchidos atualizamtick.unfilled_ratio_x64etick.part_filled_orders_remainingpara liquidação posterior; as próprias ordens permanecem não gastas até que seu proprietário chameSettleLimitOrder. - Roteamento de taxa unilateral — quando
pool.fee_on = Token0OnlyouToken1Only, a etapa de swap ainda computa a mesma entrada-saída de comércio; a taxa é então roteada para o lado configurado. Para direções onde o lado de taxa configurado é a saída, a taxa é deduzida da saída de swap (o usuário recebeout − fee); para direções onde é a entrada, o comportamento corresponde aFromInput. Vejais_fee_on_input(zero_for_one)eis_fee_on_token0(zero_for_one)emPoolState.
Swap (V1) implementa a mesma taxa dinâmica, roteamento de taxa unilateral e correspondência de ordem limitada que SwapV2; o único recurso que lhe falta é suporte Token-2022 — ambos os cofres devem ser SPL Token clássico. Pools com qualquer mint Token-2022 devem ser trocados via SwapV2. O agregador e SDK já preferem V2 para cada perna CLMM, então os chamadores não precisam ramificar no tipo de mint.
OpenLimitOrder
Coloca uma ordem de venda em um tick específico. A ordem fica em uma coorte FIFO por tick e é preenchida conforme o preço passa.
Argumentos
Contas restantes —
[0] tick_array_bitmap_extension, necessário apenas ao inicializar um array de tick cujo índice inicial cai fora do bitmap inline do pool. Não passe nada caso contrário.
Mudança de lista de contas (lançamento 2026-07).
OpenLimitOrder agora também leva as contas do lado de saída — output_token_account, output_vault e output_vault_mint — além do lado de entrada. Elas são usadas apenas para validação: o programa rejeita a ordem se a conta de token de entrada ou saída do proprietário estiver congelada. Isso garante que um preenchimento possa realmente ser liquidado para a ATA de saída do proprietário, o que importa para mints Token-2022 de lista de permissões / congelados por padrão (por exemplo, tokens permissionados) onde uma conta pode ainda não estar descongelada. Os clientes construídos contra a lista de contas unilateral mais antiga devem adicionar as três contas de saída.- Nem
input_token_accountnemoutput_token_accountestá congelado (caso contrárioNotApproved). pool_state.statuspermite tanto swap (bit 4) quanto operações de ordem limitada (bit 5) (caso contrárioNotApproved).tick_index % pool.tick_spacing == 0e dentro de[MIN_TICK, MAX_TICK].tick_indexestá no lado direito depool.tick_currentpara a direção escolhida (vender token0 → tick deve estar acima do atual, e vice-versa). Vender em um tick já cruzado seria correspondido imediatamente e é rejeitado.
limit_orderexiste, capturandotick.order_phaseetick.unfilled_ratio_x64no tempo de abertura.tick.orders_amount += amount(na coorte atual).limit_order_nonce.order_nonce += 1.OpenLimitOrderEventemitido.
NotApproved (conta de token de entrada ou saída congelada, ou o pool tem swap / ordem limitada desabilitado), ZeroAmountSpecified (amount == 0 após a taxa de transferência do lado de entrada), InvalidLimitOrderAmount (o valor produziria uma saída abaixo de 1 unidade base naquele tick, ou transbordaria u64), InvalidTickIndex (fora de [MIN_TICK, MAX_TICK], ou no lado errado de tick_current para a direção escolhida), TickAndSpacingNotMatch (tick_index % pool.tick_spacing != 0), OrderPhaseSaturated.
IncreaseLimitOrder
Adiciona a uma ordem aberta existente. Apenas chamável pelo owner da ordem.
Argumentos
system_program.
Pré-condições
limit_order.owner == signer.- A ordem ainda está na mesma coorte (
tick.order_phase == limit_order.order_phase). Se a coorte já começou a ser preenchida, a ordem é parcialmente liquidada — o chamador deve chamarDecreaseLimitOrderouSettleLimitOrderprimeiro para avançar.
- Transfere
amountda ATA do proprietário parainput_vault. limit_order.total_amount += amount;tick.orders_amount += amount.
DecreaseLimitOrder
Reduz ou cancela completamente uma ordem aberta. Paga o restante não preenchido de volta ao proprietário, mais qualquer saída já liquidada por preenchimentos parciais anteriores.
Argumentos
Efeito
- Recomputa o valor preenchido da ordem a partir do
unfilled_ratio_x64da coorte desde a abertura. - Envia saída preenchida para
output_token_account. - Envia
amountde entrada não preenchida de volta parainput_token_account. - Atualiza
limit_orderde acordo. Se o novo restante não preenchido for zero, o programa fecha a conta e reembolsa aluguel paraowner.
SettleLimitOrder
Envia tokens de saída preenchidos para o proprietário sem alterar o restante não preenchido da ordem. Útil quando operadores auto_withdraw querem pagar gradualmente preenchimentos parciais de longa duração.
Chamador — ou o owner da ordem, ou o limit_order_admin do programa (uma carteira quente operacional off-chain que executa um loop de operador automatizado). O operador não tem outra autoridade — não pode mover fundos do usuário fora de enviar saída preenchida para a ATA owner.
Contas
Efeito
- Computa a saída cumulativa devida usando
(limit_order.unfilled_ratio_x64, tick.unfilled_ratio_x64). - Transfere o delta para
output_token_account. - Atualiza
limit_order.settled_output. - Não fecha a ordem; ela ainda está aberta contra qualquer entrada restante.
CloseLimitOrder
Fecha uma conta de ordem totalmente consumida. O aluguel sempre retorna para limit_order.owner independentemente de quem assina.
Chamador — ou owner ou limit_order_admin.
Pré-condições
- A ordem tem zero restante não preenchido (ou
amount == total_amountfoi preenchido e liquidado, ou o proprietário diminuiu anteriormente a ordem para zero e esqueceu de fechar).
- Fecha
limit_order; aluguel é enviado paralimit_order.owner.
CreateDynamicFeeConfig (admin)
Cria um conjunto de parâmetros reutilizável sob um índice u16.
Argumentos
Erros comuns —
InvalidDynamicFeeConfigParams se decay_period <= filter_period ou qualquer campo com valor 0 estiver fora dos limites.
UpdateDynamicFeeConfig (admin)
Modifica um DynamicFeeConfig existente. Pools que já capturaram a configuração no tempo de criação não são atualizados retroativamente; apenas pools recém-criados que referenciam esta configuração pegarão os novos valores.
Argumentos — mesmos cinco campos de calibração que CreateDynamicFeeConfig (filter_period, decay_period, reduction_factor, dynamic_fee_control, max_volatility_accumulator); index é fixo na criação e não é re-passado aqui.
CollectProtocolFee / CollectFundFee
Varre taxas de protocolo/fundo acumuladas dos cofres do pool para um destinatário, zerando os campos correspondentes PoolState.protocol_fees_* / fund_fees_*. Este não é o layout do CPMM — CLMM não tem conta authority, e os campos de destinatário são nomeados recipient_token_account_{0,1} em vez de recipient_token_{0,1}_account.
Argumentos — amount_0_requested: u64, amount_1_requested: u64.
Alterado em 2026-09: novas configurações não pegam mais seus proprietários de taxa do signatário.
create_amm_config agora escreve o protocol_fee_owner::ID codificado do programa em owner e fund_fee_owner::ID em fund_owner. Antes, copiava a chave do signatário de admin em ambos. Na mainnet, estes são as mesmas chaves já armazenadas em todas as 21 configurações existentes. Os endereços estão em reference/program-addresses.Os signatários aceitos acima são inalterados. O admin ainda pode coletar de qualquer configuração, e contas AmmConfig existentes não são reescritas. Leia owner / fund_owner da conta em vez de assumir qualquer valor. Os parâmetros UpdateAmmConfig 3 e 4 ainda os giram.CollectExcessLamports
Varredura de admin de lamports acima do mínimo isento de aluguel em contas que CLMM controla. Foi adicionado na atualização 2026-09 para recuperar o excesso de financiamento que a redução de aluguel SIMD-0437 deixa em contas criadas antes de cada etapa.
Apenas o excesso se move. Saldos de token, dados de conta, proprietários, estado do pool e a curva de preço não são tocados. Uma conta já no seu mínimo é deixada como está, então a instrução pode ser re-executada com segurança após cada etapa de lançamento.
Argumentos: nenhum.
Contas
Escopo: um pool por chamada. CLMM não tem autoridade de cofre em nível de programa. Os cofres de cada pool são de propriedade de seu próprio
PoolState. Cada origem de programa de token deve portanto ter o pool_state no slot 2 como sua autoridade: token_vault_0, token_vault_1, ou um dos cofres de recompensa daquele pool. Se você passar o cofre de outro pool ou uma conta de token do usuário, a verificação de proprietário do programa de token falha e toda a instrução reverte. Não é pulada. Mints de NFT de posição não podem ser varridos, porque sua autoridade de mint é revogada quando a posição é aberta.
Como cada conta de origem é manipulada
O programa faz duas passagens sobre remaining_accounts: cada CPI do programa de token primeiro, depois os débitos diretos. Intercalar os dois aborta com o erro UnbalancedInstruction do runtime, então a ordem é fixa no programa e você não precisa classificar a lista você mesmo.
O tamanho da transação é o limite real de quantas fontes cabem em uma chamada. É a mesma restrição que a varredura do lado da carteira descrita em
solana-fundamentals/rent-and-reclaimable-rent.
Erros comuns:
NotApproved(6000): signatário errado.LamportsCalculateError(6052): a volta redonda wSOL não resultou em zero.- Um erro de incompatibilidade de proprietário do programa de token: uma origem de token não é de propriedade de
pool_state. InsufficientFunds: uma conta de propriedade do programa contém menos que seu próprio mínimo de aluguel.
@raydium-io/raydium-sdk-v2 não fornece um construtor para este caminho de admin. Codifique-o manualmente a partir do IDL.
InitializeReward
Adiciona um novo fluxo de recompensa a um pool. Até 3 fluxos podem estar ativos de uma vez.
Argumentos — uma única struct, param: InitializeRewardParam:
param em vez de três argumentos posicionais.
Contas

