> ## Documentation Index
> Fetch the complete documentation index at: https://docs.raydium.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Matemática do AMM v4

> Invariante de produto constante com a convenção de taxas do AMM v4, conversão de preço de reserva para livro de ordens, construção de grade de ordens-alvo e a etapa de liquidação de PnL.

<Info>
  **Esta página foi traduzida automaticamente por IA. A versão em inglês é a fonte oficial.**

  [Ver versão em inglês →](/products/amm-v4/math)
</Info>

## O invariante

O pool mantém `coin_reserve × pc_reserve = k`, onde (após a remoção do OpenBook em 2026-07):

```
coin_reserve = coin_vault_balance - accrued_pnl_coin
pc_reserve   = pc_vault_balance   - accrued_pnl_pc
```

Dois pontos importantes:

1. As reservas agora são **apenas de vault**. O termo histórico de open-order (tokens que o pool tinha em custódia como ordens limitadas do OpenBook) foi removido — na prática, era zero muito antes da remoção. Você pode calcular `k` diretamente dos saldos de vault on-chain.
2. O acúmulo de PnL (`need_take_pnl_*`) é subtraído para que a curva seja conservada quando o admin coleta as taxas. O mesmo princípio que a exclusão de `protocol_fees_*` do CPMM.

O programa calcula isso via `calc_total_without_take_pnl_no_orderbook` (a variante histórica ciente de orderbook foi removida).

Toda operação `Swap*` garante que `k' ≥ k` após adicionar a parte de taxa do LP de volta às reservas.

## Convenção de taxas

