> ## 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 곡선 규칙

> 플랫폼이 크리에이터가 선택할 수 있는 런칭 파라미터를 제약하는 방식: 그룹 확인, (필드, 연산자, 값) 제약 모델, 그리고 9가지 플레이북 — 정확한 티어, 값 범위, 졸업-밸류에이션 상한, 마이그레이션 하한, 토큰 타입 게이팅, 시간 제한 프로모션.

<Info>
  **이 페이지는 AI 자동 번역입니다. 모든 내용은 영문판을 기준으로 합니다.**

  [영문판 보기 →](/products/launchlab/curve-rules)
</Info>

<Info>
  **곡선 규칙**은 플랫폼이 "어떤 런칭을 호스팅할 의향이 있는가?"에 대해 내리는 답입니다. [`GlobalConfig`](/ko/products/launchlab/global-config)는 프로토콜 하한선을 설정합니다 — 최소 10M 공급량, 곡선에서 판매되는 공급량의 최소 20% 등 — 이 하한선들은 의도적으로 넓어서 모든 종류의 플랫폼이 그 아래에 들어갈 수 있습니다. 곡선 규칙은 여기서 플랫폼이 이를 좁혀서 실제로 지원하는 제품의 형태로 만드는 곳입니다.

  규칙은 자신의 `PlatformCurveRule` 계정에 존재하며, (플랫폼, [`GlobalConfig`](/ko/products/launchlab/global-config)) 쌍마다 하나씩 있습니다. 설정이 이미 허용하는 것만 좁힐 수 있습니다. 규칙은 프로토콜 제한을 절대 확대할 수 없습니다.
</Info>

## 개념 모델

바깥쪽에서 안쪽으로 세 가지 수준:

```
GlobalConfig       프로토콜 하한선      "공급량 >= 10M, 판매율 >= 20%, ..."
  └─ PlatformCurveRule   당신의 규칙     "그리고 내 플랫폼에서: 이 중 하나"
       └─ 체크 그룹    하나의 형태     "공급량 = 1B AND 자금 조성 [80, 90] SOL"
            └─ 제약    하나의 체크    "(Supply, Eq, 1_000_000_000)"
```

두 수준의 중첩이 표현력을 만듭니다:

* **한 그룹 내의 제약들은 AND 연산됩니다.** 모두 만족해야 합니다.
* **한 규칙 내의 그룹들은 OR 연산됩니다.** 런칭은 단 하나의 그룹을 만족하는 순간 허용됩니다.

따라서 그룹은 하나의 허용된 *형태*이고, 규칙은 제공하는 형태들의 메뉴입니다. 규칙은 최대 10개의 그룹을 보유할 수 있고, 그룹은 최대 25개의 제약을 보유할 수 있습니다.

기억할 가치가 있는 두 가지 경계 사례:

| 상태                        | 의미                                      |
| ------------------------- | --------------------------------------- |
| 규칙 계정 없음, 또는 0개 그룹을 가진 규칙 | 플랫폼이 해당 설정에 대해 런칭 파라미터를 제약하지 않습니다.      |
| 0개 제약을 가진 그룹              | 그 그룹은 모든 런칭과 일치하므로, 전체 규칙이 모든 것을 허용합니다. |

