Non-EVM Standards
Solana Token-2022 Guide
A complete guide to Solana Token-2022 and SPL token extensions, covering advanced features, use cases and implementation details.
Token-2022, the Extensible Token Standard, defines a modular framework for SPL tokens on Solana, enabling programmable extensions directly appended to mint and account structures for custom behaviors like compliance hooks and privacy. For Real World Asset (RWA) protocols, this standard is especially valuable, as tokens can represent fractional claims on tokenized Treasuries, real estate, commodities, or other off-chain collateral while maintaining a lightweight, high-throughput interface for minting, transfers, and extensions without full smart contract overhead.
Before Token-2022, Solana RWA projects relied on custom programs or legacy SPL tokens, resulting in fragmented compliance logic, inconsistent metadata handling, and scalability bottlenecks during high-volume settlements. Token-2022 resolved this by introducing composable extensions that embed rules natively into tokens, reducing program size and costs. For RWA builders, the standard provides a flexible abstraction layer that supports off-chain verification flows, such as oracle-fed KYC, confidential balances for privacy, or transfer restrictions for regulatory gating, while preserving seamless composability with Solana DeFi like Jupiter DEX or lending protocols.
A key design principle is native extensibility, where tokens expose standardized SPL interfaces augmented by optional modules without revealing internal hook logic. This is well suited to RWA tokens where transfers may depend on off-chain data feeds or asynchronous compliance cycles, yet integrators like wallets or aggregators still need reliable, auditable operations.
Use of Token-2022 in RWA Contexts
Token-2022 is the foundational standard for RWA tokens on Solana because it abstracts the complexity of tokenizing and managing real-world assets into a composable, SPL-compatible interface. While traditional DeFi tokens wrap liquid assets like SOL for simple transfers, RWA tokens adapt the model to illiquid, regulated assets, tokenized private credit, commercial real estate, commodities, or bond portfolios, where on-chain tokens represent legally backed off-chain value held by custodians or SPVs.
Key Applications in RWA Development
Fractional Ownership and Liquidity Provision
Many RWAs are high-value and indivisible (for example, a ten-million-dollar building or a portfolio of private credit). Token-2022 allows developers to mint fungible tokens proportional to deposits, unlocking fractional ownership and secondary-market liquidity.
- Implement
mint_towith metadata extensions to link tokens to off-chain deeds or valuations. - Tokens can trade freely on DEXs, offering liquidity for assets that would otherwise be locked for years.
- Example: A real estate token where metadata embeds property docs, and transfer hooks restrict to verified holders.
Yield Accrual and NAV Management
Transfer fee extensions automate revenue distribution (e.g., rental yields from real estate tokens), with hooks querying oracles (e.g., Pyth) for real-time NAV updates. This supports auto-accrual without manual interventions, ideal for tokenized bonds or funds.
Using trusted sources (Pyth, Switchboard) ensures accurate pricing in hooks, critical for compliance and for investor transfers. Regulators increasingly expect transparent audit trails, and Token-2022 provides this without exposing internal extension state.
Redemption and Settlement Mechanics
RWA redemptions are inherently asynchronous, as physical settlement layers (banks, custodians, transfer agents) cannot finalize instantly.
Patterns include:
burnwith pausable extensions for queuing.- Custom hook logic for async flows.
- Memo-required events for signed claims.
- Proof-of-reserve checks before fulfillment.
These guardrails prevent unauthorized burns and ensure token solvency, especially for semi-liquid assets like private credit or T-bills.
Composability Across the RWA Stack
Token-2022 tokens plug directly into Solana DeFi:
- Marginfi accepts tokens as collateral.
- Jupiter pairs can provide deep secondary liquidity.
- Aggregators (e.g., Kamino) route into Token-2022 natively.
For regulated RWAs:
- Pair with transfer hooks for investor eligibility gating.
- Combine with group extensions for modular compliance.
- Integrate identity proofs via metadata.
This drastically reduces integration complexity, for example, a tokenized invoice token can list across lending markets without custom adapters.
Developer Advantages in RWA Builds
- Regulatory Alignment: Modular extensions hide off-chain custodian processes while preserving accurate hooks for MiFID II/MiCA-aligned disclosures.
- Extensibility: Hooks (such as transfer hooks) allow injecting RWA-specific logic i.e., pricing oracles, geofencing, or IPFS-pinned compliance policies.
- Risk Isolation: Tokens remain fully SPL compliant, and pauses do not freeze wallet-held balances.
- Upgrade Path: Legacy SPL tokens can migrate via wrappers, preserving TVL and simplifying audits.
Solana Labs’ implementation offers a secure foundation, which teams customize for RWA nuances such as custody-fee accrual, bypass lists, or settlement delays.
To visualize the end-to-end flow in an RWA token, the following sequence diagram captures the typical mint - transfer - burn cycle. It illustrates how users interact with the token mint, how extensions interact with hooks and oracles, and how off-chain compliance updates flow back on-chain through memos or validations. This representation is especially important for understanding asynchronous transfers, delayed settlements, and hook-driven compliance in RWA systems.
This diagram highlights how Token-2022 acts as the connective tissue between on-chain token operations and off-chain asset realities. Mints append extensions proportional to contributed value, hooks capture real-world compliance as transfers execute, and memo functions help manage slippage during burns. For illiquid RWA portfolios, the model can be extended with explicit transfer restrictions between the mint (M) and the custodian or SPV (C) to handle delayed settlement cycles.
Core Specification
A Token-2022 mint must implement the core SPL Token interface for its fungible structure, the extensible representation of a user’s proportional claim on the underlying asset. Optional extensions enable advanced features like confidential transfers, a valuable enhancement for RWA use cases where institutions manage share privacy without needing full programs.
In Token-2022, the mint behaves like any SPL token (balance queries, total supply, transfers), while extensions refer to appended modules for collateral management. The standard enforces a clean separation between base tokens and extensions, ensuring predictable operations and seamless integration across Solana and RWA systems.
Key Definitions
- Mint: The token configuration with appended extension data, e.g., a tokenized Treasury bill or credit note.
- Account: The token balance holder, extensible for confidential proofs or fees.
- Total Supply: The aggregate token value managed by the mint, equal to the sum of principal, accrued extensions, and adjustments for fees or losses.
- Extension Modules: (e.g., Transfer Hook, Metadata) Provide idealized, fee-agnostic behaviors for UI, analytics, and oracle integrations. They represent the mathematical relationship between base tokens and extended logic.
- Hook Functions: (e.g., pre/post-transfer) Provide near-exact estimates of expected outcomes, reflecting fees, rounding, or NAV changes, without executing state updates. These enable accurate transaction planning.
- Rounding Rules: Token-2022 mandates rounding in favor of the mint:
- Round down when issuing tokens or deductions, preventing dilution.
- Round up when applying fees or requirements, protecting existing participants. These rules ensure fair distribution and discourage precision-based attacks.
The Token-2022 standard defines 20+ optional extensions, organized by their roles in compliance, privacy, and metadata. Every extension is appended at mint initialization, ensuring a single source of truth for token behavior and movements. Below is the Rust-equivalent interface, accompanied by developer notes covering edge cases, rounding behavior, and considerations specific to RWA tokens such as asynchronous hooks and oracle-driven updates.
1use anchor_lang::prelude::*;
2use anchor_spl::token_interface::{Mint, TokenAccount};
3
4#[program]
5pub mod token_2022 {
6 use super::*;
7
8 // Base SPL Mint with Extensions
9 pub fn initialize_mint(
10 ctx: Context<InitializeMint>,
11 decimals: u8,
12 authority: Pubkey,
13 ) -> Result<()> {
14 // Core mint setup
15 Ok(())
16 }
17
18 // Extension: Transfer Hook
19 pub fn initialize_transfer_hook(
20 ctx: Context<InitializeTransferHook>,
21 hook_program_id: Pubkey,
22 ) -> Result<()> {
23 // Append hook module
24 Ok(())
25 }
26
27 // Extension: Confidential Transfers
28 pub fn enable_confidential_transfers(ctx: Context<EnableConfidential>) -> Result<()> {
29 // ZK setup
30 Ok(())
31 }
32
33 // Extension: Transfer Fee
34 pub fn initialize_transfer_fee(
35 ctx: Context<InitializeFee>,
36 basis_points: u16,
37 max_fee: u64,
38 ) -> Result<()> {
39 // Fee config
40 Ok(())
41 }
42
43 // Extension: Metadata Pointer
44 pub fn initialize_metadata_pointer(
45 ctx: Context<InitializeMetadata>,
46 authority: Pubkey,
47 metadata_address: Pubkey,
48 ) -> Result<()> {
49 // Link to URI
50 Ok(())
51 }
52
53 // Transfer with Extensions
54 pub fn transfer_with_extensions(
55 ctx: Context<TransferWithExtensions>,
56 amount: u64,
57 extra: Vec<u8>, // Hook data
58 ) -> Result<()> {
59 // Invoke hooks, apply fees
60 Ok(())
61 }
62
63 #[event]
64 pub struct TransferEvent {
65 pub amount: u64,
66 pub from: Pubkey,
67 pub to: Pubkey,
68 }
69
70 #[event]
71 pub struct FeeEvent {
72 pub fee_amount: u64,
73 pub withheld_to: Pubkey,
74 }
75}Detailed Function Breakdown
Below is an extension-by-extension explanation of the Token-2022 interface, including edge cases, rounding behavior, and RWA-specific implementation guidance for regulated assets, off-chain settlement, and hook-driven validation.
initialize_mint()
Sets up the base mint structure (82 bytes) with decimals and authority. In RWA tokens, this pins the initial configuration for tokenized Treasury bills, USDC wrappers, or credit notes.
This value is immutable post-initialization to avoid governance-based changes.
initialize_transfer_hook()
Appends the transfer hook module, linking to a custom program for pre/post logic.
- RWA Integration: For compliance-based assets, invoke oracle-fed validations (Pyth / Switchboard).
- Edge Case: Must handle rebasing-like extensions or tokens with dynamic authorities.
enable_confidential_transfers()
Activates ZK proofs for hidden balances using ElGamal encryption.
- Formula: Encrypted commitments for privacy-preserving proofs.
- Usage: Auditor integrations, risk dashboards.
- RWA Note: Reflects pure private holdings, does not account for redemption delays or custody fees.
initialize_transfer_fee()
Configures fee deduction (basis points, max per transfer) to a recipient or withheld account.
- Ensures no precision-based arbitrage.
- RWA Note: Useful for custody-fee disclosures in regulated markets.
initialize_metadata_pointer()
Stores a URI (e.g., IPFS) to off-chain JSON with asset details.
- Return max for “no limit” on metadata size.
- RWA Note: Enforce investor caps, jurisdiction restrictions, or temporary pauses due to regulatory flags.
transfer_with_extensions()
Executes transfer, invoking hooks and applying extensions. Emits TransferEvent.
- Requires prior approval on source account.
- Includes compliance hooks for KYC/AML evaluation.
- RWA Note:
- For illiquid assets (such as real estate and private credit): pair with pausable extensions for asynchronous settlement.
- Trigger oracle checks for sanctions/residency validation.
Extensions Mirror (e.g., burn, pause)
Burn-focused mirror of the transfer flow.
- burn(amount) requires exact quantity; extensions may vary post-fees.
- RWA Use Case: Redemption where holders burn fixed tokens based on agreement.
Reference Implementation
Solana Labs’ Token-2022 offers a mature, security-audited foundation for building extensible tokens. The program inherits from SPL Token, providing a clean extension surface for RWA-specific logic. Its design encourages minimal overrides while still supporting custom hook models, fee configs, compliance layers, and Oracle integration.
Key capabilities include:
- Inflation Attack Protection: The implementation prevents dilution by enforcing authority checks. Early minters cannot exploit low-supply corner cases to extract excess value.
- Rounding Compliance: All extensions use checked arithmetic for precise, deterministic operations that adhere to SPL requirements of rounding in favor of the mint. This eliminates subtle precision-drift exploits.
- Extensible Hooks: Lifecycle hooks such as pre/post-transfer allow developers to embed RWA-specific functionality, NAV oracle checks, compliance gating, settlement status validation, or fee accounting, without modifying core logic.
- Flexible Structure: Token-2022 builds on SPL’s base, with optional CPI guards or access controls for regulated administration. This makes it straightforward to integrate custodial controls, upgrade pathways, or role-gated operations required in regulated RWA environments.
1use anchor_lang::prelude::*;
2use anchor_spl::token_2022::{self, Token2022};
3
4declare_id!("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");
5
6#[program]
7pub mod rwa_token_2022 {
8 use super::*;
9
10 pub fn create_rwa_mint(
11 ctx: Context<CreateRwaMint>,
12 decimals: u8,
13 fee_basis: u16,
14 hook_id: Pubkey,
15 ) -> Result<()> {
16 let mint = &mut ctx.accounts.mint;
17 token_2022::initialize_mint(
18 CpiContext::new(
19 ctx.accounts.token_program.to_account_info(),
20 token_2022::InitializeMint {
21 mint: mint.to_account_info(),
22 rent: ctx.accounts.rent.to_account_info(),
23 },
24 ),
25 decimals,
26 &ctx.accounts.authority.key(),
27 )?;
28
29 // Add RWA extensions
30 token_2022::initialize_transfer_fee(
31 CpiContext::new(
32 ctx.accounts.token_program.to_account_info(),
33 token_2022::InitializeTransferFee { /* accounts */ },
34 ),
35 fee_basis,
36 0, // max_fee
37 )?;
38
39 token_2022::initialize_transfer_hook(
40 CpiContext::new(
41 ctx.accounts.token_program.to_account_info(),
42 token_2022::InitializeTransferHook { /* accounts */ },
43 ),
44 hook_id,
45 )?;
46
47 Ok(())
48 }
49}
50
51#[derive(Accounts)]
52pub struct CreateRwaMint<'info> {
53 #[account(
54 init,
55 payer = payer,
56 mint::token_program = token_program,
57 mint::decimals = decimals
58 )]
59 pub mint: Account<'info, Mint>,
60 pub token_program: Program<'info, Token2022>,
61 // Additional accounts...
62}- The initializer pins extensions at creation. For RWA tokens, prefer immutable configs and link metadata to IPFS for provenance.
- Authority can be multisig for clarity in UIs.
Mint Flow (User-Facing)
User-level instructions call core logic with extensions.
1pub fn mint_to(ctx: Context<MintTo>, amount: u64) -> Result<()> {
2 let cpi_accounts = anchor_spl::token::MintTo {
3 mint: ctx.accounts.mint.to_account_info(),
4 to: ctx.accounts.to.to_account_info(),
5 authority: ctx.accounts.authority.to_account_info(),
6 };
7 let cpi_program = ctx.accounts.token_program.to_account_info();
8 let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);
9 anchor_spl::token::mint_to(cpi_ctx, amount)?;
10
11 // Invoke post-mint hook if enabled
12 if let Some(hook) = ctx.accounts.hook_program.key() {
13 // Custom RWA logic
14 }
15
16 emit!(MintEvent { amount, to: ctx.accounts.to.key() });
17 Ok(())
18}- Use CPI for safe minting.
- Override pre-mint to add compliance checks (KYC, caps) and revert early if onboarding fails.
- For illiquid or async-backed assets, combine mint with provisional issuance and hook finalization to avoid over-minting.
Transfer Flow
Symmetric to mint, transfer invokes extensions, then updates accounts.
1pub fn transfer(ctx: Context<Transfer>, amount: u64) -> Result<()> {
2 // Pre-hook invoke
3 if let Some(hook) = ctx.accounts.hook.key() {
4 let pre_cpi = // CPI to hook pre-transfer
5 invoke(&pre_ix, /* accounts */)?;
6 }
7
8 let cpi_accounts = anchor_spl::token::Transfer {
9 from: ctx.accounts.from.to_account_info(),
10 to: ctx.accounts.to.to_account_info(),
11 authority: ctx.accounts.authority.to_account_info(),
12 };
13 let cpi_ctx = CpiContext::new(ctx.accounts.token_program.to_account_info(), cpi_accounts);
14 anchor_spl::token::transfer(cpi_ctx, amount)?;
15
16 // Post-hook and fees
17 // Apply transfer fee if enabled
18 if ctx.accounts.fee_config.is_some() {
19 // Deduct and emit
20 }
21
22 emit!(TransferEvent { amount, from: ctx.accounts.from.key(), to: ctx.accounts.to.key() });
23 Ok(())
24}- Hook-first follows checks-effects-interactions and reduces reentrancy risk.
- For queued transfers, implement pre-hook to check status and push into a compliance queue.
- Add transfer rate limits or liquidity buffers to defend against sudden runs.
Hook Integration
Default hooks are no-op; RWA overrides query oracles.
1pub fn pre_transfer_hook(ctx: Context<PreTransfer>, amount: u64) -> Result<()> {
2 // Default: No-op
3 // Override for RWA: Integrate Pyth / Switchboard for KYC
4 let nav = // Oracle query
5 require!(ctx.accounts.user.kyc_verified && amount <= nav_limit, Error::Invalid);
6 Ok(())
7}- nav query uses timestamp/nonce to prevent replay.
- Consider a last-valid-proof fallback and staleness policy.
Adding Transfer Fees (Example: 0.5% fee)
Fee handling keeps execution consistent.
1const FEE_BASIS: u16 = 50; // 0.5%
2
3pub fn apply_fee(amount: u64) -> (u64, u64) {
4 let fee = amount * u64::from(FEE_BASIS) / 10000;
5 (amount - fee, fee) // Net, fee
6}- Keep fee accounting transparent: emit FeeEvent and track separately.
- For RWA products, fees may fund custody/legal, document in metadata.

