> ## 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.

# CPMM matematiği

> Sabit-çarpım değişmezi, SwapBaseInput ve SwapBaseOutput, Token-2022 transfer-ücreti işleme ve gözlem hesabının nasıl güncellendiği.

<Info>
  **Bu sayfa yapay zekâ tarafından otomatik olarak çevrilmiştir. İngilizce sürüm esas alınır.**

  [İngilizce sürümü görüntüle →](/products/cpmm/math)
</Info>

## Değişmez

CPMM, iki kasasında klasik sabit-çarpım değişmezini korur:

$$
x \cdot y = k
$$

burada `x`, vault0 bakiyesidir **alındıktan sonra** herhangi bir Token-2022 transfer ücreti, ve `y` de benzer şekilde. Her swap, ticaret ücretleri LP'ye (protokol, fon ve yaratıcı paketleri `k`'ya doğru sayılmaz — kasada bulunurlar ancak eğri görünümünden hariç tutulurlar, aşağıdaki [Eğri üzerindeki ücretler](#eğri-üzerindeki-ücretler) bölümüne bakınız) alındıktan sonra `k' ≥ k` bırakmalıdır. `k` bu nedenle LP'ler ücret tahakkuk ettirdikçe zaman içinde monoton olarak artar.

LP payları havuzun rezervleri tarafından fiyatlandırılır, `k` tarafından değil:

$$
\text{token0 cinsinden LP fiyatı} = \frac{x}{\text{lpSupply}}, \qquad \text{token1 cinsinden LP fiyatı} = \frac{y}{\text{lpSupply}}
$$

`ΔLP` LP tokenini yakarak tam olarak `ΔLP × x / lpSupply` token0 ve `ΔLP × y / lpSupply` token1 geri alırsınız. Ne eğri ne de `k` yatırım veya çekim sırasında hareket eder — yalnızca swaplar fiyatı değiştirir.

## Swap yolunda ücret modeli

CPMM her swapda **iki bağımsız oranlı ücret** uygular:

* **Ticaret ücreti** giriş tarafında alınır, `AmmConfig.trade_fee_rate` oranında ücretlendirilir. Daha sonra LP, protokol ve fon paylarına bölünür (LP payı kasada kalır ve `k`'yı büyütür; protokol ve fon payları kasa muhasebesi dışında çıkarılır).
* **Yaratıcı ücreti** (yalnızca `enable_creator_fee == true` olduğunda etkin) `AmmConfig.creator_fee_rate` oranında ücretlendirilir. **Giriş** tarafında veya **çıkış** tarafında alınır, `PoolState.creator_fee_on` ve swap yönüne bağlı olarak (bkz. [`products/cpmm/fees`](/tr/products/cpmm/fees#ücretlerin-alındığı-ticaretin-hangi-tarafı)). Kendi bir pakettidir — asla ticaret ücretinin bir dilimi değildir.

<Note>
  **Protokolün yaratıcı ücretinin payı bu sayfada hiçbir yerde görünmez ve bu kasıtlıdır.** `CollectCreatorFee` tahakkuk eden ücretleri eğrinin zaten hariç tuttuğu iki sayaç arasında hareket ettirdiğinde uygulanır — bir swap sırasında değil. Swap matematiği, teklifler ve `k` bununla ve bunu olmadan aynıdır. Bkz. [`products/cpmm/fees`](/tr/products/cpmm/fees#protokolün-yaratıcı-ücretinin-payı).
</Note>

Tanımlayalım:

* `FEE_RATE_DENOMINATOR = 1_000_000`
* `trade_fee_rate` — `AmmConfig`'den, örn. `2500` = ilgili hacim tarafının %0,25'i
* `creator_fee_rate` — `AmmConfig`'den, örn. `1000` = ilgili hacim tarafının %0,10'u
* `protocol_fee_rate`, `fund_fee_rate` — `1/FEE_RATE_DENOMINATOR` birimlerinde **ticaret ücretinin**, hacmin değil

Yaratıcı ücreti giriş tarafında olduğunda:

```
total_input_fee = ceil(amount_in * (trade_fee_rate + creator_fee_rate) / FEE_RATE_DENOMINATOR)
creator_fee     = floor(total_input_fee * creator_fee_rate / (trade_fee_rate + creator_fee_rate))
trade_fee       = total_input_fee - creator_fee
amount_in_after_fees = amount_in - total_input_fee
```

Yaratıcı ücreti çıkış tarafında olduğunda:

```
trade_fee            = ceil(amount_in * trade_fee_rate / FEE_RATE_DENOMINATOR)
amount_in_after_fees = amount_in - trade_fee
amount_out_curve     = curve_output(amount_in_after_fees, ...)
creator_fee          = ceil(amount_out_curve * creator_fee_rate / FEE_RATE_DENOMINATOR)
amount_out           = amount_out_curve - creator_fee
```

Her iki durumda da ticaret ücreti aynı şekilde bölünür:

```
protocol_fee   = floor(trade_fee * protocol_fee_rate / FEE_RATE_DENOMINATOR)
fund_fee       = floor(trade_fee * fund_fee_rate     / FEE_RATE_DENOMINATOR)
lp_fee         = trade_fee - protocol_fee - fund_fee     // creator_fee burada çıkarılmaz
```

`protocol_fee + fund_fee + creator_fee` tutarı kasalarda tutulur ancak havuz durumunda ayrı olarak izlenir (`protocol_fees_token*`, `fund_fees_token*`, `creator_fees_token*`). Sabit-çarpım değişmezi `k' ≥ k` kontrol ettiğinde, kasa bakiyeleri **eksi** üç tahakkuk etmiş ancak henüz toplanmamış ücret kullanır — böylece LP'ler yalnızca `lp_fee` yakalarlar.

Toplama talimatları ve çalışılmış sayısal örnekler için [`products/cpmm/fees`](/tr/products/cpmm/fees) bölümüne bakınız.

## SwapBaseInput (giriş-kesin)

"Kullanıcı bize giriş mint'inin tam olarak `amount_in` kadarını verir ve çıkış mint'inin en az `minimum_amount_out` kadarını alır."

Şimdilik Token-2022'yi göz ardı ederek:

```
amount_in_after_trade_fee = amount_in - trade_fee
amount_out                = y − (x * y) / (x + amount_in_after_trade_fee)
```

Cebir yoluyla:

$$
\text{amount\_out} = \frac{y \cdot \Delta x_{\text{net}}}{x + \Delta x_{\text{net}}}
$$

burada `Δx_net = amount_in_after_trade_fee`.

Program daha sonra kasa muhasebesi öyle günceller ki, `trade_fee`'nin protokol/fon/yaratıcıya ait kısmı "tahakkuk" paketlerinde oturur (eğrinin sonraki `x`'ine dahil değildir), LP payı ise sonraki swap için `x`'e katılır.

### Giriş tarafında Token-2022

Giriş mint'inin bir transfer-ücreti uzantısı varsa, **mint** kullanıcı → kasa transferinde ücretini keser. Yani kasa aslında `amount_in − transfer_fee_in(amount_in)` alır. CPMM programı bu nedenle şunu hesaplar:

```
amount_actually_received = amount_in − transfer_fee_in(amount_in)
trade_fee                = ceil(amount_actually_received * trade_fee_rate / FEE_RATE_DENOMINATOR)
amount_in_after_trade_fee = amount_actually_received − trade_fee
```

ve eğriyi `amount_in_after_trade_fee` karşısında çalıştırır. Bu önemlidir çünkü **eğri fiyatı kasaya inen net tutardan hesaplanır**, kullanıcının başlık tutarından değil.

### Çıkış tarafında Token-2022

Çıkış mint'inin bir transfer ücreti varsa, havuz `amount_out`'u kasasından kullanıcıya gönderir. **Mint** daha sonra çıkışta ücretini alır, böylece kullanıcı `amount_out − transfer_fee_out(amount_out)` alır. Program `amount_out`'u eğriden her zamanki gibi hesaplar, ancak teklifleri gösterirken havuzun "kasa gönderme" numarasını "kullanıcı alma" numarasına dönüştürmek entegratörün sorumluluğudur.

### Kayma kontrolü

`amount_out` hesaplandıktan sonra:

```
require(amount_out >= minimum_amount_out, "AmountSpecifiedLessThanMinimum")
```

Çıkış mint'i bir transfer ücreti alırsa, SDK transfer ücretini `minimum_amount_out` ayarlamadan önce uygular, böylece kayma sabiti kasanın gönderdiği şey değil, kullanıcının gerçekten alacağı şey cinsinden ifade edilir.

## SwapBaseOutput (çıkış-kesin)

"Kullanıcı çıkış mint'inin tam olarak `amount_out` kadarını alacak ve giriş mint'inin en fazla `maximum_amount_in` kadarını ödemeye isteklidir."

Eğriyi `Δx_net` için ters çevirerek:

$$
\Delta x_{\text{net}} = \left\lceil \frac{x \cdot \text{amount\_out}}{y - \text{amount\_out}} \right\rceil
$$

Tavan önemlidir — tamsayı kesintisinden sonra `k' ≥ k` garantisini verir. Sonra:

```
// Net in'den brüt in'e geri çalış.
// ücret brüt üzerinde uygulanır, yani:
//   net = brüt − ceil(brüt * oran / D)
//       ≈ brüt * (D − oran) / D
// doğru yerlerde tavanla ters çevirerek:
gross_needed = ceil(Δx_net * D / (D − trade_fee_rate))
```

Token-2022 girişinde şu şekilde sarın:

```
gross_needed_before_mint_fee
  = inflate_for_transfer_fee(gross_needed, input_mint)
```

böylece kullanıcı, mint'in transfer-ücreti kesintisinden sonra havuz yine de `gross_needed` alacak kadar öder.

### Kayma kontrolü

```
require(gross_needed_before_mint_fee <= maximum_amount_in, "AmountSpecifiedExceedsMaximum")
```

## Çalışılmış örnek

Havuz durumu, Token-2022'yi göz ardı ederek:

* `x = 1_000_000_000_000` (token0'ın 1.000.000,000000, 6 ondalak)
* `y = 2_000_000_000_000` (token1'in 2.000.000,000000, 6 ondalak)
* `AmmConfig`: `trade_fee_rate = 2500`, `protocol_fee_rate = 120_000`, `fund_fee_rate = 40_000`, `creator_fee_rate = 0`

Kullanıcı: `SwapBaseInput` ile `amount_in = 1_000_000_000` (token0'ın 1.000,000000). Yaratıcı ücreti devre dışı (`enable_creator_fee = false`).

```
trade_fee                = ceil(1_000_000_000 * 2500 / 1_000_000)       = 2_500_000
  protocol_fee           = floor(2_500_000 * 120_000 / 1_000_000)       = 300_000
  fund_fee               = floor(2_500_000 *  40_000 / 1_000_000)       = 100_000
  lp_fee                 = 2_500_000 − 300_000 − 100_000                 = 2_100_000
creator_fee              = 0                                              // devre dışı

amount_in_after_trade_fee = 1_000_000_000 − 2_500_000                    = 997_500_000

amount_out = y − (x * y) / (x + Δx_net)
           = 2_000_000_000_000
             − (1_000_000_000_000 * 2_000_000_000_000)
               / (1_000_000_000_000 + 997_500_000)
           = 1_993_011_971

new_vault0_raw   = x + amount_in                                        = 1_001_000_000_000
new_vault1       = y − amount_out                                       = 1_998_006_988_029

// Vault0'da alınan 1_000_000_000'den 400_000'i "tahakkuk ücreti"
// (protokol + fon) eğrinin hariç tutması gereken:
curve_x          = new_vault0_raw − (protocol_fees_token0 + fund_fees_token0)
                 = 1_001_000_000_000 − 400_000
                 = 1_000_999_600_000

k' = curve_x * new_vault1 ≈ 2.000_004_196_E24  ≥  k = 2.0E24   ✓
```

Aynı havuzun `enable_creator_fee = true` olması ve giriş tarafında `creator_fee_rate = 1000` (%0,10) olması durumunda, program `total_input_fee = ceil(1_000_000_000 * 3500 / 1_000_000) = 3_500_000` ücretlendirir, sonra bunu `creator_fee = 1_000_000` ve `trade_fee = 2_500_000` olarak böler. `trade_fee` üzerindeki protokol/fon/LP aritmetiği yukarıdaki örnekten değişmez — yaratıcı ücreti kendi pakettidir, `creator_fees_token0`'a tahakkuk eder ve protokol ve fon paketleriyle birlikte `curve_x`'ten hariç tutulur.

Giriş mint'inin %1 Token-2022 transfer ücreti varsa, kasa `1_000_000_000` yerine `990_000_000` token alır ve sonraki her hesaplama bu net tutarı kullanır.

## Gözlem güncelleme kuralı

Her swapda, program yeni bir gözlemi halka tamponuna itip itmeyeceğini değerlendirir:

```
let since_last = now − observations[head].block_timestamp;
if since_last >= MIN_OBSERVATION_INTERVAL {
    let price0 = (vault1 << 32) / vault0;            // Q32.32-ish
    let price1 = (vault0 << 32) / vault1;
    let head' = (head + 1) % OBSERVATION_NUM;
    observations[head'] = Observation {
        block_timestamp: now,
        cumulative_token0_price_x32:
            observations[head].cumulative_token0_price_x32 + price0 * since_last,
        cumulative_token1_price_x32:
            observations[head].cumulative_token1_price_x32 + price1 * since_last,
    };
    head = head';
}
```

İki özellik:

* **Kümülatif fiyat, spot fiyat değil.** Tek bir gözlem bir fiyat değildir. `t0` zamanından `t1` zamanına TWAP almak için, her ucuna en yakın gözlemleri okuyun ve `(cumulative(t1) − cumulative(t0)) / (t1 − t0)` hesaplayın.
* **Örnekler hız sınırlıdır.** Aynı slotta arka arkaya swaplar bir gözlemi paylaşabilir. Bir swaptan hemen sonra bir gözlem okumak bu nedenle bir slot kadar eski görünebilir — bu normaldir.

Daha fazlası [`products/clmm/accounts`](/tr/products/clmm/accounts) bölümünde.

## Eğri üzerindeki ücretler

Bu ince kısım ve çağrı yapmaya değer. Eğri aritmetiği **net** kasa bakiyeleri karşısında çalışır — yani ham SPL bakiyesi eksi tahakkuk eden protokol, fon ve yaratıcı ücretleri (üçü de bağımsız paketlerdir — bkz. [`products/cpmm/fees`](/tr/products/cpmm/fees)). Somut bir resim:

```
raw_vault_balance   = bir RPC getTokenAccountBalance'in döndürdüğü
accrued_fees        = protocol_fees_token{0,1} + fund_fees_token{0,1} + creator_fees_token{0,1}
curve_balance       = raw_vault_balance − accrued_fees
invariant           = curve_balance0 * curve_balance1
```

Entegratörler için sonuçlar:

* **Ham bakiyelerden teklif vermeyin.** Önce tahakkuk eden ücret alanlarını çıkarın veya `SwapBaseInput`'u simülasyon olarak çağırın ve dönüşünü alın.
* **`CollectProtocolFee` tokenları kasadan çıkarır.** Toplama sonrasında `raw_vault_balance` düşer ancak `curve_balance` değişmez; havuzun fiyatı hareket etmez. Bu kasıtlıdır.

## Kesinlik ve taşma

* Tüm eğri aritmetiği `x * y` üzerinde taşmayı önlemek için `u128` ara değerlerini kullanır.
* Bölme sıfıra doğru yuvarlanır, ancak `SwapBaseOutput`'un `Δx_net` yukarı yuvarlanır ve ücret hesaplaması `trade_fee` üzerinde yukarı ve alt bölünmelerde aşağı yuvarlanır. Bu yuvarlama yönleri, değişmezin tamsayı kesintisi nedeniyle asla azalmaması için seçilir.
* Aşırı kasa oranlarına sahip havuzlar (milyarlar : 1) küçük işlemlerde kesinlik tabanlarına çarpabilir; program bu durumda `ZeroTradingTokens` döndürür. Bkz. [`reference/error-codes`](/tr/reference/error-codes).

## Sonraki adım

* [`products/cpmm/fees`](/tr/products/cpmm/fees) — tam ücret katmanı ve toplama semantiği.
* [`products/cpmm/instructions`](/tr/products/cpmm/instructions) — bu matematiği çağıran talimatlar.
* [`algorithms/constant-product`](/tr/algorithms/constant-product) — AMM v4 ve CPMM'de paylaşılan `x · y = k` türetimi ve kenar durumları.

Kaynaklar:

* [`raydium-io/raydium-cp-swap` — `states/curve.rs` içinde swap matematiği](https://github.com/raydium-io/raydium-cp-swap)
* [`security/audits`](/tr/security/audits) bölümünde bağlantılı Raydium denetim raporları


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.