Create a new mint
Outline
In this chapter, we will go through on how to create new mint. The final outcome of this chapter could be found here
You could think of mint as a metadata about a token that is being transferred to an account. A mint could be initialised in a context. In anchor framework the struct is passed as a context.
First let's import anchor_spl into the project so that we can create a mint. Add below in your cargo.toml file and run anchor test or anchor build to check if everything is working fine.
anchor-spl = "^0.25.0"

Generally in Solana, any accounts that involve in the modification of state, are passed from the client side. This is done for parallel execution of programs. Refer this article from Anatoly Yakovenko
It becomes easier in to access these accounts using anchor framework. Pass these accounts as context parameter to an instruction.
How to create a CreateMint context ?
A struct can be defined as a context in an anchor program. Let us look at how this could be achieved.
First import the dependencies
use anchor_lang::prelude::*;
use anchor_spl::token::{Mint, Token};
Then, define a context(struct) for accessing these instructions. The CreateMint struct is decorated with #[derive(Accounts)]. This helps in deserialisation of accounts described in this struct
#[derive(Accounts)]
pub struct CreateMint<'info> {
#[account(
init,
seeds = [
b"spl-token-mint".as_ref(),
],
bump,
payer = payer,
mint::authority = payer,
mint::decimals = 0,
mint::freeze_authority = payer
)]
pub spl_token_mint: Account<'info, Mint>, // ---> 1
#[account(mut)]
pub payer: Signer<'info>, // ---> 2
pub system_program: Program<'info, System>, // ---> 3
pub token_program: Program<'info, Token>, // ---> 4
// this is required for spl token mint
pub rent: Sysvar<'info, Rent>, // ---> 5
#[account(
init,
space = 8 + Vault::LEN,
seeds = [
b"vault"
],
bump,
payer = payer
)]
pub vault : Account<'info, Vault>, // ---> 6
}
In the above code, 6 accounts are passed.
-
An
spl_token_mintaccount is created. In Solana, it is recommended to derive the account addresses using Program Derived Addresses (PDA). They are a deterministically generated address based on the program ID. Please refer this to know more about PDAs. We setting other metadata fields likemint::authorityandmint::freeze_authoritytopayer. We are settingmint::decimalsto0for easy demonstration purpose. You could set the value to any number as you like-to. -
payeris the one who is paying for callingcreate_mintinstruction. The account is asigneraccount and is set tomut. -
We must pass
system_programas well while invoking any instruction in solana program. This helps creating accounts. Refer this to know more. -
token_programaccount is for interacting withtoken-program. -
rentaccount is used bytoken-programduring mint account creation. -
vaultaccount is a PDA generated account. It is used for storing the state of the program.Vaultstruct is passed into the account generic where actual state is stored. We will have to pass in the space as well. To calculate the space for storing please refer this.
We are passing Vault with vault account. To store the state of a program, a struct could be defined as follows
// Store the state
#[account]
pub struct Vault {
bump : u8, //1
spl_token_mint_bump:u8, // 1
authority : Pubkey, //32
spl_token_mint : Pubkey //32
}
impl Vault {
pub const LEN: usize =1 + 1 + 32 + 32;
}
The Vault struct stores bumps and authority of who initialised this program. Later, you can use this to secure your program by restricting the access to the instructions. Stored bumps are used later for deriving PDA addresses in other instructions.
How to create an instruction?
Above created context is passed as an argument to an instruction. An instruction is a function where we could achieve a set of described procedure. This is usually a state change in the Solana blockchain. Any executed instruction is Turing complete.
Let us create an instruction which accepts the context as a parameter.
pub fn create_mint(ctx: Context<CreateMint>) -> Result<()> {
let vault = &mut ctx.accounts.vault;
vault.authority = ctx.accounts.payer.key();
vault.spl_token_mint_bump = *ctx.bumps.get("spl_token_mint").unwrap();
vault.bump = *ctx.bumps.get("vault").unwrap();
vault.spl_token_mint = ctx.accounts.spl_token_mint.key();
Ok(())
}
In the instruction above, we are storing the bumps and other state values into the Vault state.
Now let us run the below command
anchor test
Now should see an error in the output. Like below.

Let's fix this in the next chapter