本页内容由 AI 自动翻译,所有内容以英文版本为准。查看英文版 →
自 2026-07 程序升级以来,AMM v4 的 OpenBook / Serum 依赖已被移除。旧版 v1 的
SwapBaseIn / SwapBaseOut、Deposit 和 Withdraw 指令保持原有的账户布局以保证向后兼容:市场账户仍在原位置被接受,但不再被验证或使用(不发起 CPI)。新的集成应使用 V2 交换入口点,它们完全省略了市场账户。多条指令已被移除并现在会回滚——见 changelog 条目。下面的账户列表使用 Raydium SDK 中的字段名;底层 IDL 有时使用 serum_* 前缀。2026-09 程序升级添加了一条管理员指令 WithdrawExcessLamports(标签 18),并从 CreateConfigAccount 中移除了 rent sysvar。交易者或 LP 调用的所有内容都保持不变。见 2026-09-09 changelog 条目。指令清单
SDK 仅为面向用户的指令公开构建器。维护指令通常由 Raydium keeper 调用。
已移除 / 不再可调用(其客户端构建器已删除):
Initialize(标签 0,使用 Initialize2)、MonitorStep(2)、MigrateToOpenBook(5)、WithdrawSrm(8)、PreInitialize(10,使用 Initialize2)、SimulateInfo(12)、AdminCancelOrders(13)。
携带这些标签之一的交易会失败;程序永远不会执行该指令。将这七条都视为已删除,而不是要处理的错误路径。
Initialize2
引导一个新的 AMM v4 池,绑定到现有的 OpenBook 市场。
参数
W、签名者 S)
两种被接受的布局。 上面 19 个账户的列表是推荐的那一种。为了向后兼容,程序也会读取一个
21 个账户的旧版布局,它在位置 7 插入一个被忽略的
amm_open_orders,在位置 16 插入一个被忽略的
market_program —— 这正是仓库内的 initialize2 指令构建器仍在生成的形式。其他任何长度都会按
旧版布局按位置解析,并且会失败。- 铸造给创建者的 LP =
sqrt(init_coin_amount × init_pc_amount) − 10^coin_mint.decimals。LP 小数位等于coin_mint.decimals,因此被减去的数量恰好是整整一个 LP 代币;它从未被铸造,永久退出流通。如果sqrt(...)低于该值,指令会以InitLpAmountTooLess回滚。 AmmInfo.lp_amount存储完整的sqrt(...),不是已铸造的数量 —— 因此lp_mint.supply永久比amm.lp_amount低整整一个 LP 代币。所有按比例的计算都使用amm.lp_amount。- 不发布 OpenBook 订单(订单簿网格已被移除)。
AmmInfo.market记录在槽位 15 传入的账户,但AmmInfo.open_orders和AmmInfo.market_program都被写为Pubkey::default(),而coin_lot_size/pc_lot_size/min_size被初始化为0。在旧版的 21 账户布局上,额外的amm_open_orders和market_program账户会被读取后丢弃。
InvalidCoinMint(coin 与 pc 铸币相同)、InvalidConfigAccount(amm_config PDA 错误)、InvalidFee(创建池费用目标错误)、InvalidProgramAddress(amm_authority 错误或 nonce 错误)、RepeatCreateAmm(该市场已存在池)、InitLpAmountTooLess、InvalidSupply(某个初始数量为 0,或 LP 铸币已有供应量)、AlreadyInUse。
Deposit
添加流动性。
参数
数学 — 标准按比例分配。使用池的有效储备(金库 + 账面上),SDK 计算产生给定 LP 数量的 coin/pc 对,并根据
max_* 检查。如果任一方超过上限,则以 ExceededSlippage 回滚。
Withdraw
销毁 LP,接收两种代币。
参数
不再有从 OpenBook 结算的步骤 —— 按比例分配的数学直接使用金库余额。
SwapBaseIn
精确输入交换。始终是AMM 路径交换(不通过 OpenBook 匹配路由)。
为新代码使用 V2 变体。 由于 AMM v4 的 OpenBook 依赖已被移除,V1 入口点(
SwapBaseIn、SwapBaseOut)仍然期望完整的 17 账户列表(或 18 个带可选 target-orders 账户),但 OpenBook/市场账户现在按位置被接受并被忽略——它们不被验证,不发起 CPI。传递错误的账户数量仍会以 WrongAccountsNumber 回滚,但市场账户内容不再被检查。新的集成应使用 SwapBaseInV2 / SwapBaseOutV2,它们采用更小的账户列表,代表当今的规范执行路径。V1 形式在此记录以供完整性和阅读现有链上交易。
数学 — 见
products/amm-v4/math。
前置条件
AmmStatus::from_u64(amm.status).swap_permission()为真 —— 也就是status为1(Initialized)、6(SwapOnly)或7(WaitingTrade)。status是枚举值,不是位掩码;见products/amm-v4/accounts。amm.state_data.pool_open_time <= now。amount_in > 0。user_source_token_account至少持有amount_in。
- 用户失去
amount_in的源代币,获得amount_out ≥ minimum_amount_out的目标代币。 - 交易费留在金库中,提高不变式
k。need_take_pnl_*计数器不会被交换触及 —— 协议 PnL 会在下一次Deposit、Withdraw或WithdrawPnl时根据k的增量重新计算(Processor::calc_take_pnl)。 - 注意:
state_data.swap_*_in_amount/swap_*_out_amount分析计数器不再更新——其值被冻结。使用交易日志进行交易量分析。
ExceededSlippage、InvalidInput、InvalidStatus、NotAllowed(coin/pc mint 相同)。
SwapBaseOut
精确输出,SwapBaseIn 的反向。账户相同。
参数
SwapBaseInV2 / SwapBaseOutV2
变体交换入口点(标签 16 / 17),完全跳过 OpenBook 账户。数学与 V1 路径相同,但账户列表缩小到仅 AMM 端和用户——8 个账户,amm_open_orders 不被传递:
池储备现在是金库余额(减去待处理 PnL),所以报价数学直接且与 v1 路径相同。使用 V2 来节省计算并避免传递(现在被忽略的)市场账户。Raydium 路由器在通过 AMM v4 路由时始终使用 V2 形式。
参数与 V1 形式相同(
SwapBaseInV2 的 amount_in / minimum_amount_out;SwapBaseOutV2 的 max_amount_in / amount_out)。
MonitorStep 和其他已移除的指令
历史上,MonitorStep 驱动池的 OpenBook 交互:它结算已成交的订单(通过 OpenBook CPI 将收益从市场金库移到池金库),取消陈旧订单,并发布新订单以缩小 target_orders 和 amm_open_orders 之间的差距。随着 OpenBook 依赖的移除,没有什么可驱动的,指令已消失。任何仍调用它的 keeper 或集成必须移除该调用。
WithdrawPnl / TakePnl
管理员清扫累积的协议费。
参数
WithdrawPnl不接受参数;它读取need_take_pnl_*并移动这些确切的数量。
效果
- 从
pool_coin_token_account转移need_take_pnl_coin到pnl_coin_token_account。 - pc 相同。
- 将
need_take_pnl_coin和need_take_pnl_pc置零。 - 逻辑更改:如果金库余额不足以覆盖累积的 PnL,指令直接返回
TakePnlError(它不再操纵订单簿状态)。
SetParams
管理员参数更改,由 Raydium 多签调用。参数是 param: u8 标签 + 有效负载。
CreateConfigAccount / UpdateConfigAccount
程序级 AmmConfig PDA(seed ["amm_config_account_seed"])的管理员管理。该账户只持有三个有意义的字段 —— pnl_owner、cancel_owner 和 create_pool_fee —— 外加两个保留的填充区域;没有池创建标志。UpdateConfigAccount 用 param = 0 设置 pnl_owner,用 param = 1 设置 cancel_owner,用 param = 2 设置 create_pool_fee。
在 2026-09 中更改,向后兼容。
CreateConfigAccount 不再读取 rent sysvar。其账户列表现在是 4 个账户,从 5 个下降:程序从
Rent::get() 读取 rent 参数,而不是反序列化传入的 sysvar 账户——这是 Solana 3.0 依赖升级使其自然的做法。被移除的账户是列表中的最后一个,处理程序通过 next_account_info 按位置读取其账户,没有长度检查。因此,仍传递旧 5 账户列表的现有管理员工具继续工作:尾部 rent 账户根本不被读取。在方便时更新它,不是紧急的。UpdateConfigAccount 不变。Initialize2 在位置 3 保留 rent sysvar,并仍然使用它:程序停止在其上调用 Rent::from_account_info,但它仍被转发到创建池金库和 LP mint 的 spl_token::initialize_account 和 initialize_mint CPI 中。不要从账户列表中删除它。
WithdrawExcessLamports
管理员清扫坐在程序控制的账户上 rent-exempt 最小值之上的 lamport。在 2026-09 升级中添加,以恢复 SIMD-0437 rent 减少 在每个步骤之前创建的账户上留下的过度资金。
它仅移动超额部分。代币余额、账户数据、所有者和池状态保持不变,指令在已处于最小值的账户上是无操作的——所以重复触发和在每次推出步骤后再次触发是安全的。
参数 — 无。有效负载是单个标签字节 18。
账户
每个源账户的处理方式
程序根据源账户的
owner 分派:
常见错误 —
InvalidSignAccount(错误的签名者)、InvalidSplTokenProgram(槽 3 中的错误程序)、InvalidProgramAddress(错误的 amm_authority)、LamportsCalculateError(自定义代码 60;wSOL 往返没有净为零)和来自程序所有路径的 InsufficientFunds,当账户持有少于其自身 rent 最小值时。
无 SDK 构建器。 @raydium-io/raydium-sdk-v2 不为此指令提供构建器,raydium-sdk-V2-demo 仓库也不提供——这是管理员路径。手动编码,就像 solana-fundamentals/rent-and-reclaimable-rent 中的钱包端清扫对 token-program 指令所做的那样。
状态变化矩阵
OpenBook 列已消失——没有指令再触及订单簿。接下来去哪里
products/amm-v4/code-demos— 交换和 LP 流的 TypeScript 示例。products/amm-v4/fees—WithdrawPnl详情和费用分割。reference/error-codes— 前向参考表(AMM v4 错误列在该页面上)。
- Raydium AMM program —
raydium-io/raydium-amm - Raydium SDK v2
Liquidity模块 - OpenBook program — 市场端的账户验证

