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

# Các lệnh CPMM

> Mọi lệnh trên chương trình CPMM, với các đối số, danh sách tài khoản, điều kiện trước/sau và các lỗi có thể trả về.

<Info>
  **Trang này được dịch tự động bằng AI. Phiên bản tiếng Anh là bản chính thức.**

  [Xem bản tiếng Anh →](/products/cpmm/instructions)
</Info>

<Info>
  Trang này là tài liệu tham khảo lệnh chính thức. Để xem mã thực tế soạn các lệnh này, hãy xem [`products/cpmm/code-demos`](/vi/products/cpmm/code-demos). Để xem ý nghĩa mã lỗi, hãy xem [`reference/error-codes`](/vi/reference/error-codes).

  Nâng cấp chương trình 2026-09 đã xây dựng lại CPMM trên Anchor 1.0.2 / Solana 3.1.10, thêm lệnh quản trị `CollectExcessLamports`, loại bỏ danh sách mint Token-2022 được mã hóa cứng, và thay đổi những gì `CreateAmmConfig` ghi vào `protocol_owner` / `fund_owner`. Không có lệnh nào hướng tới người dùng thay đổi tài khoản, đối số hoặc toán học của nó. Xem [mục nhập nhật ký 2026-09-09](/vi/reference/changelog/2026-09-09-cpmm-anchor-1-and-excess-lamports).
</Info>

<Warning>
  **Cả hai lệnh thu thập phí người tạo đã thay đổi danh sách tài khoản của chúng vào ngày 2026-09-19.** `CollectCreatorFee` nhận thêm `creator_fee_share`; `CollectCreatorFeePermissionless` nhận thêm `amm_config` **và** `creator_fee_share`. Cả hai đều được **nối vào sau `system_program`**, vì vậy mọi tài khoản mà một máy khách hiện có đã truyền đều giữ nguyên chỉ số của nó — nhưng các tài khoản mới là bắt buộc, vì vậy một giao dịch được xây dựng dựa trên bố cục cũ hơn sẽ thiếu tài khoản và bị từ chối với `AccountNotEnoughKeys` (`3005`) của Anchor. Hai lệnh quản trị được thêm — `CreateCreatorFeeShare` và `CloseCreatorFeeShare` — và `UpdateAmmConfig` nhận một `param = 8` mới. Xem [mục nhập nhật ký 2026-09-19](/vi/reference/changelog/2026-09-19-cpmm-creator-fee-protocol-share).
</Warning>

## Tóm tắt lệnh

| Tên phân biệt | Ai ký | Nó làm gì |
| - | - | - |
| `Initialize` | người tạo pool | Tạo một pool CPMM mới từ hai mint và một `AmmConfig`. Không cần phép; bất kỳ ai cũng có thể gọi nó. Mã hóa cứng `enable_creator_fee = false` trên pool mới. Tài khoản `pool_state` có thể là PDA chính tắc hoặc một keypair ngẫu nhiên mới (xem tài khoản Initialize). |
| `InitializeWithPermission` | người trả tiền + người nắm giữ PDA `Permission` | Biến thể có quyền của `Initialize`. Người gọi (`payer`) phải sở hữu một PDA `Permission` được lấy từ khóa công khai của chính họ. Được sử dụng bởi các nền tảng cần tạo pool có cổng (ví dụ: tốt nghiệp LaunchLab). Cho phép người gọi ghim `creator_fee_on` (`BothToken` / `OnlyToken0` / `OnlyToken1`) và buộc `enable_creator_fee = true` trên pool mới. Trường `creator` trên `pool_state` được đặt thành một tài khoản `creator` được truyền riêng biệt, không phải người trả tiền. Tính linh hoạt PDA chính tắc hoặc keypair ngẫu nhiên giống như `Initialize` cho `pool_state`. |
| `Deposit` | LP | Thêm thanh khoản ở cả hai token; nhận token LP. |
| `Withdraw` | LP | Đốt token LP; nhận cả hai token cơ bản theo tỷ lệ. |
| `SwapBaseInput` | người hoán đổi | Hoán đổi đầu vào chính xác (`amount_in` vào, ≥ `minimum_amount_out` ra). |
| `SwapBaseOutput` | người hoán đổi | Hoán đổi đầu ra chính xác (≤ `maximum_amount_in` vào, `amount_out` ra). |
| `CollectProtocolFee` | `protocol_owner` (từ `AmmConfig`) | Quét phí giao thức tích lũy từ các vault. |
| `CollectFundFee` | `fund_owner` (từ `AmmConfig`) | Quét phí quỹ tích lũy từ các vault. |
| `CollectCreatorFee` | `pool_creator` | Quét phí người tạo tích lũy (nếu phí người tạo được bật), trừ đi phần của giao thức, được ghi vào bộ phí giao thức của pool. |
| `CollectCreatorFeePermissionless` | bất kỳ người trả tiền nào | Quét phí người tạo tích lũy đến các tài khoản token chính tắc của `pool_creator`, trừ đi phần chia sẻ giao thức tương tự. Người trả tiền có thể tạo ATA nhận thiếu nhưng không thể chuyển hướng chuyển khoản. |
| `UpdatePoolStatus` | `admin` | Tạm dừng / tiếp tục các hoạt động cụ thể trên pool thông qua bitmask. |
| `UpdateAmmConfig` | `admin` | Thay đổi tỷ lệ phí hoặc chủ sở hữu giao thức/quỹ trên một `AmmConfig`. |
| `CreateAmmConfig` | `admin` | Tạo một tầng phí mới (tài khoản `AmmConfig` mới). |
| `CreatePermissionPda` | `admin` hoặc người tạo PDA quyền được ủy quyền | Mint một PDA `Permission` cho phép một cơ quan cụ thể gọi `InitializeWithPermission`. |
| `ClosePermissionPda` | `admin` hoặc người tạo PDA quyền chuyên dụng | Thu hồi một PDA `Permission` được cấp trước đó. Kể từ nâng cấp 2026-09, cơ quan tạo chuyên dụng cũng có thể đóng một khoản cấp mà nó đã cấp; trước đó chỉ có admin. |
| `CreateSupportMintAssociated` | `admin` hoặc chủ sở hữu mint hỗ trợ chuyên dụng | Đăng ký một mint Token-2022 sẽ không thành công danh sách cho phép tiện ích mở rộng, bằng cách tạo PDA `SupportMintAssociated` của nó. |
| `CloseSupportMintAssociated` | `admin` hoặc chủ sở hữu mint hỗ trợ chuyên dụng | Xóa đăng ký mint. |
| `CollectExcessLamports` | `admin` hoặc ví thu thập lamport chuyên dụng | Quét lamport vượt quá mức tối thiểu miễn phí thuê từ các vault, mint LP và PDA được CPMM kiểm soát. Được thêm vào 2026-09. |
| `CreateCreatorFeeShare` | `admin` hoặc chủ sở hữu chia sẻ phí người tạo chuyên dụng | Đặt chia sẻ giao thức tùy chỉnh của phí người tạo cho một cặp `(creator, amm_config)`, ghi đè `AmmConfig.creator_fee_share_rate`. Được thêm vào 2026-09-19. |
| `CloseCreatorFeeShare` | `admin` hoặc chủ sở hữu chia sẻ phí người tạo chuyên dụng | Xóa ghi đè đó; cặp quay lại mặc định cấu hình. Được thêm vào 2026-09-19. |

