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

# LaunchLab 曲線規則

> 平台如何限制創作者可選擇的啟動參數：檢查群組、(欄位、運算子、值) 約束模型，以及九個範本 — 精確分層、價值帶、畢業估值上限、遷移下限、代幣類型閘門和時間限制促銷。

<Info>
  **本頁內容由 AI 自動翻譯，所有內容以英文版本為準。**

  [查看英文版 →](/products/launchlab/curve-rules)
</Info>

<Info>
  **曲線規則**是平台對「我願意託管哪些啟動？」的回答。[`GlobalConfig`](/zh-Hant/products/launchlab/global-config) 設定協議下限 — 至少 10M 供應量、至少 20% 的供應量在曲線上銷售等等 — 這些下限刻意設得很寬鬆，以便每種平台都能符合。曲線規則是你的平台將其縮小到你的產品實際支援的形狀的地方。

  規則存放在自己的 `PlatformCurveRule` 帳戶中，每個 (平台、[`GlobalConfig`](/zh-Hant/products/launchlab/global-config)) 配對一個。它們只能縮小配置已允許的內容；規則永遠無法擴寬協議限制。
</Info>

## 心智模型

三個層級，從外到內：

```
GlobalConfig       協議下限      「供應量 >= 10M、銷售率 >= 20%、...」
  └─ PlatformCurveRule   你的規則     「在我的平台上：這些形狀之一」
       └─ 檢查群組    一個形狀     「供應量 = 1B 且募資在 [80, 90] SOL」
            └─ 約束 一個檢查    「(Supply, Eq, 1_000_000_000)」
```

這兩個層級的嵌套使其具有表達力：

* **一個群組內的約束是 AND 的。** 所有約束都必須成立。
* **一個規則內的群組是 OR 的。** 啟動一旦滿足任何單一群組就被允許。

所以一個群組是一個允許的*形狀*，規則是你提供的形狀菜單。一個規則最多可容納 10 個群組，一個群組最多 25 個約束。

有兩個邊界情況值得記住：

| 狀態              | 含義                    |
| --------------- | --------------------- |
| 沒有規則帳戶，或規則有零個群組 | 平台不限制該配置的啟動參數。        |
| 一個有零個約束的群組      | 該群組匹配每個啟動，所以整個規則允許一切。 |

規則只在 `PlatformConfig.restrict_curve_param` 為 `1` 時生效。在 `0` 時，程式根本不讀取規則，這也是你用來推出規則和回滾規則的開關。

## 約束

約束是一個 `(欄位、運算子、值)` 三元組。沒有其他東西 — 沒有表達式、沒有嵌套。

```rust theme={null}
pub struct ParamConstraint {
    pub field: u8,    // 哪個啟動參數，見下表
    pub op:    u8,    // 0 Eq, 1 Gte (最小值), 2 Lte (最大值), 3 Neq
    pub value: u128,
}
```

**範圍是兩個約束**在同一群組內的同一欄位上：一個 `Gte` 作為下限，一個 `Lte` 作為上限。同一 `(欄位、運算子)` 配對在一個群組內不能出現兩次，這防止你寫出兩個矛盾的最小值。

### 欄位

<Info>
  欄位 ID 是永久的。新欄位只會被追加，所以一旦規則帳戶持有它，ID 的含義就永遠不會改變。
</Info>

