> ## 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.

# 質押與可回收質押

> Solana 在 SIMD-0437 下分五個步驟將質押豁免最低額度削減 90%。在各步驟前建立的帳戶保有其原始資金——本文說明這些超額部分是什麼、哪些程式會退還它們，以及如何找到並回收它們。

<Info>
  **本頁內容由 AI 自動翻譯，所有內容以英文版本為準。**

  [查看英文版 →](/solana-fundamentals/rent-and-reclaimable-rent)
</Info>

<Info>
  質押是可退款的保證金，不是費用。SIMD-0437 分五個獨立閘門的步驟降低每個帳戶必須持有的保證金。在某個步驟前建立的帳戶會保留其原始資金餘額，因此每個步驟都會讓它們超額資金化。SPL Token 和 Token-2022 程式可以透過 `WithdrawExcessLamports` 退還這個差額，而不需關閉帳戶或觸及其代幣餘額。沒有過期時間——超額部分會保留在你自己的帳戶中，直到你選擇移動它。
</Info>

如果你是 Solana 帳戶資金機制的新手，請先閱讀[帳戶模型](/zh-Hant/solana-fundamentals/account-model)。

## 質押實際上是什麼

Solana 上的每個帳戶都持有一筆 SOL 保證金，其大小由它佔用的空間決定。這筆錢不會被花費——當帳戶關閉時會全額退還。公式如下：

```
minimum_balance(data_len) = (ACCOUNT_STORAGE_OVERHEAD + data_len) × lamports_per_byte
```

`ACCOUNT_STORAGE_OVERHEAD` 是每個帳戶都要支付的固定 128 位元組，無論其內容如何。`lamports_per_byte` 是 SIMD-0437 改變的全網常數。

標準 165 位元組的 SPL 代幣帳戶因此一直需要 `(128 + 165) × 6,960 = 2,039,280` lamports——這就是你在錢包開啟關聯代幣帳戶時看到扣除的約 0.00203928 SOL。

## SIMD-0437 改變了什麼

SIMD-0437 將 `lamports_per_byte` 從 6,960 削減到 696——削減 90%——透過五個獨立的功能閘門推出，讓驗證者能逐步吸收狀態增長的影響。

| 步驟    | `lamports_per_byte` | 相對原始值削減 | 165 位元組代幣帳戶的質押     |
| ----- | ------------------- | ------- | ------------------ |
| —（原始） | 6,960               | —       | 2,039,280 lamports |
| 1     | 6,333               | 9%      | 1,855,569 lamports |
| 2     | 5,080               | 27%     | 1,488,440 lamports |
| 3     | 2,575               | 63%     | 754,475 lamports   |
| 4     | 1,322               | 81%     | 387,346 lamports   |
| 5     | 696                 | 90%     | 203,928 lamports   |

步驟 1 在 2026 年 9 月 3 日於主網啟動。其餘步驟在其功能閘門啟用時推出；將時程表視為可能變更，並從叢集讀取即時值而不是硬編碼。

<Note>
  SIMD-0437 依賴 SIMD-0194，後者棄用質押豁免閾值「以避免在功能啟動時設定質押參數時進行不必要的浮點運算」。實際上，`Rent` sysvar 現在攜帶 `lamports_per_byte_year = 6,333` 搭配 `exemption_threshold = 1.0`，而不是舊的 `3,480 × 2` 分割（產生 6,960）。不要自己相乘這兩個欄位——呼叫 `getMinimumBalanceForRentExemption` 並讓叢集回答。
</Note>

## 為什麼現有帳戶持有過多

降低常數改變了帳戶*需要*的金額。它不改變帳戶*擁有*的金額。在 6,960 lamports 每位元組時資金化的帳戶在步驟 1 啟動後保留該餘額，因此超額資金化為：

```
excess = (128 + data_len) × (old_rate − new_rate)
```

對於步驟 1 後的 165 位元組 SPL 代幣帳戶，這是 `293 × (6,960 − 6,333) = 183,711` lamports，或每個帳戶約 0.000184 SOL。攜帶擴展的 Token-2022 帳戶更大，因此它持有成比例更多——182 位元組帳戶超額資金化 `310 × 627 = 194,370` lamports。

