Skip to main content
Esta página foi traduzida automaticamente por IA. A versão em inglês é a fonte oficial.Ver versão em inglês →
Uma regra de curva é a resposta de uma plataforma para “quais lançamentos estou disposto a hospedar?”. GlobalConfig define o piso do protocolo — pelo menos 10M de supply, pelo menos 20% da supply vendida na curva, e assim por diante — e esses pisos são deliberadamente amplos para que todo tipo de plataforma se encaixe neles. Uma regra de curva é onde sua plataforma os estreita para a forma que seu produto realmente suporta.As regras vivem em sua própria conta PlatformCurveRule, uma por par (plataforma, GlobalConfig). Elas só podem estreitar o que a config já permite; uma regra nunca pode ampliar um limite do protocolo.

O modelo mental

Três níveis, de fora para dentro:
Os dois níveis de aninhamento são o que torna isso expressivo:
  • Restrições dentro de um grupo são ANDadas. Todas elas devem ser válidas.
  • Grupos dentro de uma regra são ORados. Um lançamento é permitido assim que satisfaz qualquer grupo único.
Então um grupo é uma forma permitida, e a regra é o menu de formas que você oferece. Uma regra comporta até 10 grupos, e um grupo até 25 restrições. Dois casos extremos valem a pena memorizar: Uma regra entra em vigor apenas enquanto PlatformConfig.restrict_curve_param é 1. Em 0 o programa não lê regras, que é também o switch que você usa para desativar uma regra e para revertê-la.

Restrições

Uma restrição é uma tripla (campo, operador, valor). Nada mais — sem expressões, sem aninhamento.
Um intervalo são duas restrições no mesmo campo dentro de um grupo: um Gte para o piso e um Lte para o teto. O mesmo par (campo, operador) não pode aparecer duas vezes em um grupo, o que impede que você escreva dois mínimos contraditórios.

Campos

Os ids de campo são permanentes. Novos campos são apenas adicionados, então um id nunca muda de significado uma vez que uma conta de regra o contém.
Os campos derivados são os que tornam as regras portáveis. Fixar Supply e TotalFundRaisingB em números exatos fixa uma forma de lançamento; restringir FundRaisingRateB fixa a relação entre eles e permite que um criador escolha qualquer supply que a mantenha.
Campos de taxa são apenas comparáveis dentro de uma GlobalConfig, porque seus denominadores dependem do mint quote dessa config e de seus decimais. Isso não é uma limitação na prática: uma regra é escopo de uma config por construção.

Os nove playbooks

Cada playbook abaixo é uma regra. Restrições são escritas como (campo, operador, valor).

1. Um tier padrão

A regra mais simples, e o comportamento exato que a lista branca de parâmetros de curva aposentada oferecia: uma forma, fixada. Qualquer lançamento que desvie em qualquer um dos três é rejeitado com CurveParamNotMatchPlatformRule.

2. Uma banda em vez de um número

A razão pela qual bandas existem: um criador escolhe uma meta de arrecadação com a qual você se sente confortável, sem você enumerar cada valor. Um grupo, quatro restrições, e o criador tem um corredor de 50–200 SOL. Sob a lista branca antiga isso precisava de uma entrada por valor permitido, e o cap de dez entradas tornava impossível.

3. Tiers lado a lado

Grupos são ORados, então cada tier é um grupo. A ordem importa para computação, não para semântica: a avaliação para no primeiro grupo que corresponde, então coloque seu tier mais usado primeiro.

4. Uma banda de avaliação de graduação

FundRaisingRateB é TotalFundRaisingB / Supply em milionésimos. Restringi-lo limita o quão ricamente um token pode se graduar independentemente da supply que o criador escolheu. Com uma supply de 1e12 e um mint quote de 9 decimais, 85e9 / 1e12 × 1e6 = 85_000 fica dentro dessa banda. Um criador que dobra a supply deve aproximadamente dobrar a meta para ficar nela — que é o ponto. Duas restrições substituem o que seria uma tabela de pares (supply, target).

5. Um piso de migração

MigrateRateA é a fração da supply que realmente chega ao pool CPMM na graduação: Supply − TotalSellA − TotalLockedAmount, sobre supply. É a profundidade do pool graduado, e é o único knob do protocolo sem equivalente no lado da plataforma antes das regras existirem. Pelo menos 15% da supply chega ao pool. Um criador não pode vender 95% na curva e deixar um livro raso para trás.
Se os parâmetros não somam — uma quantidade bloqueada maior do que o que resta após a venda da curva — o valor derivado não pode ser computado e a restrição falha fechada, então o lançamento é rejeitado em vez de silenciosamente permitido.

6. Vesting que você realmente impõe