| ID | 欄位                       | 單位          | 備註                                                 |
| -- | ------------------------ | ----------- | -------------------------------------------------- |
| 0  | `CurveType`              | 列舉          | 0 常數乘積、1 固定價格、2 線性價格                               |
| 1  | `MigrateType`            | 列舉          | 新啟動必須是 `1` (CPMM) 無論如何                             |
| 2  | `MigrateCpmmFeeOn`       | 列舉          | 0 僅報價、1 兩個代幣                                       |
| 3  | `Supply`                 | 基本單位        | 完整代幣供應量                                            |
| 4  | `TotalSellA`             | 基本單位        | 在曲線上銷售。僅常數乘積配置 — 見 [曲線類型限制](#曲線類型限制)               |
| 5  | `TotalFundRaisingB`      | 報價單位        | 畢業目標                                               |
| 6  | `TotalLockedAmount`      | 基本單位        | 歸屬預算                                               |
| 7  | `CliffPeriod`            | 秒           | 解鎖開始前的等待時間                                         |
| 8  | `UnlockPeriod`           | 秒           | 解鎖持續時間                                             |
| 9  | `BaseTokenProgram`       | 列舉          | 0 SPL Token、1 Token-2022                           |
| 10 | `TransferFeeEnabled`     | 布林值         | 1 當基礎鑄幣帶有 `TransferFeeConfig`                      |
| 11 | `TransferFeeBasisPoints` | 1/10 000    | 沒有擴展時為 0                                           |
| 12 | `TransferFeeMaximumFee`  | 基本單位        | 沒有擴展時為 0                                           |
| 13 | `SellRateA`              | 1/1 000 000 | 衍生：`TotalSellA / Supply`。僅常數乘積                     |
| 14 | `LockRate`               | 1/1 000 000 | 衍生：`TotalLockedAmount / Supply`                    |
| 15 | `MigrateAmountA`         | 基本單位        | 衍生：`Supply − TotalSellA − TotalLockedAmount`。僅常數乘積 |
| 16 | `MigrateRateA`           | 1/1 000 000 | 衍生：`MigrateAmountA / Supply`。僅常數乘積                 |
| 17 | `FundRaisingRateB`       | 1/1 000 000 | 衍生：`TotalFundRaisingB / Supply`                    |
| 18 | `UnixTimestamp`          | 秒           | 啟動的區塊時間                                            |

衍生欄位是使規則可移植的原因。將 `Supply` 和 `TotalFundRaisingB` 固定到精確數字會固定一個啟動形狀；限制 `FundRaisingRateB` 會固定它們之間的*關係*，讓創作者選擇任何保持它的供應量。

<Warning>
  速率欄位只能在一個 `GlobalConfig` 內比較，因為它們的分母取決於該配置的報價鑄幣及其小數位數。這在實踐中不是限制：規則按構造被限定到一個配置。
</Warning>

## 九個範本

下面的每個範本都是一個規則。約束寫成 `(欄位、運算子、值)`。

### 1. 一個標準分層

最簡單的規則，也是已停用的曲線參數白名單提供的精確行為：一個形狀，固定。

| 群組 | 約束                                                                                                |
| -- | ------------------------------------------------------------------------------------------------- |
| 0  | `(Supply, Eq, 1_000_000_000e6)`、`(TotalSellA, Eq, 800_000_000e6)`、`(TotalFundRaisingB, Eq, 85e9)` |

任何在三個中任何一個偏離的啟動都被拒絕，錯誤為 `CurveParamNotMatchPlatformRule`。

### 2. 帶而不是數字

帶存在的原因：創作者選擇你滿意的募資目標，無需你列舉每個值。

| 群組 | 約束                                                                                                 |
| -- | -------------------------------------------------------------------------------------------------- |
| 0  | `(Supply, Eq, 1_000_000_000e6)`、`(TotalFundRaisingB, Gte, 50e9)`、`(TotalFundRaisingB, Lte, 200e9)` |

一個群組、四個約束，創作者有 50–200 SOL 的走廊。在舊白名單下，這需要每個允許值一個條目，十個條目的上限使其不可能。

### 3. 並排的分層

群組是 OR 的，所以每個分層是一個群組。

| 群組 | 約束                                                                 | 分層 |
| -- | ------------------------------------------------------------------ | -- |
| 0  | `(Supply, Eq, 1_000_000_000e6)`、`(TotalFundRaisingB, Eq, 85e9)`    | 標準 |
| 1  | `(Supply, Eq, 100_000_000e6)`、`(TotalFundRaisingB, Eq, 30e9)`      | 小型 |
| 2  | `(Supply, Eq, 10_000_000_000e6)`、`(TotalFundRaisingB, Gte, 500e9)` | 鯨魚 |

順序對計算很重要，對語義不重要：評估在第一個匹配的群組處停止，所以把你最常用的分層放在前面。

### 4. 畢業估值帶

`FundRaisingRateB` 是 `TotalFundRaisingB / Supply` 以百萬分之一計。限制它會限制代幣畢業的豐富程度，無論創作者選擇的供應量如何。

| 群組 | 約束                                                                   |
| -- | -------------------------------------------------------------------- |
| 0  | `(FundRaisingRateB, Gte, 60_000)`、`(FundRaisingRateB, Lte, 120_000)` |

使用 1e12 供應量和 9 位小數報價鑄幣，`85e9 / 1e12 × 1e6 = 85_000` 位於該帶內。創作者若將供應量翻倍，必須大致將目標翻倍以保持在其內 — 這就是重點。兩個約束替代了原本需要的 `(供應量、目標)` 配對表。

### 5. 遷移下限

`MigrateRateA` 是實際進入 CPMM 池的供應量份額，在畢業時：`Supply − TotalSellA − TotalLockedAmount`，除以供應量。它是畢業池的深度，也是唯一在規則出現前沒有平台端等效物的協議旋鈕。

| 群組 | 約束                             |
| -- | ------------------------------ |
| 0  | `(MigrateRateA, Gte, 150_000)` |

至少 15% 的供應量進入池。創作者不能在曲線上銷售 95% 並留下淺薄的帳簿。

<Note>
  如果參數不相加 — 鎖定金額大於曲線銷售後剩餘的 — 衍生值無法計算，約束失敗關閉，所以啟動被拒絕而不是無聲地允許。
</Note>

### 6. 你實際執行的歸屬

`GlobalConfig.max_lock_rate` 從上方限制歸屬。規則可以在其下放置下限，並要求真正的懸崖。

| 群組 | 約束                                                                                   |
| -- | ------------------------------------------------------------------------------------ |
| 0  | `(LockRate, Gte, 50_000)`、`(LockRate, Lte, 200_000)`、`(CliffPeriod, Gte, 2_592_000)` |

供應量的 5% 到 20% 歸屬，至少 30 天的懸崖。對於其宣傳是「無即時解鎖啟動」的平台很有用。

### 7. 代幣類型閘門

`BaseTokenProgram` 和 `TransferFeeEnabled` 是獨立的，這很重要：沒有 `TransferFeeConfig` 的 Token-2022 鑄幣報告 `TransferFeeEnabled = 0`，就像 SPL Token 鑄幣一樣。

| 意圖              | 群組 | 約束                                                        |
| --------------- | -- | --------------------------------------------------------- |
| 僅 SPL Token     | 0  | `(BaseTokenProgram, Eq, 0)`                               |
| 僅 Token-2022    | 0  | `(BaseTokenProgram, Eq, 1)`                               |
| Token-2022，無轉帳費 | 0  | `(BaseTokenProgram, Eq, 1)`、`(TransferFeeEnabled, Eq, 0)` |
| 無轉帳費，任一程式       | 0  | `(TransferFeeEnabled, Eq, 0)`                             |

### 8. 條件轉帳費上限

沒有「if」運算子，也不需要 — 兩個群組表達條件。

| 群組 | 約束                                                                                                       | 讀作                  |
| -- | -------------------------------------------------------------------------------------------------------- | ------------------- |
| 0  | `(TransferFeeEnabled, Eq, 0)`                                                                            | 無轉帳費：可以             |
| 1  | `(TransferFeeEnabled, Eq, 1)`、`(TransferFeeBasisPoints, Lte, 100)`、`(TransferFeeMaximumFee, Gte, 1_000)` | 有費用：最多 1%，且最大費用實際設定 |

零速率 `TransferFeeConfig` 不會通過群組 0：擴展存在，所以 `TransferFeeEnabled` 是 `1`，只有群組 1 可以接受它。

### 9. 時間限制促銷，提前排程

`UnixTimestamp` 是啟動的區塊時間，所以一個群組可以攜帶自己的有效期窗口。你今天寫兩個群組，切換在自己發生。

| 群組 | 約束                                                                     | 窗口             |
| -- | ---------------------------------------------------------------------- | -------------- |
| 0  | `(UnixTimestamp, Lte, 1_767_225_600)`、`(TotalFundRaisingB, Gte, 30e9)` | 促銷期：30 SOL 最小值 |
| 1  | `(UnixTimestamp, Gte, 1_767_225_601)`、`(TotalFundRaisingB, Gte, 80e9)` | 之後：80 SOL 最小值  |

邊界處不需要交易。成本是兩個群組槽而不是一個。

## 曲線類型限制

四個欄位讀取 `TotalSellA`：`TotalSellA`、`SellRateA`、`MigrateAmountA` 和 `MigrateRateA`。在常數乘積配置上，創作者提供該數字。在固定價格或線性價格配置上，曲線改為衍生它，程式比較的值是 `0`，這會拒絕每個啟動。

與其讓你寫一個無聲地阻止你自己配置的規則，程式在非常數乘積配置上在寫入時拒絕這四個欄位，錯誤為 `CurveRuleFieldNotSupportedByCurve`。目前只存在常數乘積配置，所以實踐中你不會遇到此錯誤。

## 發送前檢查

鏈上檢查的兩個方向都可離線使用，所以創作者和平台都不必通過觀看交易回滾來學習規則。

<Info>
  **版本橫幅。**

  * SDK：`@raydium-io/raydium-sdk-v2@0.2.42-alpha` 是本網站上每個其他代碼演示所固定的版本。下面的兩個幫助器隨著 SDK 發佈曲線規則支援而到達；在那之前，從程式的 `platform_curve_rule.rs` 移植它們或呼叫程式並讀取錯誤代碼。
  * 叢集：先在 Solana `devnet` 上測試 — 見 [先在 devnet 上測試](#先在-devnet-上測試)。
  * 程式 ID：見 [`reference/program-addresses`](/zh-Hant/reference/program-addresses)

  兩個幫助器都是純函數。它們不觸及任何 RPC，所以在表單中的每次按鍵都可以安全執行。
</Info>

### 在啟動前：這些參數會通過嗎？

`checkLaunchAgainstCurveRule` 精確鏡像程式的啟動時檢查，包括其失敗關閉行為。在你的啟動表單中執行它，你可以用原因禁用提交按鈕，而不是讓創作者為回滾交易付費。

```ts theme={null}
import {
  checkLaunchAgainstCurveRule,
  getPdaPlatformCurveRule,
  LaunchpadCurveRuleBaseTokenProgram,
  LaunchpadCurveRuleField,
  PlatformCurveRule,
} from "@raydium-io/raydium-sdk-v2";
import BN from "bn.js";

const platformConfig = await raydium.launchpad.getPlatformConfig(platformConfigId);

// 在 0 時程式根本不讀取規則，所以沒有什麼要檢查的
if (platformConfig.restrictCurveParam !== 0) {
  const ruleId = getPdaPlatformCurveRule(programId, platformConfigId, configId).publicKey;
  const ruleAccount = await connection.getAccountInfo(ruleId);

  const result = checkLaunchAgainstCurveRule({
    // 當帳戶不存在時為 undefined — 平台沒有為此配置寫規則
    rule: ruleAccount === null ? undefined : PlatformCurveRule.decode(ruleAccount.data),
    context: {
      curveType: globalConfig.curveType,
      migrateType: 1,
      migrateCpmmFeeOn: 0,
      supply: new BN("1000000000000000"),
      totalSellA: new BN("793100000000000"),
      totalFundRaisingB: new BN("85000000000"),
      totalLockedAmount: new BN(0),
      cliffPeriod: new BN(0),
      unlockPeriod: new BN(0),
      baseTokenProgram: LaunchpadCurveRuleBaseTokenProgram.SplToken,
      // 當基礎鑄幣不帶轉帳費擴展時省略 transferFee
      unixTimestamp: new BN(Math.floor(Date.now() / 1000)),
    },
  });

  if (!result.ok) {
    // 每個群組都拒絕了啟動；每個條目列出該群組的所有失敗約束
    for (const group of result.groupFailures) {
      for (const c of group.unsatisfied) {
        console.log(
          `群組 ${group.groupId}: ${LaunchpadCurveRuleField[c.field]} 是 ${c.actual ?? "不可計算"},`,
          `規則想要運算子 ${c.op} ${c.value.toString()}`,
        );
      }
    }
  }
}
```

幫助器重現而不是近似的三件事：

* **缺失的規則帳戶和沒有群組的規則都通過。** 沒有約束的群組也是。為不存在的帳戶傳遞 `rule: undefined`；不要將其視為拒絕。
* **不可計算的值失敗關閉。** 零供應量沒有速率，鎖定金額大於曲線銷售留下的沒有遷移金額。`actual` 回來 `undefined`，約束計為不滿足，完全如鏈上。
* **報告所有失敗的約束，不只是第一個。** 程式短路因為它只需要判決；幫助器收集一切，所以你的表單可以一次列出每個問題。

它無法知道的唯一事情是你的交易實際著陸的區塊時間。如果規則在邊界附近使用 `UnixTimestamp`，將通過視為暫定。

### 在寫規則前：這個群組有效嗎？

`checkCurveRuleGroupWritable` 鏡像 `UpdatePlatformCurveRule` 的寫入時驗證 — 約束 ID、重複 `(欄位、運算子)` 規則、兩個計數限制和曲線類型限制。在簽署前在你的平台管理工具中執行它。

```ts theme={null}
import {
  checkCurveRuleGroupWritable,
  LaunchpadCurveRuleField,
  LaunchpadCurveRuleOp,
} from "@raydium-io/raydium-sdk-v2";

const constraints = [
  { field: LaunchpadCurveRuleField.Supply, op: LaunchpadCurveRuleOp.Eq, value: new BN("1000000000000000") },
  { field: LaunchpadCurveRuleField.TotalFundRaisingB, op: LaunchpadCurveRuleOp.Gte, value: new BN("50000000000") },
  { field: LaunchpadCurveRuleField.TotalFundRaisingB, op: LaunchpadCurveRuleOp.Lte, value: new BN("200000000000") },
];

const writable = checkCurveRuleGroupWritable({
  groupId: 0,
  constraints,
  curveType: globalConfig.curveType,
  // 規則已持有的 ID，所以替換群組不會被誤認為添加一個
  existingGroupIds: existingRule?.groups.map((g) => g.groupId) ?? [],
});

// 每個錯誤攜帶交易會失敗的程式錯誤代碼
if (!writable.ok) console.log(writable.errors);
```

<Note>
  通過此檢查意味著交易不會因格式不正確而被拒絕。它對規則是否是你的意思沒有說什麼 — 一個群組可以完全有效，仍然拒絕你的 UI 可以產生的每個啟動。這就是上面的啟動端檢查的用途：寫入群組後，通過 `checkLaunchAgainstCurveRule` 執行你的產品提供的每個形狀，並確認每個仍然找到一個群組。
</Note>

### 先在 devnet 上測試

在主網上啟用 `restrict_curve_param` 會立即改變你的創作者可以做的事，對每個啟動。在觸及主網前在 devnet 上排練整個序列：

1. 在 devnet 上建立平台配置和規則，並寫入你打算發佈的相同群組。
2. 通過 `checkLaunchAgainstCurveRule` 執行你的 UI 可以產生的每個啟動形狀，並確認判決是你期望的 — 應該通過的形狀和應該被拒絕的形狀。
3. 啟用 `restrict_curve_param`，然後實際啟動應該通過的代幣和應該被拒絕的代幣。第二個應該失敗，錯誤為 `CurveParamNotMatchPlatformRule` (`6025`)，而不是 `NotEnoughRemainingAccounts` (`6018`) — 後者意味著你的建構器沒有追加規則 PDA，檢查沒有真正被執行。
4. 只有在主網上重複，順序相同。

將 SDK 指向 devnet，使用 `cluster: "devnet"` 當你載入它時，並從 [`reference/program-addresses`](/zh-Hant/reference/program-addresses) 取得 devnet 程式 ID。

第 3 步是值得堅持的。離線幫助器和鏈上程式是相同規則的兩個實現，devnet 啟動是證明它們對你的規則一致的 — 包括你的啟動建構器是否根本傳遞帳戶。

## 操作規則

### 委派的管理員

編輯規則是日常工作；平台管理員金鑰通常是多簽。`PlatformConfig.curve_rule_manager` 正是為此而存在：通過 `UpdatePlatformConfig::CurveRuleManager` 設定一次，該熱錢包可以自己建立、更新、移除和關閉規則帳戶。平台管理員並行保留相同的權力，所以丟失的管理員金鑰是可恢復的 — 用另一個管理員呼叫輪換它。

受損管理員金鑰的範圍：它可以鬆動或刪除你的參數規則，可以回收規則帳戶的租金。它不能觸及費用錢包、歸屬、CPMM 配置、不能翻轉 `restrict_curve_param`，不能破壞 `GlobalConfig` 限制。將其視為配置金鑰，而不是金庫金鑰。

### 租金跟隨內容

規則帳戶建立時不持有群組，並在每次更改時調整大小，所以你為實際寫入的規則付費。移除群組會將差額退款給簽署者。

| 規則內容           | 帳戶大小      | 租金           |
| -------------- | --------- | ------------ |
| 空（剛建立）         | 150 位元組   | \~0.0019 SOL |
| 1 群組、2 約束      | 200 位元組   | \~0.0023 SOL |
| 3 群組、每個 4 約束   | 408 位元組   | \~0.0037 SOL |
| 10 群組、每個 25 約束 | 4 790 位元組 | \~0.034 SOL  |

### 推出順序

1. 在 devnet 上排練整個序列 — 見 [先在 devnet 上測試](#先在-devnet-上測試)。
2. 建立規則帳戶並寫入其群組。還沒有任何改變 — 使用 `restrict_curve_param` 仍為 `0` 程式不讀取它們。
3. 使用 [`checkLaunchAgainstCurveRule`](#在啟動前這些參數會通過嗎) 離線檢查規則：對於你的 UI 可以產生的每個啟動形狀，確認某個群組接受它。
4. 將 `restrict_curve_param` 設定為 `1`。從那一刻起，你的創作者的啟動被檢查。
5. 要回滾，再次將其設定為 `0`。規則帳戶保持完整。

<Warning>
  你的啟動建構器必須在 `restrict_curve_param` 為 `1` 時將規則 PDA 追加到 `remaining_accounts`。程式要求帳戶存在，即使它還不存在，所以創作者不能通過省略它來跳過檢查 — 缺失帳戶是 `NotEnoughRemainingAccounts`，而不是通過。衍生是 `[b"platform_curve_rule", platform_config, global_config]`。
</Warning>

## 啟動時的成本

檢查在啟用時在每個啟動上執行，所以其計算成本是每次啟動稅。端到端測量 — PDA 衍生、`remaining_accounts` 掃描、反序列化和評估：

| 規則內容           | 便宜欄位   | 衍生欄位   |
| -------------- | ------ | ------ |
| 啟用，無規則帳戶       | 1 936  | —      |
| 1 群組、2 約束      | 2 576  | 2 926  |
| 3 群組、每個 4 約束   | 3 624  | 5 724  |
| 10 群組、每個 25 約束 | 24 344 | 68 094 |

「便宜」是直接欄位讀取，如 `Supply`；「衍生」是計算的，如 `MigrateRateA`，每個約束成本約 223 CU，而直接讀取約 48。即使是完全載入的衍生約束規則也保持在預設 200 000 CU 每指令預算的三分之一以內，現實的三群組規則在 6 000 以下。群組被評估直到一個匹配，所以將你的常見分層放在前面是免費節省。

## 下一步去哪裡

* [`products/launchlab/platform-config`](/zh-Hant/products/launchlab/platform-config) — 閘門和委派規則的 `PlatformConfig` 欄位。
* [`products/launchlab/global-config`](/zh-Hant/products/launchlab/global-config) — 規則縮小的協議下限。
* [`products/launchlab/instructions`](/zh-Hant/products/launchlab/instructions) — 四個規則指令及其帳戶。
* [`products/launchlab/accounts`](/zh-Hant/products/launchlab/accounts) — 帳戶清單中的 `PlatformCurveRule`。
* [`sdk-api/typescript-sdk`](/zh-Hant/sdk-api/typescript-sdk) — 兩個檢查幫助器所在的 SDK 表面。
* [`reference/changelog/2026-08-31-launchlab-platform-curve-rules`](/zh-Hant/reference/changelog/2026-08-31-launchlab-platform-curve-rules) — 替代曲線參數白名單的內容，以及解碼器必須改變的內容。

來源：

* `raydium-launch/programs/launchpad/src/states/platform_curve_rule.rs` — `PlatformCurveRule`、`CurveRuleGroup`、`ParamConstraint`、欄位和運算子 ID 空間，以及 `CurveRuleContext::value_of`。
* `raydium-launch/programs/launchpad/src/utils/platform_curve_rule.rs` — 啟動時檢查。
* `raydium-launch/programs/launchpad/src/instructions/platform/` — `create`、`update`、`remove` 和 `close_platform_curve_rule`。
