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

# Règles de courbe LaunchLab

> Comment une plateforme contraint les paramètres de lancement que ses créateurs peuvent choisir : groupes de vérification, le modèle de contrainte (champ, opérateur, valeur), et neuf modèles — paliers exacts, bandes de valeur, plafonds de valorisation à la graduation, planchers de migration, gating par type de token, et promotions limitées dans le temps.

<Info>
  **Cette page est traduite automatiquement par IA. La version anglaise fait foi.**

  [Voir la version anglaise →](/products/launchlab/curve-rules)
</Info>

<Info>
  Une **règle de courbe** est la réponse d'une plateforme à la question « quels lancements suis-je prêt à héberger ? ». [`GlobalConfig`](/fr/products/launchlab/global-config) définit le plancher du protocole — au moins 10M de supply, au moins 20% de la supply vendue sur la courbe, et ainsi de suite — et ces planchers sont volontairement larges pour que chaque type de plateforme s'y inscrive. Une règle de courbe est l'endroit où votre plateforme les affine à la forme que votre produit supporte réellement.

  Les règles vivent dans leur propre compte `PlatformCurveRule`, un par paire (plateforme, [`GlobalConfig`](/fr/products/launchlab/global-config)). Elles ne peuvent que restreindre ce que la config autorise déjà ; une règle ne peut jamais élargir une limite du protocole.
</Info>

## Le modèle mental

Trois niveaux, de l'extérieur vers l'intérieur :

```
GlobalConfig       plancher du protocole      "supply >= 10M, taux de vente >= 20%, ..."
  └─ PlatformCurveRule   votre règle     "et sur ma plateforme : l'une de ces formes"
       └─ groupe de vérification    une forme     "supply = 1B ET levée de fonds dans [80, 90] SOL"
            └─ contrainte une vérification    "(Supply, Eq, 1_000_000_000)"
```

Les deux niveaux d'imbrication sont ce qui rend cela expressif :

* **Les contraintes à l'intérieur d'un groupe sont combinées avec ET.** Toutes doivent être satisfaites.
* **Les groupes à l'intérieur d'une règle sont combinés avec OU.** Un lancement est autorisé dès qu'il satisfait un seul groupe.

Donc un groupe est une *forme* autorisée, et la règle est le menu des formes que vous proposez. Une règle peut contenir jusqu'à 10 groupes, et un groupe jusqu'à 25 contraintes.

Deux cas limites méritent d'être mémorisés :

| État                                                  | Signification                                                                 |
| ----------------------------------------------------- | ----------------------------------------------------------------------------- |
| Pas de compte de règle, ou une règle avec zéro groupe | La plateforme ne restreint pas les paramètres de lancement pour cette config. |
| Un groupe avec zéro contrainte                        | Ce groupe correspond à chaque lancement, donc la règle entière autorise tout. |

Une règle ne prend effet que si `PlatformConfig.restrict_curve_param` est `1`. À `0`, le programme ne lit pas du tout les règles, ce qui est aussi le commutateur que vous utilisez pour déployer une règle et pour la revenir en arrière.

## Contraintes

Une contrainte est un triplet `(champ, opérateur, valeur)`. Rien d'autre — pas d'expressions, pas d'imbrication.

```rust theme={null}
pub struct ParamConstraint {
    pub field: u8,    // quel paramètre de lancement, voir le tableau ci-dessous
    pub op:    u8,    // 0 Eq, 1 Gte (min), 2 Lte (max), 3 Neq
    pub value: u128,
}
```

Une **plage est deux contraintes** sur le même champ à l'intérieur d'un groupe : une `Gte` pour le plancher et une `Lte` pour le plafond. La même paire `(champ, opérateur)` ne peut pas apparaître deux fois dans un groupe, ce qui vous empêche d'écrire deux minimums contradictoires.

### Champs

<Info>
  Les identifiants de champ sont permanents. Les nouveaux champs ne sont jamais qu'ajoutés, donc un identifiant ne change jamais de signification une fois qu'un compte de règle le contient.