Bitmask trạng thái: `status` của mỗi pool là một `u8` trong đó bit 0 = deposit bị vô hiệu hóa, bit 1 = withdraw bị vô hiệu hóa, bit 2 = swap bị vô hiệu hóa (`PoolStatusBitIndex { Deposit, Withdraw, Swap }` trong chương trình). Một bit rõ ràng có nghĩa là hoạt động được phép; một bit được đặt có nghĩa là nó bị tạm dừng. `UpdatePoolStatus` nhận một `u8` thô và ghi đè giá trị hiện có.

Các phần tiếp theo đi qua từng phần chi tiết. Thứ tự tài khoản tuân theo IDL CPMM; SDK và máy khách Rust trong `raydium-cp-swap/programs/cp-swap/src/instructions` khớp với thứ tự này.

## `Initialize`

Tạo một pool CPMM mới.

**Đối số**

```
init_amount_0: u64
init_amount_1: u64
open_time:     u64   // Unix timestamp; hoán đổi bị từ chối trước thời điểm này
```

**Tài khoản** (W = có thể ghi, S = ký)

| # | Tên | W | S | Ghi chú |
| - | - | - | - | - |
| 1 | `creator` | W | S | Trả tiền thuê; được ghi lại là `pool_state.pool_creator`. |
| 2 | `amm_config` | | | Tầng phí được chọn. |
| 3 | `authority` | | | PDA cơ quan toàn cầu CPMM. |
| 4 | `pool_state` | W | S\* | `init`ed ở đây. **Hoặc** PDA chính tắc `["pool", amm_config, token_0_mint, token_1_mint]` **hoặc** một keypair ngẫu nhiên mới — khi không phải PDA chính tắc, chương trình yêu cầu `pool_state` ký (`require_eq!(pool_account_info.is_signer, true)`). Đường dẫn keypair ngẫu nhiên cho phép người tạo tránh các nỗ lực front-running trên PDA chính tắc. Các PDA hạ lưu (`lp_mint`, `vaults`, `observation_state`) được lấy từ `pool_state.key()` dù sao. |
| 5 | `token_0_mint` | | | Được sắp xếp: `token_0_mint < token_1_mint`. |
| 6 | `token_1_mint` | | | |
| 7 | `lp_mint` | W | | `init`ed ở đây. Cơ quan được đặt thành `authority`. |
| 8 | `creator_token_0` | W | | ATA nguồn cho `init_amount_0`. |
| 9 | `creator_token_1` | W | | ATA nguồn cho `init_amount_1`. |
| 10 | `creator_lp_token` | W | | ATA của người tạo trên `lp_mint`. `init` (không phải `init_if_needed`) — nó không được tồn tại, điều mà nó không thể, vì `lp_mint` được tạo trong cùng một lệnh này. |
| 11 | `token_0_vault` | W | | `init`ed ở đây. Sở hữu bởi `authority`. |
| 12 | `token_1_vault` | W | | |
| 13 | `create_pool_fee` | W | | ATA đích cho `create_pool_fee` được trả bởi người tạo. |
| 14 | `observation_state` | W | | `init`ed ở đây. |
| 15 | `token_program` | | | SPL Token (cho mint LP). |
| 16 | `token_0_program` | | | SPL Token hoặc Token-2022. |
| 17 | `token_1_program` | | | SPL Token hoặc Token-2022. |
| 18 | `associated_token_program` | | | |
| 19 | `system_program` | | | |
| 20 | `rent` | | | |

`*` `pool_state` chỉ ký trên đường dẫn keypair ngẫu nhiên; đường dẫn PDA chính tắc chạy mà không cần `pool_state` ký.

**Điều kiện trước**

