Skip to content

Token standards

On Ethereum a token is a contract that implements an interface (ERC-20 for fungible, ERC-721 for unique, ERC-1155 and ERC-6909 for many token types in one contract, ERC-4626 for yield-bearing vault shares), so every token has its own code and its own bugs. On Solana a token is a mint account handled by one shared Token program, with each holder’s balance in a separate token account, and the Token-2022 program lets issuers switch on optional behaviours (transfer fees, transfer hooks, confidential balances, permanent delegates) without deploying code. The trade-off is flexibility per token versus one audited program that every wallet and DEX can trust, and both ecosystems have learned that a “transfer” which does something extra breaks integrators’ assumptions.

An Ethereum token is like a private club that prints its own membership cards and writes its own rules; clubs agree to use the same card format (the standard) so a single card reader works everywhere, but any club can quietly change what “hand over the card” does. A Solana token is like an account at a shared registry office: everyone’s balances are kept in the same kind of ledger by one clerk who follows one rulebook, and with Token-2022 the issuer fills in a checklist of optional rules (charge a fee on transfer, phone a compliance officer before each transfer, hide the amounts) when the token is created.

A token is a number next to your name in a shared list, plus rules for moving that number to someone else. On Ethereum each token has its own little program with its own list and its own rules, and everyone agrees on the names of the buttons so wallets know what to press. On Solana there is one program that keeps the lists for every token, and your balance of each token lives in its own small storage box. The newer Solana program lets whoever creates a token turn on extras such as a small fee on every transfer or keeping the amounts secret, without writing any new code.

A compliance-minded issuer launches a token with a 1% transfer fee and an allow-list check on every transfer. Alice sends 100 tokens to Bob.

  1. Before. Alice holds 100, Bob 0, the issuer’s fee vault 0. On Ethereum both balances are entries in the token contract’s storage; on Solana Alice’s balance sits in her token account (owned by the Token-2022 program) and Bob’s token account may not exist yet.
  2. Ethereum. The issuer wrote a custom ERC-20 whose transfer deducts a fee and consults an allow-list mapping. Alice calls transfer(Bob, 100). The contract checks Bob is allowed, moves 99 to Bob and 1 to the fee vault, and emits Transfer events. Alice 0, Bob 99, vault 1. A DEX that assumed “transfer 100 means receive 100” now has 1 token less than its internal accounting says.
  3. Solana, creation-time choices. The issuer created the mint with the TransferFeeConfig extension (100 basis points) and the TransferHook extension pointing at an allow-list program. These are fixed at initialisation; most extensions cannot be added later.
  4. Solana, the transfer. Alice’s wallet builds a TransferChecked instruction listing both token accounts, the mint and the hook’s extra accounts (from the extra-account-metas PDA). Token-2022 debits Alice 100, credits Bob 99, records 1 as withheld in Bob’s token account, then invokes the hook program with every account read-only; if the hook rejects Bob, the whole transaction reverts.
  5. After. Alice 0, Bob 99 plus 1 withheld, sweepable later by the issuer’s withdraw authority. Any Token-2022-aware DEX or wallet saw the fee coming because it is declared in the mint’s extension data, not hidden in custom code.
  • Myth: “Solana tokens are smart contracts like ERC-20s.” Reality: Almost all Solana tokens are data accounts processed by one shared Token program; the SPL Token program handled about 1.5 million transactions an hour as of 2025-08 (Solana Foundation).
  • Myth: “ERC-20 approve is safe to change directly.” Reality: EIP-20 itself warns that changing a non-zero allowance is a known attack vector and that UIs “SHOULD … set the allowance first to 0”.
  • Myth: “Token-2022 extensions can be toggled at any time.” Reality: “Most extensions can’t be added after an account is initialized” and some are mutually exclusive, e.g. NonTransferable with TransferFeeConfig (Solana docs).
  • Myth: “A transfer hook can drain the sender’s wallet.” Reality: During the hook CPI “all accounts from the initial transfer are converted to read-only accounts” and the sender’s signer privileges do not extend to the hook (Solana docs).
  • Myth: “Confidential transfers make Solana tokens anonymous.” Reality: They hide amounts and balances, not parties, and support an optional global auditor key (Helius).

Ethereum standardises the interface and lets every token bring its own code; Solana standardises the code and lets every token bring its own configuration.

