本页内容由 AI 自动翻译,所有内容以英文版本为准。查看英文版 →
LaunchLab 提供了一套精简的指令集:六个面向用户的调用加上少数管理员原语。SDK 包装了所有这些;本页为聚合器、监控工具和需要 CPI 的程序记录了原始接口。2026-09 程序升级在 Anchor 1.0.2 / Solana 3.1.10 上重建了 LaunchLab,并清除了三个过渡机制:已弃用的
Initialize 现在总是失败,MigrateToAmm 失去了它的三个参数和每个 OpenBook 账户,而 get_upgrade_timestamp 门控(使多个检查以时钟为条件)已消失。它还添加了一个管理员指令 CollectExcessLamports。参见 2026-09-09 更新日志条目。指令清单
“ExactIn/ExactOut” 分割镜像 CPMM 的
SwapBaseInput / SwapBaseOutput — 在链上它们是具有略微不同舍入的单独指令判别器。
毕业路径选择。 每个新的 InitializeV2 和 InitializeWithToken2022 调用必须设置 migrate_type = 1(CPSWAP)。任何尝试初始化新的 AMM v4 绑定池都会返回 MigrateTypeNotMatch。amm_creator_fee_on 仅选择生成的 CPMM 创建者费用是否适用于报价代币或两个代币;它不选择目标程序。遗留的 Initialize 根本无法创建启动(见下文)。
MigrateToAmm 对于在此限制之前使用 migrate_type = 0 初始化的现有 PoolState 仍可调用。该版本不重写现有池状态或删除遗留指令。
报价端代币程序。 报价代币可由 SPL Token 程序或 Token-2022 拥有。每个接触它的指令 — CreateConfig、InitializeV2、InitializeWithToken2022、所有四个交易指令、CollectFee、CollectMigrateFee、ClaimCreatorFee、ClaimPlatformFee 和 ClaimPlatformFeeFromVault — 在其报价程序账户槽中接受拥有程序。账户位置没有改变;只有接受的值改变了。传递实际拥有 GlobalConfig.quote_mint 的程序,你可以从现有启动的 PoolState.token_program_flag bit1 读取它(见 accounts)或从代币账户的所有者读取。
已弃用的 Initialize 在这里无关紧要:其报价程序账户仍然类型为 SPL Token,自 2026-09 升级以来该指令在读取任何账户之前失败。通过 InitializeV2 或 InitializeWithToken2022 启动。
MigrateToCpswap 是另一个例外,方向相反 — 它无条件地接受两个程序而不是每个代币一个。见下面的 迁移账户。
Initialize
创建新启动。相对已弃用的 Initialize,InitializeV2 只多了 amm_fee_on 参数;账户的数量和顺序完全相同,唯一的账户级差异是 quote_token_program 的类型为 Interface<TokenInterface>,因此可以接受 Token-2022 报价铸币。
参数
四个位置参数,而不是一个结构体。(InitializeWithToken2022 追加第五个参数 transfer_fee_extension_param: Option<TransferFeeExtensionParams>;已弃用的 Initialize 去掉了 amm_fee_on。)
global_config.curve_type 匹配,否则指令会以 InputNotMatchCurveConfig(6003)回滚。不存在 open_time,没有 quote_mint 参数(它来自 global_config),没有 fees 结构体,也没有 post_graduation_lp_policy —— LP 处置在 PlatformConfig 上设置,而不是按每个启动设置。
账户 —— 共 18 个(16 个声明的,加上 #[event_cpi] 追加的两个)
前置条件
quote_mint ∈ launch_config.allowed_quote_mints。base_supply_graduation ≤ base_supply_max。- 费用参数通过
launch_config.max_*_fee_rate检查。 open_time ≥ now − slop(SDK 强制≥ now;程序容忍轻微回溯)。curve_type被识别。
base_mint有supply = curve_param.supply,全部在base_vault中。- 铸币权限在同一条指令中、供应量铸造完毕后立刻被撤销(
set_authority(MintTokens, None))—— 而不是在毕业时。因此基础铸币永久固定供应量,之后任何指令都无法再铸造。 PoolState初始化为status = Fund(0)、real_a = 0、real_b = 0。total_fund_raising_b直接来自curve_param.total_quote_fund_raising。- 对于带有
TransferFeeConfig的InitializeWithToken2022:transfer_fee_config_authority = launch_authority,当该字段被设置时withdraw_withheld_authority = PlatformConfig.transfer_fee_extension_auth,否则为launch_authority。提取端在铸币创建时被写入,正是为了让平台可以在毕业前扫除扣留的费用。见platform-config。
NotApproved(6000,对已弃用的 Initialize 无条件触发)、InvalidInput(6002,违反了来自 GlobalConfig 的某个供应量/费率/募资下限)、InputNotMatchCurveConfig(6003,curve_param 变体与 global_config.curve_type 不匹配)、MigrateTypeNotMatch(6007,migrate_type != 1)、MathOverflow(6008)、VestingRatioTooHigh(6010)、NoSupportExtension(6017)、NotEnoughRemainingAccounts(6018)、InvalidPlatformAllowConfig(6022)、CurveParamNotMatchPlatformRule(6025)。Anchor 的 address = / constraint = 检查失败会表现为 2xxx 代码,而不是上述之一 —— 程序的错误枚举里并不存在 InvalidQuoteMint、FeeRateTooHigh 或 InvalidCurveParams。
Buy(规范变体:BuyExactIn)
用户提供固定的输入数量;曲线计算输出。
参数
剩余账户 —— 费用管线,按这个确切顺序读取:
share_fee_receiver—— 仅当share_fee_rate > 0时。system_program—— 总是需要;会检查== System::id(),否则报InvalidInput。platform_fee_vault—— PDA[platform_config, quote_token_mint];首次使用时创建。creator_fee_vault—— PDA[creator, quote_token_mint];首次使用时创建。
NotEnoughRemainingAccounts(6018)。这里没有 associated_token_program
槽位,而 system_program 是一个剩余账户,而不是声明的账户。
前置条件
launch_state.status == Active。now ≥ open_time。user_quote_ata.balance ≥ quote_in。quote_in > 0。
- 将
quote_in分割为quote_in_after_fee和费用部分。 - 牛顿求解曲线以获得给定后费用报价的
base_out。 require(base_out ≥ minimum_base_out)否则还原ExceededSlippage。- 移动
quote_in用户 → 金库。移动base_out金库 → 用户。 - 更新
base_sold += base_out、quote_reserve_real += quote_in_after_fee × (lp_share / total_share)。 - 更新费用计数器(
protocol_fees_quote、creator_fees_quote)。 state_data.num_buys += 1。- 如果更新后
quote_reserve_real ≥ quote_reserve_target,SDK 通常在同一交易中链接Graduateix。程序不在Buy内自动毕业 — 需要后续的Graduate。
BuyExactOut
用户指定精确的 base_out;程序计算 quote_in。
参数
BuyExactIn 相同的账户,以及相同的剩余账户约定。使用闭式二次积分(或 curve_type 1 的 CPMM 逆)而不是牛顿迭代。
Sell / SellExactIn / SellExactOut
Buy 的镜像。用户将 base_in 返回到曲线并接收 quote_out。费用从 quote_out 中扣除,所以用户收到的少于原始集成收益。
前置条件 —
user_base_ata.balance ≥ base_in。- 卖出不能将
base_sold推低于 0(给定会计一致,与上述冗余)。 - 启动是
Active。
Buy。base_sold 减少,quote_reserve_real 减少。费用仍然累积。
报价端转账费用
当报价代币携带TransferFeeConfig 时,金库移动的金额和支付者被扣除或记入的金额不同,滑点界限针对支付者端进行检查。在没有扩展的报价代币上,下面的每种情况都与普通遗留代币相同。
报价的两个后果:
- 计算为代币无费用的界限被拒绝。将无费用成本作为
maximum_amount_in传递,或将无费用收益作为minimum_amount_out传递,会以ExceededSlippage还原。 real_quote仅按到达金库的内容推进。5% 报价代币上的BuyExactInamount_in将real_quote移动amount_in × 0.95。
10000 基点)无法反演,在精确输出路径上以 CalculateOverflow 还原。
两个交易端代币也被限制为在其匹配槽中传递的程序,所以不匹配的 base_token_program 现在失败而不是被忽略。见 algorithms/token-2022-transfer-fees 了解底层费用数学。
交易剩余账户
所有四个交易指令通过remaining_accounts 按此顺序接受其费用管道:
在 2026-09 中改变:最后三个现在是无条件的,
system_program 被验证。 在此版本之前,程序仅在 unix_timestamp >= get_upgrade_timestamp() 时读取它们,并在该时刻之前完全跳过平台/创建者费用分割。时间戳已过去,所以主网上的行为实际上没有改变 — 但分支已从代码中消失,仍然省略三个账户的构建器现在总是以 NotEnoughRemainingAccounts(6018)失败,而不仅仅在切换后。system_program 槽另外针对 System::id() 进行检查,如果它持有其他任何内容则返回 InvalidInput(6002),而以前任何账户都在该位置被接受。MigrateToAmm / MigrateToCpswap
一旦曲线达到 total_quote_fund_raising,将启动毕业到可交易的池中。新启动仅限 CPMM。MigrateToAmm 为存储的 migrate_type 为 0 的现有池保留。
谁签署
MigrateToAmm— 绑定GlobalConfig上记录的migrate_to_amm_wallet。MigrateToCpswap— 绑定GlobalConfig上记录的migrate_to_cpswap_wallet。
- 验证
pool_state.status == Migrate(即quote_reserve_target已达到)。否则以PoolMigrated(状态已是Migrated)或PoolFunding(仍在融资)还原。 - 验证
pool_state.migrate_type匹配指令(AMM 为0,CPMM 为1)。否则以MigrateTypeNotMatch还原。 - 计算毕业后的储备:
base_amount_out = base_vault.amount − vesting_schedule.total_locked_amountquote_amount_out = quote_vault.amount − quote_protocol_fee − migrate_fee − platform_fee
- CPI 到目标程序(
AMM v4 Initialize2或CPMM InitializeWithPermission)使用这些储备创建毕业后的池。 - 对于在 2026-08-17 升级后执行的 CPMM 迁移,将
platform_scale + creator_scale合并为一个平台拥有的锁定 LP 份额,并最多向platform_nft_wallet铸造一个费用密钥 NFT。烧毁burn_scale余数。在升级之前,creator_scale被单独锁定,其费用密钥去往代币创建者。已完成的历史迁移不被修改。对于遗留 AMM v4 毕业,LP 处置遵循该指令的现有流程。 - (无代币权限步骤。
base_mint.mint_authority已在启动创建时设置为None— 见下面的注释。) - 翻转
pool_state.status = Migrated,设置vesting_schedule.start_time = block_time + cliff_period。
TransferFeeConfig 的 Token-2022 代币且 PlatformConfig.transfer_fee_extension_auth 非默认时,迁移也将该扩展的权限重新分配给平台密钥:
transfer_fee_config_authority总是被重新分配。启动authorityPDA 在整个毕业前阶段持有它,所以总有东西要移动。WithheldWithdraw仅在authorityPDA 仍然持有它时被重新分配。从 2026-08-27 起创建的启动已经在代币创建时在该权限上携带transfer_fee_extension_auth,所以该步骤被跳过。守卫是什么保持迁移不在这些代币上还原 — PDA 无法签署它不再持有的权限。
transfer_fee_extension_auth 在迁移时是 Pubkey::default(),两个权限都不移动,两个都永久保留在 authority PDA。见 platform-config。
基础代币的供应从创建时固定,而不是从毕业时。
InitializeV2 和 InitializeWithToken2022 将整个供应铸造到基础金库中,然后在同一指令中立即撤销 MintTokens,所以 base_mint.mint_authority 对启动的整个生命周期都是 None。迁移不接触它。(本页的早期版本将撤销放在毕业时;那是错误的。)迁移唯一可以移动的权限是下面描述的 Token-2022 转账费用权限。BuyExactIn、BuyExactOut、SellExactIn、SellExactOut 将以 PoolMigrated 拒绝。生成的 AMM 池是规范的,交易就像任何其他 AMM v4 / CPMM 池一样。
常见错误 — PoolFunding、PoolMigrated、MigrateTypeNotMatch、InvalidCpSwapConfig、MathOverflow。
CPMM 迁移剩余账户
构建MigrateToCpswap 的客户端必须使用这些固定的 remaining_accounts 索引:
指令至少需要十个剩余账户。支持代币账户是只读 CPI 输入。即使代币没有初始化的支持记录,也要派生两个地址。仍然附加创建者锁账户或省略索引 8–9 的旧构建器必须更新。
在 2026-09 中改变。 两个清理,都不改变正确的构建器:
- 权限 CPMM 路径现在是唯一的路径。
MigrateToCpswap曾经根据unix_timestamp >= get_upgrade_timestamp()在InitializeCpSwap和InitializeCpSwapWithPermission之间选择。时间戳助手和遗留 CPI 都消失了,所以权限路径 — 因此十账户最小值 — 无条件应用。 - 三个地址约束从账户结构移到指令体中。
platform_config、base_vault和quote_vault仍然需要匹配存储在PoolState上的值,但不匹配现在由require_keys_eq!而不是 Anchor 的address =约束引发。检查是等价的;只有错误表面不同 — 你得到 Anchor 的通用RequireKeysEqViolated(2502)而不是ConstraintAddress(2012),它被报告而没有账户名。更新任何匹配这三个账户的2012的错误处理。
CPMM 迁移代币程序
MigrateToCpswap 无条件地接受两个代币程序并自己计算出哪个拥有每个代币。其两个代币程序账户相应重命名:
它们替换了前面的
base_token_program(拥有基础代币的任何程序)和 quote_token_program(总是遗留)。位置没有改变,所以这是值变化而不是布局变化 — 但两个值几乎相反,保持传递旧对的构建器一旦任一代币是 Token-2022 代币就会在需要遗留程序的地方提供 Token-2022。
即使两个代币都不使用它,也需要遗留程序,因为 CPMM LP 代币和锁定流动性费用密钥 NFT 总是存在于它上面。
平台 GlobalConfig 允许列表
PlatformConfig.restrict_global_config 控制检查:
0:平台接受任何其他有效的GlobalConfig;不需要允许账户。1:Initialize、InitializeV2和InitializeWithToken2022必须在remaining_accounts中的任何地方包含匹配的PlatformAllowConfig。
CreatePlatformAllowConfig 和 ClosePlatformAllowConfig 创建或关闭 PDA。其种子是 [b"platform_allow_config", platform_config, global_config]。前面的管理员管理的 PlatformGlobalAccess 指令和 PDA 已停用。
平台启动参数规则
四个指令管理一个PlatformCurveRule 账户。所有四个都由 PlatformConfig.curve_rule_manager 或平台管理员签署 — 程序通过从签署者重新派生 PlatformConfig PDA 来接受管理员,所以没有单独的账户证明它。既不是的签署者返回 InvalidCurveRuleAuthority。
platform_curve_rule 是 [b"platform_curve_rule", platform_config, global_config] 处的 PDA。
Create分配不持有任何组的账户。该状态不限制任何内容。Update使用该group_id更新或插入组,如果存在则完全替换它。它调整账户大小以适应,所以签署者为其增长的租金补充,并接收其收缩的租金。超过第十个的新组返回CurveRuleGroupsExceeded;超过 25 个约束、未知字段或运算符,或同一组中相同的(field, op)对两次返回InvalidCurveRuleConstraint;非常数乘积配置上的四个TotalSellA派生字段返回CurveRuleFieldNotSupportedByCurve。Remove按 id 删除一个组,收缩账户并退款差额。未知 id 返回CurveRuleGroupNotExist。Close将整个租金返回给签署者。即使restrict_curve_param保持1,配置也不再受限制。
UpdatePlatformConfig::RestrictCurveParam(0 | 1),只有平台管理员可以调用。
在启动路径上。 当 restrict_curve_param 是 1 时,InitializeV2 和 InitializeWithToken2022 需要 remaining_accounts 中的规则 PDA — 包括当它不存在时,所以省略它无法跳过检查。缺少账户是 NotEnoughRemainingAccounts;满足无组的启动是 CurveParamNotMatchPlatformRule。检查在 GlobalConfig 自己的限制之前运行,只能缩小它们。模型和剧本:products/launchlab/curve-rules。两个错误都可以客户端避免 — SDK 将此检查镜像为纯函数,见 发送前检查。
CollectFee
单个启动上协议累积交易费用的管理员扫除。
参数 — 无。
账户
效果 — 从
quote_vault 转账 pool_state.quote_protocol_fee 到 recipient_token_account,然后清零计数器。可在第一次买入后的任何时间调用。
CollectMigrateFee
毕业时累积的迁移费用的管理员扫除。与 CollectFee 相同的账户形状,migrate_fee_owner 作为签署者(而不是 protocol_fee_owner)和 pool_state.migrate_fee 作为排空的计数器。
ClaimCreatorFee
每个创建者对创建者拥有的每个使用相同报价代币的启动累积创建者费用的扫除。排空每个创建者费用金库,而不是每个池的。
参数 — 无。
账户
效果 — 转账
creator_fee_vault 的全部余额到 recipient_token_account。如果金库为空,以大于零检查还原。
ClaimPlatformFee
每个平台扫除,直接排空启动的报价金库。当平台想要为一个特定启动声称其份额而不通过聚合平台金库时使用。
参数 — 无。
账户
效果 — 从
quote_vault 转账 pool_state.platform_fee 到 recipient_token_account,清零计数器。
ClaimPlatformFeeFromVault
每个平台聚合扫除。排空平台的每个报价代币费用金库,该金库从通过平台路由的每个启动累积费用。
参数 — 无。
账户
效果 — 转账
platform_fee_vault 的全部余额到 recipient_token_account。如果金库为空则还原。
CollectExcessLamports
LaunchLab 控制的账户上超过租金豁免最低限额的 lamports 的管理员扫除。在 2026-09 升级中添加,以便协议可以回收 SIMD-0437 租金减少 在每个步骤之前创建的账户上留下的过度资金。
只有超额移动。代币余额、账户数据、所有者、曲线状态和归属不受触及,指令对已在其最小值的账户是无操作 — 所以在每个推出步骤后重新运行是安全的。
参数 — 无。
账户
选择
authority
账户被无检查传递并由程序解析,程序重新派生 LaunchLab 的所有三个权限 PDA 并匹配:
不匹配三个中任何一个的密钥使整个指令以
InvalidOwner(6001)失败。
每个源账户如何处理
基础代币无法被扫除。
InitializeV2 和 InitializeWithToken2022 在铸造供应的同一指令中撤销基础代币上的 MintTokens,所以没有密钥可以为它签署 WithdrawExcessLamports — 代币的租金永久保留在原处。
常见错误 — InvalidOwner(6001,错误的签署者或不是三个 PDA 之一的 authority)、LamportsCalculateError(6031,wSOL 往返没有净为零)和来自程序拥有路径的 InsufficientFunds,当账户持有少于其自己的租金最低限额时。
无 SDK 构建器。 @raydium-io/raydium-sdk-v2 不为此指令提供构建器,raydium-sdk-V2-demo 仓库也不提供 — 它是管理员路径。手工编码,就像 solana-fundamentals/rent-and-reclaimable-rent 中的钱包端扫除对代币程序指令所做的那样。
归属和平台配置指令
这些在专用页面上记录,因为每个都有自己的状态模型:CreateVestingAccount、CreatePlatformVestingAccount、ClaimVestedTokenCreatePlatformConfig、UpdatePlatformConfig、CreatePlatformAllowConfig、ClosePlatformAllowConfigCreatePlatformCurveRule、UpdatePlatformCurveRule、RemovePlatformCurveRule、ClosePlatformCurveRuleCreateConfig、UpdateConfig
状态变化矩阵
下一步去哪里
products/launchlab/code-demos— 每个指令的 TypeScript 示例。products/launchlab/accounts— 完整状态形状。reference/error-codes— LaunchLab 错误枚举。
- Raydium SDK v2
LaunchLab模块 - Raydium LaunchLab 程序源

