Following Part 1: understanding SPL Token Mint, this article introduces the technical details of the SPL associated token program, another popular official Solana smart contract.
The program provides a convenient way to manage a user’s token accounts from a wallet address. Its program id: ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL
The idea is to create a PDA (i.e., program-derived account) from a user’s wallet address and a token mint. There are two main benefits:
*wallet address — in fact, it can be any pubkey that can be signed by an authority; e.g., a System account or a PDA (see deep dive on Solana account model).
In the following, we will elaborate on two instructions:
To create a new associated token account (ATA), users need to supply the following six accounts to function process_create_associated_token_account:
The function first calls get_associated_token_address_and_bump_seed_internal to compute the associated_token_address (i.e., the PDA) and validates the user input:
Internally, the PDA is computed using Pubkey::find_program_address and is uniquely determined by three addresses (in seeds):
Then, the ATA is created by calling create_pda_account , and its program owner is set to spl_token_program_id (i.e., only the spl_token_program can modify the PDA account’s data):
In spl_token_2022 , it also ensures that the ATA’s owner cannot be changed by calling initialize_immutable_owner:
Finally, the ATA (which is a Token account) is initialized by setting its account.mint to token_mint_address and account.owner to wallet_address :
Note 1: account.owner here is not the program-level owner (i.e., the spl_token_program) of the ATA, but its real authority (i.e., the wallet_address). In other words, wallet_address fully owns the newly created ATA and the owner of wallet_address must sign to transfer tokens from the ATA.
Note 2: If the ATA for a given wallet_address does not yet exist, it may be created by anybody by issuing a transaction containing the AssociatedTokenAccountInstruction::Create instruction.
A caveat of using the associated token program is that users may (unintentionally) create a nested ATA:
an associated token account owned by an associated token account
Once that happened, users cannot move funds from a nested ATA because it is not owned by the user’s wallet address, but a PDA.
The RecoverNested instruction is used to address this issue. It closes a nested ATA and transfers its tokens to the wallet’s ATA (and transfers its lamports to the wallet).
The input wallet_account_info account must be signed, and the destination_associated_token_account_info account is the recipient of the transferred tokens:
The transferred token amount and mint decimals are extracted from the nested ATA. The signer_seeds (i.e., owner_associated_token_account_signer_seeds) include three addresses and the bump_seed:
The bump_seed is the bump seed returned from creating owner_associated_token_address , which is the PDA owner of the nested ATA (i.e., nested_associated_token_account_info ).
In the next few articles, we will continue to highlight the technical details of a few more Solana programs that are frequently used.
Sec3 (formerly Soteria) is founded by leading minds in the fields of blockchain security and software verification.
We are pleased to provide audit services to high-impact Dapps on Solana. Please visit sec3.dev or email contact@sec3.dev