GlobalConfig.max_lock_rate limita vesting de cima. Uma regra pode colocar um piso sob ele, e exigir um cliff real. Entre 5% e 20% da supply bloqueada, com pelo menos um cliff de 30 dias. Útil para uma plataforma cuja proposta é “sem lançamentos com desbloqueio instantâneo”.

7. Gating por tipo de token

BaseTokenProgram e TransferFeeEnabled são independentes, o que importa: um mint Token-2022 sem TransferFeeConfig relata TransferFeeEnabled = 0 assim como um mint SPL Token faz.

8. Um cap de taxa de transferência condicional

Não há operador “if”, e nenhum é necessário — dois grupos expressam a condição. Uma TransferFeeConfig de taxa zero não passa pelo grupo 0: a extensão está presente, então TransferFeeEnabled é 1 e apenas o grupo 1 pode aceitá-la.

9. Uma promo com prazo, agendada antecipadamente

UnixTimestamp é o tempo de bloco do lançamento, então um grupo pode carregar sua própria janela de validade. Você escreve ambos os grupos hoje e a mudança acontece por conta própria. Nenhuma transação é necessária no limite. O custo é dois slots de grupo em vez de um.

Restrições de tipo de curva

Quatro campos leem TotalSellA: TotalSellA, SellRateA, MigrateAmountA, e MigrateRateA. Em uma config de produto constante o criador fornece esse número. Em uma config de preço fixo ou preço linear a curva o deriva em vez disso, e o valor que o programa compara é 0, o que rejeitaria todo lançamento. Em vez de deixar você escrever uma regra que silenciosamente bloqueia sua própria config, o programa recusa esses quatro campos no tempo de escrita em uma config não-produto-constante, com CurveRuleFieldNotSupportedByCurve. Apenas configs de produto constante existem hoje, então na prática você não encontrará esse erro.

Verifique antes de enviar

Ambas as direções da verificação on-chain estão disponíveis off-chain, então nem um criador nem uma plataforma precisa aprender uma regra observando transações reverterem.
Banner de versão.
  • SDK: @raydium-io/raydium-sdk-v2@0.2.42-alpha é a versão que todo outro demo de código neste site é fixado. Os dois helpers abaixo chegam com a versão do SDK que envia suporte a regra de curva; até então, porte-os do platform_curve_rule.rs do programa ou chame o programa e leia o código de erro.
  • Cluster: teste no devnet do Solana primeiro — veja Teste no devnet primeiro.
  • ID do programa: veja reference/program-addresses
Ambos os helpers são funções puras. Eles não tocam RPC, então são seguros para executar em cada keystroke em um formulário.

Antes de um lançamento: esses parâmetros passarão?

checkLaunchAgainstCurveRule espelha a verificação de tempo de lançamento do programa exatamente, incluindo seu comportamento de falha fechada. Execute-o em seu formulário de lançamento e você pode desabilitar o botão de envio com um motivo em vez de deixar o criador pagar por uma transação revertida.
Três coisas que o helper reproduz em vez de aproximar:
  • Uma conta de regra ausente, e uma regra sem grupo, ambas passam. Assim como um grupo sem restrições. Passe rule: undefined para uma conta inexistente; não a trate como uma rejeição.
  • Valores não computáveis falham fechado. Uma supply zero não tem taxas, e uma quantidade bloqueada maior do que o que a venda da curva deixa não tem quantidade de migração. actual volta undefined e a restrição conta como insatisfeita, exatamente como on-chain.
  • Todas as restrições falhando são relatadas, não apenas a primeira. O programa faz short-circuit porque só precisa de um veredicto; o helper coleta tudo para que seu formulário possa listar cada problema de uma vez.
A única coisa que ele não pode saber é o tempo de bloco em que sua transação realmente chegará. Se uma regra usa UnixTimestamp perto de um limite, trate uma aprovação como provisória.

Antes de escrever uma regra: esse grupo é válido?

checkCurveRuleGroupWritable espelha a validação de tempo de escrita de UpdatePlatformCurveRule — ids de restrição, a regra de (campo, operador) duplicado, ambos os limites de contagem, e a restrição de tipo de curva. Execute-o em sua ferramenta de admin de plataforma antes de assinar.
Passar nessa verificação significa que a transação não será rejeitada por ser malformada. Isso não diz nada sobre se a regra é o que você quis — um grupo pode ser perfeitamente válido e ainda rejeitar todo lançamento que sua UI pode produzir. É para isso que a verificação do lado do lançamento acima serve: depois de escrever um grupo, execute cada forma que seu produto oferece através de checkLaunchAgainstCurveRule e confirme que cada uma ainda encontra um grupo.