O AMM v4 usa **taxas de razão** (pares numerador/denominador) em vez da convenção `1/1_000_000` do CPMM / CLMM. A struct `Fees` on-chain (veja [`Fees::initialize`](https://github.com/raydium-io/raydium-amm/blob/master/program/src/state.rs) no código-fonte do programa) tem como padrão:

```
Fees {
  min_separate_numerator:    5,
  min_separate_denominator:  10_000,   //  5/10_000 = 0.05%

  trade_fee_numerator:      25,
  trade_fee_denominator:    10_000,    // 25/10_000 = 0.25% — usado para precificação de ordens limitadas do OpenBook

  pnl_numerator:            12,
  pnl_denominator:          100,       // 12/100   = 12%   — participação do protocolo DA taxa de swap

  swap_fee_numerator:       25,
  swap_fee_denominator:     10_000,    // 25/10_000 = 0.25% — taxa bruta em swaps no caminho AMM
}
```

Interpretação (padrões publicados na mainnet):

* **Taxa total de swap:** `swap_fee = amount_in × 25 / 10_000 = 0.25%` da entrada bruta.
* **Participação do protocolo:** `pnl_numerator / pnl_denominator = 12 / 100 = 12%` **da taxa de swap**, o que resulta em `0.25% × 12% = 0.03%` do volume. Esta participação se acumula nos contadores de PnL e é coletada por `WithdrawPnl`.
* **Participação do LP:** os `88%` restantes da taxa de swap, o que resulta em `0.25% × 88% = 0.22%` do volume. Permanece no pool e inflaciona `k`.
* **Sem participação de fundo.** O AMM v4 não possui a divisão de taxa de fundo do CPMM/CLMM.

Note que `pnl_numerator / pnl_denominator` é uma fração **da taxa**, não do volume de negociação — uma leitura comum errada desses nomes de campo.

`trade_fee_numerator / trade_fee_denominator` (também `25 / 10_000`) era historicamente usado pela integração do OpenBook ao calcular preços inclusivos de taxa para a grade de ordens limitadas do AMM. Com o código do OpenBook removido, este campo é vestigial; a taxa de swap ativa é `swap_fee_*`.

Desvios desses padrões são raros, mas existem em alguns pools legados; sempre leia as taxas de `AmmInfo.fees` antes de fazer uma cotação.

## Matemática de swap direto (caminho AMM)

O caso mais simples: o usuário faz swap contra os vaults do pool sem interagir com o OpenBook. As reservas internas do pool (incluindo alocações on-book) são o denominador.

**SwapBaseIn (entrada exata):**

```
amount_after_fee = amount_in − ceil(amount_in × swap_fee_numerator / swap_fee_denominator)
amount_out = amount_after_fee × out_reserve
           / (in_reserve + amount_after_fee)
require(amount_out >= minimum_amount_out)
```

As reservas usadas aqui são os saldos de vault (menos PnL acumulado). Historicamente, a fórmula também adicionava os tokens que o AMM tinha bloqueados em ordens do OpenBook; **esse termo foi removido** — as reservas efetivas agora são iguais aos saldos brutos de vault menos PnL pendente. O caminho `MonitorStep` / liquidação implícita que costumava atualizar o lado do OpenBook foi removido.

**SwapBaseOut (saída exata):**

```
amount_in_after_fee = ceil(in_reserve × amount_out / (out_reserve − amount_out))
amount_in_gross     = ceil(amount_in_after_fee × swap_fee_denominator
                            / (swap_fee_denominator − swap_fee_numerator))
require(amount_in_gross <= maximum_amount_in)
```

## Interação com livro de ordens (histórico)

<Note>
  **Removido.** A construção de grade descrita nesta seção reflete como o AMM v4 *originalmente* espelhava a curva em um mercado do OpenBook. A integração do OpenBook — incluindo o crank `MonitorStep` e a lógica de grade `build_orders` — foi **removida do programa** (atualização de 2026-07). A matemática abaixo é preservada puramente como contexto histórico para o que as contas on-chain `target_orders` / `amm_open_orders` foram uma vez dimensionadas.
</Note>

Separadamente dos swaps do usuário, o AMM v4 historicamente colocava uma **grade** de ordens limitadas no mercado do OpenBook. A grade era calculada a partir dos parâmetros `AmmInfo`:

* **`depth`** — número de níveis de preço por lado.
* **`amount_wave`** — unidade de tamanho base por nível.
* **`min_size`**, **`coin_lot_size`**, **`pc_lot_size`** — restrições do mercado OpenBook.
* **`state_data.swap_acc_coin_fee`**, **`swap_acc_pc_fee`** — contadores de taxa cumulativa desde o último `TakePnl`.

O programa deriva preços por nível caminhando para fora do preço da curva atual em passos de razão constante:

```
price_level(k) = curve_price × (1.0001 ^ k)       # conceitualmente
size_level(k)  = amount_wave × f(depth, k)        # afinado por profundidade
```

Os preços e tamanhos exatos são determinados por `target_orders` calculados em `build_orders` e comparados com `amm_open_orders` a cada `MonitorStep`. Qualquer divergência resulta em cancelamentos + novos posts. Ordens recém-preenchidas no OpenBook se liquidam nos vaults do pool na próxima operação que atualiza o lado do OpenBook.

Integradores raramente precisam calcular a grade — o keeper do Raydium a mantém — mas é útil saber que:

* Um pool com **liquidez on-book** significativa tem essa liquidez contribuindo para `k`, não ociosa.
* Um mercado OpenBook desatualizado (fila de eventos cheia, cranks bloqueados) impede atualizações de grade; o AMM pode então cotar preços que divergem do livro de ordens visível até o próximo crank.

## Etapa de liquidação (PnL)

A participação do protocolo de 0.03% se acumula em `state_data.need_take_pnl_coin` e `state_data.need_take_pnl_pc`. `TakePnl` move essas quantidades para fora dos vaults para o destino especificado pelo admin, depois zera os contadores.

Propriedade crucial: as reservas no invariante são sempre calculadas **menos** PnL acumulado, então `TakePnl` não move a curva. Isso corresponde à convenção do CPMM.

## Exemplo trabalhado

Estado do pool:

* `coin_reserve = 1_000_000_000_000` (1.000.000 lado coin; 6 decimais)
* `pc_reserve   = 2_000_000_000_000` (2.000.000 lado pc; 6 decimais)
* Taxas: padrão `swap = 25/10_000`, `pnl = 3/10_000`.

Usuário: `SwapBaseIn` entrada exata `1_000_000_000` coin (1.000 coin).

```
swap_fee        = ceil(1_000_000_000 * 25 / 10_000)    = 2_500_000
amount_after_fee =                                      997_500_000

amount_out = amount_after_fee * pc_reserve
           / (coin_reserve + amount_after_fee)
           = 997_500_000 * 2_000_000_000_000
           / (1_000_000_000_000 + 997_500_000)
           ≈ 1_995_015_009  (1.995,015 pc)

// Dos 2_500_000 de taxa de swap:
pnl_share = 2_500_000 * 3 / 25  = 300_000    (vai para protocolo via need_take_pnl_coin)
lp_share  = 2_500_000 * 22 / 25 = 2_200_000  (permanece em coin_reserve)

new coin_reserve = 1_000_000_000_000 + 1_000_000_000                 = 1_001_000_000_000
                   (dos quais 300_000 é PnL acumulado)
  curve coin_reserve = 1_001_000_000_000 − 300_000 = 1_000_999_700_000
new pc_reserve   = 2_000_000_000_000 − 1_995_015_009                 ≈ 1_998_004_984_991

k' = curve_coin_reserve * new_pc_reserve
   ≈ 2.000_002_701E24
k  = 1_000_000_000_000 * 2_000_000_000_000
   = 2.0E24
k' > k   ✓
```

A participação do LP (`2_200_000`) não é separada em lugar nenhum — é simplesmente o resíduo que eleva `k'`.

## Regras de precisão

* Multiplicações de reserva usam `u128`; divisões finais arredondam para zero.
* `swap_fee` arredonda para cima (para que o pool não cobre menos).
* `amount_in` para `SwapBaseOut` arredonda para cima (para que o usuário não pague menos).
* Pools com razões de reserva extremas podem atingir `ZeroTradingTokens` em entradas muito pequenas; mesma convenção que CPMM.

## Limitações vs CPMM

* As reservas do AMM v4 agora são apenas de vault, então você **pode** cotar diretamente dos saldos de vault (menos `need_take_pnl_*`) — o requisito anterior de adicionar os valores `open_orders.free` / `open_orders.locked` não se aplica mais. A cotação do SDK / API permanece a opção mais simples.
* O AMM v4 não expõe um TWAP estruturado on-chain. Consumidores externos que desejam um preço apoiado por AMM-v4 devem calculá-lo eles mesmos a partir de logs de negociação.
* Token-2022 não é suportado.

## Próximos passos

* [`products/amm-v4/instructions`](/pt/products/amm-v4/instructions) — onde `SwapBaseIn`, `Deposit`, etc. se conectam.
* [`products/amm-v4/fees`](/pt/products/amm-v4/fees) — mecânica completa de taxas, detalhes de `TakePnl`.
* [`algorithms/constant-product`](/pt/algorithms/constant-product) — a derivação compartilhada.

Fontes:

* [Código-fonte do programa Raydium AMM — `raydium-io/raydium-amm`](https://github.com/raydium-io/raydium-amm)
* Módulo `Liquidity` do Raydium SDK v2