單獨來看這是微不足道的。一個多年來與數百個代幣互動過的錢包持有這個金額的有意義倍數，到步驟 5 時，每個 165 位元組帳戶在其最低額度上方有 1,835,352 lamports（約 0.00184 SOL）。

## 哪些帳戶可以退還它

程式擁有帳戶中的超額 lamports 只能由該程式移動。因此，你是否可以在不關閉帳戶的情況下回收質押完全取決於哪個程式擁有它。

<CardGroup cols={2}>
  <Card title="SPL Token 和 Token-2022" icon="circle-check">
    兩者都公開 `WithdrawExcessLamports`。帳戶保持開啟，保留其代幣餘額，並簡單地降至目前最低額度。
  </Card>

  <Card title="其他所有程式" icon="circle-xmark">
    沒有等效指令。質押只在帳戶關閉時釋放——這是一個具有自身前置條件的破壞性操作，不是質押掃描。
  </Card>
</CardGroup>

具體來說，對於 Raydium 使用者持有的帳戶類型：

| 帳戶               | 擁有者                                           | 可以就地退還超額嗎？                                                  |
| ---------------- | --------------------------------------------- | ----------------------------------------------------------- |
| SPL 代幣帳戶         | `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` | 是——`WithdrawExcessLamports`                                 |
| Token-2022 代幣帳戶  | `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | 是——`WithdrawExcessLamports`                                 |
| 包裝 SOL（原生）代幣帳戶   | 任一代幣程式                                        | 否——見下文                                                      |
| CLMM 頭寸          | Raydium CLMM                                  | 否——質押在頭寸關閉時退還                                               |
| OpenBook v1 開放訂單 | OpenBook v1                                   | 否——僅 `CloseOpenOrders`                                      |
| OpenBook v2 開放訂單 | OpenBook v2                                   | 否——僅 `close_open_orders_account`                            |
| 質押帳戶             | 質押程式                                          | 否——SIMD-0490 將 `rent_exempt_reserve` 固定在 2,282,880 lamports |

包裝 SOL 帳戶是唯一的代幣程式例外：它們的 lamport 餘額*就是*它們的代幣餘額，所以兩個程式都以 `TokenError::NativeNotSupported` 拒絕它們。Token-2022 為此情況添加了 `UnwrapLamports`（判別式 45）；`@solana/spl-token` 從 0.4.15 開始提供 `createUnwrapLamportsInstruction`。在質押掃描中跳過原生帳戶並有意處理它們。

## `WithdrawExcessLamports` 指令

兩個代幣程式指令列舉中的判別式 **38**。來自 `spl-token-interface`：

```rust theme={null}
/// This instruction is to be used to rescue SOL sent to any TokenProgram
/// owned account by sending them to any other account, leaving behind only
/// lamports for rent exemption.
///
/// 0. `[writable]` Source Account owned by the token program
/// 1. `[writable]` Destination account
/// 2. `[signer]` Authority
/// 3. `..3+M` `[signer]` M signer accounts
WithdrawExcessLamports,
```

三個特性使它可以安全地對錢包中的每個帳戶執行：

* **它不需要金額。** 程式自己計算 `source.lamports − rent.minimum_balance(source.data_len())`，所以它永遠無法將帳戶降至目前最低額度以下，並且隨著後續步驟啟動保持正確。
* **它不關閉任何東西。** 帳戶保留其資料、其擁有者和其代幣餘額。
* **它是冪等的。** 對已在最低額度的帳戶執行它會移動零 lamports 並成功。

凍結的代幣帳戶仍然符合條件：凍結限制代幣移動，不限制 lamports。

### 建立指令

`@solana/spl-token` 不匯出它的建構器。截至 `0.4.15`，列舉項目仍被註解掉：

```ts theme={null}
// packages/spl-token/src/instructions/types.ts
export enum TokenInstruction {
    // ...
    TransferHookExtension = 36,
    // ConfidentialTransferFeeExtension = 37,
    // WithdrawalExcessLamports = 38,   // ← not exposed
    MetadataPointerExtension = 39,
    // ...
}
```

直接編碼它。有效負載是單個判別式位元組：

```ts theme={null}
import { PublicKey, TransactionInstruction } from "@solana/web3.js";