Teste no devnet primeiro

Habilitar restrict_curve_param na mainnet muda o que seus criadores podem fazer, imediatamente, para todo lançamento. Ensaie a sequência inteira no devnet antes de tocar na mainnet:
  1. Crie uma config de plataforma e uma regra no devnet, e escreva os mesmos grupos que você pretende enviar.
  2. Execute cada forma de lançamento que sua UI pode produzir através de checkLaunchAgainstCurveRule, e confirme que os veredictos são os que você espera — tanto as formas que devem passar quanto as formas que devem ser rejeitadas.
  3. Habilite restrict_curve_param, então realmente lance um token que deveria passar e um que deveria ser rejeitado. O segundo deveria falhar com CurveParamNotMatchPlatformRule (6025), não com NotEnoughRemainingAccounts (6018) — o último significa que seu builder não está adicionando o PDA de regra e a verificação não está sendo realmente exercida.
  4. Apenas então repita na mainnet, na mesma ordem.
Aponte o SDK para devnet com cluster: "devnet" quando você o carrega, e pegue o ID do programa devnet de reference/program-addresses. O passo 3 é o que vale a pena insistir. O helper off-chain e o programa on-chain são duas implementações das mesmas regras, e um lançamento devnet é o que prova que eles concordam para sua regra — incluindo que seu builder de lançamento passa a conta.

Operando uma regra

O gerenciador delegado

Editar regras é trabalho rotineiro; uma chave de admin de plataforma é geralmente um multisig. PlatformConfig.curve_rule_manager existe exatamente para isso: defina-o uma vez através de UpdatePlatformConfig::CurveRuleManager, e essa carteira quente pode então criar, atualizar, remover e fechar contas de regra por conta própria. O admin de plataforma retém o mesmo poder em paralelo, então uma chave de gerenciador perdida é recuperável — rotacione-a com outra chamada de admin. Escopo de uma chave de gerenciador comprometida: ela pode afrouxar ou deletar suas regras de parâmetro, e pode reclamar o aluguel de uma conta de regra. Ela não pode tocar em carteiras de taxa, vesting, a config CPMM, não pode virar restrict_curve_param, e não pode quebrar um limite de GlobalConfig. Trate-a como uma chave de configuração, não uma chave de tesouro.

Aluguel segue o conteúdo

Uma conta de regra é criada sem grupo e redimensionada em cada mudança, então você paga pelas regras que realmente escreveu. Remover um grupo reembolsa a diferença para o signatário.

Ordem de lançamento

  1. Ensaie a sequência inteira no devnet — veja Teste no devnet primeiro.
  2. Crie a conta de regra e escreva seus grupos. Nada muda ainda — com restrict_curve_param ainda em 0 o programa não as lê.
  3. Verifique a regra off-chain com checkLaunchAgainstCurveRule: para cada forma de lançamento que sua UI pode produzir, confirme que algum grupo a aceita.
  4. Defina restrict_curve_param para 1. A partir desse momento os lançamentos de seus criadores são verificados.
  5. Para reverter, defina-o para 0 novamente. A conta de regra é deixada intacta.
Seu builder de lançamento deve adicionar o PDA de regra a remaining_accounts enquanto restrict_curve_param é 1. O programa requer que a conta esteja presente mesmo quando ela não existe ainda, para que um criador não possa pular a verificação omitindo-a — uma conta ausente é NotEnoughRemainingAccounts, não uma aprovação. A derivação é [b"platform_curve_rule", platform_config, global_config].

Custo no tempo de lançamento

A verificação executa em todo lançamento enquanto está habilitada, então seu custo de computação é um imposto por lançamento. Medido de ponta a ponta — derivação de PDA, a varredura de remaining_accounts, desserialização e avaliação: “Barato” é uma leitura de campo direto como Supply; “derivado” é um computado como MigrateRateA, que custa cerca de 223 CU por restrição contra cerca de 48. Mesmo uma regra totalmente carregada de restrições derivadas fica dentro de um terço do orçamento padrão de 200 000 CU por instrução, e uma regra realista de três grupos fica sob 6 000. Grupos são avaliados até um corresponder, então ordenar seu tier comum primeiro é economia gratuita.

Para onde ir a seguir

Fontes:
  • raydium-launch/programs/launchpad/src/states/platform_curve_rule.rsPlatformCurveRule, CurveRuleGroup, ParamConstraint, os espaços de id de campo e operador, e CurveRuleContext::value_of.
  • raydium-launch/programs/launchpad/src/utils/platform_curve_rule.rs — a verificação de tempo de lançamento.
  • raydium-launch/programs/launchpad/src/instructions/platform/create, update, remove, e close_platform_curve_rule.