About

Stranded lamports on SPL token accounts and mints.

P-token's WithdrawExcessLamports Instruction

What's going on

SPL token accounts, multisig accounts, and mints need to hold a small SOL balance to stay rent-exempt (~0.002 SOL for a token account, ~0.001 SOL for a mint, and ~0.003 SOL for a multisig account). People sometimes accidentally send SOL to mint, token or multisig accounts instead of a wallet. Any lamports in an account above the minimum rent have historically been stranded: because the token program owns the mint/token/multisig account, there is no normal Token instruction that has access to them.

P-token, an efficient rewrite of the SPL Token program, went live on epoch 971. The rewrite included a few new instructions, including WithdrawExcessLamports which lets the appropriate authority/owner claim excess lamports back down to the rent-exempt minimum without touching the token balance or supply. The ability to claim stranded lamports depends on the account type.

How recovery works

WithdrawExcessLamports lets the appropriate authority claim the stranded lamports back down to the rent-exempt minimum without touching the token balance or supply. The signer rules differ per account type:

  • Mint with a mint authority — the authority signs. Easy.
  • Mint with no authority, off-curve pubkey — the program that owns the address (its PDA derivation source) can sign, via a custom instruction that invokes WithdrawExcessLamports on the Token program.
  • Mint with no authority, on-curve pubkey — only the original keypair of the mint can sign. Mint keypairs are commonly discarded after launch, so these are often unrecoverable.
  • Token account— the account's owner signs.
  • Multisig — any M of N configured signers co-sign.

With @solana/kit and the @solana-program/token client, assembling the call is one instruction:

import { createClient } from '@solana/kit';
import { getWithdrawExcessLamportsInstruction } from '@solana-program/token';

await client.sendTransaction([
    getWithdrawExcessLamportsInstruction({
        authority,
        destination: client.payer.address,
        source: mint.address, // or token/multisig account address
    }),
]);

Full devnet walkthrough (create mint → fund → revoke authority → withdraw with the mint keypair): withdrawMintLamports.ts.

Program source: p-token withdraw_excess_lamports.rs.

About the mint snapshot

The mint browser is a static snapshot taken at epoch 970, filtered to mints with more than 1 SOL stranded. Balances drift as people fund or recover accounts, so the live state may differ — paste any address into the lookup page for a fresh RPC read.

The snapshot only includes mints. For token accounts, multisig accounts, and wallets, use the lookup page — it queries them on demand and (for wallets) paginates through every SPL token account where the token account's owner address is the same as the address you pasted.

What the lookup does

For an address you paste, the tool calls getAccountInfo and inspects the owner:

  • Owned by SPL Token or Token-2022 — decode the account, identify it as a mint, token account, or multisig, and compute lamports − rentExemptMinimum.
  • Anything else (system program, PDAs, unknown owners) — treat as a wallet and run getProgramAccounts against the SPL Token program with a memcmp filter on the owner field (offset 32), paginating through every token account where this pubkey is the owner. We surface any account with a lamport balance above the rent-exempt minimum.

For mints, we also report the signer kind— mint-authority, off-curve PDA, or on-curve keypair — so you can tell at a glance who'd need to sign to recover the excess.