Understanding Solana’s Mint Accounts and Token Accounts

Jorge Londoño, Ph.D
8 min readFeb 26, 2022

--

Solana dApp development poses some new challenges, specially for those who, like me, had some previous experience with Ethereum-like development where smart contracts include both, code and state storage. In the Solana world, programs do not contain any data, but instead reference accounts where data can be stored. This is a huge paradigm change for developers, but one that greatly helps improve performance as this enables programs to run concurrently, as long as they are not accessing the same account data.

An additional plus is that there is no need to deploy a new program for each new token, as is typically the case when using the ERC-20 standard. In fact, the functionality of a token is always the same, what differs is the data associated with a particular token. For this reason, Solana developers included a standard Token Program already deployed and ready for anyone to use for creating, minting, trading, and even burning tokens.

One picture says it all

The following diagram illustrates the relationships between the Token Program, the accounts it uses, and the related roles:

Token Program, Accounts and Roles
Figure 1: Token Program, related Accounts and Roles (made with Sketchboard.io)

The first element is the Token Program itself, which is already deployed and ready to use.

Mint Accounts

When someone wants to create a new token, he uses the create-token function to initialize a new Mint Account, which contains basic information about the token: The mint-authority which is a public-key (pubkey) authorized to mint this token, the freeze-authority who can freeze token accounts (to be described below), and some additional data as the total supply of the token, the number of decimals, and the isInitialized flag. This account stores general information about the token and who has permissions over it. Observe that there is no data about token holdings of particular individuals. These are stored in Token Accounts.

Token Accounts

The token account holds information about the tokens owned by a pubkey. Ownership relationships become a bit confusing, though. The token account itself is owned by the Token program and it is the Token program who controls access to these tokens using the owner, close-authority and delegate fields within the account. The owner is the pubkey who can spend/transfer the tokens, the close-authority can close the account, and the owner can give rights to a delegate pubkey to spend up to a delegatedAmount of tokens. Besides these fields, there are also a few flags: isInitialized, isFrozen, isNative. By default, token accounts are initialized upon creation, are not frozen and are not native. Previously, we saw the mint account defines a freeze-authority, who has the right to freeze the tokens in a user account. Often times, the freeze-authority is null (all zeroes). In that case, no one can freeze the corresponding tokens held in the token account.

Too much theory, let’s see all of this in practice

Solana CLI

We are going to be using the Solana Tool Suite to interact with the Token program. You can get it here:

Once installed, we can configure the tool suite to connect to devnet as follows:

solana config set --url devnet

Create a user account

Users need a keypair (i.e. public key and its corresponding private key) to hold SOL and transact with the Solana blockchain. They also need to hold some SOL to pay fees to the network. Thankfully, the development network “airdrops” a small amount of SOL to whoever requests.

Let us first create a keypair by using the solana-keygen command from the tool suite:

solana-keygen new -o ~/.config/solana/kp_alice.json
KP_ALICE=~/.config/solana/kp_alice.json
PK_ALICE=`solana address -k $KP_ALICE`
echo $PK_ALICE

Environment variables KP_ALICE and PK_ALICE refer to the file containing the private key, and the value of the public key respectively.

Then, request an airdrop for this account and check the balance afterwards using the following commands:

solana airdrop 1 $PK_ALICE
solana balance $PK_ALICE
Figure 1: Getting and airdrop and checking the balance

Creating the mint account

The create-token function within the spl-token program creates the mint account. By default the initial supply is zero, and the freezing-authority is null. The following commands create the mint account, store its pubkey in the ALICE_TOKEN variable and display both, the supply of the token, and Alice’s SOL balance after paying fees:

spl-token create-token \
--mint-authority $KP_ALICE \
--fee-payer $KP_ALICE
ALICE_TOKEN=<token address>
spl-token supply $ALICE_TOKEN
solana balance $PK_ALICE
Figure 2: Creation of the mint account

An interesting thing about the Solana blockchain is that anyone can look at the raw hexadecimal content of an account. Let’s check the mint account with the following command:

solana account $ALICE_TOKEN

The following figure shows a sample output:

Figure 3: Contents of the mint account

The first 6 lines are the account’s metadata an show its pubkey, the balance, the owner, if it is executable, the rent epoch, and the length. As explained before, the owner of the mint account is the Token program. The public key is generated during the creation of the account and uniquely identifies a given token. A small balance (transferred from the fee-payer) is assigned to the account to “pay the rent”, which in the Solana world is the cost of storing the account data in the blockchain. This amount is computed to match a “rent-exempt” minimum, so that actually there is no need to pay rent as long as the account holds this minimum.

