Skip to main content
Эта страница переведена с помощью ИИ. За эталон принимается английская версия.Открыть английскую версию →
Правило кривой — это ответ платформы на вопрос «какие запуски я готов размещать?». GlobalConfig устанавливает протокольный минимум — минимум 10M предложения, минимум 20% предложения продано на кривой и так далее — и эти минимумы намеренно широкие, чтобы под них подходила любая платформа. Правило кривой — это то, где вы сужаете их до формы, которую ваш продукт действительно поддерживает.Правила хранятся в собственном аккаунте PlatformCurveRule, по одному на пару (платформа, GlobalConfig). Они могут только сужать то, что уже разрешает конфиг; правило никогда не может расширить протокольное ограничение.

Концептуальная модель

Три уровня, от внешнего к внутреннему:
Два уровня вложенности делают это выразительным:
  • Ограничения внутри одной группы объединяются через AND. Все они должны выполняться.
  • Группы внутри одного правила объединяются через OR. Запуск разрешён, как только он удовлетворяет любой одной группе.
Таким образом, группа — это одна допустимая форма, а правило — это меню форм, которые вы предлагаете. Правило может содержать до 10 групп, а группа — до 25 ограничений. Два граничных случая стоит запомнить: Правило вступает в силу только при PlatformConfig.restrict_curve_param равном 1. При 0 программа вообще не читает правила, это также переключатель, который вы используете для развёртывания правила и его отката.

Ограничения

Ограничение — это тройка (поле, операция, значение). Ничего больше — никаких выражений, никакой вложенности.
Диапазон — это два ограничения на одно поле внутри одной группы: Gte для минимума и Lte для максимума. Одна пара (поле, операция) не может появиться дважды в одной группе, что предотвращает написание двух противоречивых минимумов.

Поля

Идентификаторы полей постоянны. Новые поля добавляются только в конец, поэтому идентификатор никогда не меняет своё значение, как только аккаунт правила его содержит.
Производные поля — это то, что делает правила портативными. Привязка Supply и TotalFundRaisingB к точным числам фиксирует одну форму запуска; ограничение FundRaisingRateB фиксирует отношение между ними и позволяет создателю выбрать любое предложение, которое его сохраняет.
Поля ставок сравнимы только внутри одного GlobalConfig, потому что их знаменатели зависят от quote mint этого конфига и его decimals. На практике это не ограничение: правило по конструкции ограничено одним конфигом.

Девять сценариев

Каждый сценарий ниже — это одно правило. Ограничения записаны как (поле, операция, значение).

1. Один стандартный уровень

Самое простое правило и точное поведение, которое предлагал снятый с производства whitelist параметров кривой: одна форма, зафиксированная. Любой запуск, отклоняющийся в любом из трёх параметров, отклоняется с CurveParamNotMatchPlatformRule.

2. Диапазон вместо числа

Причина существования диапазонов: создатель выбирает целевой объём сбора средств, с которым вы согласны, без перечисления каждого значения. Одна группа, четыре ограничения, и создатель имеет коридор 50–200 SOL. При старом whitelist это требовало одной записи на каждое допустимое значение, и лимит в десять записей делал это невозможным.

3. Уровни рядом

Группы объединяются через OR, поэтому каждый уровень — это группа. Порядок имеет значение для вычислений, а не для семантики: оценка останавливается на первой группе, которая совпадает, поэтому поместите ваш наиболее используемый уровень первым.

4. Диапазон оценки при выпуске

FundRaisingRateB — это TotalFundRaisingB / Supply в миллионных долях. Ограничение его ограничивает, насколько богато токен может выпуститься, независимо от предложения, которое выбрал создатель. С предложением 1e12 и 9-десятичным quote mint, 85e9 / 1e12 × 1e6 = 85_000 находится внутри этого диапазона. Создатель, который удвоит предложение, должен примерно удвоить целевой объём, чтобы остаться в нём — это и есть смысл. Два ограничения заменяют то, что иначе было бы таблицей пар (предложение, целевой объём).

5. Минимум миграции

MigrateRateA — это доля предложения, которая действительно попадает в пул CPMM при выпуске: Supply − TotalSellA − TotalLockedAmount, делённое на предложение. Это глубина выпущенного пула, и это единственный протокольный рычаг без эквивалента на стороне платформы до появления правил. Минимум 15% предложения достигает пула. Создатель не может продать 95% на кривой и оставить поверхностную книгу позади.
Если параметры не складываются — заблокированная сумма больше, чем остаётся после продажи на кривой — производное значение не может быть вычислено и ограничение не срабатывает, поэтому запуск отклоняется, а не молча разрешается.

6. Vesting, который вы действительно обеспечиваете

GlobalConfig.max_lock_rate ограничивает vesting сверху. Правило может установить минимум, и требовать реальный cliff. От 5% до 20% предложения заблокировано, с минимум 30-дневным cliff. Полезно для платформы, чей слоган — «никаких запусков с мгновенной разблокировкой».

7. Гейтинг по типу токена

BaseTokenProgram и TransferFeeEnabled независимы, что важно: mint Token-2022 без TransferFeeConfig сообщает TransferFeeEnabled = 0 так же, как mint SPL Token.

8. Условный потолок комиссии за передачу

Нет оператора «если», и он не нужен — две группы выражают условие. Нулевая ставка TransferFeeConfig не проходит через группу 0: расширение присутствует, поэтому TransferFeeEnabled равен 1 и только группа 1 может его принять.

9. Ограниченная по времени акция, запланированная заранее

UnixTimestamp — это время блока запуска, поэтому группа может нести своё собственное окно действительности. Вы пишете обе группы сегодня, и переключение происходит само по себе. На границе не требуется никакой транзакции. Стоимость — две группы вместо одной.

Ограничения по типу кривой

Четыре поля читают TotalSellA: TotalSellA, SellRateA, MigrateAmountA и MigrateRateA. На constant-product конфиге создатель предоставляет это число. На fixed-price или linear-price конфиге кривая вместо этого его выводит, и значение, которое программа сравнивает, — это 0, что отклонило бы каждый запуск. Чтобы не позволить вам написать правило, которое молча блокирует ваш собственный конфиг, программа отказывает в этих четырёх полях во время записи на non-constant-product конфиге с CurveRuleFieldNotSupportedByCurve. Сегодня существуют только constant-product конфиги, поэтому на практике вы не встретите эту ошибку.

Проверьте перед отправкой

Обе стороны проверки on-chain доступны off-chain, поэтому ни создателю, ни платформе не нужно изучать правило, наблюдая за откатом транзакций.
Баннер версии.
  • SDK: @raydium-io/raydium-sdk-v2@0.2.42-alpha — это версия, к которой привязаны все остальные примеры кода на этом сайте. Два помощника ниже поступают с выпуском SDK, который поставляет поддержку curve-rule; до тех пор портируйте их из platform_curve_rule.rs программы или вызовите программу и прочитайте код ошибки.
  • Кластер: сначала протестируйте на Solana devnet — см. Сначала протестируйте на devnet.
  • Program ID: см. reference/program-addresses
Оба помощника — это чистые функции. Они не касаются RPC, поэтому безопасно запускать их на каждом нажатии клавиши в форме.

Перед запуском: пройдут ли эти параметры?

checkLaunchAgainstCurveRule точно отражает проверку программы во время запуска, включая её поведение fail-closed. Запустите её в форме запуска и вы можете отключить кнопку отправки с причиной вместо того, чтобы позволить создателю платить за откатившуюся транзакцию.
Три вещи, которые помощник воспроизводит, а не приблизительно:
  • Отсутствующий аккаунт правила и правило без группы оба проходят. Так же как и группа без ограничений. Передайте rule: undefined для несуществующего аккаунта; не рассматривайте это как отклонение.
  • Невычислимые значения не срабатывают. Нулевое предложение не имеет ставок, и заблокированная сумма больше, чем остаётся после продажи на кривой, не имеет суммы миграции. actual возвращается undefined и ограничение считается неудовлетворённым, точно как on-chain.
  • Все неудовлетворённые ограничения сообщаются, не только первое. Программа короткозамыкается, потому что ей нужен только вердикт; помощник собирает всё, чтобы ваша форма могла перечислить каждую проблему сразу.
Единственное, что он не может знать, — это время блока, в которое ваша транзакция действительно приземлится. Если правило использует UnixTimestamp рядом с границей, рассматривайте прохождение как предварительное.

Перед написанием правила: действительна ли эта группа?

checkCurveRuleGroupWritable отражает валидацию во время записи UpdatePlatformCurveRule — идентификаторы ограничений, правило дублирования (поле, операция), оба лимита подсчёта и ограничение по типу кривой. Запустите её в инструменте администратора платформы перед подписанием.
Прохождение этой проверки означает, что транзакция не будет отклонена за неправильный формат. Это ничего не говорит о том, является ли правило тем, что вы имели в виду — группа может быть совершенно действительной и всё ещё отклонять каждый запуск, который может произвести ваш UI. Для этого предназначена проверка на стороне запуска выше: после написания группы запустите каждую форму, которую может произвести ваш продукт, через checkLaunchAgainstCurveRule и подтвердите, что каждая всё ещё находит группу.

Сначала протестируйте на devnet

Включение restrict_curve_param на mainnet меняет то, что могут делать ваши создатели, немедленно, для каждого запуска. Отрепетируйте всю последовательность на devnet перед тем, как трогать mainnet:
  1. Создайте конфиг платформы и правило на devnet, и напишите те же группы, которые вы намерены отправить.
  2. Запустите каждую форму запуска, которую может произвести ваш UI, через checkLaunchAgainstCurveRule, и подтвердите, что вердикты — это те, которые вы ожидаете — как формы, которые должны пройти, так и формы, которые должны быть отклонены.
  3. Включите restrict_curve_param, затем действительно запустите токен, который должен пройти, и один, который должен быть отклонен. Второй должен не пройти с CurveParamNotMatchPlatformRule (6025), а не с NotEnoughRemainingAccounts (6018) — последнее означает, что ваш builder не добавляет PDA правила и проверка не действительно выполняется.
  4. Только затем повторите на mainnet, в том же порядке.
Пункт 3 — это тот, на котором стоит настаивать. Off-chain помощник и on-chain программа — это две реализации одних и тех же правил, и запуск на devnet — это то, что доказывает, что они согласны для вашего правила — включая то, что ваш builder запуска передаёт аккаунт вообще.

Управление правилом

Делегированный менеджер

Редактирование правил — это рутинная работа; ключ администратора платформы обычно — это multisig. PlatformConfig.curve_rule_manager существует именно для этого: установите его один раз через UpdatePlatformConfig::CurveRuleManager, и этот горячий кошелёк может затем создавать, обновлять, удалять и закрывать аккаунты правил самостоятельно. Администратор платформы сохраняет ту же власть параллельно, поэтому потерянный ключ менеджера восстанавливаем — ротируйте его другим вызовом администратора. Область скомпрометированного ключа менеджера: он может ослабить или удалить ваши правила параметров и вернуть себе rent аккаунта правила. Он не может трогать кошельки комиссий, vesting, конфиг CPMM, не может переключить restrict_curve_param и не может нарушить лимит GlobalConfig. Рассматривайте это как ключ конфигурации, а не ключ казны.

Rent следует за содержимым

Аккаунт правила создаётся без группы и изменяется в размере при каждом изменении, поэтому вы платите за правила, которые вы действительно написали. Удаление группы возвращает разницу подписывающему.

Порядок развёртывания

  1. Отрепетируйте всю последовательность на devnet — см. Сначала протестируйте на devnet.
  2. Создайте аккаунт правила и напишите его группы. Ничего не меняется — при restrict_curve_param всё ещё 0 программа их не читает.
  3. Проверьте правило off-chain с checkLaunchAgainstCurveRule: для каждой формы запуска, которую может произвести ваш UI, подтвердите, что какая-то группа её принимает.
  4. Установите restrict_curve_param на 1. С этого момента запуски ваших создателей проверяются.
  5. Чтобы откатить, установите его на 0 снова. Аккаунт правила остаётся нетронутым.
Ваш builder запуска должен добавить PDA правила в remaining_accounts пока restrict_curve_param равен 1. Программа требует, чтобы аккаунт был присутствующим даже когда он ещё не существует, поэтому создатель не может пропустить проверку, опустив его — отсутствующий аккаунт — это NotEnoughRemainingAccounts, а не прохождение. Вывод — это [b"platform_curve_rule", platform_config, global_config].

Стоимость во время запуска

Проверка выполняется при каждом запуске пока она включена, поэтому её стоимость вычислений — это налог за запуск. Измеренный end-to-end — вывод PDA, сканирование remaining_accounts, десериализация и оценка: «Дешёвый» — это прямое чтение поля, такое как Supply; «производный» — это вычисленный, такой как MigrateRateA, который стоит примерно 223 CU за ограничение против примерно 48. Даже полностью загруженное правило производных ограничений остаётся внутри трети бюджета по умолчанию 200 000 CU за инструкцию, и реалистичное трёхгруппное правило — под 6 000. Группы оцениваются до тех пор, пока одна не совпадёт, поэтому размещение вашего общего уровня первым — это бесплатная экономия.

Куда дальше

Источники:
  • raydium-launch/programs/launchpad/src/states/platform_curve_rule.rsPlatformCurveRule, CurveRuleGroup, ParamConstraint, пространства идентификаторов полей и операций, и 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.