Skip to main content
Esta página foi traduzida automaticamente por IA. A versão em inglês é a fonte oficial.Ver versão em inglês →
O ID do programa e as seeds das PDAs para CPMM estão listados canonicamente em reference/program-addresses. Esta página se concentra em para que serve cada conta e os invariantes que ela mantém, não nos endereços codificados.

As seis contas de um pool CPMM

Cada pool CPMM é totalmente descrito por seis endereços derivados do programa (PDAs) sob o programa CPMM, mais uma conta AmmConfig compartilhada que ele referencia. Uma vez que você tenha os dois mints, pode derivar tudo deterministicamente sem tocar na rede. E a configuração compartilhada: E uma conta opcional por criador:

Derivando um pool a partir de nada além de dois mints

Sempre ordene os mints antes de derivar a PDA do pool. A seed faz hash dos dois mints em ordem de bytes, não em ordem do usuário. Dois pools com (A, B) e (B, A) colidiriam on-chain — a ordenação é como o programa torna o mapeamento canônico.
O ID do pool nem sempre é a PDA canônica. Initialize aceita um keypair signatário arbitrário como pool_state além da PDA acima. Se a conta passada não corresponder à PDA canônica, o programa exige que seja um signatário — ou seja, o criador passa um keypair novo que assina. Esta é a defesa contra front-run: qualquer terceiro correndo para pegar a PDA canônica pode ser contornado pelo criador legítimo usando um keypair aleatório. As PDAs downstream (lpMint, vault0, vault1, observation) ainda são derivadas de poolState.key(), então permanecem únicas para qualquer endereço usado. Quando você indexa pools, sempre descubra o ID do pool a partir do estado on-chain (por exemplo, contas PoolState sob o programa CPMM), não derivando a PDA canônica — a última perderá pools com keypair aleatório.

Layouts de conta

As definições completas em Rust vivem na fonte raydium-cp-swap. Os campos abaixo são os que você lerá de uma integração.

PoolState

O que realmente ler:
  • lp_supply — o total de LP interno do pool. Não é igual ao suprimento do mint de LP: é exatamente 100 unidades base mais alto, porque as 100 unidades bloqueadas são contadas aqui mas nunca são mintadas. Toda a matemática de compartilhamento de LP (depósito, saque) divide por lp_supply, então use este campo e não substitua o suprimento on-chain do mint.
  • protocol_fees_token{0,1}, fund_fees_token{0,1} — taxas acumuladas ainda não varridas. Estas não afetam o preço do swap; ficam nos vaults até que CollectProtocolFee / CollectFundFee seja chamado. protocol_fees_token{0,1} também recebe a parte do protocolo da taxa de criador quando uma taxa de criador é coletada, então cresce fora dos swaps — veja products/cpmm/fees.
  • status — um bitmask controlando se Swap, Deposit, Withdraw são permitidos. Atualizado pelo admin via UpdatePoolStatus. O SDK verifica isso antes de construir uma transação; se você está fazendo CPI diretamente, verifique você mesmo.
  • token0_program / token1_program — o programa de token para fazer CPI para cada vault. Um pode ser SPL Token clássico e o outro Token-2022; são independentes.
  • open_time — um timestamp Unix. Swaps antes desta hora falham. Depósitos são permitidos antes de open_time para que o pool possa ser semeado.
  • creator_fee_on / enable_creator_fee — juntos controlam se a taxa de criador opcional está ativa para este pool e de qual lado do swap ela é coletada. enable_creator_fee == false zera o caminho de taxa de criador inteiramente. Quando habilitado, creator_fee_on seleciona: 0 = pegar taxa de qualquer token que seja a entrada do swap (BothToken); 1 = pegar taxa de token_0 apenas (pular em swaps token_1 → token_0); 2 = pegar taxa de token_1 apenas. Definido na criação do pool via InitializeWithPermission; não pode mudar depois.
  • creator_fees_token_{0,1} — taxas de criador acumuladas, varridas por CollectCreatorFee ou CollectCreatorFeePermissionless. Ambos os caminhos zeram os contadores completos, mas desde a atualização de compartilhamento de taxa de criador de 2026-09-19 apenas parte do saldo sai do pool: a parte do protocolo é adicionada a protocol_fees_token_{0,1} e o restante é transferido para o criador. O caminho sem permissão fixa os destinatários para as ATAs canônicas de pool_creator. PoolState em si não mudou — não há contador separado para o valor compartilhado.