Ethereum: interfaces implemented by every token

Section titled “Ethereum: interfaces implemented by every token”

ERC-20 (Vogelsteller and Buterin, 2015-11) defines totalSupply, balanceOf, transfer, transferFrom, approve, allowance and the Transfer/Approval events, so “any tokens on Ethereum [can] be re-used by other applications: from wallets to decentralized exchanges”. Balances are a mapping in the contract’s storage; a transfer is two storage writes. Two footguns are written into the standard: transfer “SHOULD throw” on insufficient balance but early tokens returned false instead, so “Callers MUST handle false”; and the approve race, where a spender front-runs an allowance change to spend both the old and new amounts.

ERC-721 (Entriken et al., 2018-01) tracks unique assets (ownerOf, approve, setApprovalForAll, tokenURI); its safeTransferFrom calls onERC721Received on contract recipients “and throws if the return value is not” the magic selector. ERC-1155 (Radomski et al., 2018-06) holds many fungible and non-fungible types in one contract with batch transfers and a required onERC1155Received callback. ERC-6909 (Riley et al., 2023-04) strips this down: no mandatory callbacks, no batching, and a hybrid permission model where approve(spender, id, amount) grants a per-id allowance and setOperator(spender, true) grants everything, because “removing mandatory callbacks and removing the word ‘safe’ from all method names improves the safety of the control flow by default”. Uniswap v4 uses ERC-6909 claims inside its PoolManager because “minting and burning ERC-6909 tokens are more gas-efficient because they don’t require external function calls” (Uniswap docs, accessed 2026-08).

ERC-4626 (Santoro et al., 2021-12) standardises yield-bearing vaults over one ERC-20 asset. Shares are minted in proportion to assets:

shares=assets×totalSupplytotalAssets,assets=shares×totalAssetstotalSupply,\text{shares} = \text{assets}\times\frac{\text{totalSupply}}{\text{totalAssets}},\qquad \text{assets} = \text{shares}\times\frac{\text{totalAssets}}{\text{totalSupply}},

with convertToShares/convertToAssets required to “round down towards 0” and deposit, mint, withdraw, redeem rounding in the vault’s favour. The standard warns that preview* values “are manipulable by altering on-chain conditions and are not always safe to be used as price oracles”.

Solana: one program, many accounts, optional extensions

Section titled “Solana: one program, many accounts, optional extensions”

A Solana token consists of a mint account (supply, decimals, mint and freeze authorities) and one token account per holder per mint, all owned by the Token program; the associated token account is the canonical PDA derived from [wallet, mint] (Helius). The SPL Token program supports mint, transfer, burn, approve/delegate, freeze and close. Because state is per-account, two holders’ transfers write different accounts and execute in parallel (see /foundations/accounts-and-execution/). Each token account must be rent-exempt (about 0.00204 SOL for 165 bytes), refundable on close.

Token-2022 (Token Extensions) is a second program with the same base layout plus type-length-value tlv_data after the base state; “extensions are optional features you can add to a token mint or token account” and are chosen at creation (Solana docs). The ExtensionType enum (as of 2026-08) includes mint extensions such as TransferFeeConfig, MintCloseAuthority, ConfidentialTransferMint, DefaultAccountState, NonTransferable, InterestBearingConfig, PermanentDelegate, TransferHook, TokenMetadata, ScaledUiAmount and Pausable, and account extensions such as TransferFeeAmount (withheld fees), ConfidentialTransferAccount, ImmutableOwner, MemoTransfer and CpiGuard. Mechanics that matter for DeFi:

  • Transfer fee. A rate in basis points set on the mint; on each transfer the fee is withheld inside the recipient’s token account (TransferFeeAmount) and later swept by the withdraw authority: fee=amount×bps10,000\text{fee} = \text{amount}\times\frac{\text{bps}}{10{,}000}.
  • Transfer hook. The mint names a program implementing the Transfer Hook Interface (Execute, optional InitializeExtraAccountMetaList); “for every token transfer … the Token Extensions program makes a Cross Program Invocation” with accounts read-only, enabling royalties, allow/deny lists and custom events (Solana docs).
  • Confidential transfers. Balances and amounts are Twisted ElGamal ciphertexts (a Pedersen commitment plus decryption handle), validated by sigma-protocol proofs (validity, equality, zero-balance, fee, Bulletproof range proofs); balances are split into pending and available to defeat front-running of proofs; an optional auditor key can decrypt amounts (Helius).
  • Interest-bearing / scaled UI. Only the displayed amount changes; the raw balance does not.
  • Permanent delegate. An authority that “will always have the authority to manage tokens from a mint”, including transfers or burns from any account (Helius).

