Token-2022 In Depth
Token-2022 (Token Extensions) is the Solana token program that keeps the familiar mint, account, and transfer model of classic SPL Token while allowing optional extensions to attach extra fields and rules at initialization.
Search across all documentation pages
Token-2022 (Token Extensions) is the Solana token program that keeps the familiar mint, account, and transfer model of classic SPL Token while allowing optional extensions to attach extra fields and rules at initialization.
It is not a new chain and not a silent upgrade of the classic program. It is a different program ID with a compatible base layout, larger accounts when extensions are enabled, and client and venue compatibility that varies by extension.
This page is the umbrella for token-2022-extensions: how Token-2022 relates to classic Token, how the extension model works, what the major extensions mean for product and code, and how migration actually happens.
TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb) is a superset token program: same base mint and token-account concepts as classic SPL Token (TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA), plus a type-length-value (TLV) extension region for fees, hooks, metadata, soulbound rules, yield display, and confidential amounts.Classic SPL Token is the long-standing program most wallets and DEXs assume by default. Its mint and token account layouts are fixed: supply, decimals, authorities, balances, delegates, frozen state. Policy beyond that lives in separate programs (marketplaces, Metaplex metadata PDAs, custom transfer wrappers).
Token-2022 keeps that base layout at the front of the account and appends extension data. Without extensions, a Token-2022 mint behaves much like a classic mint for mint, burn, and transfer, but:
Tokenkeg....There is no shared upgrade path that flips an existing classic mint into Token-2022. Same brand, new program means new mint, new ATAs, and an operational holder and liquidity migration.
Extensions are optional modules initialized when the mint and/or token account is created (or, for some account extensions, when the account is configured). They live in a TLV region after the base SPL fields.
Practical rules:
jsonParsed where supported, official Token-2022 codecs, or DAS for reads; still branch on program ID for writes.| Family | Intent | Typical pain if ignored |
|---|---|---|
| Transfer fee | Withhold bps (and max) on transfers | Wrong UX amounts; fees never harvested |
| Transfer hook | CPI custom program on transfer | Missing extra accounts; failed txs |
| Metadata / pointer | Name, symbol, URI on or beside mint | Blank branding in non-aware wallets |
| Permanent delegate | Fixed authority can always move tokens (holders keep their own transfer rights) | Undisclosed seizure power |
| Non-transferable | Block ordinary transfers (soulbound) | Failed sells; DEX listing impossible |
| Interest-bearing | Rate-based balance growth display | Stale amount UI |
| Default account state | New accounts start frozen or initialized | Surprise freeze until thaw |
| Confidential transfer | ZK-hidden amounts | Wrong public amount; unsupported wallets |
Token metadata embeds name, symbol, and URI in mint extension data so simple fungibles do not need a Metaplex Token Metadata PDA for basic branding. Metadata pointer stores a pubkey that points at an external metadata account when you want metadata off the mint itself.
URI usually references off-chain JSON (image, description); prefer immutable storage over mutable HTTP hosts. Explorers and DAS increasingly index Token-2022 metadata, but some wallets still expect Metaplex for NFT-like assets. On-mint metadata does not by itself make an NFT.
Detail: Metadata & Metadata Pointer.
A transfer hook mint stores a custom program id. On every transfer (and related move), Token-2022 invokes that program so policy runs atomically with the token move: allowlists, royalty ledgers, compliance checks, accounting.
The hook program must implement the interface Token-2022 expects and stay minimal (CU is shared with the transfer). It must also be a separate program: the hook runs as a nested CPI while Token-2022 - and whatever program initiated the transfer - are still on the call stack, so a hook that calls back into either fails with ReentrancyNotAllowed. Your own program cannot be its own mint's hook. Clients must resolve and pass extra accounts the hook requires from the on-chain extra-account-meta PDA; missing accounts is the most common integration failure. Prefer the built-in transfer fee extension when the only need is basis-point revenue.
Detail: Transfer Hooks. Fees: Transfer Fees.
Permanent delegate embeds a pubkey on the mint that can transfer tokens without the usual per-account delegate approval from the holder. It is strong issuer control for reclaim paths, and a serious trust disclosure for users.
Non-transferable marks the mint so standard transfers fail. Tokens are effectively soulbound after issue (credentials, badges, non-tradable access). Mint and burn may still apply under authorities you configure. Secondary markets and AMM pools are the wrong product surface.
Often combined with default account state frozen so new accounts cannot move funds until a freeze authority thaws after KYC or claim flow.
Detail: Permanent Delegate & Non-Transferable.
Interest-bearing stores a rate (and rate authority) on the mint. Token-2022 applies that rate when converting raw units to a UI amount, so the displayed balance grows over time while the stored amount and the mint's supply stay exactly where they were. Nothing is minted; this is a display convention for savings-style product math, not real yield. UIs must refresh with extension-aware reads.
Default account state sets whether new token accounts start initialized or frozen. Frozen-by-default is a compliance and airdrop pattern: creation succeeds, transfers wait on thaw.
Confidential transfers use zero-knowledge proofs so amounts can rest and move in encrypted form while the program still enforces conservation of value. The classic public amount field is not the full economic picture once value is deposited into confidential state. Proof generation is client-side and wallet or RPC support is narrower than plain transfers.
Details: Interest-Bearing & Default Account State, Confidential Transfers.
Migrating from classic SPL Token means: design the Token-2022 mint and extension set; confirm wallet, DEX, custody, and indexer support; snapshot holders (and LP positions); create the new mint and airdrop or claim into Token-2022 ATAs; dual-run both mints; then sunset legacy deposits.
There is no on-chain "upgrade this mint" instruction across programs. Programs that accept arbitrary user mints should use token_interface (Anchor) or equivalent dual paths so classic and Token-2022 can coexist during transition.
Detail: Migrating from SPL Token.
End-to-end, a Token-2022 asset touches three layers:
Mint init (program ID Token-2022 + extension TLV)
|
v
Token accounts / ATAs (same program ID in derivation)
|
v
Instructions (transfer, mint, freeze, harvest, hook CPI, confidential proofs)
|
v
Clients, wallets, routers, vaults (branch on owner + extensions)Program ID is the first branch. Before building ATA PDAs or transfer instructions, read the mint account's owner. If it is Token-2022, every subsequent builder, CPI target, and package must match.
ATA derivation includes the token program. With a new Token-2022 mint you always get new ATAs. Passing the wrong tokenProgram yields a wrong address and silent empty-account bugs.
Extension interactions compound. Transfer fee plus hook means fee math and hook accounts both apply. Non-transferable plus permanent delegate blocks user transfer while the delegate may still move value. Default frozen plus thaw authority creates accounts that cannot transfer until thaw. Confidential plus public deposit or withdraw needs multi-step UI state (public, pending, confidential).
Anchor dual mint programs. Prefer InterfaceAccount + TokenInterface over classic-only Token constraints when vaults list external or user-chosen mints. Never mix the two module trees in one account struct: anchor_spl::token::{Mint, TokenAccount} are classic-Token-only and their owner check rejects Token-2022 accounts. In native Rust the same split applies to instruction builders - spl_token::instruction::* starts with check_program_account and returns IncorrectProgramId for the Token-2022 id, so Token-2022 needs spl_token_2022::instruction::*. There is no "just pass the other program account" path.
CLI and stack. With Solana CLI 3.0.10, point spl-token at Token-2022 via --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb. Local work on Agave 4.1.1-class validators, Surfpool, or LiteSVM still requires correct program and extension init order. @solana/kit 7.0.0 supplies typed RPC and codecs; detect owner via getAccountInfo, then encode with Token-2022-aware helpers.
Default to classic SPL Token when you need maximum venue compatibility and no extension is required. Choose Token-2022 when an extension is a hard product requirement and you have verified support. Shipping Token-2022 only because it is newer is how launches strand liquidity.
Treat mint init as a security and legal document:
For each enabled extension, verify target wallets (display, send, ATA create, fee net amounts), DEX or router routes and hook extra accounts, custody deposit support, indexer or DAS balance semantics, and your own program paths (token_interface, fee harvest, hook metas). Smoke-test small amounts on devnet and mainnet before large liquidity.
Transfer fees need harvest or crank paths so withheld tokens reach treasury. Hooks need versioned extra-account resolvers in every client path. Interest-bearing needs UI refresh policy. Confidential needs key custody and proof generation architecture (worker, server, or specialized wallet).
Greenfield is one mint and one ATA tree. Migration is dual mint registry, dual pools, dual analytics, and a communication plan. Budget engineering for dual-run; it usually outlasts airdrop day.
A separate Solana token program that preserves classic mint and account concepts while allowing optional TLV extensions for fees, hooks, metadata, policy, yield display, and confidential amounts.
TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb. Classic SPL Token remains TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA.
When you need a specific extension classic Token cannot provide and you have verified wallet, DEX, and custody support for that set; otherwise classic Token maximizes compatibility.
Generally you configure extensions at mint and account initialization. Plan the set before mainnet; do not assume later feature flags.
ATA derivation includes the token program id. Always pass Token-2022's program id when deriving and creating accounts for Token-2022 mints.
A transfer fee withholds basis points inside Token-2022. A transfer hook CPI-calls a custom program for arbitrary policy and requires extra accounts from every client.
No. Frozen is an account state that can be thawed. Non-transferable is a mint-level rule that blocks ordinary transfers for that mint's tokens.
A fixed authority on the mint can move tokens without the usual holder-approved delegate pattern. Disclose it and secure the key with multisig or governance when used.
The extension family is centered on amount privacy via ZK proofs and encrypted balances; do not assume full identity privacy on a public L1 without a broader design.
Use anchor-spl token_interface types (InterfaceAccount, TokenInterface) and branch clients on mint owner program id.
Operationally: snapshot, new Token-2022 mint, airdrop or claim into new ATAs, dual-run, then sunset. There is no single upgrade instruction.
Start with Token-2022 Basics for concrete CLI and client steps, then the extension pages under Related for metadata, policy, yield, confidential transfers, and migration.
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, Rust 1.91.1, and @solana/kit 7.0.0.
Reviewed by Chris St. John·Last updated Jul 15, 2026