DEV Community

Cover image for Building Multi‑Extension Tokens on Solana and making it compliance goated
NIRANJAN LAMICHHANE
NIRANJAN LAMICHHANE Subscriber

Posted on

Building Multi‑Extension Tokens on Solana and making it compliance goated

After 36 days of diving into Solana development, I finally reached the most exciting milestone: composability.

Solana’s Token Extensions allow you to combine multiple features into a single mint — without writing complex smart contract logic.

In this post, I’ll walk you through two real‑world scenarios:

  1. Day 37 – A token with transfer fee, interest‑bearing, and metadata extensions.
  2. Day 38 – A compliance‑gated token with default frozen accounts (perfect for regulated finance).

All commands are tested on Devnet using the spl-token CLI. Let’s go!


Day 37: The Triple‑Extension Token

The Goal

Create a mint that:

  • Charges a 1% transfer fee (capped at 5 tokens).
  • Grows in value over time (interest‑bearing, 5 bps annually).
  • Stores its name, symbol, and URI directly on‑chain (metadata).

Step 1 – Create the Mint

One command, no backslashes (Windows‑friendly):

spl-token --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb create-token --decimals 2 --transfer-fee-basis-points 100 --transfer-fee-maximum-fee 500 --interest-rate 5 --enable-metadata
Enter fullscreen mode Exit fullscreen mode

Output (yours will differ):

Creating token DrcSSbxxb63GiZiaXd1tFPRwwofFV3pJHSpFY1aCvcjN under program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
Address:  DrcSSbxxb63GiZiaXd1tFPRwwofFV3pJHSpFY1aCvcjN
Decimals:  2
Enter fullscreen mode Exit fullscreen mode

Save the mint address — we’ll call it $MINT.

Step 2 – Initialize Metadata

spl-token initialize-metadata $MINT "ArcCoin" "ARC" "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/CompressedCoil/metadata.json"
Enter fullscreen mode Exit fullscreen mode

Step 3 – Verify All Extensions

spl-token display $MINT
Enter fullscreen mode Exit fullscreen mode

Result (abridged):

Extensions
  Interest-bearing:
    Current rate: 5bps
  Transfer fees:
    Current fee: 100bps
    Current maximum: 50000
  Metadata Pointer:
    Metadata address: DrcSSbxxb63GiZiaXd1tFPRwwofFV3pJHSpFY1aCvcjN
  Metadata:
    Name: ArcCoin
    Symbol: ARC
Enter fullscreen mode Exit fullscreen mode

All three extensions are active ✅

Step 4 – Create an Account and Mint 1000 Tokens

spl-token create-account $MINT
spl-token mint $MINT 1000
spl-token balance $MINT   # 1000
Enter fullscreen mode Exit fullscreen mode

Step 5 – Test the Transfer Fee

Create a second wallet (if you haven’t already):

solana-keygen new --outfile second-wallet.json --no-bip39-passphrase --force
solana airdrop 1 second-wallet.json   # fund for rent
Enter fullscreen mode Exit fullscreen mode

Create its token account and transfer 100 tokens:

spl-token create-account $MINT --owner second-wallet.json
spl-token transfer $MINT 100 second-wallet.json --expected-fee 1 --allow-unfunded-recipient
Enter fullscreen mode Exit fullscreen mode

Check balances:

spl-token balance $MINT                     # 900
spl-token balance $MINT --owner second-wallet.json   # 99
Enter fullscreen mode Exit fullscreen mode

The 1 token fee is withheld in the recipient’s account.

Step 6 – Harvest Withheld Fees

# Find recipient’s token account
spl-token accounts --owner second-wallet.json -v
# Withdraw to your own token account
spl-token withdraw-withheld-tokens YOUR_TOKEN_ACCOUNT RECIPIENT_TOKEN_ACCOUNT
Enter fullscreen mode Exit fullscreen mode

After harvest:

spl-token balance $MINT   # 901 (the fee is yours)
Enter fullscreen mode Exit fullscreen mode

Day 37 takeaway – three extensions working together, no custom program required.


Day 38: Compliance‑Gated Token (Default Frozen)

The Goal

Create a mint where every token account starts frozen. Only the freeze authority can thaw (approve) an account. This is how a regulated stablecoin or KYC‑gated platform works at the protocol level.

Step 1 – Create the Mint with --default-account-state frozen

spl-token create-token --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb --enable-freeze --default-account-state frozen
Enter fullscreen mode Exit fullscreen mode

Output:

Address:  4jC4rjpi5wh1TKd2b8cLyAqFm9a68jmGRF1qPEnkENjm
Decimals:  9
Enter fullscreen mode Exit fullscreen mode

Save as $MINT_FROZEN.

Step 2 – Create Two Token Accounts (Both Will Be Frozen)

spl-token create-account $MINT_FROZEN                # yours
spl-token create-account $MINT_FROZEN --owner second-wallet.json   # second wallet
Enter fullscreen mode Exit fullscreen mode

Step 3 – Try to Mint (Must Fail)

spl-token mint $MINT_FROZEN 100
Enter fullscreen mode Exit fullscreen mode

Expected error:

Error: Account is frozen
Enter fullscreen mode Exit fullscreen mode

✅ The enforcement works – even the mint authority cannot bypass it.

Step 4 – Thaw Your Account (The “KYC Approval”)

First find your token account address (spl-token accounts), then:

spl-token thaw YOUR_TOKEN_ACCOUNT
Enter fullscreen mode Exit fullscreen mode

Step 5 – Mint Now Succeeds

spl-token mint $MINT_FROZEN 100
spl-token balance $MINT_FROZEN   # 100
Enter fullscreen mode Exit fullscreen mode

Step 6 – Transfer to Still‑Frozen Second Account (Must Fail)

spl-token transfer $MINT_FROZEN 50 second-wallet.json --allow-unfunded-recipient
Enter fullscreen mode Exit fullscreen mode

Error: Account is frozen (destination).

Step 7 – Thaw Second Account, Then Transfer Succeeds

spl-token thaw SECOND_WALLET_TOKEN_ACCOUNT
spl-token transfer $MINT_FROZEN 50 second-wallet.json --allow-unfunded-recipient
spl-token balance $MINT_FROZEN --owner second-wallet.json   # 50
Enter fullscreen mode Exit fullscreen mode

Day 38 takeaway – compliance is enforced at the runtime level, not in off‑chain code.


What I Learned

  • Composability is powerful – you can mix and match extensions like LEGO bricks.
  • The CLI abstracts complexity – one command sets up TLV‑encoded extension data.
  • Default frozen accounts are a game‑changer for regulated finance on Solana.
  • Debugging on Windows requires absolute paths and careful attention to program IDs (the correct one is TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb – note the lowercase z).

Top comments (0)