AmmConfig

Três coisas para ter cuidado:
  1. trade_fee_rate e creator_fee_rate são frações do volume, ambas denominadas em unidades de 1/1_000_000. 2500 significa 0,25% do volume de trade. protocol_fee_rate e fund_fee_rate são frações da taxa de trade (não do volume), no mesmo denominador 1/1_000_000. A taxa de criador não é uma fração da taxa de trade — é sua própria taxa independente. A aritmética completa está em products/cpmm/fees.
  2. index é um u16, então a seed hash usa 2 bytes big-endian. Erro de um byte na ordem de bytes é um bug de integração comum.
  3. AmmConfig é imutável no nível do pool. Um pool aponta para um AmmConfig na criação e nunca muda. Mudanças de taxa se propagam porque o pool lê a configuração a cada swap — mas o pool não pode ser movido entre tiers de taxa.
Uma nota sobre taxas de criador: a taxa em si (creator_fee_rate) vive em AmmConfig e é compartilhada entre o tier de taxa. Se um pool particular realmente a cobra (enable_creator_fee) e de qual lado do swap ela cai (creator_fee_on) vivem em PoolState. A taxa de criador é independente da taxa de trade — é sua própria taxa, acumulada em seus próprios contadores (creator_fees_token_{0,1}), e nunca reduz as partes de LP / protocolo / fundo da taxa de trade. A varredura é via CollectCreatorFee ou a CollectCreatorFeePermissionless restrita por destino, e ambos os caminhos entregam uma parte do saldo acumulado ao protocolo no caminho — em creator_fee_share_rate, ou na taxa em uma PDA CreatorFeeShare quando uma existe para esse par (creator, amm_config). Veja products/cpmm/fees para a mecânica completa.

Permission

Uma pequena conta de controle de acesso usada por InitializeWithPermission. O programa CPMM suporta um caminho de criação de pool com permissão para que outros programas (por exemplo, LaunchLab ao graduar um token para CPMM) possam provar que têm direito de criar um pool contra um determinado AmmConfig.
A PDA de Permission é criada via CreatePermissionPda pelo admin do CPMM ou por uma autoridade dedicada de criador de PDA de permissão. Desde a atualização de 2026-09, ClosePermissionPda aceita os mesmos dois signatários; antes era apenas admin. Usuários finais não interagem com esta conta diretamente — é encanamento para fluxos entre programas. Veja security/admin-and-multisig para o limite de função e reference/program-addresses para endereços canônicos.

CreatorFeeShare

Uma conta opcional que substitui a parte do protocolo da taxa de criador para um par (criador de pool, AmmConfig). Adicionado pela atualização de compartilhamento de taxa de criador de 2026-09-19.
Como se comporta:
  • É opcional, mas a conta nunca é opcional na instrução. CollectCreatorFee e CollectCreatorFeePermissionless ambas declaram creator_fee_share com a restrição de seed acima e a levam em cada chamada. O programa então verifica se a conta está vazia ou de propriedade estrangeira; se assim for, volta para AmmConfig.creator_fee_share_rate. Então um cliente deve sempre derivar e passar o endereço, independentemente de a conta existir ou não.
  • share_rate é limitado a FEE_RATE_DENOMINATOR_VALUE (1_000_000) na criação, e novamente quando a divisão é executada. 1_000_000 roteia toda a taxa de criador para o protocolo; 0 não roteia nada.
  • Criado e fechado pelo admin ou uma autoridade dedicada através de CreateCreatorFeeShare / CloseCreatorFeeShare. Fechá-lo retorna o aluguel ao signatário e volta o par para o padrão da configuração; o criador do pool não é um signatário em nenhum caminho.
  • É codificado no criador, não no pool. Uma conta governa cada pool que o criador tem naquele AmmConfig. Um criador com pools em dois tiers de taxa precisa de duas contas para ser coberto em ambos.