* Mint được sắp xếp (`token_0_mint < token_1_mint` theo thứ tự byte).
* Không mint nào sử dụng tiện ích mở rộng ngoài danh sách cho phép CPMM (`TransferFeeConfig`, `MetadataPointer`, `TokenMetadata`, `InterestBearingConfig`, `ScaledUiAmount`) — xem [`products/cpmm/accounts`](/vi/products/cpmm/accounts#vaults-and-token-2022). Một mint có PDA `SupportMintAssociated` (seed `[b"support_mint", mint]`) tồn tại sẽ bỏ qua kiểm tra tiện ích mở rộng — **nhưng bạn phải nối PDA đó vào `remaining_accounts`**. Chương trình chỉ quét các tài khoản bạn truyền và không bao giờ tải PDA tự nó, vì vậy dựa vào sổ đăng ký mà không cung cấp tài khoản vẫn thất bại với `NotSupportMint` (`6007`). Thứ tự không quan trọng (khớp theo khóa); truyền một mục cho mỗi mint cần bỏ qua. Sổ đăng ký đó là bỏ qua duy nhất kể từ khi nâng cấp 2026-09 loại bỏ danh sách mint bốn được mã hóa cứng.
* `creator` có ít nhất `init_amount_0` và `init_amount_1` trong các ATA tương ứng.
* `amm_config.disable_create_pool == false`.

**Điều kiện sau**

* `pool_state.lp_supply = sqrt(init_amount_0 * init_amount_1)` — căn bậc hai **đầy đủ**. Người tạo được mint `lp_supply − 100`; 100 đơn vị cơ sở bị khóa được tính trong `lp_supply` nhưng không bao giờ được mint.
* Vì vậy `lp_mint.supply == pool_state.lp_supply − 100` trong suốt vòng đời của pool. Tất cả toán học chia sẻ LP (deposit, withdraw) chia cho `lp_supply`, vì vậy hãy sử dụng trường đó và không thay thế cung cấp trên chuỗi của mint. Hoàn nguyên với `InitLpAmountTooLess` nếu `sqrt(...) < 100`.
* `observation_state` được khởi tạo; `observation_index = 0` và `pool_id = pool_state.key()`.
* Lamport `create_pool_fee` được chuyển từ người tạo đến người nhận và được đồng bộ hóa dưới dạng SOL gốc (nó là một ATA wSOL).
* Bitmask trạng thái của pool là `0` (deposit / withdraw / swap đều được bật).
* `enable_creator_fee = false` và `creator_fee_on = BothToken`. `Initialize` **không** hỗ trợ bật phí người tạo — đường dẫn đó là `InitializeWithPermission`.
* `open_time` được tăng lên `block_timestamp + 1` nếu người gọi truyền một giá trị `<= block_timestamp`. Hoán đổi bị từ chối trước `open_time`; deposit và withdraw hoạt động ngay lập tức.

**Lỗi phổ biến** (danh sách đầy đủ trong [`reference/error-codes`](/vi/reference/error-codes))

* `InvalidInput` — mint không được sắp xếp hoặc mint giống hệt nhau.
* `NotSupportMint` — tiện ích mở rộng Token-2022 bị chặn.
* `ExceededSlippage` — hiếm khi; nếu `init_amount_0/1` dẫn đến zero LP do không khớp số thập phân.

## `Deposit`

Thêm thanh khoản ở cả hai token theo tỷ lệ với pool.

**Đối số**

```
lp_token_amount:   u64   // bao nhiêu token LP để mint cho LP
maximum_token_0:   u64
maximum_token_1:   u64
```

**Tài khoản**

| # | Tên | W | S |
| - | - | - | - |
| 1 | `owner` | | S |
| 2 | `authority` | | |
| 3 | `pool_state` | W | |
| 4 | `owner_lp_token` | W | |
| 5 | `token_0_account` | W | |
| 6 | `token_1_account` | W | |
| 7 | `token_0_vault` | W | |
| 8 | `token_1_vault` | W | |
| 9 | `token_program` | | |
| 10 | `token_program_2022` | | |
| 11 | `vault_0_mint` | | |
| 12 | `vault_1_mint` | | |
| 13 | `lp_mint` | W | |

**Toán học**

```
total_0 = vault_0 − protocol_fees_0 − fund_fees_0 − creator_fees_0    // tương tự cho side 1

needed_token_0 = ceil(lp_token_amount * total_0 / lp_supply)
transfer_0     = needed_token_0 + inverse_transfer_fee(needed_token_0) // Token-2022
require(transfer_0 <= maximum_token_0, "ExceededSlippage")             // tương tự cho side 1
```

Hai chi tiết đáng lưu ý: cơ sở tỷ lệ là tổng vault **không bao gồm phí** (`vault_amount_without_fee`, tức là số dư thô trừ đi các bộ đếm giao thức, quỹ và người tạo tích lũy), không phải số dư vault thô; và giới hạn slippage được kiểm tra so với những gì người trả tiền thực sự chuyển, *sau* khi phí chuyển Token-2022 được thêm vào, không phải so với chuyển động vault brutto.

Không thay đổi tỷ lệ `k` — cả hai tổng và `lp_supply` được chia tỷ lệ theo cùng một hệ số.

**Điều kiện sau**

* `lp_supply += lp_token_amount`.
* `vault_0 += needed_token_0` (trừ bất kỳ phí chuyển Token-2022 nào trên đầu vào).
* `vault_1 += needed_token_1` (trừ bất kỳ phí chuyển Token-2022 nào trên đầu vào).

**Lỗi phổ biến** — `ExceededSlippage`, `ZeroTradingTokens`, `InvalidStatus` nếu deposit bị tạm dừng.

## `Withdraw`

Đốt token LP và nhận cả hai token cơ bản theo tỷ lệ.

**Đối số**

```
lp_token_amount:   u64
minimum_token_0:   u64
minimum_token_1:   u64
```

**Tài khoản**

| # | Tên | W | S |
| - | - | - | - |
| 1 | `owner` | | S |
| 2 | `authority` | | |
| 3 | `pool_state` | W | |
| 4 | `owner_lp_token` | W | |
| 5 | `token_0_account` | W | |
| 6 | `token_1_account` | W | |
| 7 | `token_0_vault` | W | |
| 8 | `token_1_vault` | W | |
| 9 | `token_program` | | |
| 10 | `token_program_2022` | | |
| 11 | `vault_0_mint` | | |
| 12 | `vault_1_mint` | | |
| 13 | `lp_mint` | W | |
| 14 | `memo_program` | | |

13 tài khoản đầu tiên giống hệt như `Deposit`, và `lp_mint` có thể ghi được vì token LP được đốt. `Withdraw` thêm một tài khoản thứ 14, `memo_program` (bị ràng buộc `address = memo::ID`) — `Deposit` không. Một `Withdraw` 13 tài khoản không thành công giải mã Anchor, vì vậy LP không thể thoát.

**Toán học**

```
total_0 = vault_0 − protocol_fees_0 − fund_fees_0 − creator_fees_0    // tương tự cho side 1

out_token_0     = min(total_0, floor(lp_token_amount * total_0 / lp_supply))
receive_token_0 = out_token_0 − transfer_fee(out_token_0)             // Token-2022
require(receive_token_0 >= minimum_token_0, "ExceededSlippage")       // tương tự cho side 1

// Như với Deposit: cơ sở là tổng vault không bao gồm phí, và sàn được
// kiểm tra so với những gì LP thực sự nhận được, sau khi phí chuyển.
```

**Điều kiện sau**

* `lp_supply -= lp_token_amount`.
* Vault gửi `out_token_0` / `out_token_1` (brutto; người dùng nhận trừ bất kỳ phí chuyển Token-2022 nào).

## `SwapBaseInput`

Hoán đổi đầu vào chính xác.

**Đối số**

```
amount_in:            u64
minimum_amount_out:   u64
```

**Tài khoản**

| # | Tên | W | S |
| - | - | - | - |
| 1 | `payer` | | S |
| 2 | `authority` | | |
| 3 | `amm_config` | | |
| 4 | `pool_state` | W | |
| 5 | `input_token_account` | W | |
| 6 | `output_token_account` | W | |
| 7 | `input_vault` | W | |
| 8 | `output_vault` | W | |
| 9 | `input_token_program` | | |
| 10 | `output_token_program` | | |
| 11 | `input_token_mint` | | |
| 12 | `output_token_mint` | | |
| 13 | `observation_state` | W | |

Thứ tự **đầu vào → đầu ra** là theo hướng của người dùng, không phải theo `token_0 / token_1` chính tắc của pool. Chương trình tìm ra vault nào là nào bằng cách khớp mint.

**Toán học** — xem [`products/cpmm/math`](/vi/products/cpmm/math).

**Điều kiện trước**

* `open_time <= now`.
* `pool_status` cho phép hoán đổi.
* Không mint nào bị tạm dừng hoặc đóng băng cho cơ quan này.
* `amount_in > 0`.

**Lỗi phổ biến**

* `ExceededSlippage` — `amount_out < minimum_amount_out`.
* `ZeroTradingTokens` — giao dịch làm tròn thành không.
* `NotApproved` — pool bị tạm dừng cho hoán đổi thông qua `UpdatePoolStatus`.
* `InvalidInput` — mint không khớp với bất kỳ mint vault nào của pool.

## `SwapBaseOutput`

Hoán đổi đầu ra chính xác.

**Đối số**

```
max_amount_in:  u64
amount_out:     u64
```

**Tài khoản** — giống như `SwapBaseInput`.

**Toán học** — đường cong nghịch đảo với trần, xem [`products/cpmm/math`](/vi/products/cpmm/math).

**Lỗi phổ biến** — `ExceededSlippage` (`gross_in > max_amount_in`), `ZeroTradingTokens`, `InvalidInput`, `NotApproved`.

## `CollectProtocolFee`

Quét phí giao thức tích lũy từ các vault đến đích giao thức.

**Đối số** — không có.

**Tài khoản**

| # | Tên | W | S | Ghi chú |
| - | - | - | - | - |
| 1 | `owner` | | S | Phải bằng `amm_config.protocol_owner` **hoặc** khóa admin được mã hóa cứng của chương trình. |
| 2 | `authority` | | | |
| 3 | `pool_state` | W | | |
| 4 | `amm_config` | | | |
| 5 | `token_0_vault` | W | | |
| 6 | `token_1_vault` | W | | |
| 7 | `vault_0_mint` | | | |
| 8 | `vault_1_mint` | | | |
| 9 | `recipient_token_0_account` | W | | |
| 10 | `recipient_token_1_account` | W | | |
| 11 | `token_program` | | | |
| 12 | `token_program_2022` | | | |

**Hiệu ứng**

```
transfer pool_state.protocol_fees_token0 from vault_0 to recipient_0
transfer pool_state.protocol_fees_token1 from vault_1 to recipient_1
pool_state.protocol_fees_token0 = 0
pool_state.protocol_fees_token1 = 0
```

Không thay đổi số dư hiệu quả của đường cong (phí tích lũy đã bị loại trừ).

**Lỗi phổ biến** — `InvalidOwner` (`6001`) nếu người ký không phải là `amm_config.protocol_owner` cũng không phải là admin chương trình. (Không có `NotApproved` trên đường dẫn này.)

## `CollectFundFee`

Hình dạng giống như `CollectProtocolFee` nhưng được ký bởi `amm_config.fund_owner` — hoặc, một lần nữa, admin chương trình — và đặt lại các bộ đếm `fund_fees_*`. Cùng `InvalidOwner` trên một người ký sai.

## `CollectCreatorFee`

Được ký bởi `pool_state.pool_creator`. Nó giải quyết phí người tạo tích lũy và chuyển phần của người tạo đến các tài khoản token của người tạo.

**Đối số** — không có.

**Tài khoản**

| # | Tên | W | S | Ghi chú |
| - | - | - | - | - |
| 1 | `creator` | W | S | Bị ràng buộc `address = pool_state.pool_creator`. |
| 2 | `authority` | | | PDA cơ quan vault toàn cầu CPMM. |
| 3 | `pool_state` | W | | Giữ các bộ đếm phí người tạo tích lũy. |
| 4 | `amm_config` | | | Bị ràng buộc `address = pool_state.amm_config`. Mang `creator_fee_share_rate` mặc định. |
| 5 | `token_0_vault` | W | | Phải khớp với vault token 0 của pool. |
| 6 | `token_1_vault` | W | | Phải khớp với vault token 1 của pool. |
| 7 | `vault_0_mint` | | | Phải khớp với `token_0_vault.mint`. |
| 8 | `vault_1_mint` | | | Phải khớp với `token_1_vault.mint`. |
| 9 | `creator_token_0` | W | | Đích cho phần token 0 của người tạo. |
| 10 | `creator_token_1` | W | | Đích cho phần token 1 của người tạo. |
| 11 | `token_0_program` | | | SPL Token hoặc Token-2022, khớp với token 0. |
| 12 | `token_1_program` | | | SPL Token hoặc Token-2022, khớp với token 1. |
| 13 | `associated_token_program` | | | |
| 14 | `system_program` | | | |
| 15 | `creator_fee_share` | | | **Được thêm vào 2026-09-19**, được nối vào sau `system_program`. PDA tại `["creator_fee_share", creator, amm_config]`. Phải được truyền trên mỗi lệnh gọi, nhưng **không bắt buộc phải tồn tại** — khi nó trống hoặc không được sở hữu bởi CPMM, chương trình quay lại `amm_config.creator_fee_share_rate`. Ràng buộc seed vẫn áp dụng, vì vậy địa chỉ phải là PDA chính tắc. |

**Hiệu ứng**

```
share_rate = creator_fee_share.share_rate   (nếu tài khoản tồn tại)
           | amm_config.creator_fee_share_rate   (nếu không)

shared_i  = floor(creator_fees_token_i * share_rate / 1_000_000)
creator_i = creator_fees_token_i - shared_i

transfer creator_i from vault_i to creator_token_i
pool_state.protocol_fees_token_i += shared_i     // ở lại trong vault
pool_state.creator_fees_token_i   = 0
pool_state.recent_epoch = current epoch
```

Phần của giao thức không bao giờ rời khỏi vault ở đây — nó được dán nhãn lại là phí giao thức và chờ `CollectProtocolFee`. Cả hai bộ đếm đã bị loại trừ khỏi chế độ xem đường cong của vault, vì vậy giá của pool không di chuyển. Dẫn xuất đầy đủ trong [`products/cpmm/fees`](/vi/products/cpmm/fees#protocol-share-of-the-creator-fee).

**Lỗi phổ biến** — `NoFeeCollect` khi cả hai bộ đếm người tạo đều bằng không (được kiểm tra trước khi chia), `InvalidInput` (`6003`) nếu `share_rate` được giải quyết vượt quá `1_000_000`, `MathOverflow` (`6011`) nếu đặt phần sẻ sẽ tràn `protocol_fees_token_*`, và lỗi `ConstraintSeeds` của Anchor nếu `creator_fee_share` không phải là PDA chính tắc.

## `CollectCreatorFeePermissionless`

Bất kỳ ai cũng có thể kích hoạt thu thập phí người tạo. Lệnh luôn gửi phần của người tạo đến các tài khoản token liên kết chính tắc được sở hữu bởi `pool_state.pool_creator`; người gọi không thể chọn người tạo hoặc đích khác. Nếu bất kỳ ATA nào bị thiếu, người trả tiền sẽ tài trợ cho việc tạo của nó.

`CollectCreatorFee` gốc vẫn có thể gọi được, vì vậy một người tạo muốn ký cho bộ sưu tập của riêng họ vẫn có thể.

**Đối số** — không có.

**Tài khoản**

| # | Tên | W | S | Ghi chú |
| - | - | - | - | - |
| 1 | `payer` | W | S | Bất kỳ người ký nào; tài trợ cho ATA người tạo bị thiếu. |
| 2 | `creator` | | | Phải bằng `pool_state.pool_creator`; không ký. |
| 3 | `authority` | | | PDA cơ quan vault toàn cầu CPMM. |
| 4 | `pool_state` | W | | Giữ các bộ đếm phí người tạo tích lũy. |
| 5 | `token_0_vault` | W | | Phải khớp với vault token 0 của pool. |
| 6 | `token_1_vault` | W | | Phải khớp với vault token 1 của pool. |
| 7 | `vault_0_mint` | | | Phải khớp với `token_0_vault.mint`. |
| 8 | `vault_1_mint` | | | Phải khớp với `token_1_vault.mint`. |
| 9 | `creator_token_0` | W | | ATA chính tắc của người tạo cho `vault_0_mint`; được tạo nếu bị thiếu. |
| 10 | `creator_token_1` | W | | ATA chính tắc của người tạo cho `vault_1_mint`; được tạo nếu bị thiếu. |
| 11 | `token_0_program` | | | SPL Token hoặc Token-2022, khớp với token 0. |
| 12 | `token_1_program` | | | SPL Token hoặc Token-2022, khớp với token 1. |
| 13 | `associated_token_program` | | | Tạo một ATA nhận thiếu. |
| 14 | `system_program` | | | Tài trợ cho việc tạo tài khoản từ `payer`. |
| 15 | `amm_config` | | | **Được thêm vào 2026-09-19**, được nối vào sau `system_program`. Bị ràng buộc `address = pool_state.amm_config`. |
| 16 | `creator_fee_share` | | | **Được thêm vào 2026-09-19**, được nối vào cuối cùng. Cùng PDA và cùng quy tắc tồn tại tùy chọn như trên `CollectCreatorFee`. |

<Warning>
  Hai tài khoản mới được **nối vào sau `system_program`**, chứ không phải được chèn vào. Mọi tài khoản từ `payer` đến `system_program` đều giữ nguyên vị trí mà nó có trước khi nâng cấp, vì vậy đây là một sự phá vỡ sạch sẽ: một giao dịch được xây dựng dựa trên bố cục mười bốn tài khoản trước khi nâng cấp không sai lệch một vault thành một tài khoản cấu hình — nó chỉ đơn giản là truyền quá ít tài khoản và Anchor từ chối nó với `AccountNotEnoughKeys` (`3005`) trước khi bất kỳ ràng buộc nào chạy. Các tài khoản vẫn là bắt buộc, vì vậy hãy nối cả hai và làm mới IDL; không có đường dẫn tương thích nào cho bố cục cũ.
</Warning>

**Hiệu ứng** — giống hệt như `CollectCreatorFee` ở trên: phần chia sẻ được giải quyết từ `creator_fee_share` hoặc `amm_config`, phần của giao thức được ghi vào `protocol_fees_token_{0,1}`, phần của người tạo được chuyển đến ATA người tạo, cả hai bộ đếm người tạo được đặt lại thành không, và `recent_epoch` được cập nhật. Trả về `NoFeeCollect` khi cả hai bộ đếm đều bằng không.

## `UpdatePoolStatus`

Tạm dừng hoặc tiếp tục các hoạt động riêng lẻ trên một pool. Trường `status` là một bitmask:

| Bit | Cờ | Hiệu ứng khi được đặt |
| - | - | - |
| 0 | `DEPOSIT_DISABLED` | `Deposit` từ chối với `NotApproved`. |
| 1 | `WITHDRAW_DISABLED` | `Withdraw` từ chối. |
| 2 | `SWAP_DISABLED` | `SwapBaseInput` / `SwapBaseOutput` từ chối. |

**Đối số**

```
status: u8      // bitmask mới
```

**Tài khoản**

| # | Tên | W | S | Ghi chú |
| - | - | - | - | - |
| 1 | `authority` | | S | Phải khớp với khóa admin trên chương trình CPMM. |
| 2 | `pool_state` | W | | |

Khóa admin là một pubkey **được biên dịch vào chương trình** (`crate::admin::ID`), không phải cơ quan nâng cấp BPF — thay đổi nó yêu cầu nâng cấp chương trình. Xem [`reference/program-addresses`](/vi/reference/program-addresses) để biết giá trị và [`security/admin-and-multisig`](/vi/security/admin-and-multisig) để biết ai nắm giữ nó.

## `CreateAmmConfig`

Tạo một tầng phí mới.

**Đối số**

```
index:             u16
trade_fee_rate:    u64
protocol_fee_rate: u64
fund_fee_rate:     u64
create_pool_fee:   u64
creator_fee_rate:  u64
```

**Tài khoản**

| # | Tên | W | S | Ghi chú |
| - | - | - | - | - |
| 1 | `owner` | W | S | Admin. |
| 2 | `amm_config` | W | | `init`ed ở đây. |
| 3 | `system_program` | | | |

**Điều kiện trước**

* Không có `AmmConfig` hiện có với cùng `index`.
* `protocol_fee_rate + fund_fee_rate <= FEE_RATE_DENOMINATOR_VALUE`.

<Note>
  **Thay đổi vào 2026-09: chủ sở hữu phí cấu hình mới không còn đến từ người ký.** `create_amm_config` bây giờ ghi `protocol_fee_owner::ID` được mã hóa cứng của chương trình vào `protocol_owner` và `fund_fee_owner::ID` vào `fund_owner`, thay vì sao chép khóa người ký admin vào cả hai. Địa chỉ nằm trong [`reference/program-addresses`](/vi/reference/program-addresses#cpmm-fee-owner-wallets).

  Hậu quả: phí trên một `AmmConfig` mới được tạo sẽ hạ cánh trong các ví phí chuyên dụng thay vì của admin. Admin vẫn là một người ký *được chấp nhận* để thu thập — `CollectProtocolFee` / `CollectFundFee` chấp nhận `amm_config.protocol_owner` / `fund_owner` **hoặc** `crate::admin::ID` — vì vậy không có gì phải xoay để quét; những gì đã thay đổi chỉ là nơi các khoản tiền đi theo mặc định. **Các tài khoản `AmmConfig` hiện có không được viết lại** — bất kỳ điều gì được lưu trữ trên chúng vẫn chi phối, vì vậy luôn đọc `protocol_owner` / `fund_owner` từ tài khoản thay vì giả định bất kỳ giá trị nào. Các tham số `UpdateAmmConfig` `3` và `4` vẫn xoay chúng.
</Note>

## `UpdateAmmConfig`

Thay đổi tỷ lệ phí hoặc quyền sở hữu trên một `AmmConfig` hiện có. Nhận một `param: u8` (trường nào để cập nhật) và một `value: u64`. Bảng điều phối đầy đủ:

* `param = 0` → `trade_fee_rate` (khẳng định `trade_fee_rate + creator_fee_rate < 1_000_000`)
* `param = 1` → `protocol_fee_rate` (khẳng định `≤ 1_000_000` và `+ fund_fee_rate ≤ 1_000_000`)
* `param = 2` → `fund_fee_rate` (khẳng định `≤ 1_000_000` và `+ protocol_fee_rate ≤ 1_000_000`)
* `param = 3` → `protocol_owner`. Khóa mới **không** nằm trong `value`: nối nó dưới dạng `remaining_accounts[0]` (chỉ đọc là được). Nó không được là pubkey mặc định, và bỏ qua tài khoản sẽ hoảng sợ trên một `unwrap()`.
* `param = 4` → `fund_owner`. Cơ chế giống như `3`.
* `param = 5` → `create_pool_fee`
* `param = 6` → `disable_create_pool` (bất kỳ `value` khác không nào sẽ vô hiệu hóa)
* `param = 7` → `creator_fee_rate` (khẳng định `creator_fee_rate + trade_fee_rate < 1_000_000`)
* `param = 8` → `creator_fee_share_rate` (khẳng định `≤ 1_000_000`). Được thêm vào 2026-09-19. Phần chia sẻ mặc định của giao thức **của phí người tạo** trên tầng này; xem [`products/cpmm/fees`](/vi/products/cpmm/fees#protocol-share-of-the-creator-fee). Nó không liên quan đến `protocol_fee_rate`, chia phí giao dịch.

Bất kỳ `param` nào khác sẽ trả về `InvalidInput`.

Các thay đổi được ký bởi admin và ảnh hưởng đến **mọi pool được ràng buộc với `AmmConfig` này** trên hoán đổi tiếp theo. Không có di chuyển; các pool chỉ đơn giản đọc các giá trị mới.

## `CreateCreatorFeeShare`

Đặt chia sẻ giao thức tùy chỉnh của phí người tạo cho một cặp `(creator, amm_config)`, ghi đè `AmmConfig.creator_fee_share_rate` cho mọi pool mà người tạo đó sở hữu trên tầng phí đó. Được thêm vào nâng cấp chia sẻ phí người tạo 2026-09-19.

**Đối số**

```
share_rate: u64   // chia sẻ của giao thức CỦA phí người tạo, trên FEE_RATE_DENOMINATOR = 1_000_000
```

**Tài khoản**

| # | Tên | W | S | Ghi chú |
| - | - | - | - | - |
| 1 | `owner` | W | S | Phải là admin chương trình CPMM **hoặc** chủ sở hữu chia sẻ phí người tạo chuyên dụng — xem [`reference/program-addresses`](/vi/reference/program-addresses#cpmm-creator-fee-share-authority). Bất kỳ người ký nào khác sẽ thất bại với `InvalidOwner` (`6001`). Trả tiền thuê. |
| 2 | `creator` | | | Người tạo pool mà tỷ lệ áp dụng. Không được kiểm tra — nó không phải là người tạo pool hiện có, và nó không ký. |
| 3 | `amm_config` | | | Tầng phí mà tỷ lệ áp dụng. |
| 4 | `creator_fee_share` | W | | `init`ed ở đây tại `["creator_fee_share", creator, amm_config]`, `space = 145`. |
| 5 | `system_program` | | | |

**Điều kiện trước**

* `share_rate <= 1_000_000`, nếu không `InvalidInput` (`6003`).
* PDA không được tồn tại — `init` của Anchor thất bại trên lệnh gọi thứ hai cho cùng một cặp. Để thay đổi tỷ lệ, hãy đóng tài khoản và tạo lại nó.

**Điều kiện sau**

* `creator_fee_share` lưu trữ `bump`, `creator`, `amm_config` và `share_rate`.
* Mọi `CollectCreatorFee` / `CollectCreatorFeePermissionless` tiếp theo trên một pool được tạo bởi `creator` dưới `amm_config` sẽ giải quyết chia sẻ từ tài khoản này thay vì cấu hình.

<Note>
  Người tạo pool không phải là bên tham gia lệnh này và không ký nó. Tỷ lệ được đọc tại thời điểm thu thập, vì vậy một ghi đè được tạo sau khi phí đã tích lũy sẽ áp dụng cho số dư tích lũy đó.
</Note>

## `CloseCreatorFeeShare`

Xóa ghi đè. Cặp quay lại `AmmConfig.creator_fee_share_rate`.

**Đối số** — không có.

**Tài khoản**

| # | Tên | W | S | Ghi chú |
| - | - | - | - | - |
| 1 | `owner` | W | S | Cùng hai người ký được chấp nhận như `CreateCreatorFeeShare`; nhận tiền thuê. |
| 2 | `creator` | | | Người tạo pool mà tỷ lệ áp dụng. |
| 3 | `amm_config` | | | Tầng phí mà tỷ lệ áp dụng. |
| 4 | `creator_fee_share` | W | | Đóng cho `owner`. Phải là PDA chính tắc cho cặp. |
| 5 | `system_program` | | | |

**Điều kiện sau**

* Tài khoản được đóng và lamport của nó đi đến `owner`.
* Bộ sưu tập cho cặp đó giải quyết chia sẻ từ `amm_config.creator_fee_share_rate` một lần nữa — đó là `0` trừ khi admin đã đặt `UpdateAmmConfig` param `8`.

## `CollectExcessLamports`

Quét admin của lamport ngồi trên mức tối thiểu miễn phí thuê trên các tài khoản CPMM kiểm soát. Được thêm vào nâng cấp 2026-09 để giao thức có thể lấy lại quá mức tài trợ mà [SIMD-0437 rent reduction](/vi/solana-fundamentals/rent-and-reclaimable-rent) để lại trên các tài khoản được tạo trước mỗi bước.

Chỉ phần dư di chuyển. Số dư token, dữ liệu tài khoản, chủ sở hữu, trạng thái pool và đường cong không bị ảnh hưởng, và lệnh là không hoạt động so với một tài khoản đã ở mức tối thiểu của nó — vì vậy nó an toàn để chạy lại sau mỗi bước triển khai.

**Đối số** — không có.

**Tài khoản**

| # | Tên | W | S | Ghi chú |
| - | - | - | - | - |
| 1 | `collect_lamports_wallet` | W | S | Đích cho mọi lamport được quét. Phải là admin chương trình CPMM hoặc ví thu thập lamport chuyên dụng — xem [`reference/program-addresses`](/vi/reference/program-addresses#excess-lamports-collection-wallets). Bất kỳ người ký nào khác sẽ thất bại với `InvalidOwner`. |
| 2 | `authority` | | | PDA cơ quan vault-và-LP-mint CPMM tại seed `[b"vault_and_lp_mint_auth_seed"]`. Nó ký các CPI của chương trình token. |
| 3 | `token_program` | | | SPL Token. |
| 4 | `token_program_2022` | | | Token-2022. Cả hai đều được yêu cầu vô điều kiện; chương trình chọn cho mỗi tài khoản nguồn. |
| 5.. | `remaining_accounts` | W | | `M` tài khoản nguồn để quét, bất kỳ số lượng nào, bất kỳ thứ tự nào. |

<Note>
  **Sửa chữa thứ tự, 2026-09-19.** Chương trình bây giờ thực hiện hai lần vượt qua `remaining_accounts` — mọi CPI chương trình token trước, sau đó là các khoản nợ trực tiếp của các PDA được CPMM kiểm soát. Xen kẽ chúng đã hủy bỏ với `UnbalancedInstruction` của runtime ("tổng số dư tài khoản trước và sau lệnh không khớp") bất cứ khi nào một PDA được nợ trước một CPI, vì các thay đổi lamport đang chờ xử lý của người gọi chỉ được xóa vào các tài khoản mà CPI thực sự mang theo. Người gọi không phải tự nhóm hoặc sắp xếp danh sách.
</Note>

**Cách xử lý mỗi tài khoản nguồn**

Chương trình điều phối trên `owner` của tài khoản nguồn:

| Chủ sở hữu tài khoản nguồn | Xử lý |
| - | - |
| SPL Token hoặc Token-2022, tài khoản token không gốc hoặc mint — vault pool và mint LP | CPI `WithdrawExcessLamports` (phân biệt chương trình token `38`), được ký bởi `authority`. |
| SPL Token hoặc Token-2022, **gốc** (wSOL) tài khoản token | `WithdrawExcessLamports` từ chối các tài khoản gốc. Chương trình CPI `SyncNative`, đo lường bao nhiêu `amount` được bao bọc tăng lên, `UnwrapLamports` (phân biệt `45`) cho chính xác delta đó, sau đó yêu cầu số dư được bao bọc bằng giá trị trước đồng bộ hóa của nó — nếu không `LamportsCalculateError` (`6015`). Một vault pool phía SOL do đó giữ lại toàn bộ thanh khoản của nó. |
| Chương trình CPMM tự nó — `PoolState`, `AmmConfig`, `ObservationState`, `Permission`, `SupportMintAssociated` | Chương trình nợ tài khoản trực tiếp xuống `rent.minimum_balance(data_len)`. |
| Bất cứ điều gì khác | **Bỏ qua im lặng.** Không có lỗi, không có lamport di chuyển. |

Vì nó nhận một danh sách `remaining_accounts` không bị ràng buộc, kích thước giao dịch là giới hạn thực tế — cùng ràng buộc như quét phía ví được mô tả trong [`solana-fundamentals/rent-and-reclaimable-rent`](/vi/solana-fundamentals/rent-and-reclaimable-rent#batching-how-many-fit-in-one-transaction).

**Lỗi phổ biến** — `InvalidOwner` (`6001`, người ký sai), `LamportsCalculateError` (`6015`, vòng wSOL không lưới thành không), và `InsufficientFunds` từ đường dẫn được sở hữu bởi chương trình khi một tài khoản giữ ít hơn mức tối thiểu thuê của chính nó.

**Không có trình xây dựng SDK.** `@raydium-io/raydium-sdk-v2` không vận chuyển một trình xây dựng cho lệnh này, cũng không có kho `raydium-sdk-V2-demo` — nó là một đường dẫn admin. Mã hóa nó bằng tay, theo cách quét phía ví trong [`solana-fundamentals/rent-and-reclaimable-rent`](/vi/solana-fundamentals/rent-and-reclaimable-rent#building-the-instruction) làm cho lệnh chương trình token.

## Ma trận thay đổi trạng thái

| Lệnh | `lp_supply` | Số dư Vault | Trường phí tích lũy | `observation` |
| - | - | - | - | - |
| `Initialize` | + init LP | + `init_amount_{0,1}` | 0 | init |
| `InitializeWithPermission` | + init LP | + `init_amount_{0,1}` | 0 | init |
| `Deposit` | + | + cả hai | — | — |
| `Withdraw` | − | − cả hai | — | — |
| `SwapBaseInput` | — | + vào, − ra | + `trade_fee` chia thành giao thức/quỹ; + `creator_fee` nếu được bật | + (nếu khoảng thời gian đã trôi qua) |
| `SwapBaseOutput` | — | + vào, − ra | + `trade_fee` chia thành giao thức/quỹ; + `creator_fee` nếu được bật | + (nếu khoảng thời gian đã trôi qua) |
| `CollectProtocolFee` | — | − (bằng bộ đếm giao thức) | `protocol_*` → 0 | — |
| `CollectFundFee` | — | − (bằng bộ đếm quỹ) | `fund_*` → 0 | — |
| `CollectCreatorFee` | — | − (chỉ bằng phần của người tạo) | `creator_*` → 0; `protocol_*` += phần được chia | — |
| `CollectCreatorFeePermissionless` | — | − (chỉ bằng phần của người tạo) | `creator_*` → 0; `protocol_*` += phần được chia | — |
| `UpdatePoolStatus` | — | — | — | — |
| `CreateCreatorFeeShare` | — | — | — | — |
| `CloseCreatorFeeShare` | — | — | — | — |
| `CollectExcessLamports` | | | | |


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