本页内容由 AI 自动翻译,所有内容以英文版本为准。查看英文版 →
Raydium 不接受任意的 Token-2022 铸币。CPMM 和 CLMM 都运行严格的允许列表模式:默认只有一小组扩展通过;其他所有扩展在池创建时被拒绝。每个程序通过一种机制接纳单个铸币——管理员管理的按铸币注册表 PDA。两个程序之前在各个位置都有硬编码的绕过机制;现在全部已删除。本页是关于强制执行内容和位置的单页参考,包含程序源代码的引用。
程序级支持
允许列表检查位于:
- CPMM:
raydium-cp-swap/programs/cp-swap/src/utils/token.rs中的is_supported_mint,从Initialize和InitializeWithPermission调用。 - CLMM:
raydium-clmm/programs/amm/src/util/token.rs中的is_supported_mint,从CreatePool调用。 - LaunchLab:
raydium-launchpad/programs/launchpad/src/instructions/initialize_with_token_2022.rs中的initialize_with_token_2022(源代码不公开)。
CLMM 头寸 NFT 冻结(受限发行者)
头寸 NFT 账户默认保持解冻。CLMM 仅在头寸使用 V2 开放路径且至少一个金库铸币的当前freeze_authority 出现在硬编码的 frozen_position_nft_authorities::IDS 列表中时才冻结一个。该列表是替代 CLMM 早期 Superstate 令牌检测的内容,它携带旧启发式匹配的相同发行者权限。将池 PDA 设置为头寸 NFT 铸币的冻结权限本身不是冻结。这是头寸托管规则,不是池创建允许列表:
- 池可以已存在并保持可交换。
- 头寸 NFT 铸币使用 CLMM 池 PDA 作为其自己的冻结权限;底层发行者不控制头寸 NFT。
OpenPositionV2覆盖 Token-2022 池资产上的经典 SPL 头寸 NFT。OpenPositionWithToken22Nft覆盖 Token-2022 头寸 NFT。OpenPositionV1 不检查金库铸币,无法服务由发货列表针对的 Token-2022 受限资产。- 现有头寸保持不变。
ClosePosition 在客户端将池作为第一个剩余账户传递时原子地解冻和销毁。见products/clmm/ticks-and-positions。
LaunchLab 报价铸币
LaunchLab 的两个铸币受限方式非常不同,不对称性很容易被忽视。- 基础铸币——LaunchLab 创建它。Token-2022 基础铸币仅通过
initialize_with_token_2022可达,程序将仅附加MetadataPointer和(可选)TransferFeeConfig。任何其他内容返回NoSupportExtension。预先存在的 Token-2022 铸币根本无法作为基础提供。当附加TransferFeeConfig时,铸币的transfer_fee_config_authority是启动权限 PDA 直到毕业,而其withdraw_withheld_authority是平台配置的transfer_fee_extension_auth(从铸币创建开始)——launchpad 程序本身没有提取扣留指令。见products/launchlab/platform-config。 - 报价铸币——LaunchLab 不创建它也不筛选它。
CreateConfig接受给定的铸币账户,所以报价端没有is_supported_mint等价物。唯一的限制是管理员选择绑定到GlobalConfig的铸币。
TransferHook 报价铸币会在每次买入、卖出和费用索赔时在每个以其报价的池中运行其钩子,PermanentDelegate 报价铸币会让委托人扫空这些池的报价金库。两者都不被程序阻止。
LaunchLab 一旦绑定报价铸币就正确处理的内容:
- 报价金库、两个费用金库和分享费接收者的令牌账户都在报价铸币自己的程序上创建。
- 报价端的
TransferFeeConfig被计入所有四个交易指令,滑点界限针对支付者的净额而不是金库的总移动进行检查。见products/launchlab/instructions。 PoolState.token_program_flag记录两个铸币的程序——bit0 用于基础铸币,bit1 用于报价铸币。按位解码;字节不是布尔值。见products/launchlab/accounts。
Initialize 指令仍然采用仅限遗留的报价程序,所以具有 Token-2022 报价铸币的配置仅通过 InitializeV2 和 InitializeWithToken2022 可达。
CPMM 和 CLMM 扩展允许列表
在下面涵盖的两个短路之后,程序迭代铸币的扩展,如果它携带任何不在这五个中的扩展,则拒绝铸币:
不在此列表中的任何内容——
TransferHook、NonTransferable、ConfidentialTransferMint、PermanentDelegate、MintCloseAuthority、DefaultAccountState、GroupPointer、GroupMemberPointer、MemberPointer、Pausable 等——导致 is_supported_mint 返回 false 并且池创建恢复。
相关行(CPMM,CLMM 中形状相同):
cp-swap/src/utils/token.rs
绕过路径
不符合允许列表的 Token-2022 铸币仍然可以被接纳,通过每个程序中的一种机制。两个程序过去也携带硬编码的绕过机制;其中没有一个存活。is_supported_mint 现在在两个程序中是逐字节相同的函数:遗留 SPL Token 铸币通过,具有注册表 PDA 的铸币通过,其他所有内容必须仅携带允许列表中的扩展。
唯一的绕过:按铸币注册表
两个程序都查询种子为[b"support_mint", mint] 的 SupportMintAssociated PDA。如果该 PDA 对铸币存在,则无论其扩展集如何,铸币都被接纳。
每个程序都有自己的 PDA 副本(它们在不同的程序 ID 下派生)、自己的 CreateSupportMintAssociated / CloseSupportMintAssociated 对,以及自己的专用权限与共享管理员:
这四个密钥(CPMM 和 CLMM × 主网和开发网)列在支持代币注册表权限下。
在两个程序中,指令接受 crate::admin::ID 或该程序的专用权限,并要求铸币由 Token-2022 拥有。效果:特定的 Token-2022 铸币可以选择加入池创建,无需程序升级——这就是为什么硬编码列表可以消失。
每个程序从它拥有的每个池创建路径查询注册表:CPMM 从 Initialize 和 InitializeWithPermission(后者是 LaunchLab 毕业使用的,所以注册的铸币也毕业和创建),CLMM 从 CreatePool、CreateCustomizablePool 和 CreatePermissionedPool。
移除的绕过
两个硬编码机制都已从部署的程序中删除。它们在这里仅被记录,因为针对较旧行为编写的集成可能仍然假设它们。静态 MINT_WHITELIST——已移除
一个基础 58 铸币地址常量数组曾经在扩展迭代之前短路 is_supported_mint。CLMM 的包含六个地址,在 2026-07-24 删除;CPMM 的包含相同集合的前四个,在 2026-09-09 升级中删除。
已为这些铸币之一存在的池继续交易——铸币检查仅在池创建时运行。现在为其中一个创建新池需要为其注册 PDA。
Superstate 权限形状检测——已移除
CLMM 曾短暂通过权限形状而不是地址识别 Superstate 的令牌化资产:Token-2022 铸币,其freeze_authority 和 永久委托都等于 superstate_allowlist::ID,DefaultAccountState 设置为 Frozen,被接纳。这是一个启发式,所以任何具有相同形状的未来铸币都会被自动接纳。
它在 2026-07-31 与 superstate_allowlist 模块一起删除。替代它的更窄,服务于不同的目的:frozen_position_nft_authorities::IDS,它不接纳任何东西——它决定头寸 NFT 是否被冻结,并在上面描述。旧启发式匹配的一个发行者权限是该列表中的一个条目。
绕过不豁免的内容
绕过跳过扩展允许列表,但程序仍然强制:- 铸币由
Token或Token-2022拥有。自定义令牌程序被上游拒绝。 - 池金库使用 Token-2022 池的正确 ATA 扩展创建(
ImmutableOwner等)。 - 所有转账都通过
transfer_checked——费用承载铸币在金库中着陆正确的金额。
TransferHook 的白名单或 PDA 注册铸币不会获得交换时检查;钩子会简单地在每次转账时运行,可能会破坏交换。因此,注册铸币是高信任操作。
“被阻止”语义
当is_supported_mint 返回 false 时,池创建以 ErrorCode::NotSupportMint(CPMM)/ ErrorCode::NotSupportMint(CLMM)恢复。见reference/error-codes了解数字代码。
现有池无法追溯地失败此检查——限制仅在创建时运行。铸币扩展对于 Raydium 拒绝的类别是不可变的(转账钩子、不可转移、机密转账无法在创建后添加),所以静态检查是充分的。
为什么每个被排除的扩展被排除
- TransferHook——在每次转账时调用自定义程序,具有任意 CU 消耗、任意失败条件,以及重新进入调用程序的能力。不存在安全沙箱。一些 DEX 维护钩子允许列表;Raydium 不。
- NonTransferable——
Transfer总是失败。池无法获得托管。 - ConfidentialTransfer——转账金额被加密;曲线无法为交换定价。
- PermanentDelegate——委托的持有者可以扫空任何令牌账户,包括池金库。仅通过注册铸币可接纳,这是受信任的发行者(例如受监管的稳定币)逐案例上线的方式。
- MintCloseAuthority——铸币可以关闭;现有池变得不可用。默认不允许。
- DefaultAccountState (Frozen)——池 ATA 会着陆在
Frozen状态,需要按账户解冻。仅通过注册铸币可接纳,这假设发行者在注册时解冻机构账户。 - Group/Member 指针——不是主动有害,但未审查。默认不允许以保持表面狭窄。
转账费会计
对于携带TransferFeeConfig 的铸币,每次交换、存款和提款移动的金额少于名义金额。涉及两个单独的数字,SDK 将它们分开:
- 池费(LP + 协议 + 基金 + 创建者)来自曲线。
raydium.cpmm.computeSwapAmount({ ... })将其作为fee返回,以及amountIn、amountOut、minAmountOut、executionPrice、priceImpact和原始swapResult。 - Token-2022 转账费来自铸币,不是池。它由
@raydium-io/raydium-sdk-v2中的getTransferAmountFee助手计算,返回GetTransferAmountFee:
computePairAmount 返回 inputAmountFee 和 anotherAmount 作为 GetTransferAmountFee 值。
正确的 UI 显示:
- 输入金额加上其转账
fee作为”你发送” - 输出金额减去其转账
fee作为”你接收” - 池
fee作为单独的行——它不是 Token-2022 费
amountIn → amountOut 的幼稚 UI 低估了成本。将集群中的 epochInfo 传递到这些助手中,而不是缓存它;epoch 是选择铸币 older 和 newer 费用配置之间的内容。
maximumFee 上限
Token-2022 转账费按转账上限。对于具有 10,000 令牌上限的 1% 铸币,100,000,000 令牌转账仅支付 10,000 费用。SDK 的 computeSwapAmount 应用上限;直接程序调用者必须复制它。
Epoch 转换
铸币权限可以安排在下一个 epoch 激活的费率变更。在转换窗口期间,两个配置(older、newer)同时存在于铸币上,TransferChecked 按当前 epoch 选择。CPMM SwapV2 和 CLMM SwapV2 都在 accounts 中传递完整的铸币账户,所以程序读取正确的配置而无需额外查找。
如果你通过 Trade API 或 SDK 提前引用多个 epoch,执行费可能与引用费不同——由较旧配置的 maximum_fee_basis_points 限制。
利息承载和 ScaledUiAmount
池持有本金;“UI 金额”是本金乘以时间相关或管理员设置的缩放因子。交换数学在本金上运行:pool.token0Vault.amount 视为本金。
“Token-2022 池”定义
如果任一铸币具有programId == TokenzQdB...,则池是 Token-2022 池。API 显示这个:
programId 分派,使用 hasTransferFee 显示 UI 警告。
SDK 助手
常见集成错误
- 仅预检程序 ID。 铸币可以是 Token-2022 且不受支持。在允许池创建之前,针对允许列表遍历扩展列表,并检查铸币的注册表 PDA。
- 当铸币根本不被接受时信任 SDK 的报价。 报价 API 不拒绝报价——池创建是恢复的。在在 UI 中公开池创建之前,离线确认
is_supported_mint语义。 - 报价时不考虑转账费削减。 具有 0.25% CPMM 池两侧 1% 转账费的铸币的有效费约为 2.25%,而不是 0.25%。使用 SDK 报价或 Trade API 报价——永远不要仅从池的费用等级手动计算费。
- 在 Token-2022 池上调用遗留
Swap指令。Swap早于 Token-2022。每当任一铸币是 Token-2022 时使用SwapV2。 - 自动列出新的 Token-2022 铸币。 钱包和聚合器应在向用户显示铸币之前检查
TransferHook和NonTransferable;两者都对 Raydium 不利。
未来工作
Solana 生态系统和协议路线图项目,将改变此矩阵:- Solana 级别允许列表转账钩子程序(生态系统约定演变)。
- 机密转账兼容 AMM(研究阶段)。
- 更广泛的 CPMM 按铸币注册表(与 CLMM 奇偶)。
- 注册表的公共读取路径,所以 UI 可以告诉”不受支持”与”不受支持但已注册”,无需自己派生 PDA。
指针
algorithms/token-2022-transfer-fees——交换中的费用数学。products/cpmm/instructions——SwapV2、Initialize。products/clmm/instructions——SwapV2、CreatePool、CreateSupportMintAssociated。reference/error-codes——NotSupportMint每个程序的数字代码。
raydium-cp-swap/programs/cp-swap/src/utils/token.rs——is_supported_mint、support_mint_associated_is_initialized。raydium-clmm/programs/amm/src/util/token.rs——is_supported_mint、support_mint_associated_is_initialized、frozen_position_nft_authorities、position_nft_must_freeze。raydium-clmm/programs/amm/src/instructions/admin/create_support_mint_associated.rs——按铸币注册表指令。raydium-launchpad/programs/launchpad/src/instructions/initialize_with_token_2022.rs——LaunchLab Token-2022 基础铸币创建。raydium-launchpad/programs/launchpad/src/instructions/admin/create_config.rs——LaunchLab 报价铸币绑定(无扩展检查)。