export function createWithdrawExcessLamportsInstruction(params: {
  source: PublicKey;        // the token account holding excess lamports
  destination: PublicKey;   // where the excess goes — usually the wallet itself
  authority: PublicKey;     // owner of `source`, or the multisig account
  multiSigners?: PublicKey[];
  programId: PublicKey;     // TOKEN_PROGRAM_ID or TOKEN_2022_PROGRAM_ID
}): TransactionInstruction {
  const { source, destination, authority, multiSigners = [], programId } = params;
  return new TransactionInstruction({
    programId,
    keys: [
      { pubkey: source, isSigner: false, isWritable: true },
      { pubkey: destination, isSigner: false, isWritable: true },
      { pubkey: authority, isSigner: !multiSigners.length, isWritable: false },
      ...multiSigners.map((pubkey) => ({ pubkey, isSigner: true, isWritable: false })),
    ],
    data: Buffer.from([38]),
  });
}
```

為每個帳戶傳遞其自己的 `programId`。SPL Token 和 Token-2022 指令可以共享一筆交易，但每個都必須發送到擁有其來源帳戶的程式。

在主網上測量，該指令在 SPL Token 程式上花費 270 個計算單位，在 Token-2022 上花費 1,414 個——任何一種方式都可以忽略不計。真正的限制是交易大小，而不是計算。

## 尋找可回收帳戶

不要從硬編碼的費率推導超額。詢問叢集每個帳戶現在需要什麼，這樣相同的程式碼在所有五個步驟中保持有效：

```ts theme={null}
const [tokenResp, token2022Resp] = await Promise.all([
  connection.getTokenAccountsByOwner(owner, { programId: TOKEN_PROGRAM_ID }),
  connection.getTokenAccountsByOwner(owner, { programId: TOKEN_2022_PROGRAM_ID }),
]);
const raw = [...tokenResp.value, ...token2022Resp.value];

// one lookup per distinct account size — a wallet normally has two or three
const spaces = Array.from(new Set(raw.map(({ account }) => account.data.length)));
const minimums = new Map(
  await Promise.all(
    spaces.map(async (space) => [space, await connection.getMinimumBalanceForRentExemption(space)] as const),
  ),
);

const reclaimable = raw.filter(({ account }) => {
  // wrapped SOL carries its token balance as lamports — both programs refuse it.
  // The `is_native` COption tag sits at offset 109 in the token account layout,
  // which Token-2022 preserves before its extension data.
  if (account.data.readUInt32LE(109) === 1) return false;
  return account.lamports > minimums.get(account.data.length)!;
});
```

`getMinimumBalanceForRentExemption(0)` 是一個有用的旁路：它返回恰好 `128 × lamports_per_byte`，所以除以 128 可以告訴你叢集在哪個推出步驟上，而無需解析 `Rent` sysvar。

## 批次：一筆交易中能放多少

每個 `WithdrawExcessLamports` 指令貢獻一個唯一的可寫帳戶金鑰——編譯訊息中的 32 位元組——加上約 7 位元組的指令編碼。目的地、授權和費用支付者都是同一個錢包，所以它們之間只花費一個金鑰。

針對 1,232 位元組的交易限制，計算預算指令和區塊雜湊後大約 26 個指令符合。**每筆交易 20 個**是安全的工作數字，也是 Raydium 自己的實現使用的。因此，擁有 116 個可回收帳戶的錢包在六筆交易中掃描，每筆交易一個 5,000 lamport 基本費用。

注意經濟學：費用按交易收費，而不是按帳戶收費。回收較少帳戶不會花費更少，這就是為什麼部分掃描很少值得額外往返。

## 透過 Raydium 回收

[raydium.io/reclaim-rent](https://raydium.io/reclaim-rent) 頁面掃描連接錢包的 SPL Token 和 Token-2022 帳戶，顯示按程式分割的總額，並在批次交易中掃描所有內容。掃描是唯讀的——直到你按下**回收所有質押**才簽署。

該頁面刻意僅涵蓋代幣帳戶。只能透過關閉來釋放質押的帳戶類型被排除而不是列為不可用，因為關閉帳戶是一個不同的、破壞性的操作。

## 從 SDK 演示回收

<Info>
  **版本橫幅。** 演示針對 Solana mainnet-beta 上的 `@raydium-io/raydium-sdk-v2@0.2.42-alpha`，已驗證 2026-09。`WithdrawExcessLamports` 是手工編碼的，獨立於 SDK 版本；SDK 僅用於交易建立和批次。
</Info>

[`raydium-sdk-V2-demo/src/rent`](https://github.com/raydium-io/raydium-sdk-V2-demo/tree/master/src/rent) 中的兩個指令碼：

```bash theme={null}
# read-only: what can this wallet reclaim, and what would it be worth after all five steps
yarn dev src/rent/checkReclaimableRent.ts
yarn dev src/rent/checkReclaimableRent.ts <any wallet address>

