Interest-Bearing & Default Account State
Interest-bearing Token-2022 mints accrue yield over time via an on-chain rate mechanism. Default account state sets whether new token accounts start initialized or frozen, gating who can receive transfers until thawed.
Recipe
# Interest-bearing mint
spl-token create-token \
--program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb \
--decimals 6 \
--enable-interest-bearing \
--rate-authority <PUBKEY>
# Default frozen new accounts
spl-token create-token \
--program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb \
--default-account-state frozenWhen to reach for this:
- On-chain savings-style products displaying APY
- Compliance tokens requiring KYC thaw before transfers
- Airdrops that recipients must claim via thaw flow
- Treasury tokens accruing nominal yield without external lending program
Working Example
# Create interest-bearing mint (rate set in extension init)
MINT=$(spl-token create-token \
--program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb \
--decimals 6 \
--enable-interest-bearing | awk '/Creating token/{print $3}')
spl-token display "$MINT" --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEbuse anchor_lang::prelude::*;
use anchor_spl::token_interface::{Mint, TokenAccount, TokenInterface};
#[derive(Accounts)]
pub struct ThawAfterKyc<'info> {
pub mint: InterfaceAccount<'info, Mint>,
#[account(mut)]
pub holder_token: InterfaceAccount<'info, TokenAccount>,
pub freeze_authority: Signer<'info>,
pub token_program: Interface<'info, TokenInterface>,
}
pub fn thaw_after_kyc(ctx: Context<ThawAfterKyc>) -> Result<()> {
// CPI ThawAccount after off-chain KYC verification
Ok(())
}// UI: read interest rate from mint extension; show accrued balance estimate
// Note: displayed yield may use timestamp-based calculation client-sideWhat this demonstrates:
- Interest rate authority can update APY parameters per extension rules
- Default frozen state blocks transfers until
ThawAccountby freeze authority - New ATAs inherit default state at creation time
Deep Dive
How It Works
- Interest-bearing: Rate stored in mint extension; balances scale with time formula defined by Token-2022 spec
- Default account state:
Initialized(normal) orFrozenfor new accounts - Freeze authority required to thaw gated accounts
- Wallets must call refresh/update instructions where required by spec
Extension Comparison
| Extension | Affects | Authority |
|---|---|---|
| Interest-bearing | Balance growth | Rate authority |
| Default account state | New account transfers | Freeze authority |
TypeScript Notes
// Before transfer: check account state via jsonParsed RPC
// if (state === "frozen") prompt user to complete KYC thaw flowGotchas
- APY display without refresh - stale UI amounts. Fix: follow Token-2022 refresh instruction cadence in clients.
- Frozen airdrop surprise - users cannot move tokens. Fix: document claim + thaw steps upfront.
- Freeze authority centralization - issuer can lock all holders. Fix: multisig freeze authority or revoke after distribution.
- Interest vs DeFi yield - extension accrual differs from lending protocol APY. Fix: do not conflate in marketing.
- DEX pools with frozen default - pool ATAs may need explicit thaw at setup. Fix: test pool creation flow end-to-end.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| External lending protocol | Real yield from borrowers | Simple branded savings UX |
| Transfer hook KYC | Per-transfer checks | Account-level gating sufficient |
| Manual freeze per account | Selective lock | All new accounts should start frozen |
FAQs
What is interest-bearing extension?
On-mint configuration accrues balance over time per Token-2022 rate formula.
What is default account state?
Whether newly created token accounts for the mint start initialized or frozen.
Who thaws frozen accounts?
Freeze authority via ThawAccount instruction after your KYC policy passes.
Can interest rate change?
Rate authority updates per extension rules - document governance.
Do all wallets show accrued interest?
Support varies - you may need custom UI calculations.
Compatible with transfer fees?
Yes with careful UX - fees apply on transfers, interest accrues separately.
Can default state be initialized?
Yes - standard behavior equivalent to classic SPL accounts.
Impact on AMMs?
Frozen accounts cannot transfer - pools must use initialized/thawed accounts.
Is this real DeFi yield?
Extension math only - not lending market yield unless integrated off-chain.
Testing on devnet?
Create extension mint on devnet; verify thaw and transfer gating paths.
Immutable default state?
Often set at mint init - plan before mainnet.
Relation to freeze authority?
Default frozen requires active freeze authority to thaw - same as classic freeze.
Related
- Authorities - freeze authority
- Permanent Delegate & Non-Transferable - control extensions
- Token-2022 Best Practices - gating UX
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, and LiteSVM 0.6.x.