</Info>

| id | Champ                    | Unité           | Notes                                                                                                                                |
| -- | ------------------------ | --------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| 0  | `CurveType`              | enum            | 0 produit constant, 1 prix fixe, 2 prix linéaire                                                                                     |
| 1  | `MigrateType`            | enum            | Les nouveaux lancements doivent être `1` (CPMM) de toute façon                                                                       |
| 2  | `MigrateCpmmFeeOn`       | enum            | 0 quote uniquement, 1 les deux tokens                                                                                                |
| 3  | `Supply`                 | unités de base  | La supply de token complète                                                                                                          |
| 4  | `TotalSellA`             | unités de base  | Vendu sur la courbe. Configs de produit constant uniquement — voir [Restrictions de type de courbe](#restrictions-de-type-de-courbe) |
| 5  | `TotalFundRaisingB`      | unités de quote | La cible de graduation                                                                                                               |
| 6  | `TotalLockedAmount`      | unités de base  | Budget de vesting                                                                                                                    |
| 7  | `CliffPeriod`            | secondes        | Attendre avant que le déverrouillage commence                                                                                        |
| 8  | `UnlockPeriod`           | secondes        | Durée du déverrouillage                                                                                                              |
| 9  | `BaseTokenProgram`       | enum            | 0 SPL Token, 1 Token-2022                                                                                                            |
| 10 | `TransferFeeEnabled`     | bool            | 1 quand le mint de base porte `TransferFeeConfig`                                                                                    |
| 11 | `TransferFeeBasisPoints` | 1/10 000        | 0 sans l'extension                                                                                                                   |
| 12 | `TransferFeeMaximumFee`  | unités de base  | 0 sans l'extension                                                                                                                   |
| 13 | `SellRateA`              | 1/1 000 000     | Dérivé : `TotalSellA / Supply`. Produit constant uniquement                                                                          |
| 14 | `LockRate`               | 1/1 000 000     | Dérivé : `TotalLockedAmount / Supply`                                                                                                |
| 15 | `MigrateAmountA`         | unités de base  | Dérivé : `Supply − TotalSellA − TotalLockedAmount`. Produit constant uniquement                                                      |
| 16 | `MigrateRateA`           | 1/1 000 000     | Dérivé : `MigrateAmountA / Supply`. Produit constant uniquement                                                                      |
| 17 | `FundRaisingRateB`       | 1/1 000 000     | Dérivé : `TotalFundRaisingB / Supply`                                                                                                |
| 18 | `UnixTimestamp`          | secondes        | Heure de bloc du lancement                                                                                                           |

Les champs dérivés sont ceux qui rendent les règles portables. Épingler `Supply` et `TotalFundRaisingB` à des nombres exacts fixe une forme de lancement ; contraindre `FundRaisingRateB` fixe la *relation* entre eux et permet à un créateur de choisir n'importe quelle supply qui la maintient.

<Warning>
  Les champs de taux ne sont comparables que dans une `GlobalConfig`, car leurs dénominateurs dépendent du mint de quote de cette config et de ses décimales. Ce n'est pas une limitation en pratique : une règle est délimitée à une config par construction.
</Warning>

## Les neuf modèles

Chaque modèle ci-dessous est une règle. Les contraintes sont écrites comme `(champ, opérateur, valeur)`.

### 1. Un palier standard

La règle la plus simple, et le comportement exact que la liste blanche de paramètres de courbe retirée offrait : une forme, épinglée.

| Groupe | Contraintes                                                                                         |
| ------ | --------------------------------------------------------------------------------------------------- |
| 0      | `(Supply, Eq, 1_000_000_000e6)`, `(TotalSellA, Eq, 800_000_000e6)`, `(TotalFundRaisingB, Eq, 85e9)` |

Tout lancement qui s'écarte dans l'un des trois est rejeté avec `CurveParamNotMatchPlatformRule`.

### 2. Une bande au lieu d'un nombre

La raison pour laquelle les bandes existent : un créateur choisit une cible de levée de fonds avec laquelle vous êtes à l'aise, sans que vous énumériez chaque valeur.

| Groupe | Contraintes                                                                                          |
| ------ | ---------------------------------------------------------------------------------------------------- |
| 0      | `(Supply, Eq, 1_000_000_000e6)`, `(TotalFundRaisingB, Gte, 50e9)`, `(TotalFundRaisingB, Lte, 200e9)` |

Un groupe, quatre contraintes, et le créateur a un corridor de 50–200 SOL. Sous l'ancienne liste blanche, cela nécessitait une entrée par valeur autorisée, et le plafond de dix entrées le rendait impossible.

### 3. Paliers côte à côte

Les groupes sont combinés avec OU, donc chaque palier est un groupe.

| Groupe | Contraintes                                                         | Palier   |
| ------ | ------------------------------------------------------------------- | -------- |
| 0      | `(Supply, Eq, 1_000_000_000e6)`, `(TotalFundRaisingB, Eq, 85e9)`    | Standard |
| 1      | `(Supply, Eq, 100_000_000e6)`, `(TotalFundRaisingB, Eq, 30e9)`      | Petit    |
| 2      | `(Supply, Eq, 10_000_000_000e6)`, `(TotalFundRaisingB, Gte, 500e9)` | Baleine  |

L'ordre importe pour le calcul, pas pour la sémantique : l'évaluation s'arrête au premier groupe qui correspond, donc mettez votre palier le plus utilisé en premier.

### 4. Une bande de valorisation à la graduation

`FundRaisingRateB` est `TotalFundRaisingB / Supply` en millionièmes. La contraindre plafonne la richesse avec laquelle un token peut se diplômer indépendamment de la supply que le créateur a choisie.

| Groupe | Contraintes                                                           |
| ------ | --------------------------------------------------------------------- |
| 0      | `(FundRaisingRateB, Gte, 60_000)`, `(FundRaisingRateB, Lte, 120_000)` |

Avec une supply de 1e12 et un mint de quote à 9 décimales, `85e9 / 1e12 × 1e6 = 85_000` se situe à l'intérieur de cette bande. Un créateur qui double la supply doit à peu près doubler la cible pour rester dedans — c'est le point. Deux contraintes remplacent ce qui serait autrement un tableau de paires `(supply, cible)`.

### 5. Un plancher de migration

`MigrateRateA` est la part de la supply qui atterrit réellement dans le pool CPMM à la graduation : `Supply − TotalSellA − TotalLockedAmount`, divisé par la supply. C'est la profondeur du pool diplômé, et c'est le seul bouton du protocole sans équivalent côté plateforme avant que les règles n'existent.

| Groupe | Contraintes                    |
| ------ | ------------------------------ |
| 0      | `(MigrateRateA, Gte, 150_000)` |

Au moins 15% de la supply atteint le pool. Un créateur ne peut pas vendre 95% sur la courbe et laisser un carnet peu profond derrière.

<Note>
  Si les paramètres ne s'additionnent pas — un montant verrouillé plus grand que ce qui reste après la vente de courbe — la valeur dérivée ne peut pas être calculée et la contrainte échoue fermée, donc le lancement est rejeté plutôt que silencieusement autorisé.
</Note>

### 6. Vesting que vous appliquez réellement

`GlobalConfig.max_lock_rate` plafonne le vesting par le haut. Une règle peut mettre un plancher dessous, et exiger une vraie falaise.

| Groupe | Contraintes                                                                            |
| ------ | -------------------------------------------------------------------------------------- |
| 0      | `(LockRate, Gte, 50_000)`, `(LockRate, Lte, 200_000)`, `(CliffPeriod, Gte, 2_592_000)` |

Entre 5% et 20% de la supply verrouillée, avec au moins une falaise de 30 jours. Utile pour une plateforme dont le pitch est « pas de lancements avec déverrouillage instantané ».

### 7. Gating par type de token

`BaseTokenProgram` et `TransferFeeEnabled` sont indépendants, ce qui importe : un mint Token-2022 sans `TransferFeeConfig` rapporte `TransferFeeEnabled = 0` tout comme un mint SPL Token le fait.

| Intention                                            | Groupe | Contraintes                                                |
| ---------------------------------------------------- | ------ | ---------------------------------------------------------- |
| SPL Token uniquement                                 | 0      | `(BaseTokenProgram, Eq, 0)`                                |
| Token-2022 uniquement                                | 0      | `(BaseTokenProgram, Eq, 1)`                                |
| Token-2022, pas de frais de transfert                | 0      | `(BaseTokenProgram, Eq, 1)`, `(TransferFeeEnabled, Eq, 0)` |
| Pas de frais de transfert, l'un ou l'autre programme | 0      | `(TransferFeeEnabled, Eq, 0)`                              |

### 8. Un plafond de frais de transfert conditionnel

Il n'y a pas d'opérateur « si », et aucun n'est nécessaire — deux groupes expriment la condition.

| Groupe | Contraintes                                                                                                | Se lit comme                                                                  |
| ------ | ---------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| 0      | `(TransferFeeEnabled, Eq, 0)`                                                                              | Pas de frais de transfert : c'est bon                                         |
| 1      | `(TransferFeeEnabled, Eq, 1)`, `(TransferFeeBasisPoints, Lte, 100)`, `(TransferFeeMaximumFee, Gte, 1_000)` | Avec des frais : au maximum 1%, et un frais maximum qui est réellement défini |

Une `TransferFeeConfig` à taux zéro ne glisse pas à travers le groupe 0 : l'extension est présente, donc `TransferFeeEnabled` est `1` et seul le groupe 1 peut l'accepter.

### 9. Une promo limitée dans le temps, programmée à l'avance

`UnixTimestamp` est l'heure de bloc du lancement, donc un groupe peut porter sa propre fenêtre de validité. Vous écrivez les deux groupes aujourd'hui et le basculement se fait tout seul.

| Groupe | Contraintes                                                             | Fenêtre                        |
| ------ | ----------------------------------------------------------------------- | ------------------------------ |
| 0      | `(UnixTimestamp, Lte, 1_767_225_600)`, `(TotalFundRaisingB, Gte, 30e9)` | Période promo : minimum 30 SOL |
| 1      | `(UnixTimestamp, Gte, 1_767_225_601)`, `(TotalFundRaisingB, Gte, 80e9)` | Après : minimum 80 SOL         |

Aucune transaction n'est nécessaire à la limite. Le coût est deux emplacements de groupe au lieu d'un.

## Restrictions de type de courbe

Quatre champs lisent `TotalSellA` : `TotalSellA`, `SellRateA`, `MigrateAmountA`, et `MigrateRateA`. Sur une config de produit constant, le créateur fournit ce nombre. Sur une config de prix fixe ou de prix linéaire, la courbe le dérive à la place, et la valeur que le programme compare est `0`, ce qui rejetterait chaque lancement.

Plutôt que de vous laisser écrire une règle qui bloque silencieusement votre propre config, le programme refuse ces quatre champs au moment de l'écriture sur une config non-produit-constant, avec `CurveRuleFieldNotSupportedByCurve`. Seules les configs de produit constant existent aujourd'hui, donc en pratique vous ne rencontrerez pas cette erreur.

## Vérifier avant d'envoyer

Les deux directions de la vérification on-chain sont disponibles hors-chain, donc ni un créateur ni une plateforme n'a besoin d'apprendre une règle en regardant les transactions revenir.

<Info>
  **Banneau de version.**

  * SDK : `@raydium-io/raydium-sdk-v2@0.2.42-alpha` est la version à laquelle tous les autres démos de code sur ce site sont épinglés. Les deux assistants ci-dessous arrivent avec la version du SDK qui expédie le support des règles de courbe ; jusqu'à alors, portez-les depuis le `platform_curve_rule.rs` du programme ou appelez le programme et lisez le code d'erreur.
  * Cluster : testez d'abord sur Solana `devnet` — voir [Testez d'abord sur devnet](#testez-dabord-sur-devnet).
  * ID du programme : voir [`reference/program-addresses`](/fr/reference/program-addresses)

  Les deux assistants sont des fonctions pures. Ils ne touchent aucun RPC, donc ils sont sûrs à exécuter à chaque frappe dans un formulaire.
</Info>

### Avant un lancement : ces paramètres passeront-ils ?

`checkLaunchAgainstCurveRule` reflète exactement la vérification du programme au moment du lancement, y compris son comportement d'échec fermé. Exécutez-le dans votre formulaire de lancement et vous pouvez désactiver le bouton d'envoi avec une raison au lieu de laisser le créateur payer pour une transaction annulée.

```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 le programme ne lit pas du tout les règles, donc il n'y a rien à vérifier
if (platformConfig.restrictCurveParam !== 0) {
  const ruleId = getPdaPlatformCurveRule(programId, platformConfigId, configId).publicKey;
  const ruleAccount = await connection.getAccountInfo(ruleId);

  const result = checkLaunchAgainstCurveRule({
    // undefined quand le compte n'existe pas — la plateforme n'a écrit aucune règle pour cette config
    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,
      // omettez transferFee entièrement quand le mint de base ne porte pas d'extension de frais de transfert
      unixTimestamp: new BN(Math.floor(Date.now() / 1000)),
    },
  });

  if (!result.ok) {
    // chaque groupe a rejeté le lancement ; chaque entrée liste toutes les contraintes défaillantes de ce groupe
    for (const group of result.groupFailures) {
      for (const c of group.unsatisfied) {
        console.log(
          `groupe ${group.groupId}: ${LaunchpadCurveRuleField[c.field]} est ${c.actual ?? "non calculable"},`,
          `la règle veut op ${c.op} ${c.value.toString()}`,
        );
      }
    }
  }
}
```

Trois choses que l'assistant reproduit plutôt que d'approximer :

* **Un compte de règle manquant, et une règle sans groupe, passent tous les deux.** Tout comme un groupe sans contrainte. Passez `rule: undefined` pour un compte inexistant ; ne le traitez pas comme un rejet.
* **Les valeurs non calculables échouent fermées.** Une supply zéro n'a pas de taux, et un montant verrouillé plus grand que ce que la vente de courbe laisse n'a pas de montant de migration. `actual` revient `undefined` et la contrainte compte comme non satisfaite, exactement comme on-chain.
* **Toutes les contraintes défaillantes sont rapportées, pas seulement la première.** Le programme court-circuite parce qu'il n'a besoin que d'un verdict ; l'assistant collecte tout pour que votre formulaire puisse lister chaque problème à la fois.

La seule chose qu'il ne peut pas savoir est l'heure de bloc à laquelle votre transaction atterrira réellement. Si une règle utilise `UnixTimestamp` près d'une limite, traitez un passage comme provisoire.

### Avant d'écrire une règle : ce groupe est-il valide ?

`checkCurveRuleGroupWritable` reflète la validation au moment de l'écriture de `UpdatePlatformCurveRule` — les ids de contrainte, la règle de `(champ, opérateur)` dupliqué, les deux limites de comptage, et la restriction de type de courbe. Exécutez-le dans votre outil d'administration de plateforme avant de signer.

```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,
  // les ids que la règle détient déjà, donc remplacer un groupe n'est pas confondu avec en ajouter un
  existingGroupIds: existingRule?.groups.map((g) => g.groupId) ?? [],
});

// chaque erreur porte le code d'erreur du programme avec lequel la transaction aurait échoué
if (!writable.ok) console.log(writable.errors);
```

<Note>
  Passer cette vérification signifie que la transaction ne sera pas rejetée pour être mal formée. Cela ne dit rien sur le fait que la règle est ce que vous aviez l'intention — un groupe peut être parfaitement valide et toujours rejeter chaque lancement que votre UI peut produire. C'est ce que la vérification du côté du lancement ci-dessus est pour : après avoir écrit un groupe, exécutez chaque forme que votre produit offre à travers `checkLaunchAgainstCurveRule` et confirmez que chacune trouve toujours un groupe.
</Note>

### Testez d'abord sur devnet

Activer `restrict_curve_param` sur mainnet change ce que vos créateurs peuvent faire, immédiatement, pour chaque lancement. Répétez la séquence entière sur devnet avant de toucher mainnet :

1. Créez une config de plateforme et une règle sur devnet, et écrivez les mêmes groupes que vous avez l'intention d'expédier.
2. Exécutez chaque forme de lancement que votre UI peut produire à travers `checkLaunchAgainstCurveRule`, et confirmez que les verdicts sont ceux que vous attendez — à la fois les formes qui devraient passer et les formes qui devraient être rejetées.
3. Activez `restrict_curve_param`, puis lancez réellement un token qui devrait passer et un qui devrait être rejeté. Le second devrait échouer avec `CurveParamNotMatchPlatformRule` (`6025`), pas avec `NotEnoughRemainingAccounts` (`6018`) — ce dernier signifie que votre builder n'ajoute pas le PDA de règle et la vérification n'est pas réellement exercée.
4. Seulement alors répétez sur mainnet, dans le même ordre.

Pointez le SDK sur devnet avec `cluster: "devnet"` quand vous le chargez, et prenez l'ID du programme devnet depuis [`reference/program-addresses`](/fr/reference/program-addresses).

L'étape 3 est celle sur laquelle il vaut la peine d'insister. L'assistant hors-chain et le programme on-chain sont deux implémentations des mêmes règles, et un lancement devnet est ce qui prouve qu'ils s'accordent pour votre règle — y compris que votre constructeur de lancement passe le compte du tout.

## Exploiter une règle

### Le gestionnaire délégué

Éditer les règles est un travail de routine ; une clé d'administrateur de plateforme est généralement un multisig. `PlatformConfig.curve_rule_manager` existe exactement pour cela : définissez-le une fois via `UpdatePlatformConfig::CurveRuleManager`, et ce portefeuille chaud peut alors créer, mettre à jour, supprimer et fermer les comptes de règle par lui-même. L'administrateur de la plateforme conserve le même pouvoir en parallèle, donc une clé de gestionnaire perdue est récupérable — faites-la tourner avec un autre appel d'administrateur.

Portée d'une clé de gestionnaire compromise : elle peut assouplir ou supprimer vos règles de paramètres, et elle peut réclamer le loyer d'un compte de règle. Elle ne peut pas toucher aux portefeuilles de frais, au vesting, à la config CPMM, ne peut pas basculer `restrict_curve_param`, et ne peut pas casser une limite `GlobalConfig`. Traitez-la comme une clé de configuration, pas une clé de trésorerie.

### Le loyer suit le contenu

Un compte de règle est créé sans groupe et redimensionné à chaque changement, donc vous payez pour les règles que vous avez réellement écrites. Supprimer un groupe rembourse la différence au signataire.

| Contenu de la règle               | Taille du compte | Loyer        |
| --------------------------------- | ---------------- | ------------ |
| Vide (juste créé)                 | 150 octets       | \~0,0019 SOL |
| 1 groupe, 2 contraintes           | 200 octets       | \~0,0023 SOL |
| 3 groupes, 4 contraintes chacun   | 408 octets       | \~0,0037 SOL |
| 10 groupes, 25 contraintes chacun | 4 790 octets     | \~0,034 SOL  |

### Ordre de déploiement

1. Répétez la séquence entière sur devnet — voir [Testez d'abord sur devnet](#testez-dabord-sur-devnet).
2. Créez le compte de règle et écrivez ses groupes. Rien ne change encore — avec `restrict_curve_param` toujours à `0`, le programme ne les lit pas.
3. Vérifiez la règle hors-chain avec [`checkLaunchAgainstCurveRule`](#avant-un-lancement--ces-paramètres-passeront-ils) : pour chaque forme de lancement que votre UI peut produire, confirmez qu'un groupe l'accepte.
4. Définissez `restrict_curve_param` à `1`. À partir de ce moment, les lancements de vos créateurs sont vérifiés.
5. Pour revenir en arrière, définissez-le à `0` à nouveau. Le compte de règle est laissé intact.

<Warning>
  Votre constructeur de lancement doit ajouter le PDA de règle à `remaining_accounts` tandis que `restrict_curve_param` est `1`. Le programme exige que le compte soit présent même quand il n'existe pas encore, donc qu'un créateur ne peut pas ignorer la vérification en l'omettant — un compte manquant est `NotEnoughRemainingAccounts`, pas un passage. La dérivation est `[b"platform_curve_rule", platform_config, global_config]`.
</Warning>

## Coût au moment du lancement

La vérification s'exécute à chaque lancement tandis qu'elle est activée, donc son coût de calcul est une taxe par lancement. Mesuré de bout en bout — dérivation PDA, l'analyse `remaining_accounts`, désérialisation, et évaluation :

| Contenu de la règle               | Champs bon marché | Champs dérivés |
| --------------------------------- | ----------------- | -------------- |
| Activé, pas de compte de règle    | 1 936             | —              |
| 1 groupe, 2 contraintes           | 2 576             | 2 926          |
| 3 groupes, 4 contraintes chacun   | 3 624             | 5 724          |
| 10 groupes, 25 contraintes chacun | 24 344            | 68 094         |

« Bon marché » est une lecture de champ direct comme `Supply` ; « dérivé » est un champ calculé comme `MigrateRateA`, qui coûte environ 223 CU par contrainte contre environ 48. Même une règle complètement chargée de contraintes dérivées reste à l'intérieur d'un tiers du budget par instruction par défaut de 200 000 CU, et une règle réaliste de trois groupes est sous 6 000. Les groupes sont évalués jusqu'à ce qu'un corresponde, donc mettre votre palier commun en premier est une économie gratuite.

## Où aller ensuite

* [`products/launchlab/platform-config`](/fr/products/launchlab/platform-config) — les champs `PlatformConfig` qui gating et délèguent les règles.
* [`products/launchlab/global-config`](/fr/products/launchlab/global-config) — les planchers du protocole qu'une règle affine.
* [`products/launchlab/instructions`](/fr/products/launchlab/instructions) — les quatre instructions de règle et leurs comptes.
* [`products/launchlab/accounts`](/fr/products/launchlab/accounts) — `PlatformCurveRule` dans l'inventaire des comptes.
* [`sdk-api/typescript-sdk`](/fr/sdk-api/typescript-sdk) — la surface du SDK où vivent les deux assistants de vérification.
* [`reference/changelog/2026-08-31-launchlab-platform-curve-rules`](/fr/reference/changelog/2026-08-31-launchlab-platform-curve-rules) — ce qui a remplacé la liste blanche de paramètres de courbe, et ce que les décodeurs doivent changer.

Sources :

* `raydium-launch/programs/launchpad/src/states/platform_curve_rule.rs` — `PlatformCurveRule`, `CurveRuleGroup`, `ParamConstraint`, les espaces d'id de champ et d'opérateur, et `CurveRuleContext::value_of`.
* `raydium-launch/programs/launchpad/src/utils/platform_curve_rule.rs` — la vérification au moment du lancement.
* `raydium-launch/programs/launchpad/src/instructions/platform/` — `create`, `update`, `remove`, et `close_platform_curve_rule`.
