> ## 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、超额 lamports 回收和过渡门的终结

> LaunchLab 升级到 Agave 3.1.10 上的 Anchor 1.0.2，并添加了管理员 CollectExcessLamports 指令以回收 SIMD-0437 释放的租金。三个过渡机制已停用：已弃用的 Initialize 现在始终失败，MigrateToAmm 失去了三个参数和九个 OpenBook 账户，基于时钟的 get_upgrade_timestamp 门已删除。错误 6031 已追加。

<Info>
  **本页内容由 AI 自动翻译，所有内容以英文版本为准。**

  [查看英文版 →](/reference/changelog/2026-09-09-launchlab-anchor-1-and-excess-lamports)
</Info>

<Info>
  本条目涵盖即将推出的 LaunchLab 程序更新。在部署前已针对本地发布分支进行了验证。在依赖新指令或更改的 `MigrateToAmm` 布局之前，请确认已部署的程序。
</Info>

这是 LaunchLab 停止携带其过渡脚手架的版本。

存在三个独立的机制来使早期升级平稳落地：`get_upgrade_timestamp`，一个硬编码的截止日期，多个检查会将时钟与其进行比较；一个已弃用的 `Initialize`，在该日期之后的三天内继续工作；以及 `MigrateToAmm` 的 OpenBook 管道，在 AMM v4 于 7 月[移除了自己的 OpenBook 依赖](/zh/reference/changelog/2026-07-22-amm-v4-openbook-removal)后就没有任何东西可以与之通信。这三个都已消失。在主网上，截止日期已经过去数月，所以行为影响为零——但*失败模式*已改变，一个账户列表也发生了硬性改变。

框架同时也进行了迁移：Anchor `0.32.1` 到 `=1.0.2`，Agave 2.3.0 到 3.1.10。而且，就像在 AMM v4 和 CPMM 上一样，有一个新的管理员指令用于回收租金。

交易、费用、归属、曲线规则和平台配置保持不变。

## 集成者速览