P-Token is a drop-in rewrite of the legacy program: Transfer 4,645 → 249 CU, MintTo 4,538 → 155, Burn 4,753 → 168, with no interface change (Solana Foundation, 2025-08).

Same transfer as §2: Alice sends 100 tokens; transfer fee 1% (100 bps); allow-list hook.

Solana. Fee =100×100/10,000=1= 100\times 100/10{,}000 = 1 token. Bob’s token account after: balance 99, withheld 1. Compute: base fee 5,000 lamports (1 signature); the TransferChecked with fee logic plus the hook CPI costs the legacy instruction’s ~4,645 CU plus a CPI (1,000 CU, 946 with SIMD-0339) plus the hook’s own work, well within the 200,000 CU default; with no priority fee Alice pays 0.000005 SOL. If Bob’s token account did not exist, Alice also deposits (165+128)×3,480×22.04(165+128)\times 3{,}480\times 2 \approx 2.04 million lamports of rent (more for an account carrying extensions, since tlv_data adds bytes). Using $BERN’s real parameters instead (6.9% fee, Helius), Bob would receive 93.1 and 6.9 would be withheld.

Ethereum. The custom ERC-20’s transfer writes three slots (Alice, Bob, vault) and reads an allow-list slot. A pool that called transferFrom(Alice, pool, 100) and trusted the argument would book 100 while holding 99, the gap behind the 2020 Balancer incident; the safe pattern measures balanceOf before and after.

ERC-4626 vault check. Suppose a vault holds 1,000 assets and has 1,000 shares; Alice deposits 100 → shares =100×1,000/1,000=100= 100\times 1{,}000/1{,}000 = 100. If an attacker first donates 1,000 assets when the vault has 1 share and 1 asset, then Alice’s 100-asset deposit mints 100×1/1,001=0\lfloor 100\times 1/1{,}001\rfloor = 0 shares, which is why the standard mandates rounding down and why vaults seed initial shares.

  • PYUSD — “among the first major stablecoins to leverage Solana’s token extensions”: Permanent Delegate, Transfer Hooks, Transfer Fees (Helius) — /stablecoins/payments/.
  • $BERN — early Token-2022 token with a 6.9% transfer fee split among holders, $BONK burns and a developer fund (Helius).
  • Tokenised funds (BENJI, ACRED) — programmable compliance via Token Extensions (Helius, 2025-07) — /tradfi/tradfi-convergence-and-rwas/.
  • Confidential balances — amounts private to consumers, visible to regulators via the auditor key — /privacy/privacy-and-compliance/.
  • approve front-running (ERC-20). Documented in EIP-20: a spender who sees an allowance change from NN to MM can spend NN before and MM after; mitigation is setting to 0 first.
  • Fee-on-transfer and deflationary tokens. Balancer lost about $500k in June 2020 to a flash-loan attack exploiting “non-standard ERC20 deflationary tokens” whose burn-on-transfer desynchronised pool balances (rekt.news, secondary).
  • Receiver callbacks as reentrancy vectors. ERC-721/1155 on*Received hooks are external calls; samczsun shows an ENS name-wrapper case where the ERC-1155 callback ran before ownership of the underlying name was verified (Paradigm, 2021-08). ERC-6909 removed mandatory callbacks for exactly this reason.
  • ERC-4626 rounding and donation attacks. The standard warns that “malicious implementations which only conform to the interface but not the specification” and manipulable preview* functions can be exploited; rounding must favour the vault (EIP-4626).
  • Permanent delegate and default-frozen accounts (Token-2022). The delegate “would be able to transfer or burn tokens in anyones wallet” (Helius); DefaultAccountState frozen means holders cannot move tokens until the issuer thaws them. Both are compliance features and rug vectors, which is why RugCheck added Token-2022 support.
  • Transfer hooks that fail or censor. A reverting hook blocks every transfer of the mint and hooks can implement deny-lists, so integrators must simulate transfers rather than assume success.
  • Missing mint validation. Cashio (2022-03-23, about $48M) minted unbacked stablecoins because a collateral account’s .mint field “is never validated” (rekt.news, secondary).
  • Integrator support for Token-2022. Wallets and DEXs opt in per extension (Helius’ early-adopter list was short), and hook programs need extra accounts that generic routers must discover.
  • Confidential transfer compliance. Global auditor keys reconcile privacy with regulation, but who holds them and how selective disclosure works for DeFi pools is unsettled (Helius; see /privacy/privacy-and-compliance/).
  • Non-standard ERC-20 behaviour. No EIP forces fee-on-transfer or rebasing tokens to advertise themselves; Solana’s declarative extensions are one answer, Ethereum has no equivalent.
  • ERC-1155 vs ERC-6909. Whether the ecosystem migrates to callback-free multi-tokens beyond Uniswap v4 is open (EIP-6909 rationale).
  • Cost of one shared program. P-Token’s 95% saving shows how much headroom a monolithic program leaves; one shared program versus per-token logic remains a design choice, not a solved problem.
