Solana’s Token Program, Explained

Breaking down how fungible and non-fungible tokens work in Solana.

Solana’s Account Model

  • An account either holds data (e.g. how many tokens you have) or is an executable program (i.e. a smart contract). I refer to the former as “data accounts” and the latter as “program accounts.” Importantly, unlike Ethereum, program accounts do not store state. All state is stored in data accounts.
  • Each account contains the following fields 👇
  • Each account has a unique address (similar to Ethereum). Most addresses are the public key of a keypair.
  • Each account is owned by a program. By default, a newly created account is owned by a built-in program called the “System Program.” Only the owner of an account can modify it.
The account on the left is a program account that can increment a counter. The counter’s value needs to be stored in a separate data account. The data account is owned by the program account, which means the program account can modify the data account’s state.

What is Solana’s Token Program?

  • Token minting
  • Token transferring
  • Token burning

How Does Solana’s Token Program Work?

$ echo $SOLADDR1
3sdsSwWWjjGA7HpPBQfGaXRE2HqmdKicMXHRapqLAu4L
$ echo $SOLADDR2
ES2C1YPzNh5JjQu7DdxrveaPUHj9CnrRWSdrFo4ku5Zh
$ spl-token create-token --mint-authority ~/my_solana_wallet1.json                                         
Creating token 6ifRGEkJ6XmEjuqfTFNqAjjomUiDJTjRv4GHqBH6usWr
$ solana account $TOKEN1
Public Key: Aqf1rBKNQYgX1mjE64STwV3miEwXEe2ioZzD7n4vkpXk
Balance: 0.0014616 SOL
Owner: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
Executable: false
Rent Epoch: 207
Length: 82 (0x52) bytes
0000: 01 00 00 00 2a b0 1a 64 bb c5 f0 df bf 57 d5 61 ....*..d.....W.a
0010: 56 a8 b8 85 8f a8 0b 09 f1 f1 a2 dc 4d 51 b3 63 V...........MQ.c
0020: 8f 72 bd e9 00 00 00 00 00 00 00 00 09 01 00 00 .r..............
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0050: 00 00 ..
https://explorer.solana.com/address/TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA?cluster=devnet
https://explorer.solana.com/address/Aqf1rBKNQYgX1mjE64STwV3miEwXEe2ioZzD7n4vkpXk?cluster=devnet
  • Address—I hope this is self-explanatory 😛 This is just the mint account’s address.
  • Current Supply—The number of tokens that have been minted. Since we just created the token, it is 0.
  • Mint Authority—The public key of the keypair that is allowed to mint tokens (we specified this with the --mint-authority flag. If anyone else tries to mint tokens, it will fail.
  • Decimals—This dictates the smallest denomination of the token. For NFTs, it should be zero. Nine is the default.
  • “Internal Solana relations” refers to the owner field that is set on every account, e.g. the owner that’s displayed when you run solana account $TOKEN1.
  • “User-space relations” refers to when a relation between two accounts is encoded in an account’s data, e.g. the “mint authority” field we saw above.
The Token Program’s owner is the BPF Loader. I don’t picture it here because it’s not that important, and it clutters up the diagram.
$ spl-token create-account $TOKEN1 --owner $SOLADDR1                              
Creating account 9EYnoqiBQmJPR55db44cF4wkN1PD5D6vjxEz61r2Ujak
$ solana account $TOKENACCT1
Public Key: 9EYnoqiBQmJPR55db44cF4wkN1PD5D6vjxEz61r2Ujak
Balance: 0.00203928 SOL
Owner: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
Executable: false
Rent Epoch: 207
https://explorer.solana.com/address/9EYnoqiBQmJPR55db44cF4wkN1PD5D6vjxEz61r2Ujak?cluster=devnet
$ spl-token balance $TOKEN1 --owner $SOLADDR1
0
$ spl-token mint $TOKEN1 10 $TOKENACCT1 --mint-authority ~/my_solana_wallet1.json
Minting 10 tokens
Token: Aqf1rBKNQYgX1mjE64STwV3miEwXEe2ioZzD7n4vkpXk
Recipient: 9EYnoqiBQmJPR55db44cF4wkN1PD5D6vjxEz61r2Ujak
$ spl-token balance $TOKEN1 --owner $SOLADDR1
10
The token balance gets updated in Solana Explorer as well. https://explorer.solana.com/address/9EYnoqiBQmJPR55db44cF4wkN1PD5D6vjxEz61r2Ujak?cluster=devnet.
$ spl-token accounts  --owner $SOLADDR1                                                                                                      
Token Balance
---------------------------------------------------------------
Aqf1rBKNQYgX1mjE64STwV3miEwXEe2ioZzD7n4vkpXk 10
$ spl-token mint $TOKEN1 10 $TOKENACCT1 --mint-authority ~/my_solana_wallet2.json
Minting 10 tokens
Token: Aqf1rBKNQYgX1mjE64STwV3miEwXEe2ioZzD7n4vkpXk
Recipient: 9EYnoqiBQmJPR55db44cF4wkN1PD5D6vjxEz61r2Ujak
RPC response error -32002: Transaction simulation failed: Error processing Instruction 0: custom program error: 0x4 [5 log messages]
$ spl-token transfer $TOKEN1 1 $SOLADDR2 --owner ~/my_solana_wallet1.json
Transfer 5 tokens
Sender: 9EYnoqiBQmJPR55db44cF4wkN1PD5D6vjxEz61r2Ujak
Recipient: ES2C1YPzNh5JjQu7DdxrveaPUHj9CnrRWSdrFo4ku5Zh
Recipient associated token account: FFednTgQRKDbGYjXrXk8SWPfzSJW3Q8ApN5mGCpGdAtE
Error: Recipient's associated token account does not exist. Add `--fund-recipient` to fund their account
  1. Create a token account for the recipient and then transfer the tokens.
  2. Use the --fund-recipient flag. This makes the sender pay for creating the recipient’s token account.
$ spl-token create-account $TOKEN1 --owner $SOLADDR2
Creating account FFednTgQRKDbGYjXrXk8SWPfzSJW3Q8ApN5mGCpGdAtE
$ spl-token transfer $TOKEN1 1 $SOLADDR2 --owner ~/my_solana_wallet1.json
Transfer 1 tokens
Sender: 9EYnoqiBQmJPR55db44cF4wkN1PD5D6vjxEz61r2Ujak
Recipient: ES2C1YPzNh5JjQu7DdxrveaPUHj9CnrRWSdrFo4ku5Zh
Recipient associated token account: FFednTgQRKDbGYjXrXk8SWPfzSJW3Q8ApN5mGCpGdAtE
$ spl-token balance $TOKEN1 --owner $SOLADDR2
1
$ spl-token wrap 1 ~/my_solana_wallet1.json
Wrapping 1 SOL into DXWzvX3RtZbito65G8ZgqmEzJM6Z6Fqy7NHkbpEmCUZD
$ spl-token unwrap DXWzvX3RtZbito65G8ZgqmEzJM6Z6Fqy7NHkbpEmCUZD ~/my_solana_wallet1.json
Unwrapping DXWzvX3RtZbito65G8ZgqmEzJM6Z6Fqy7NHkbpEmCUZD
Amount: 1 SOL
Recipient: 3sdsSwWWjjGA7HpPBQfGaXRE2HqmdKicMXHRapqLAu4L

Wait, What About NFTS?

  • Use --decimals 0 when creating the token, since there should only be one of them.
  • After minting one token, disable future minting. This ensures there will only ever be one token.
  • A single program called the Token Program is able to create new token types, mint new tokens, and transfer tokens between accounts.
  • Unlike ERC20 tokens, where each new type of token is associated with a new ERC20 smart contract, there is only one Token Program. However, each new type of token is associated with a new mint account.
  • If a user wants to own some tokens of a particular type, they need to have a token account. In other words, if someone owns five different types of tokens, they will have five different token accounts.
  • You can wrap SOL in an SPL token, which allows it to be easily exchanged for other SPL tokens.
  • A non-fungible SPL token is a token with zero decimals that has minted one copy and disabled future minting.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Matt Lim

Software Engineer. Tweeting @pencilflip. Mediocre boulderer, amateur tennis player, terrible at Avalon. https://www.mattlim.me/