LogoAnchor Docs

Create a Token Mint

Learn how to create and initialize token mint accounts in Solana programs using Anchor. Covers creating mint accounts with generated keypairs or PDAs with code examples.

What is a Mint Account?

A mint account is an account type in Solana's Token Programs that uniquely represents a token on the network and stores global metadata about the token.

/// Mint data.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Mint {
  /// Optional authority used to mint new tokens. The mint authority may only
  /// be provided during mint creation. If no mint authority is present
  /// then the mint has a fixed supply and no further tokens may be
  /// minted.
  pub mint_authority: COption<Pubkey>,
  /// Total supply of tokens.
  pub supply: u64,
  /// Number of base 10 digits to the right of the decimal place.
  pub decimals: u8,
  /// Is `true` if this structure has been initialized
  pub is_initialized: bool,
  /// Optional authority to freeze token accounts.
  pub freeze_authority: COption<Pubkey>,
}

Note that both the Token Program and Token Extension Program have the same base implementation for the Mint account.

Every token on Solana is represented by a mint account where the address of the mint account acts as its unique identifier on the network.

For example, the USDC stablecoin on Solana is identified by the mint address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v. This mint address serves as USDC's unique identifier across the entire Solana ecosystem. You can view details about this mint account on Solana Explorer.

Usage

Use the token_interface module from the anchor-spl crate to interact with both the Token Program and Token Extension Program. This module provides types for working with both token programs, allowing you to write code that's compatible with either program.

snippet

use anchor_spl::token_interface::{Mint, TokenInterface};
 
// --snip--
 
#[derive(Accounts)]
pub struct CreateMint<'info> {
    #[account(mut)]
    pub signer: Signer<'info>,
    #[account(
        init,
        payer = signer,
        mint::decimals = 6,
        mint::authority = signer.key(),
        mint::freeze_authority = signer.key(),
    )]


    pub mint: InterfaceAccount<'info, Mint>,


    pub token_program: Interface<'info, TokenInterface>,
    pub system_program: Program<'info, System>,
}

Account Types

The InterfaceAccount type is a wrapper that accepts accounts from either the Token Program and Token Extension Program.

The Mint type represents the base Mint data structure shared by both token programs. When an account of this type is passed in, Anchor will automatically deserialize the account data into the mint struct, regardless of which token program created it.

Account Type
pub mint: InterfaceAccount<'info, Mint>,

Account Constraints

The following account constraints are used in combination to create and initialize a new mint account:

ConstraintDescription
initCreates a new account by making a cross program invocation (CPI) to the System Program. This allocates the required space for the mint account and transfers ownership to the appropriate token program.
payerSpecifies which account will pay the rent (SOL deposit) required to create the new account.
mint::decimalsSets the number of decimal places for the token. For example, setting this to 6 means 1 token = 1,000,000 base units.
mint::authoritySets the mint authority - the account that has permission to mint new tokens. (Required)
mint::freeze_authoritySets the freeze authority - the account that has permission to freeze token accounts. (Optional) Freezing a token account prevents the token program from processing instructions that include the frozen token account (ex. transfer, burn, etc.)
Account Constraints
#[account(
    init,
    payer = <payer>,
    mint::decimals = <decimals>,
    mint::authority = <authority>,
    mint::freeze_authority = <freeze_authority>,
)]
pub mint: InterfaceAccount<'info, Mint>,

Alternatively, you can add the seeds and bump constraints to create a mint account where the address of the account is a Program Derived Address (PDA). The benefit of using a PDA is that the mint address can be derived from the same seeds at any time.

Account Constraints
#[account(
    init,
    payer = <payer>,
    mint::decimals = <decimals>,
    mint::authority = <authority>,
    mint::freeze_authority = <freeze_authority>,
    seeds = [<seeds>],
    bump
)]
pub mint: InterfaceAccount<'info, Mint>,

Note that you can use the same PDA as both the mint::authority and the mint account address. Using a PDA as the mint::authority enables your program to "sign" CPI instructions to mint new units of the token. This pattern allows for a single deterministic address for both purposes.

Examples

The following examples demonstrate how to create a mint account in an Anchor program using two different approaches:

  1. Using a generated Keypair - This is an approach where you generate a new keypair to use as the mint address. This is useful when you don't need deterministic mint addresses.

  2. Using a Program Derived Address (PDA) - This approach creates the mint where the account address is a PDA derived from seeds. This allows for deterministic mint addresses and is useful when you need to find the mint address at a later time.

Both approaches are can be done entirely using account constraints.

Create Mint using Keypair

Create a new mint account in using a generated Keypair.

lib.rs
use anchor_lang::prelude::*;
use anchor_spl::token_interface::{Mint, TokenInterface};
 
declare_id!("3pX5NKLru1UBDVckynWQxsgnJeUN3N1viy36Gk9TSn8d");
 
#[program]
pub mod token_example {
    use super::*;
 
    pub fn create_mint(ctx: Context<CreateMint>) -> Result<()> {
        msg!("Created Mint Account: {:?}", ctx.accounts.mint.key());
        Ok(())
    }
}
 
#[derive(Accounts)]
pub struct CreateMint<'info> {
    #[account(mut)]
    pub signer: Signer<'info>,
    #[account(

        init,
        payer = signer,
        mint::decimals = 6,
        mint::authority = signer.key(),
        mint::freeze_authority = signer.key(),
    )]
    pub mint: InterfaceAccount<'info, Mint>,
    pub token_program: Interface<'info, TokenInterface>,
    pub system_program: Program<'info, System>,
}

Create Mint using PDA

Create a new mint account using a Program Derived Address (PDA) as the address of the mint account.

lib.rs
use anchor_lang::prelude::*;
use anchor_spl::token_interface::{Mint, TokenInterface};
 
declare_id!("3pX5NKLru1UBDVckynWQxsgnJeUN3N1viy36Gk9TSn8d");
 
#[program]
pub mod token_example {
    use super::*;
 
    pub fn create_mint(ctx: Context<CreateMint>) -> Result<()> {
        msg!("Created Mint Account: {:?}", ctx.accounts.mint.key());
        Ok(())
    }
}
 
#[derive(Accounts)]
pub struct CreateMint<'info> {
    #[account(mut)]
    pub signer: Signer<'info>,
    #[account(



        init,
        payer = signer,
        mint::decimals = 6,
        mint::authority = mint.key(),
        mint::freeze_authority = mint.key(),
        seeds = [b"mint"],
        bump
    )]
    pub mint: InterfaceAccount<'info, Mint>,
    pub token_program: Interface<'info, TokenInterface>,
    pub system_program: Program<'info, System>,
}

On this page

Edit on GitHub