AspectEthereumSolana
What a token isA contract implementing an interfaceA mint account processed by the Token / Token-2022 program
Where balances liveMapping in the token contract’s storageOne token account per holder per mint (ATA = PDA of wallet, mint)
Custom behaviourArbitrary code per tokenDeclared extensions chosen at creation
Fee on transferCustom code; breaks naive integratorsTransferFeeConfig, withheld in recipient account
HooksERC-721/1155 receiver callbacks; ERC-6909 removes themTransferHook CPI with read-only accounts
PrivacyNone nativelyConfidential transfers (Twisted ElGamal + ZK proofs)
Vault sharesERC-4626No standard; program-specific
Multi-tokenERC-1155, ERC-6909One program handles all mints
Cost of a transferContract execution, two storage writes~4,645 CU legacy, ~249 CU P-Token (2025-08)
Upgrade pathDeploy a new contractFeature-gate the shared program

Ethereum maximises expressiveness per token at the price of integrator surprises; Solana concentrates trust in one program and makes non-standard behaviour visible in account data, at the price of a fixed menu of extensions that wallets adopt slowly.

Token Extensions (Solana docs) and “What are Token Extensions?” (Helius) — Solana Foundation documentation, as of 2026-08; Helius developer blog, 2023–2024. https://solana.com/docs/tokens/extensions · https://www.helius.dev/blog/what-is-token-2022

The Solana docs page defines Token Extensions as extra instructions of the Token-2022 program that add optional state to a mint or token account, initialised at creation and generally immutable afterwards, with some pairs incompatible (NonTransferable with TransferFeeConfig). It reproduces the ExtensionType enum, distinguishing mint extensions (transfer fee config, mint close authority, confidential transfer mint, default account state, non-transferable, interest-bearing, permanent delegate, transfer hook, metadata and group pointers, confidential mint/burn, scaled UI amount, pausable) from account extensions (withheld fee amount, confidential transfer account, immutable owner, memo transfer, CPI guard, hook and pausable markers). All extension state is stored in tlv_data after the base account and must be deserialised per extension type.

The Helius article explains the motivation: the original Token program covered mint, transfer, burn, freeze and authority updates, and developers who needed more had to fork it, which “presents challenges for achieving widespread adoption” because wallets and programs must trust every token program they support. It walks through mint extensions (transfer fees at the protocol level; transfer hooks calling a custom program on every transfer, e.g. for NFT royalties; mint close authority; interest-bearing display amounts; non-transferable “soulbound” tokens; confidential transfers) and account extensions (memo required, immutable owner, default account state frozen, permanent delegate). The confidential-transfer section is the technical core: Twisted ElGamal ciphertexts as a Pedersen commitment plus decryption handle, homomorphic addition, and the sigma proofs required per instruction (validity, ciphertext validity, zero-balance, equality, fee sigma, Bulletproof range proofs), a global auditor key for compliance, and pending/available balance separation to stop transfer-flooding from invalidating proofs. It closes with early adopters ($BERN’s 6.9% fee, FluxBeam, Backpack, RugCheck) and a comparison to SafeMoon-style fees and Aztec-style privacy on other chains.

