Soldev

Solana tokens

Last updated:

Tokens are controlled by one of the native programs on Solana the SPL program.

This program also has a set of extensions which were released in 2022:

ExtensionDescription
Permanent DelegateAllows full control over tokens of everyones accounts (seize, burn, freeze, transfer etc)
Interest Bearing TokensTokens that can increase or decrease over time
Non transferable (Soul-bound)Tokens that cannot be transferred (owner can still burn and close the account, so better than a freeze)
Immutable OwnerEnsures ownership of a token account cannot be re-assigned (enabled by default?)
ReallocateAllows an owner to reallocate the space of an account to add token extensions after it has been created
Default Account StateRestrict who can access your token, allows all newly created token accounts to have a default state (for example being frozen, which they can then interact with some service to unfreeze their account)
Close Token MintClose the actual mint account instead of just token accounts
Token MetadataStore additional metadata about the token within the mint account
Transfer HooksAdds extra functionality to the tokens when a transfer happens

Associated token accounts

An associated token account's address is based on the "logical owner" of the tokens (aka your wallet).

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Account {
    /// The mint associated with this account
    pub mint: Pubkey,
    /// The owner of this account.
    pub owner: Pubkey,
    /// The amount of tokens this account holds.
    pub amount: u64,
    /// If `delegate` is `Some` then `delegated_amount` represents
    /// the amount authorized by the delegate
    pub delegate: COption<Pubkey>,
    /// The account's state
    pub state: AccountState,
    /// If `is_native.is_some`, this is a native token, and the value logs the
    /// rent-exempt reserve. An Account is required to be rent-exempt, so
    /// the value is used by the Processor to ensure that wrapped SOL
    /// accounts do not drop below this threshold.
    pub is_native: COption<u64>,
    /// The amount delegated
    pub delegated_amount: u64,
    /// Optional authority to close the account.
    pub close_authority: COption<Pubkey>,
}

These types of accounts are configured per specific SPL Token. The docs describe them as simple counters that point to a Wallet and Mint. It holds the state for the balance on the associated mint for this particular user.

An associated token account (ATA) is simply a token account with an address that is a PDA derived from and created by the Associated Token Program. You can think of an ATA as the default token account for a user to hold units of a specific token (mint).

Only token accounts created through the Associated Token Program are referred to as associated token accounts.

Associated token account is just a token account which it's address is derived deterministically.

The Associated Token Account is a standard defining a "canonical" account for holding tokens of a particular type for a given wallet, so that it's easier to find where to send tokens of a certain type for a user.

A user can have multiple token accounts as much as possible could be made by one mint account. But with associated token account, a user can have ONE main token account for ONE mint account for his/herself. It makes other users to send tokens more easily to the other, because there's just one token account to send!

Token Account is a schema (class, structure, data layout etc) which defines how ATA structure looks. But ATA, as a concept, defines how the address is generated.

In solana ecosystem ATA concept is very crucial for tracking balance of tokens. To do this you need to know only token mint and account address, and thanks to ATA you can generate address which keeps token balance. Thanks to Token Account structure you can read data buffer by the address and get a balance of the particular token. At the same time, by knowing only ATA you can easily get information about which token this ATA about and whom belongs that amount of tokens.

The Associated Token Program acts as a helper program that creates token accounts with deterministic addresses (PDAs). When creating an associated token account, the Associated Token Program makes a CPI (Cross-Program Invocation) to either the Token Program or Token Extension Program. The created account is owned by the token program and has the same Account type structure as defined in the token program. The Associated Token Program itself maintains no state - it simply provides a standardized way to create token accounts at a deterministic address.

We can create one:

use anchor_spl::token_interface::{Mint, TokenAccount, TokenInterface};
 
// --snip--
 
#[derive(Accounts)]
pub struct CreateTokenAccount<'info> {
    #[account(mut)]
    pub signer: Signer<'info>,
    #[account(



        init_if_needed,
        payer = signer,
        token::mint = mint,
        token::authority = token_account,
        token::token_program = token_program,
        seeds = [b"token"],
        bump
    )]
    pub token_account: InterfaceAccount<'info, TokenAccount>,
    pub mint: InterfaceAccount<'info, Mint>,
    pub token_program: Interface<'info, TokenInterface>,
    pub system_program: Program<'info, System>,
}

SPL Tokens

"SPL Tokens on Solana are referred to as a Mint".

All tokens on Solana are SPL Tokens. Developers do not individually create token contracts, and instead use the shared SPL Token program to create token mint accounts (defines the token supply, decimals, authority etc.) and token accounts (for holding balances).

We don't write token programs, we instantiate new mints through the shared SPL Token program.

Creating a Token Mint

Refer to this section on the minting article.

Token accounts vs Associated token accounts

Tokenaccounts of a publickey that have a corresponding private key are usually Associated Token Accounts(ATA). An ATA is a PDA that uses the publickey and token mint as seeds. However, to generate a token account that is a PDA, you generate the PDA from your custom seeds and then instruct the Token Program to create a token account with your specified token_mint and specified authority.