# build, simulate (DRY_RUN = true by default), then send the batched sweep
yarn dev src/rent/reclaimRent.ts
```

`reclaimRent.ts` 以每筆交易 20 個帳戶的方式批次，並在一次通過中簽署所有批次：

```ts theme={null}
const batches = chunk(report.accounts, ACCOUNTS_PER_TX);

const builtTxs = await Promise.all(
  batches.map(async (batch) => {
    const builder = new TxBuilder({
      connection,
      feePayer: owner.publicKey,
      cluster: raydium.cluster,
      owner: raydium.owner,
    });
    builder.addInstruction({
      instructions: batch.map((account) =>
        createWithdrawExcessLamportsInstruction({
          source: account.pubkey,
          destination: owner.publicKey,
          authority: owner.publicKey,
          programId: account.programId,
        }),
      ),
    });
    return builder.versionBuild({ txVersion });
  }),
);

// versionMultiBuild puts the calling builder's transaction first and appends
// extraPreBuildData after it, so batch 1 drives and batches 2..n follow in order
const [firstTx, ...restTxs] = builtTxs;
const { execute } = await firstTx.builder.versionMultiBuild({ txVersion, extraPreBuildData: restTxs });
const { txIds } = await execute({ sequentially: true });
```

在發送前模擬。使用 `accounts.addresses` 的 `simulateTransaction` 返回執行後的 lamport 餘額，這是確認算術與叢集實際執行內容相符的最便宜方式。

## 你應該現在回收還是等待？

兩者都可以，差異無論如何都很小：

* **超額不會消失。** 它保留在你自己的帳戶中。沒有過期時間、沒有掃描、沒有截止日期。
* **等待會複利。** 每個步驟從相同帳戶釋放更多，步驟 5 後的一次掃描花費的費用與今天的一次掃描相同。
* **現在回收不會放棄後續步驟。** 你今天掃描的帳戶只是在目前最低額度；下一步再次使其超額資金化，你可以再次掃描它。

現在回收的唯一真實成本是基本費用，等待的唯一真實成本是 lamports 保持不動一段時間更長。

## 進一步閱讀

<CardGroup cols={2}>
  <Card title="SIMD-0437" icon="file-code" href="https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0437-incremental-rent-reduction.md">
    提案本身——五個功能閘門和分步削減的理由。
  </Card>

  <Card title="降低質押" icon="book" href="https://solana.com/upgrades/reduced-rent">
    Solana 的推出頁面：目前步驟、時程表和新帳戶的變更。
  </Card>

  <Card title="質押削減：資料支持的分析" icon="chart-line" href="https://solana.com/news/rent-reduction-deep-dive">
    經濟學和分步推出旨在管理的狀態增長風險。
  </Card>

  <Card title="帳戶模型" icon="database" href="/zh-Hant/solana-fundamentals/account-model">
    Solana 帳戶如何被資金化、擁有和關閉——上述所有內容的背景。
  </Card>
</CardGroup>