The remaining lines show the hexadecimal raw data the account contains. The pubkey of the mint-authority are the first 32 highlighted bytes. The 09 a little latter is the decimals field. In this case the freeze-authority is null (zeroed).

The following node one-liner shows the hexadecimal version of ALICE’s base58 pubkey, to corroborate:

node -e 'console.log(require("bs58").decode("TULnhBExK6hwmrmGfzcMSeDH58qCttzugnWakbmERva"))'

Creating token accounts

Any user who desires to hold any given token, needs a token account for the corresponding token. Token accounts are created with the create-account subcommand of spl-token , as follows:

spl-token create-account \
--owner $PK_ALICE \
--fee-payer $KP_ALICE $ALICE_TOKEN
ALICE_ALICETOKENACCOUNT=<token account pubkey>
Figure 4: Creating a token account

It is also interesting to look at the raw content of a token account:

solana account $ALICE_ALICETOKENACCOUNT
Figure 5: Raw content of a token account

Metadata in Figure 5 shows the public key assigned to this token account, the balance for rent-exempt storage, the owner is the Token program, among others. Highlighted in the red box is the mint account pubkey (Use node -e ‘console.log(require(“bs58”).decode(“3XspNCGyc2iD2jvwb7XMBCCqkSiztJEtv3Swv5nRa56Q”))’ to check), and the green box is the token owner, in this case ALICE’s pubkey which we already know.

Thankfully, for future needs, the spl-token utility includes a sub-command to decode token accounts for us. The command is:

spl-token account-info --address $ALICE_ALICETOKENACCOUNT

Which returns the decoded information like this:

Figure 6: Decoded token account info

Minting tokens

The mint authority can mint tokens for any user. This process updates both, the user’s balance (in the token-account) and the supply (in the mint account). To mint tokens we use the mint subcommand of spl-token as follows:

spl-token mint $ALICE_TOKEN 41394 $ALICE_ALICETOKENACCOUNT \
--fee-payer $KP_ALICE \
--mint-authority $KP_ALICE

Which produces an output like this:

Figure 7: Minting tokens

If we look at the token account, we will see the updated amount, as shown in the following figure:

Figure 8: Balance in the token account

The following one-liner lets us verify the hexadecimal value. Notice the 9 zeroes corresponding to the token decimals. Also notice that numerical values are stored in little-endian order within the token account.

node -e 'a=41394000000000; console.log(a.toString(16))'

The mint account also updates to reflect the total supply:

Figure 9: Total supply in the mint account

And, of course, the spl-token offers subcommands to check the total supply and the balance for a pubkey:

spl-token balance --address $ALICE_ALICETOKENACCOUNT
spl-token supply $ALICE_TOKEN

Which, give the following result:

Figure 10: User token balance and token supply

Burning tokens

When tokenomic policies dictate, it may be necessary to burn tokens. Alice can burn its own tokens using the subcommand burn of spl-token as follows:

spl-token burn $ALICE_ALICETOKENACCOUNT 394 \
--fee-payer $KP_ALICE \
--owner $KP_ALICE

Figure 11 illustrates burning and checking the balance and the supply afterwards:

Figure 11: Burning tokens, checking balance and supply

Closing the token account

If Alice is not going to use this particular token anymore, she can close the token account and get back the remaining SOL balance. Notice that the balance must be zero before closing the account. The following is the command to close a token account:

spl-token close \
--address $ALICE_ALICETOKENACCOUNT \
--fee-payer $KP_ALICE \
--owner $KP_ALICE

Figure 12 illustrates closing the account and shows an increase in the SOL balance accounting for the remaining balance of the token account being transferred back to Alice.

Figure 12: Closing a token account and returned SOL balance

After this, the account is erased liberating the corresponding space in the blockchain, as shown in Figure 13:

Figure 13: Closed account is erased

Closing remarks

We have discussed the conceptual elements of mint and token accounts in the Solana blockchain and illustrated their operation via the command line tools. This is only the tip of the iceberg and there are many more operations like freezing mint accounts, which is fundamental for creating NFTs, and handling delegation. Perhaps, plenty of material for future installments.

For more information, a good starting point is the official documentation:

--

--