返回博客
Solana

Solana 上的 WithdrawExcessLamports:SPL Token 与 Token-2022 指南

S
Sol Slugs Team
Sol Incinerator

定价和功能依据已核实 2026年9月3日.

WithdrawExcessLamports 是代币程序指令 38。它解决一个具体问题:铸币账户、代币账户或多签账户可能持有超过免租所需额度的 lamport,但这些 lamport 无法通过普通代币转账来转移。

WithdrawExcessLamports 有什么作用?

WithdrawExcessLamports 仅转移代币程序账户实时免租最低余额以上的 SOL。源账户保持开放,其代币或铸币数据不会变化。必要签名者取决于源账户是代币账户、铸币账户还是代币多签账户。

该指令在传统 SPL Token Program 和 Token-2022 中均可用。在 2026 租金提案之前,它可用于回收误转入代币程序所有账户的 lamport。降低租金最低余额后,其用途更广:旧账户可以保留原有余额,同时仅需更少的储备金。

权威行为说明和当前客户端示例位于 Solana 的 Withdraw Excess Lamports 文档。处理器实现也 在代币程序代码库中公开提供.

该指令需要哪些账户?

账户是否可写?是否签名?用途
source有时持有盈余 lamport 的代币账户、铸币账户或多签账户
destination接收提取的 lamport
authority取决于源账户类型证明有权提取
multiSigners使用时需要满足已配置的代币多签阈值

处理器会读取源账户的数据长度和当前租金设置,计算其最低余额,然后转移差额。它不接受调用方提供的储备金额度,因为该数值可能已过时或遭到操纵。

每种源账户类型必须由谁签名?

源账户必要权限方
由钱包所有者持有的代币账户代币账户所有者
由代币多签账户持有的代币账户所需的 M-of-N 多签成员
具有有效铸币权限的铸币账户当前铸币权限方
没有铸币权限方的铸币账户源铸币账户本身
多签源账户已配置的 M-of-N 名成员

铸币权限已撤销的情况需要特别注意。如果源铸币账户由曲线上的密钥对创建,则必须由该原始密钥对签名。如果它不在曲线上,则其控制程序必须使用正确的 PDA 签名种子调用代币程序。代币持有者或原铸币权限方均无法替代源账户签名。

如何使用 Solana 客户端构建该指令?

当前官方示例使用 @solana-program/token ,并配置 @solana/kit 客户端:

import { getWithdrawExcessLamportsInstruction } from "@solana-program/token";

const instruction = getWithdrawExcessLamportsInstruction({
    source,
    destination,
    authority,
});

await client.sendTransaction([instruction]);

此处 authority 是一个 TransactionSigner 且适合该源账户。对于多签权限方,请通过以下方式加入其共同签名者: multiSigners。生产环境中应锁定软件包版本,并针对实际使用的客户端确切版本进行编译;即使链上账户合约未发生变化,客户端类型也可能改变。

切勿硬编码 0.00203928 SOL 作为储备金。该数值是标准 165 字节代币账户的旧版最低余额,并非当前通用值。应在构建或预览交易前,根据源账户的实际数据长度查询当前最低余额。

SPL Token 与 Token-2022 在此处有何不同?

该指令的核心效果相同,但在 Token-2022 中,对数据长度作出假设的风险尤其大。铸币账户和账户扩展会增加序列化后的大小,从而提高所需储备金。若集成对每个源账户都采用标准的 82 或 165 字节大小,可能会高估盈余。

Token-2022 的 CPI Guard 是封装器的另一个实际差异。当 Guard 锁定时,即使钱包原本是有效权限方,跨程序调用也可能被拒绝。Sol Incinerator 会跳过这些源账户,而不是将一个必然失败的操作放入更大的清理交易中。

原生封装 SOL 代币账户会被拒绝,并返回 NativeNotSupported。解封原生 SOL 使用的是另一种关闭账户流程,并非提取多余 lamport。

Sol Incinerator API 如何封装该指令?

Sol Incinerator 的 v2 API 通过 Assetcinerator 构建代币程序调用,从而在链上执行协议费和可选的合作方费用。此封装器属于产品层;原始代币程序指令本身并不收取 Sol Incinerator 的费用。

在请求用户签名前,请使用经过身份验证的预览:

curl -X POST https://v2.api.sol-incinerator.com/withdraw-excess-lamports/preview \
  -H "content-type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "userPublicKey": "DESTINATION_WALLET",
    "sourceAccount": "TOKEN_ACCOUNT_MINT_OR_MULTISIG"
  }'

相关的交易和指令路由如下:

  • POST /withdraw-excess-lamports
  • POST /withdraw-excess-lamports-instructions

userPublicKey 是目标钱包和默认权限方。请提供 authorityPublicKey ,适用于必须由其他铸币权限方、源账户或多签权限方签名的情况。最多提供 11 multisigSignerPublicKeys ,用于构建代币多签流程。所有私钥均保留在本地;API 会返回供必要签名者批准的材料。

基础协议费为 200 bps。直接集成方可以添加 partnerFeeAccountpartnerFeeBps,而常规的 Solana 交易费则另行计算。请使用返回的 feeLamports 和回收字段,而不要重复使用缓存的百分比计算结果。

集成应处理哪些失败情况?

  • 无盈余: 源账户余额已达到当前储备金额度。
  • 账户所有者或布局错误: 源账户不是受支持的代币程序账户。
  • 权限无效: 所提供的签名者与解码后的源账户状态不匹配。
  • 多签不完整: 提供的有效已配置签名者数量不足。
  • 原生账户: 封装的 SOL 使用另一项操作。
  • 锁定的 CPI Guard: Token-2022 会拒绝封装器 CPI。
  • 状态已变化: 预览后,余额、权限或租金设置发生了变化。
  • 交易成本超过价值: 扣除网络费后,金额过小的提取可能并不划算。

状态可能发生变化时应重新预览,确保源账户选择具有幂等性,并且切勿将已知不符合条件的源账户与其他有效操作放入同一批次。

Sol Incinerator

Sol Incinerator

预览实时多余租金,或使用 v2 API 构建签名者安全的提取交易。

立即试用

相关阅读

常见问题

Solana 上的 WithdrawExcessLamports 有什么作用?

WithdrawExcessLamports 会将代币程序账户当前免租最低余额以上的 lamport 转移到目标钱包。源账户可以是代币账户、铸币账户或多签账户。该指令不会改变代币数量、铸币供应量、权限、扩展及其他所有序列化账户数据。

哪个权限方应为 WithdrawExcessLamports 签名?

代币账户使用其所有者或已配置的多签签名者。具有有效铸币权限的铸币账户使用该权限方。没有铸币权限方时,必须由源铸币账户本身签名,即使用其密钥对,或由控制曲线外铸币账户的程序通过 CPI 签名路径完成。

WithdrawExcessLamports 是否支持 Token-2022?

支持。该指令适用于传统 SPL Token 和 Token-2022 的账户、铸币账户及多签账户。集成必须根据源账户的实际数据长度计算租金,因为 Token-2022 扩展可能增大账户,而锁定的 CPI Guard 可能阻止通过封装器执行。

WithdrawExcessLamports 能否将代币账户余额提取到低于免租额度?

不能。代币程序会计算源账户所需的最低余额,并且只转移高于该额度的差额。原生封装 SOL 代币账户会被拒绝。应用仍应预览实时状态,因为账户余额、数据长度、租金设置和可用权限都可能在提交前发生变化。

Solana 上的 WithdrawExcessLamports:SPL Token 与 Token-2022 指南 | Sol Incinerator