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

# 路由数学

> 路由器不自己执行定价逻辑，每个跳转委托给其池程序的曲线。多跳滑点复合叠加；CLMM 跳转使用 limit_prices。

<Info>
  **本页内容由 AI 自动翻译，所有内容以英文版本为准。**

  [查看英文版 →](/products/routing/math)
</Info>

## 路由器不执行数学运算

路由程序**不实现任何定价逻辑**。它纯粹是一个编排器：接受一条路由，将账户传递给子程序，并链接代币流。

每个跳转从其自己的池程序曲线进行定价：

* **AMM v4 跳转**：使用常数乘积公式（`x · y = k`）加上 OpenBook 混合定价。参见 [`products/amm-v4/math`](/zh/products/amm-v4/math)。
* **CPMM 跳转**：使用常数乘积公式，支持可配置的费用分层。参见 [`products/cpmm/math`](/zh/products/cpmm/math)。
* **CLMM 跳转**：使用集中流动性 tick 数学。参见 [`algorithms/clmm-math`](/zh/algorithms/clmm-math)。
* **稳定币池跳转**：为类似资产使用稳定交换曲线。参见 [`products/stable/math`](/zh/products/stable/math)。

路由器的唯一作用是：

1. 通过 CPI 调用每个池的交换指令。
2. 收集输出数量。
3. 将其作为输入数量传递给下一个跳转。
4. 根据调用者的滑点限制检查最终输出。

## 滑点复合叠加

在多跳路由中，每个跳转的滑点会复合叠加。跳转 1 的小滑点在跳转 2 中变成更大的滑点，因为流入跳转 2 的量已经减少。

**示例：**

```
路由: USDC → SOL → STEP

池 1 (USDC / SOL):
  输入: 1000 USDC
  滑点: 1% (现货价会给 0.5 SOL，但你得到 0.495 SOL)
  输出: 0.495 SOL

池 2 (SOL / STEP):
  输入: 0.495 SOL (已经减少)
  滑点: 1% (现货价会给 495 STEP，但你得到 490 STEP)
  输出: 490 STEP

USDC → STEP 总有效滑点: 1.99%，而不是 1% + 1% = 2%。
```

当你提供 `minimum_amount_out` 时，路由器会根据此全局限制检查你的最终输出。每个跳转也会针对其本地费用结构检查自己的交换，但路由器不会在中途重新报价——你必须提前计算路由并加入足够的滑点容差。

## CLMM 跳转和 limit\_prices

对于进入 CLMM 池的每个跳转，路由器检查池的当前 `sqrt_price_x64` 是否在指定边界内。边界以称为 `limit_prices` 的 `VecDeque<u128>` 传递：

* 路由中每个 CLMM 跳转一个 `sqrt_price_x64`。
* `sqrt_price_x64` 是 CLMM 使用的基于 tick 的价格表示。参见 [`algorithms/clmm-math`](/zh/algorithms/clmm-math) 了解定义。
* 路由器强制执行：

```
  sqrt_price_lower <= pool.sqrt_price_x64 <= sqrt_price_upper
```

对于每个 CLMM 跳转，如果价格超出边界，则拒绝交换。

### 指令变体和 limit\_prices

* **`SwapBaseInWithUserAccount`, `SwapBaseOutWithUserAccount` (传统，标签 0 和 1)**：`limit_prices` VecDeque **必需**。如果任何跳转是 CLMM 池，空队列会被拒绝并返回错误。你必须为每个 CLMM 跳转按顺序提供一个价格。

* **`SwapBaseIn`, `SwapBaseOut` (当前，标签 8 和 9)**：`limit_prices` VecDeque **可选**。空队列被静默忽略；不执行价格检查。新代码应使用这些指令。

### 构建 limit\_prices

对于有 M 个 CLMM 跳转的路由，队列应包含恰好 M 个条目。按跳转顺序排列：

```
limit_prices = [
  sqrt_price_for_first_clmm_hop,
  sqrt_price_for_second_clmm_hop,
  ...
]
```

### 何时检查 limit\_prices

`sqrt_price_x64` 是池当前价格的快照。随着交换执行，它不断变化。你应该：

1. 从链上获取池的当前状态。
2. 计算可接受的边界（例如，当前价格的 ±0.5%）。
3. 将这些边界编码到 `limit_prices` 中。
4. 在路由指令中包含这些边界。

如果池的价格在交易到达之前超出你的边界，路由器将拒绝它。

## 费用处理

每个池根据其配置收取自己的费用：

* **AMM v4**：0.25%（固定），在 LP、协议和基金之间分配。
* **CPMM**：每个 `AmmConfig` 可配置（默认 0.25%，按分层分配方式不同）。
* **CLMM**：每个池可配置，从输入金额中扣除。
* **稳定币池**：与 AMM v4 相同，0.25% 分配。

路由器**不收取自己的费用**。所有费用处理都委托给每个子池。来自跳转 N 的输出已经扣除了该跳转的费用。

参见各个池的费用文档：

* [`products/amm-v4/fees`](/zh/products/amm-v4/fees)
* [`products/cpmm/fees`](/zh/products/cpmm/fees)
* [`products/clmm/fees`](/zh/products/clmm/fees)（如可用）
* [`products/stable/fees`](/zh/products/stable/fees)（如可用）

## 多跳会计示例

假设你通过两个常数乘积池路由 USDC → SOL → STEP，每个池费率为 0.25%：

```
输入: 1000 USDC
池 1 (USDC/SOL):
  收取费用: ceil(1000 * 0.25%) = 2.5 USDC
  曲线净输入: 997.5 USDC
  曲线输出（滑点前）: 0.5 SOL
  滑点裕度: 假设 1%，你得到 ~0.495 SOL

池 2 (SOL/STEP):
  输入: 0.495 SOL
  收取费用: ceil(0.495 * 0.25%) ≈ 0.001 SOL
  曲线净输入: 0.494 SOL
  曲线输出: ~494 STEP
  滑点裕度: 1%，你得到 ~489 STEP

最终输出: ~489 STEP
```

路由器验证：

```
489 >= minimum_amount_out  // 由调用者指定
```

如果为假，整个路由以原子方式失败。

## 精度考虑

与所有 Solana 程序一样，路由器使用整数算术：

* 所有金额都是 `u64`（lamport 或代币最小单位）。
* 曲线计算在需要时使用 `u128` 中间值以避免溢出。
* 舍入约定取决于子程序。路由器不重新舍入。

如果由于极端价格比率跳转产生零金额（例如，在 1B:1 池上交换 1 lamport），路由器将该零传播到下一个跳转，后者可能将其拒绝为不足。参见各个池的错误代码。

## 后续内容

* [`products/amm-v4/math`](/zh/products/amm-v4/math) — 常数乘积数学。
* [`products/cpmm/math`](/zh/products/cpmm/math) — CPMM 常数乘积与 Token-2022。
* [`algorithms/clmm-math`](/zh/algorithms/clmm-math) — 集中流动性定价。
* [`products/stable/math`](/zh/products/stable/math) — 稳定交换曲线。
* [`products/routing/code-demos`](/zh/products/routing/code-demos) — 路由前报价示例。
