Getting Started with Token Extensions

Token extensions are the next generation of the Solana Program Library standard. Token extensions introduce a new set of ways to extend the normal token functionality. The original Token program brought the basic capabilities of transfer, freeze, and minting tokens. Token extensions include the same feature, but come with additional features such as confidential transfers, custom transfer logic, extended metadata, and much more.

The Token Extensions program can be found with the programID TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb and is a superset of the original functionality provided by the Token Program.

How do I create a token with token extensions? #

To get started creating tokens with token extensions, you can use the Solana Tool Suite to create tokens with a CLI. Based on the extension you want to create, your command flags may be different. Below are the flags to add to create tokens with each type of extension.

ExtensionCLI Flag
Mint Close Authority--enable-close
Transfer Fees--transfer-fee <basis points> <max fee>
Non-Transferable--enable-non-transferable
Interest-Bearing--interest-rate <rate>
Permanent Delegate--enable-permanent-delegate
Transfer Hook--transfer-hook <programID>
Metadata--enable-metadata
Metadata Pointer--metadata-address <accountId>
Confidential Transfers--enable-confidential-transfers auto

You enable some extensions on a token account instead of the mint, which you can also find the required flags for each below.

ExtensionCLI Flag
Immutable OwnerIncluded by default
Required Memo on Transferenable-required-transfer-memos
CPI Guardenable-cpi-guard
Default Account State--default-account-state <state>

Now that you know what extensions are available, you can create your new token with token extensions with the following command:

spl-token --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb \
  create-token <extension flags>

With token extensions, you can mix and match based on what you need for your project. For example, if you wanted a token with transfer fees and a custom metadata, you would just use the following command to combine the extensions:

spl-token --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb \
  create-token --interest-rate 5 --enable-metadata
Info

While you can mix and match extensions, most extensions cannot be added after the token mint is created. Including non-transferrable, the various "pointer" extensions, and several others.

What extensions are compatible with each other? #

You can combine multiple extensions together, however some extensions would either not work or not make sense to combine. For example, you would not want to add transfer hooks alongside the non-transferable token extension because it would not add anything to the token and only cost more to create.

The following extension combinations either do not work together, or will not make sense to combine:

  • Non-transferable + (transfer hooks, transfer fees, confidential transfer)
  • Confidential transfer + fees (until 1.18)
  • Confidential transfer + transfer hooks (these transfers can only see source / destination accounts, therefore cannot act on the amount transferred)

Other than these, you have the option to customize with any combination of token extensions that suit your project’s needs.

How do I add custom logic to my tokens with token extensions? #

Token extensions enable you to create custom logic with your tokens while retaining full composability with dApps, wallets, and programs. The two extensions that can enable this are the Transfer Hook and Metadata extensions.

Transfer Hooks #

Transfer hooks are a powerful new extension that give token issuers greater ability to dictate how users and tokens interact. Instead of a normal transfer, any developer can insert custom logic into a program to be used with the transfer hook extension. With transfer hooks you can enable capabilities such as enforced on-chain royalties, enabling more elaborate token interactions.

It is important to note that while transfer hooks give the capability to insert custom logic within a transfer, all accounts from the initial transfer are converted to read-only accounts. This means that the signer privileges of the sender do not extend to the Transfer Hook program. This is to avoid potential unexpected logic executing on someone’s wallet who interacts with a token with transfer hooks, protecting the users.

You can start building with transfer hooks today.

Metadata #

The Metadata extension gives token issuers the ability to push any key value pair on-chain with customizable fields, all within the same account. This enables projects such as games to have their custom metadata potentially within each token, creating a wider variety of possibilities of what games can do with their in-game tokens and items.

This custom on-chain metadata also opens up the door for new standards to be created, giving opportunity to the developer community to come together to create new ways to use metadata onchain, all bundled together under token extensions.

You can start building with the metadata extension today.

How do I migrate tokens from one standard to another? #

While token extensions are a new standard for tokens, it is not a requirement that anyone migrate from one standard to another. There are reasons why you may want to stick with the original Token standard.

If you only need a transfer and freeze functionality and none of the additional features of token extensions, the Token program standard will suit your project just fine. However if you want the ability to add more advanced features, token extensions can help.

There is no way to automatically convert your tokens across standards today. A migration path does exist between the token standards, but it comes with some complications:

  • All tokens of the previous standard must be burned
  • The migration will be user opt-in only

The general recommendation is that if you want token extension capabilities for your token, start with creating your token with that standard.

What is the instruction layout for Token extensions? #

Token extensions supports the exact same instruction layouts as Token, byte for byte. For example, if you want to transfer 100 tokens on a mint with 2 decimals, you create a TransferChecked instruction, with this byte-represented data:

[12, 100, 0, 0, 0, 0, 0, 0, 0, 2]
 ^^ TransferChecked enum
     ^^^^^^^^^^^^^^^^^^^^^^^^ 100, as a little-endian 64-bit unsigned integer
                               ^ 2, as a byte

This format means the exact same thing to both Token and Token extensions. If you want to target one program over another, you just need to change the program_id in the instruction.

All new instructions in the Token extensions program start where the original Token program stops. The original Token program has 25 unique instructions, with indices 0 through 24. The token extensions program supports all of these instructions, and then adds new functionality at index 25.

What is the layout of Mints and Accounts? #

For structure layouts, the same idea mostly applies. An Account has the same exact representation between Token and Token extensions for the first 165 bytes, and a Mint has the same representation for the first 82 bytes.

Where is the source code for Token extensions? #

The Token extensions program's source is available on GitHub.

For information about the types and instructions, the Rust docs are available at docs.rs.

Has the token extensions program been audited? #

The token extensions program has been audited multiple times. The complete updated list of audits performed can be found on in the program's Security Audits documentation.

Here are the completed audits as of 13 December 2023: