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

# 2026-09-09 — LaunchLab: Anchor 1.0, excess-lamports recovery, and the end of the transition gates

> LaunchLab переходит на Anchor 1.0.2 с Agave 3.1.10 и добавляет инструкцию admin CollectExcessLamports для возврата ренты, освобождённой SIMD-0437. Три переходных механизма удалены: устаревший Initialize теперь всегда падает, MigrateToAmm теряет три аргумента и девять аккаунтов OpenBook, а gate на основе часов get_upgrade_timestamp удалён. Добавлена ошибка 6031.

<Info>
  **Эта страница переведена с помощью ИИ. За эталон принимается английская версия.**

  [Открыть английскую версию →](/reference/changelog/2026-09-09-launchlab-anchor-1-and-excess-lamports)
</Info>

<Info>
  Этот релиз описывает предстоящее обновление программы LaunchLab. Он был проверен на локальной ветке релиза перед развёртыванием. Перед использованием новой инструкции или изменённого макета `MigrateToAmm` убедитесь в развёрнутой программе.
</Info>

Это релиз, где LaunchLab избавляется от своих переходных конструкций.

Три отдельных механизма существовали, чтобы сделать более ранние обновления мягкими: `get_upgrade_timestamp` — жёстко закодированная дата переключения, которую несколько проверок сравнивали с часами; устаревший `Initialize`, который продолжал работать три дня после этой даты; и OpenBook-сантехника `MigrateToAmm`, которой было не с чем разговаривать после того, как AMM v4 [удалила собственную зависимость от OpenBook](/ru/reference/changelog/2026-07-22-amm-v4-openbook-removal) в июле. Все три исчезли. На mainnet переключение произошло месяцы назад, поэтому поведенческий эффект нулевой — но *режимы отказа* изменились, и один список аккаунтов изменился кардинально.

Фреймворк переместился одновременно: Anchor `0.32.1` на `=1.0.2`, Agave 2.3.0 на 3.1.10. И, как на AMM v4 и CPMM, появилась новая инструкция admin для возврата ренты.

Торговля, комиссии, vesting, правила кривой и конфигурация платформы не затронуты.

## TL;DR для интеграторов

* **Ни одна инструкция торговли не изменила свои аккаунты, аргументы или математику.** `BuyExactIn`, `BuyExactOut`, `SellExactIn`, `SellExactOut` идентичны на уровне байтов. Ни один макет аккаунта не изменился.
* **`Initialize` (устаревший) теперь всегда падает с `NotApproved` (`6000`),** перед чтением любого аккаунта. Используйте `InitializeV2`. Запуски, уже созданные через него, торгуют и выпускаются нормально.
* **`MigrateToAmm` — жёсткий breaking change для кошелька миграции.** Он потерял все три аргумента (`base_lot_size`, `quote_lot_size`, `market_vault_signer_nonce`) и девять аккаунтов. См. ниже.
* **Три `remaining_accounts` торговли теперь безусловно требуются,** и слот `system_program` проверяется. Построитель, который их опускает, теперь всегда падает с `NotEnoughRemainingAccounts` (`6018`) вместо падения только после переключения.
* **Добавлена одна инструкция: `CollectExcessLamports`.** Только для admin. См. [`products/launchlab/instructions`](/ru/products/launchlab/instructions#collectexcesslamports).
* **Добавлен один код ошибки: `6031` `LamportsCalculateError`.** Коды `6000`–`6030` не изменены.
* **Три ограничения адреса `MigrateToCpswap` переместились в тело инструкции,** изменив их ошибку с `ConstraintAddress` (`2012`) на `RequireKeysEqViolated` (`2502`).
* **Требуется обновление IDL.** Одна новая инструкция, один удалённый набор аргументов, девять удалённых аккаунтов, один новый вариант ошибки.

## `MigrateToAmm` потеряла свою половину OpenBook

Это изменение, которое с наибольшей вероятностью что-то сломает. Старые данные инструкции содержали 17 байт аргументов после дискриминатора; новые данные — это голый дискриминатор. Старые списки аккаунтов содержали девять аккаунтов, которые больше не существуют в структуре, поэтому всё после первого удаления смещено.

**Удалённые аргументы:** `base_lot_size: u64`, `quote_lot_size: u64`, `market_vault_signer_nonce: u8`. Все три существовали только для конфигурации рынка OpenBook, который программа использовала для инициализации через CPI. Этот CPI — `initialize_openbook_market` — исчез, вместе с проверкой `gen_vault_signer_key`, которая валидировала nonce.

**Удалённые аккаунты:** `openbook_program`, `request_queue`, `event_queue`, `bids`, `asks`, `market_vault_signer`, `market_base_vault`, `market_quote_vault` и `amm_open_orders`. Последний исчез, потому что `Initialize2` AMM v4 больше его не принимает.

**Аккаунт `market` остаётся**, в своей исходной позиции. AMM v4 по-прежнему записывает рынок как поле ссылки на `AmmInfo`, поэтому LaunchLab по-прежнему его пересылает. Два момента о нём изменились: программа больше его не инициализирует, и он теперь **полностью не валидирован** — его объявление — это голый `#[account(mut)]` без ограничений владельца, адреса или seeds, потому что `owner = openbook_program.key()` исчез вместе с аккаунтом `openbook_program` и ничего его не заменило. Всё, что кошелёк миграции передаёт туда, пересылается прямо в CPI `Initialize2` AMM v4 и записывается на новый пул. Вызывающий, который хочет подлинно инициализированный рынок за этим полем, должен создать его заранее, и программа ему об этом не скажет.

Полученный список из 23 аккаунтов полностью задокументирован на [`products/launchlab/instructions`](/ru/products/launchlab/instructions#migratetoamm-/-migratetocpswap).

`MigrateToCpswap` не затронут — у него никогда не было аргументов, и его список аккаунтов не изменился.

## Устаревший `Initialize` всегда падает

`initialize` ранее запускал мягкую deprecation: он работал до `get_upgrade_timestamp() + 3 days`, затем возвращал `NotApproved`. С удалённым помощником timestamp отказ безусловный — обработчик теперь это просто `msg!` и `err!(NotApproved)` и ничего больше.

Один момент, если вы читаете логи: структура `Accounts` не изменена и по-прежнему содержит четыре ограничения `init`, поэтому сгенерированный Anchor пролог валидации аккаунтов запускается — и создаёт эти аккаунты — перед возвратом обработчика. Транзакция откатывается в любом случае, поэтому ничего не создаётся на самом деле, но отказ появляется после валидации аккаунтов, а не до неё.

Инструкция сохранена, а не удалена, поэтому её дискриминатор остаётся занятым и IDL сохраняет стабильную форму. Его определения аргументов и аккаунтов всё ещё стоят того, чтобы быть задокументированными для декодирования исторических транзакций, и страница их сохраняет за предупреждением.

## Gate `get_upgrade_timestamp` исчез

Помощник возвращал `0` под функциями `local` и `devnet` и жёстко закодированный timestamp mainnet `1755522000` (2025-08-18 13:00 UTC) в противном случае. Четыре инструкции сравнивали часы с ним, через пять ссылок в исходном коде. Каждая становится веткой post-cut-over безусловно:

| Место вызова                                      | До                                                                                                                                                                               | После                                                                                                                            |
| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `distribute_trade_fee` (все четыре пути торговли) | Читает `system_program`, `platform_fee_vault`, `creator_fee_vault` из `remaining_accounts` только после переключения; пропускала разделение платформы/создателя комиссии до него | Всегда читает все три, **и** требует, чтобы слот `system_program` равнялся `System::id()` или возвращает `InvalidInput` (`6002`) |
| `migrate_to_cpswap`                               | Выбирал `InitializeCpSwap` до, `InitializeCpSwapWithPermission` после                                                                                                            | Всегда разрешённый CPI; устаревший помощник `initialize_cpswap` удалён, и минимум из десяти remaining accounts безусловен        |
| `initialize_with_token_2022`                      | Требовал `amm_fee_on == BothToken` до переключения; запускал проверку правила кривой платформы только после него                                                                 | Нет ограничения `amm_fee_on`; проверка правила кривой запускается всякий раз, когда установлен `restrict_curve_param`            |
| `initialize` (устаревший)                         | Падал только после переключения плюс три дня                                                                                                                                     | Всегда падает                                                                                                                    |

Timestamp mainnet более чем на год в прошлом, поэтому правильный, актуальный построитель не видит изменения поведения. Что изменилось, так это то, что **устаревший** построитель теперь падает детерминированно вместо того, чтобы казаться работающим против devnet-сборки. Новая валидация `system_program` действительно новая: этот слот ранее принимал любой аккаунт.

## `CollectExcessLamports`

Шаг 1 [SIMD-0437](/ru/solana-fundamentals/rent-and-reclaimable-rent) приземлился на mainnet 3 сентября 2026 года, сократив минимум, освобождённый от ренты, на 9% с четырьмя дополнительными шагами впереди. Каждый vault пула LaunchLab, fee vault и PDA, принадлежащий программе, созданные до шага, теперь переполнены.

Инструкция принимает четыре фиксированных аккаунта — кошелёк подписывающего/получателя, **один** PDA authority vault и оба token programs — затем любое количество исходных аккаунтов в `remaining_accounts`.

Слот `authority` — это часть, которую стоит читать внимательно. LaunchLab имеет три PDA authority vault (`vault_auth_seed`, `platform_fee_vault_auth_seed`, `creator_fee_vault_auth_seed`), и инструкция разрешает переданный вами, переполучая все три и сопоставляя; ключ, не совпадающий ни с одним, падает с `InvalidOwner` (`6001`). Потому что один вызов несёт одну authority и token program требует, чтобы фактический владелец каждого аккаунта подписал, **исходные аккаунты должны быть сгруппированы по authority** — pool vaults, platform fee vaults и creator fee vaults очищаются в отдельных транзакциях. PDA, принадлежащие программе, дебетуются напрямую и могут ехать с любой authority.

Wrapped SOL следует той же последовательности `SyncNative` → delta-sized `UnwrapLamports` → assert-unchanged, которую используют CPMM и AMM v4, с `LamportsCalculateError` (`6031`), если round-trip не нетто к нулю. SOL-quoted запуск сохраняет свой полный quote reserve.

**Base mints не могут быть очищены.** `InitializeV2` и `InitializeWithToken2022` отзывают `MintTokens` в той же инструкции, которая чеканит предложение, поэтому ни один ключ не может подписать `WithdrawExcessLamports` для base mint. Его рента заблокирована по дизайну.

Подписывающий может быть либо общим admin программы, либо выделенным кошельком collect-lamports; адреса находятся в [`reference/program-addresses`](/ru/reference/program-addresses#excess-lamports-collection-wallets).

## Переместение ограничений `MigrateToCpswap`

Три ограничения аккаунтов переместились из структуры `Accounts` в тело инструкции:

```rust theme={null}
require_keys_eq!(ctx.accounts.platform_config.key(), ctx.accounts.pool_state.platform_config);
require_keys_eq!(ctx.accounts.base_vault.key(),      ctx.accounts.pool_state.base_vault);
require_keys_eq!(ctx.accounts.quote_vault.key(),     ctx.accounts.pool_state.quote_vault);
```

Требование идентично — все три должны по-прежнему совпадать со значениями, хранящимися на `PoolState`. Только поверхность ошибки отличается: универсальный `RequireKeysEqViolated` (`2502`) Anchor, сообщённый без имени аккаунта, вместо `ConstraintAddress` (`2012`), называющего нарушающий аккаунт. Обновите любую обработку ошибок, которая совпадала с `2012` для этих трёх аккаунтов.

## Изменения цепочки инструментов и зависимостей

| Элемент                        | До                        | После                                  |
| ------------------------------ | ------------------------- | -------------------------------------- |
| `anchor-lang` / `anchor-spl`   | `0.32.1`                  | `=1.0.2`                               |
| `Anchor.toml` `solana_version` | `2.3.0`                   | `3.1.10`                               |
| README: `rustup default`       | `1.81.0`                  | `1.91.0`                               |
| README: Solana installer       | `release.anza.xyz/v2.1.0` | `release.anza.xyz/v3.1.10`             |
| README: `avm install`          | `0.31.0`                  | `1.0.2` (плюс `avm use 1.0.2`)         |
| README: Anchor repo            | `coral-xyz/anchor`        | `solana-foundation/anchor`             |
| `@coral-xyz/anchor`            | `^0.32.1`                 | заменён на `@anchor-lang/core` `1.0.2` |
| `@solana/spl-token`            | `^0.4.0`                  | `^0.4.14`                              |
| `typescript`                   | `^4.3.5`                  | `^5.6.3`                               |
| `tsconfig` target / lib        | `es6` / `es2015`          | `ES2020` / `es2020`, `skipLibCheck`    |

Два изменения на месте вызова Anchor 1.0 применяются и здесь: `Context` сворачивается с четырёх параметров lifetime на один, и `CpiContext::new` принимает `Pubkey` программы, а не её `AccountInfo`. См. [`sdk-api/rust-cpi`](/ru/sdk-api/rust-cpi#cargo-dependencies).

Два деталя системы сборки без on-chain эффекта: функция `local` была заменена на `localnet`, которая компилирует локальный кошелёк как `admin` из переменной окружения `LAUNCHPAD_LOCALNET_ADMIN` (`yarn test:local-admin` её подключает), и дублирующийся блок `[profile.release]` в `programs/launchpad/Cargo.toml` был удалён — Cargo игнорирует `[profile]` вне корня workspace, поэтому блок корня уже был действующим, включая тот факт, что `panic = "abort"` блока уровня программы никогда не применялся.

## Что не изменилось

* **Каждый макет аккаунта.** `PoolState`, `GlobalConfig`, `PlatformConfig`, `PlatformCurveRule`, `PlatformAllowConfig`, vesting records — те же размеры, те же смещения.
* **Коды ошибок `6000`–`6030`,** включая намеренно сохранённый `6020`.
* **Математика кривой, ставки комиссий, начисление комиссий, расписания vesting и разделение LP выпуска.**
* **Правила кривой платформы и allowlist `GlobalConfig`.** Те же инструкции, те же аккаунты, та же семантика; только gate на основе часов вокруг проверки правила кривой исчез.
* **Список аккаунтов `MigrateToCpswap` и индексы `remaining_accounts`.**
* **Передача authority Token-2022 transfer-fee при выпуске.**
* **Program ID.** Не изменён.

## Обновлённые страницы

* `products/launchlab/instructions` — `CollectExcessLamports` добавлена со своим списком аккаунтов, таблицей разрешения authority и предупреждением о группировке; удаления аргументов и аккаунтов `MigrateToAmm` задокументированы с полным новым списком; `Initialize` предварена предупреждением о всегда-падает; новый раздел "Trade remaining accounts", охватывающий теперь безусловные три аккаунта и проверку `system_program`; примечание `MigrateToCpswap` о пути только с разрешением и переместённых ограничениях; инвентарь и строки матрицы изменения состояния.
* `products/launchlab/overview` — баннер релиза; инварианты "CPMM-only" и base-mint исправлены.
* `products/launchlab/accounts` — время отзыва mint-authority исправлено на создание запуска (оно было задокументировано при выпуске); строка `CollectExcessLamports` добавлена.
* `reference/error-codes` — `6031` задокументирована.
* `reference/program-addresses` — новый раздел "Excess-lamports collection wallets".
* `solana-fundamentals/rent-and-reclaimable-rent` — новый раздел "What the Raydium programs sweep on their own side".
* `sdk-api/rust-cpi`, `solana-fundamentals/toolchain` — pins Anchor 1.0 и примечания миграции CPI.