* **没有交易指令改变其账户、参数或数学。** `BuyExactIn`、`BuyExactOut`、`SellExactIn`、`SellExactOut` 在字节上完全相同。没有账户布局改变。
* **`Initialize`（已弃用的那个）现在始终以 `NotApproved`（`6000`）失败，** 在读取任何账户之前。使用 `InitializeV2`。通过它创建的已启动项目正常交易和毕业。
* **`MigrateToAmm` 对迁移钱包是硬性破坏。** 它失去了全部三个参数（`base_lot_size`、`quote_lot_size`、`market_vault_signer_nonce`）和九个账户。见下文。
* **三个交易 `remaining_accounts` 现在无条件地被要求，** 并且 `system_program` 槽被验证。省略它们的构建者现在始终以 `NotEnoughRemainingAccounts`（`6018`）失败，而不是仅在截止日期后失败。
* **添加了一个指令：`CollectExcessLamports`。** 仅限管理员。见[`products/launchlab/instructions`](/zh/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`。这三个都仅存在于配置程序曾经通过 CPI 初始化的 OpenBook 市场。该 CPI——`initialize_openbook_market`——已消失，连同验证 nonce 的 `gen_vault_signer_key` 检查。

**移除的账户：** `openbook_program`、`request_queue`、`event_queue`、`bids`、`asks`、`market_vault_signer`、`market_base_vault`、`market_quote_vault` 和 `amm_open_orders`。最后一个被移除是因为 AMM v4 的 `Initialize2` 不再接受它。

**`market` 账户保留，** 在其原始位置。AMM v4 仍然将市场记录为 `AmmInfo` 上的参考字段，所以 LaunchLab 仍然转发它。关于它的两件事改变了：程序不再初始化它，并且它现在**完全未验证**——其声明是一个裸 `#[account(mut)]`，没有所有者、地址或种子约束，因为 `owner = openbook_program.key()` 与 `openbook_program` 账户一起被移除，没有任何东西替代它。迁移钱包传递的任何东西都直接转发到 AMM v4 的 `Initialize2` CPI 并记录在新池上。想要在该字段后面有真正初始化市场的调用者必须事先创建它，程序不会告诉它否则。

生成的 23 账户列表在[`products/launchlab/instructions`](/zh/products/launchlab/instructions#migratetoamm-/-migratetocpswap)上完整记录。

`MigrateToCpswap` 不受影响——它从未有参数，其账户列表保持不变。

## 已弃用的 `Initialize` 始终失败

`initialize` 之前运行软弃用：它工作到 `get_upgrade_timestamp() + 3 days`，然后返回 `NotApproved`。随着时间戳助手被删除，失败是无条件的——处理程序现在是一个 `msg!` 和 `err!(NotApproved)` 仅此而已。

如果你在读日志，有一个细节：`Accounts` 结构保持不变，仍然携带四个 `init` 约束，所以 Anchor 生成的账户验证序言运行——并创建这些账户——在处理程序返回之前。无论哪种方式交易都会还原，所以实际上没有创建任何东西，但失败出现在账户验证之后而不是之前。

指令被保留而不是移除，所以其判别器保持被占用，IDL 保持稳定的形状。其参数和账户定义仍然值得为解码历史交易而记录，页面将它们保留在警告后面。

## `get_upgrade_timestamp` 门已消失

该助手在 `local` 和 `devnet` 功能下返回 `0`，否则返回硬编码的主网时间戳 `1755522000`（2025-08-18 13:00 UTC）。四个指令将时钟与其进行比较，源中有五个引用。每个都无条件地变成截止后分支：

| 调用位置                             | 之前                                                                                                        | 之后                                                                               |
| -------------------------------- | --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| `distribute_trade_fee`（所有四个交易路径） | 仅在截止后从 `remaining_accounts` 读取 `system_program`、`platform_fee_vault`、`creator_fee_vault`；在截止前跳过平台/创建者费用分割 | 始终读取全部三个，**并且**要求 `system_program` 槽等于 `System::id()` 或返回 `InvalidInput`（`6002`） |
| `migrate_to_cpswap`              | 之前选择 `InitializeCpSwap`，之后选择 `InitializeCpSwapWithPermission`                                             | 始终是许可的 CPI；遗留的 `initialize_cpswap` 助手被删除，十个剩余账户的最小值是无条件的                         |
| `initialize_with_token_2022`     | 在截止前要求 `amm_fee_on == BothToken`；仅在截止后运行平台曲线规则检查                                                          | 没有 `amm_fee_on` 限制；只要设置了 `restrict_curve_param`，曲线规则检查就运行                        |
| `initialize`（已弃用）                | 仅在截止后加三天失败                                                                                                | 始终失败                                                                             |

主网时间戳已过去一年多，所以正确的、最新的构建者看不到行为改变。改变的是**陈旧的**构建者现在确定性地失败，而不是看起来对 devnet 构建有效。新的 `system_program` 验证是真正的新增：该槽之前接受任何账户。

## `CollectExcessLamports`

[SIMD-0437](/zh/solana-fundamentals/rent-and-reclaimable-rent) 的第 1 步于 2026 年 9 月 3 日在主网上落地，将租金豁免最小值削减了 9%，还有四个步骤要来。在步骤之前创建的每个 LaunchLab 池金库、费用金库和程序拥有的 PDA 现在都资金过剩。

指令接受四个固定账户——签名者/目标钱包、**一个**金库权限 PDA 和两个代币程序——然后 `remaining_accounts` 中任意数量的源账户。

`authority` 槽是值得仔细阅读的部分。LaunchLab 有三个金库权限 PDA（`vault_auth_seed`、`platform_fee_vault_auth_seed`、`creator_fee_vault_auth_seed`），指令通过重新推导全部三个并匹配来解析你传递的任何一个；与任何一个都不匹配的密钥以 `InvalidOwner`（`6001`）失败。因为一个调用携带一个权限，代币程序要求每个账户的实际所有者签名，**源账户必须按权限分组**——池金库、平台费用金库和创建者费用金库在单独的交易中清扫。程序拥有的 PDA 直接扣除，可以与任何权限一起进行。

包装的 SOL 遵循 CPMM 和 AMM v4 使用的相同 `SyncNative` → 增量大小的 `UnwrapLamports` → 断言不变序列，如果往返不净为零，则为 `LamportsCalculateError`（`6031`）。SOL 报价的启动保持其完整的报价储备。

**基础铸币不能被清扫。** `InitializeV2` 和 `InitializeWithToken2022` 在铸造供应的同一指令中撤销 `MintTokens`，所以没有密钥可以为基础铸币签署 `WithdrawExcessLamports`。其租金被设计地搁置。

签名者可以是共享程序管理员或专用收集 lamports 钱包；地址在[`reference/program-addresses`](/zh/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` 上的值。只有错误表面不同：Anchor 的通用 `RequireKeysEqViolated`（`2502`），报告时不带账户名，而不是 `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 安装程序             | `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 仓库               | `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` 从四个生命周期参数折叠为一个，`CpiContext::new` 接受程序的 `Pubkey` 而不是其 `AccountInfo`。见[`sdk-api/rust-cpi`](/zh/sdk-api/rust-cpi#cargo-dependencies)。

两个构建系统细节没有链上影响：`local` 功能被替换为 `localnet`，它从 `LAUNCHPAD_LOCALNET_ADMIN` 环境变量将本地钱包编译为 `admin`（`yarn test:local-admin` 连接它），`programs/launchpad/Cargo.toml` 中的重复 `[profile.release]` 块被删除——Cargo 忽略工作区根外的 `[profile]`，所以根块已经是生效的那个，包括程序级块的 `panic = "abort"` 从未被应用的事实。

## 未改变的内容

* **每个账户布局。** `PoolState`、`GlobalConfig`、`PlatformConfig`、`PlatformCurveRule`、`PlatformAllowConfig`、归属记录——相同的大小、相同的偏移。
* **错误代码 `6000`–`6030`，** 包括故意保留的 `6020`。
* **曲线数学、费率、费用应计、归属计划和毕业 LP 分割。**
* **平台曲线规则和 `GlobalConfig` 允许列表。** 相同的指令、相同的账户、相同的语义；只有围绕曲线规则检查的时钟门消失了。
* **`MigrateToCpswap` 的账户列表和 `remaining_accounts` 索引。**
* **Token-2022 转账费权限在毕业时的交接。**
* **程序 ID。** 保持不变。

## 更新的页面

* `products/launchlab/instructions` — 添加了 `CollectExcessLamports` 及其账户列表、权限解析表和分组警告；`MigrateToAmm` 的参数和账户移除已记录，包含完整的新列表；`Initialize` 以始终失败警告开头；新的"交易剩余账户"部分涵盖现在无条件的三个账户和 `system_program` 检查；`MigrateToCpswap` 关于仅许可路径和重定位约束的注释；库存和状态变化矩阵行。
* `products/launchlab/overview` — 发布横幅；"仅 CPMM"和基础铸币不变量已更正。
* `products/launchlab/accounts` — 铸币权限撤销时间已更正为启动创建（之前在毕业时记录）；添加了 `CollectExcessLamports` 行。
* `reference/error-codes` — 已记录 `6031`。
* `reference/program-addresses` — 新的"超额 lamports 收集钱包"部分。
* `solana-fundamentals/rent-and-reclaimable-rent` — 新的"Raydium 程序在其自身方面清扫的内容"部分。
* `sdk-api/rust-cpi`、`solana-fundamentals/toolchain` — Anchor 1.0 引脚和 CPI 迁移注释。