규칙은 `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`              | enum        | 0 상수곱, 1 고정가격, 2 선형가격                               |
| 1  | `MigrateType`            | enum        | 새 런칭은 어쨌든 `1` (CPMM)이어야 합니다                         |
| 2  | `MigrateCpmmFeeOn`       | enum        | 0 견적만, 1 두 토큰 모두                                    |
| 3  | `Supply`                 | 기본 단위       | 전체 토큰 공급량                                           |
| 4  | `TotalSellA`             | 기본 단위       | 곡선에서 판매됨. 상수곱 설정만 — [곡선 타입 제약](#곡선-타입-제약) 참조        |
| 5  | `TotalFundRaisingB`      | 견적 단위       | 졸업 목표                                               |
| 6  | `TotalLockedAmount`      | 기본 단위       | 베스팅 예산                                              |
| 7  | `CliffPeriod`            | 초           | 언락 시작 전 대기                                          |
| 8  | `UnlockPeriod`           | 초           | 언락 기간                                               |
| 9  | `BaseTokenProgram`       | enum        | 0 SPL Token, 1 Token-2022                           |
| 10 | `TransferFeeEnabled`     | bool        | 기본 민트가 `TransferFeeConfig`를 가질 때 1                  |
| 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>

## 9가지 플레이북

아래의 각 플레이북은 하나의 규칙입니다. 제약은 `(필드, 연산자, 값)`으로 작성됩니다.

### 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)` |

하나의 그룹, 4개의 제약, 그리고 크리에이터는 50–200 SOL 복도를 가집니다. 이전 화이트리스트에서는 허용된 각 값마다 하나의 항목이 필요했고, 10개 항목의 상한선이 불가능하게 만들었습니다.

### 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 민트는 SPL Token 민트처럼 `TransferFeeEnabled = 0`을 보고합니다.

| 의도                    | 그룹 | 제약                                                         |
| --------------------- | -- | ---------------------------------------------------------- |
| 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%, 그리고 실제로 설정된 최대 수수료 |

0 비율 `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    |

경계에서 트랜잭션이 필요하지 않습니다. 비용은 하나 대신 두 개의 그룹 슬롯입니다.

## 곡선 타입 제약

4개의 필드가 `TotalSellA`를 읽습니다: `TotalSellA`, `SellRateA`, `MigrateAmountA`, `MigrateRateA`. 상수곱 설정에서 크리에이터가 그 숫자를 제공합니다. 고정가격 또는 선형가격 설정에서 곡선이 대신 파생하고, 프로그램이 비교하는 값은 `0`이며, 이는 모든 런칭을 거부할 것입니다.

당신이 자신의 설정을 조용히 차단하는 규칙을 작성하도록 하지 않기 위해, 프로그램은 비상수곱 설정에서 쓰기 시간에 이 4개 필드를 거부하며, `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`](/ko/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 ${group.groupId}: ${LaunchpadCurveRuleField[c.field]} is ${c.actual ?? "not computable"},`,
          `rule wants op ${c.op} ${c.value.toString()}`,
        );
      }
    }
  }
}
```

헬퍼가 근사하지 않고 재현하는 3가지:

* **누락된 규칙 계정과 규칙 없는 그룹 모두 통과합니다.** 제약 없는 그룹도 마찬가지입니다. 존재하지 않는 계정에 대해 `rule: undefined`를 전달하세요. 거부로 취급하지 마세요.
* **계산 불가능한 값은 닫혀서 실패합니다.** 0 공급량은 비율이 없고, 곡선 판매 후 남은 것보다 큰 잠금 금액은 마이그레이션 금액이 없습니다. `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에서 테스트

mainnet에서 `restrict_curve_param`을 활성화하면 크리에이터가 할 수 있는 것이 즉시 변경되며, 모든 런칭에 대해 변경됩니다. mainnet을 건드리기 전에 devnet에서 전체 시퀀스를 리허설하세요:

1. devnet에서 플랫폼 설정과 규칙을 생성하고, 배포할 의도인 동일한 그룹을 작성합니다.
2. UI가 생성할 수 있는 모든 런칭 형태를 `checkLaunchAgainstCurveRule`을 통해 실행하고, 판정이 예상한 것인지 확인합니다 — 통과해야 하는 형태와 거부되어야 하는 형태 모두.
3. `restrict_curve_param`을 활성화한 다음, 통과해야 하는 토큰을 실제로 런칭하고 거부되어야 하는 토큰을 런칭합니다. 두 번째는 `CurveParamNotMatchPlatformRule` (`6025`)로 실패해야 하며, `NotEnoughRemainingAccounts` (`6018`)로 실패하지 않아야 합니다 — 후자는 빌더가 규칙 PDA를 추가하지 않고 있으며 체크가 실제로 실행되지 않고 있음을 의미합니다.
4. 그 후에만 mainnet에서 동일한 순서로 반복합니다.

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 명령당 예산의 3분의 1 내에 머물며, 현실적인 3그룹 규칙은 6 000 미만입니다. 그룹은 일치할 때까지 평가되므로, 일반적인 티어를 먼저 배치하는 것은 무료 절감입니다.

## 다음으로 갈 곳

* [`products/launchlab/platform-config`](/ko/products/launchlab/platform-config) — 규칙을 게이트하고 위임하는 `PlatformConfig` 필드.
* [`products/launchlab/global-config`](/ko/products/launchlab/global-config) — 규칙이 좁히는 프로토콜 하한선.
* [`products/launchlab/instructions`](/ko/products/launchlab/instructions) — 4개의 규칙 명령과 그들의 계정.
* [`products/launchlab/accounts`](/ko/products/launchlab/accounts) — 계정 인벤토리의 `PlatformCurveRule`.
* [`sdk-api/typescript-sdk`](/ko/sdk-api/typescript-sdk) — 두 체크 헬퍼가 사는 SDK 표면.
* [`reference/changelog/2026-08-31-launchlab-platform-curve-rules`](/ko/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`.