“Extensions are optional features you can add to a token mint or token account.” — Solana docs, What are Token Extensions? “Most extensions can’t be added after an account is initialized.” — Solana docs, What are Token Extensions? “Developers, armed with fresh ideas, have often needed to fork the Token Program to add required functionality, which presents challenges for achieving widespread adoption.” — Helius, What are Token Extensions and why is it needed? “If this extension is used the authority will have unlimited delegate privileges over any account for that mint, this can be very dangerous” — Helius, Permanent Delegate “Any outgoing funds are subtracted from its available balance whereas any incoming funds are added to its pending balance.” — Helius, Confidential Transfers

Background: the Solana account model and what a CPI is. Read the Helius article top to bottom, then the docs page’s enum and tlv_data note; skip the sigma-proof taxonomy on first pass. The hardest paragraph is the pending/available split: because a zero-knowledge proof is made against a specific encrypted balance, an incoming transfer that lands first would invalidate it, so incoming funds go to a separate pending balance the holder applies later.

Confidential transfers, marked “not live yet” in the Helius article, are now offered as Confidential Balances and used in compliance pitches (Helius, 2025); PYUSD launched on Solana with Permanent Delegate, Transfer Hooks and Transfer Fees; P-Token (2025) rewrote the legacy program for a 95% compute cut while Token-2022 remains a separate program; the enum gained ScaledUiAmount, Pausable and ConfidentialMintBurn (docs, as of 2026-08).

  1. Solana docs, “How to use the Transfer Hook extension” — read if you are writing a hook program (interface, extra-account-metas PDA, read-only rule).
  2. Helius, “Plug and Play Token Extensions” — read for hands-on creation of NFTs, interest-bearing, soulbound and delegate tokens.
  3. Helius, “Solana’s Stablecoin Landscape” — read for PYUSD’s extension choices.
  4. Solana Foundation, “Increase Bandwidth, Reduce Latency” (2025-08) — read for P-Token numbers.

EIP-20: Token Standard — Fabian Vogelsteller, Vitalik Buterin, created 2015-11-19. https://eips.ethereum.org/EIPS/eip-20

EIP-20 specifies “a standard API for tokens within smart contracts” providing transfers and third-party approvals so that “any tokens on Ethereum [can] be re-used by other applications”. The Methods section lists optional name, symbol, decimals, then totalSupply, balanceOf(owner), transfer(to, value) (must fire Transfer, should throw on insufficient balance, zero-value transfers are valid), transferFrom(from, to, value) (for withdraw workflows, should throw unless authorised), approve(spender, value) (with the race-condition note recommending set-to-zero first) and allowance(owner, spender). Events Transfer and Approval are mandatory, including on minting (from the zero address). The implementation section notes that early tokens returned false rather than throwing, so callers must handle both. Later standards inherit its shape: ERC-721 for non-fungibles, ERC-1155 and ERC-6909 for multi-token contracts, ERC-4626 for vault shares on top of an ERC-20 asset.

“This standard provides basic functionality to transfer tokens, as well as allow tokens to be approved so they can be spent by another on-chain third party.” — Abstract “clients SHOULD make sure to create user interfaces in such a way that they set the allowance first to 0 before setting it to another value for the same spender.” — Methods, approve “Callers MUST handle false from returns (bool success).” — Methods, transfer

No background beyond basic Solidity types. Read Methods and Events; the Implementation section is historical. The hardest part is the approve note: because transactions are ordered by the block producer, a spender can observe a pending allowance change and insert a transferFrom before it, which is a market-structure problem, not a coding bug.

ERC-721 (2018-01) and ERC-1155 (2018-06) added non-fungibles, batching and receiver callbacks; ERC-4626 (2021-12) standardised vault shares with explicit rounding rules; ERC-6909 (2023-04, Final) removed callbacks and introduced the operator/allowance hybrid, adopted by Uniswap v4. Fee-on-transfer and rebasing tokens remain outside any standard.

  1. EIP-4626 — read if you build or integrate vaults; rounding and preview caveats.
  2. EIP-6909 — read for the callback-free multi-token rationale.
  3. EIP-721 and EIP-1155 — read for NFT and batch semantics.
  4. Uniswap v4 docs, “ERC-6909” — read for a production use of claims instead of transfers.