A aritmética de divisão que ela impulsiona está em products/cpmm/fees.

Vaults e Token-2022

vault0 e vault1 são propriedade da PDA de autoridade do CPMM, e seu proprietário de programa de token (token_program) é SPL Token ou Token-2022, determinado na criação do pool pelo programa do mint. O pool lida com os dois casos de forma transparente — você passa o ID correto do programa de token para cada lado nas contas de instrução Swap / Deposit / Withdraw. CPMM impõe uma lista de permissões de extensão rigorosa na criação do pool (is_supported_mint em utils/token.rs). Um mint Token-2022 pode ser usado em um pool CPMM apenas se cada extensão que ele carrega estiver nesta lista:
  • TransferFeeConfig. Aplicado pelo mint em cada transferência. O pool está no lado receptor para depósitos SwapBaseInput e no lado de envio para saques. O programa calcula o valor líquido chegando ao vault e define a curva de acordo. Veja algorithms/token-2022-transfer-fees.
  • MetadataPointer e TokenMetadata. Metadados padrão on-mint. Sem efeito na matemática de swap.
  • InterestBearingConfig. O valor de UI do mint acumula juros. O vault armazena valores brutos; a curva opera apenas em valores brutos. UIs que mostram APR devem chamar os helpers Token-2022 para renderizar o valor de UI.
  • ScaledUiAmount. Extensão de escala de exibição de UI. Mesmo tratamento que InterestBearingConfig — a curva usa valores brutos.
Qualquer outra extensão — PermanentDelegate, TransferHook, DefaultAccountState, NonTransferable, ConfidentialTransfer, Group/GroupMember, MintCloseAuthority, etc. — causa Initialize rejeitar com NotSupportMint. A única exceção é um registro por mint: se uma PDA SupportMintAssociated existe na seed [b"support_mint", mint], o mint é admitido independentemente de seu conjunto de extensões. Essa PDA é criada e removida pelo admin (ou uma autoridade dedicada de suporte de mint) através de CreateSupportMintAssociated / CloseSupportMintAssociated, então integrar um mint específico não precisa mais de uma atualização de programa.
Mudado em 2026-09. CPMM anteriormente também carregava uma MINT_WHITELIST de quatro endereços codificada que contornava a verificação de extensão. Esse array foi removido; a PDA de registro é agora o único bypass. Qualquer mint que estava contando com a lista codificada precisa de uma PDA SupportMintAssociated antes que um novo pool possa ser criado para ele — pools existentes não são afetados, porque a verificação é executada apenas na criação do pool.
A lista de extensões verificadas vive na fonte CP-Swap sob programs/cp-swap/src/utils/token.rs e pode mudar com futuras atualizações de programa. Veja reference/token-2022-support para a matriz entre programas.

Observation

A conta de observação é um ring buffer de entradas ObservationState, cada uma armazenando um block_timestamp e um preço cumulativo. Em cada swap, o programa anexa uma nova observação se tempo suficiente passou desde a última. TWAPs são calculados lendo duas observações e dividindo Δcumulative / Δtime.
O ring buffer é dimensionado para 100 observações. Cada observação tem 40 bytes (8 + 16 + 16), então o array sozinho tem 4.000 bytes; ObservationState::LEN é exatamente 4.075 bytes (8 + 1 + 2 + 32 + 4.000 + 8 × 4). Duas regras de consumidor:
  • Não use uma única observação como preço. É um cumulativo, não um preço spot. Use duas delas para calcular um TWAP.
  • Escolha observações com pelo menos um bloco de distância. Swaps dentro do mesmo bloco podem não produzir uma nova observação; ler de volta a trás pode retornar o mesmo registro.
Mais matemática em products/clmm/accounts.

Ciclo de vida da conta

Pools CPMM e suas PDAs nunca são fechados. Permission, SupportMintAssociated e CreatorFeeShare são as exceções — são registros autônomos gerenciados por admin, não estado do pool, e cada um tem uma instrução de fechamento explícita. Mesmo com liquidez zero, o poolState permanece. Isto é deliberado: resemear o mesmo pool depois preserva seu buffer de observação histórico e sua derivação de PDA permanece estável.

O que ler onde

Fontes: