2020-07-16 09:13:45 -07:00
|
|
|
---
|
|
|
|
title: Token Program
|
|
|
|
---
|
|
|
|
|
2020-07-28 11:00:37 -07:00
|
|
|
A Fungible Token program on the Solana blockchain.
|
2020-07-16 09:13:45 -07:00
|
|
|
|
2020-07-28 11:00:37 -07:00
|
|
|
This program provides an interface and implementation that third parties can
|
|
|
|
utilize to create and use their tokens.
|
2020-07-16 09:13:45 -07:00
|
|
|
|
2020-07-28 11:00:37 -07:00
|
|
|
## Background
|
|
|
|
|
|
|
|
Solana's programming model and the definitions of the Solana terms used in this
|
|
|
|
document are available at:
|
2020-08-03 07:31:23 -07:00
|
|
|
|
2020-07-28 11:00:37 -07:00
|
|
|
- https://docs.solana.com/apps
|
|
|
|
- https://docs.solana.com/terminology
|
|
|
|
|
|
|
|
## Source
|
|
|
|
|
|
|
|
The Token Program's source is available on
|
|
|
|
[github](https://github.com/solana-labs/solana-program-library)
|
|
|
|
|
|
|
|
## Interface
|
|
|
|
|
|
|
|
The on-chain Token Program is written in Rust and available on crates.io as
|
2020-07-28 16:33:50 -07:00
|
|
|
[spl-token](https://docs.rs/spl-token). The program's [instruction interface
|
2020-09-03 19:21:52 -07:00
|
|
|
documentation](https://docs.rs/spl-token/2.0.4/spl_token/instruction/enum.TokenInstruction.html)
|
2020-07-28 11:00:37 -07:00
|
|
|
can also be found there.
|
|
|
|
|
|
|
|
Auto-generated C bindings are also available for the on-chain Token Program and
|
|
|
|
available
|
2020-09-01 18:41:05 -07:00
|
|
|
[here](https://github.com/solana-labs/solana-program-library/blob/master/token/program/inc/token.h)
|
2020-07-28 11:00:37 -07:00
|
|
|
|
2020-09-09 16:57:30 -07:00
|
|
|
[JavaScript
|
2020-07-28 11:00:37 -07:00
|
|
|
bindings](https://github.com/solana-labs/solana-program-library/blob/master/token/js/client/token.js)
|
2020-08-28 17:16:55 -07:00
|
|
|
are available that support loading the Token Program on to a chain and issue
|
2020-07-28 11:00:37 -07:00
|
|
|
instructions.
|
|
|
|
|
2020-08-10 09:16:56 -07:00
|
|
|
## Command-line Utility
|
|
|
|
|
|
|
|
The `spl-token` command-line utility can be used to experiment with SPL
|
|
|
|
tokens. Once you have [Rust installed](https://rustup.rs/), run:
|
|
|
|
```sh
|
|
|
|
$ cargo install spl-token-cli
|
|
|
|
```
|
|
|
|
|
2020-08-10 19:57:22 -07:00
|
|
|
The `spl-token` configuration is shared with the `solana` command-line tool.
|
|
|
|
Run `spl-token --help` for a full description of available commands.
|
2020-08-10 09:16:56 -07:00
|
|
|
|
|
|
|
### Example: Creating your own Token
|
|
|
|
|
|
|
|
```sh
|
|
|
|
$ spl-token create-token
|
|
|
|
Creating token AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM
|
|
|
|
Signature: 47hsLFxWRCg8azaZZPSnQR8DNTRsGyPNfUK7jqyzgt7wf9eag3nSnewqoZrVZHKm8zt3B6gzxhr91gdQ5qYrsRG4
|
|
|
|
```
|
|
|
|
|
|
|
|
The unique identifier of the token is `AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM`.
|
|
|
|
|
|
|
|
Tokens when initially created by `spl-token` have no supply:
|
|
|
|
```sh
|
|
|
|
spl-token supply AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM
|
|
|
|
0
|
|
|
|
```
|
|
|
|
|
|
|
|
Let's mint some. First create an account to hold a balance of the new
|
|
|
|
`AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM` token:
|
|
|
|
```sh
|
|
|
|
$ spl-token create-account AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM
|
|
|
|
Creating account 7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi
|
|
|
|
Signature: 42Sa5eK9dMEQyvD9GMHuKxXf55WLZ7tfjabUKDhNoZRAxj9MsnN7omriWMEHXLea3aYpjZ862qocRLVikvkHkyfy
|
|
|
|
```
|
|
|
|
|
|
|
|
`7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi` is now an empty account:
|
|
|
|
```sh
|
|
|
|
$ spl-token balance 7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi
|
|
|
|
0
|
|
|
|
```
|
|
|
|
|
|
|
|
Mint 100 tokens into the account:
|
|
|
|
```sh
|
|
|
|
$ spl-token mint AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM 100 \
|
|
|
|
7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi
|
|
|
|
Minting 100 tokens
|
|
|
|
Token: AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM
|
|
|
|
Recipient: 7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi
|
|
|
|
Signature: 41mARH42fPkbYn1mvQ6hYLjmJtjW98NXwd6pHqEYg9p8RnuoUsMxVd16RkStDHEzcS2sfpSEpFscrJQn3HkHzLaa
|
|
|
|
```
|
|
|
|
|
|
|
|
The token `supply` and account `balance` now reflect the result of minting:
|
|
|
|
```sh
|
|
|
|
$ spl-token supply AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM
|
|
|
|
100
|
|
|
|
$ spl-token balance 7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi
|
|
|
|
100
|
|
|
|
```
|
|
|
|
|
|
|
|
### Example: View all Tokens that you own
|
|
|
|
|
|
|
|
```sh
|
|
|
|
$ spl-token accounts
|
|
|
|
Account Token Balance
|
|
|
|
-------------------------------------------------------------------------------------------------
|
|
|
|
2ryb53FGVLVYFXmAemN7avawevuNFXwTVetMpH9ag3XZ 7e2X5oeAAJyUTi4PfSGXFLGhyPw2H8oELm1mx87ZCgwF 84
|
|
|
|
7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM 100
|
|
|
|
CqAxDdBRnawzx9q4PYM3wrybLHBhDZ4P6BTV13WsRJYJ AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM 0
|
|
|
|
JAopo117aj6HMwCRjXSyNpZfGDJRi7ukqHgs2inXD8Rc AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM 0
|
|
|
|
```
|
|
|
|
|
|
|
|
### Example: Wrapping SOL in a Token
|
|
|
|
|
|
|
|
```sh
|
|
|
|
$ spl-token wrap 1
|
|
|
|
Wrapping 1 SOL into GJTxcnA5Sydy8YRhqvHxbQ5QNsPyRKvzguodQEaShJje
|
|
|
|
Signature: 4f4s5QVMKisLS6ihZcXXPbiBAzjnvkBcp2A7KKER7k9DwJ4qjbVsQBKv2rAyBumXC1gLn8EJQhwWkybE4yJGnw2Y
|
|
|
|
```
|
|
|
|
|
|
|
|
To unwrap the Token back to SOL:
|
|
|
|
```
|
|
|
|
$ spl-token unwrap GJTxcnA5Sydy8YRhqvHxbQ5QNsPyRKvzguodQEaShJje
|
|
|
|
Unwrapping GJTxcnA5Sydy8YRhqvHxbQ5QNsPyRKvzguodQEaShJje
|
|
|
|
Amount: 1 SOL
|
|
|
|
Recipient: vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg
|
|
|
|
Signature: f7opZ86ZHKGvkJBQsJ8Pk81v8F3v1VUfyd4kFs4CABmfTnSZK5BffETznUU3tEWvzibgKJASCf7TUpDmwGi8Rmh
|
|
|
|
```
|
|
|
|
|
2020-08-10 12:55:56 -07:00
|
|
|
### Example: Transferring tokens
|
|
|
|
|
|
|
|
```
|
|
|
|
$ spl-token create-account AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM
|
|
|
|
Creating account CqAxDdBRnawzx9q4PYM3wrybLHBhDZ4P6BTV13WsRJYJ
|
|
|
|
Signature: 4yPWj22mbyLu5mhfZ5WATNfYzTt5EQ7LGzryxM7Ufu7QCVjTE7czZdEBqdKR7vjKsfAqsBdjU58NJvXrTqCXvfWW
|
|
|
|
```
|
|
|
|
```
|
|
|
|
$ spl-token accounts AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM
|
|
|
|
Account Token Balance
|
|
|
|
-------------------------------------------------------------------------------------------------
|
|
|
|
7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM 100
|
|
|
|
CqAxDdBRnawzx9q4PYM3wrybLHBhDZ4P6BTV13WsRJYJ AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM 0
|
|
|
|
```
|
|
|
|
|
|
|
|
```
|
|
|
|
$ spl-token transfer 7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi 50 CqAxDdBRnawzx9q4PYM3wrybLHBhDZ4P6BTV13WsRJYJ
|
|
|
|
Transfer 50 tokens
|
|
|
|
Sender: 7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi
|
|
|
|
Recipient: CqAxDdBRnawzx9q4PYM3wrybLHBhDZ4P6BTV13WsRJYJ
|
|
|
|
Signature: 5a3qbvoJQnTAxGPHCugibZTbSu7xuTgkxvF4EJupRjRXGgZZrnWFmKzfEzcqKF2ogCaF4QKVbAtuFx7xGwrDUcGd
|
|
|
|
```
|
|
|
|
```
|
|
|
|
$ spl-token accounts AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM
|
|
|
|
Account Token Balance
|
|
|
|
-------------------------------------------------------------------------------------------------
|
|
|
|
7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM 50
|
|
|
|
CqAxDdBRnawzx9q4PYM3wrybLHBhDZ4P6BTV13WsRJYJ AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM 50
|
|
|
|
```
|
|
|
|
|
2020-07-28 11:00:37 -07:00
|
|
|
## Operational overview
|
|
|
|
|
|
|
|
### Creating a new token type
|
|
|
|
|
|
|
|
A new token type can be created by initializing a new Mint with the
|
2020-08-28 17:16:55 -07:00
|
|
|
`InitializeMint` instruction. The Mint is used to create or "mint" new tokens,
|
2020-08-03 07:31:23 -07:00
|
|
|
and these tokens are stored in Accounts. A Mint is associated with each
|
2020-07-28 11:00:37 -07:00
|
|
|
Account, which means that the total supply of a particular token type is equal
|
|
|
|
to the balances of all the associated Accounts.
|
|
|
|
|
|
|
|
It's important to note that the `InitializeMint` instruction does not require
|
2020-08-03 07:31:23 -07:00
|
|
|
the Solana account being initialized also be a signer. The `InitializeMint`
|
2020-07-28 11:00:37 -07:00
|
|
|
instruction should be atomically processed with the system instruction that
|
|
|
|
creates the Solana account by including both instructions in the same
|
|
|
|
transaction.
|
|
|
|
|
2020-08-28 17:16:55 -07:00
|
|
|
Once a Mint is initialized, the `mint_authority` can create new tokens using the
|
|
|
|
`MintTo` instruction. As long as a Mint contains a valid `mint_authority`, the
|
|
|
|
Mint is considered to have a non-fixed supply, and the `mint_authority` can
|
|
|
|
create new tokens with the `MintTo` instruction at any time. The `SetAuthority`
|
|
|
|
instruction can be used to irreversibly set the Mint's authority to `None`,
|
|
|
|
rendering the Mint's supply fixed. No further tokens can ever be Minted.
|
|
|
|
|
|
|
|
Token supply can be reduced at any time by issuing a `Burn` instruction which
|
|
|
|
removes and discards tokens from an Account.
|
|
|
|
|
2020-07-28 11:00:37 -07:00
|
|
|
### Creating accounts
|
|
|
|
|
|
|
|
Accounts hold token balances and are created using the `InitializeAccount`
|
2020-08-03 07:31:23 -07:00
|
|
|
instruction. Each Account has an owner who must be present as a signer in some
|
2020-07-28 11:00:37 -07:00
|
|
|
instructions.
|
|
|
|
|
|
|
|
Balances can be transferred between Accounts using the `Transfer` instruction.
|
|
|
|
The owner of the source Account must be present as a signer in the `Transfer`
|
|
|
|
instruction.
|
|
|
|
|
|
|
|
An Account's owner may transfer ownership of an account to another using the
|
2020-08-28 10:04:37 -07:00
|
|
|
`SetAuthority` instruction.
|
2020-07-28 11:00:37 -07:00
|
|
|
|
|
|
|
It's important to note that the `InitializeAccount` instruction does not require
|
2020-08-03 07:31:23 -07:00
|
|
|
the Solana account being initialized also be a signer. The `InitializeAccount`
|
2020-07-28 11:00:37 -07:00
|
|
|
instruction should be atomically processed with the system instruction that
|
|
|
|
creates the Solana account by including both instructions in the same
|
|
|
|
transaction.
|
|
|
|
|
|
|
|
### Burning
|
|
|
|
|
|
|
|
The `Burn` instruction decreases an Account's token balance without transferring
|
|
|
|
to another Account, effectively removing the token from circulation permanently.
|
|
|
|
|
|
|
|
### Authority delegation
|
|
|
|
|
|
|
|
Account owners may delegate authority over some or all of their token balance
|
2020-08-03 07:31:23 -07:00
|
|
|
using the `Approve` instruction. Delegated authorities may transfer or burn up
|
2020-08-28 17:16:55 -07:00
|
|
|
to the amount they've been delegated. Authority delegation may be revoked by the
|
|
|
|
Account's owner via the `Revoke` instruction.
|
2020-07-28 11:00:37 -07:00
|
|
|
|
|
|
|
### Multisignatures
|
|
|
|
|
2020-08-28 17:16:55 -07:00
|
|
|
M of N multisignatures are supported and can be used in place of Mint
|
|
|
|
authorities or Account owners or delegates. Multisignature authorities must be
|
2020-07-28 11:00:37 -07:00
|
|
|
initialized with the `InitializeMultisig` instruction. Initialization specifies
|
|
|
|
the set of N public keys that are valid and the number M of those N that must be
|
|
|
|
present as instruction signers for the authority to be legitimate.
|
|
|
|
|
|
|
|
It's important to note that the `InitializeMultisig` instruction does not
|
2020-08-03 07:31:23 -07:00
|
|
|
require the Solana account being initialized also be a signer. The
|
2020-07-28 11:00:37 -07:00
|
|
|
`InitializeMultisig` instruction should be atomically processed with the system
|
|
|
|
instruction that creates the Solana account by including both instructions in
|
|
|
|
the same transaction.
|
|
|
|
|
2020-08-28 17:16:55 -07:00
|
|
|
### Freezing accounts
|
|
|
|
|
2020-09-16 16:20:06 -07:00
|
|
|
The Mint may also contain a `freeze_authority` which can be used to issue
|
2020-08-28 17:16:55 -07:00
|
|
|
`FreezeAccount` instructions that will render an Account unusable. Token
|
|
|
|
instructions that include a frozen account will fail until the Account is thawed
|
|
|
|
using the `ThawAccount` instruction. The `SetAuthority` instruction can be used
|
|
|
|
to change a Mint's `freeze_authority`. If a Mint's `freeze_authority` is set to
|
2020-09-16 16:20:06 -07:00
|
|
|
`None` then account freezing and thawing is permanently disabled and all
|
|
|
|
currently frozen accounts will also stay frozen permanently.
|
2020-08-28 17:16:55 -07:00
|
|
|
|
2020-07-28 11:00:37 -07:00
|
|
|
### Wrapping SOL
|
|
|
|
|
2020-08-03 07:31:23 -07:00
|
|
|
The Token Program can be used to wrap native SOL. Doing so allows native SOL to
|
2020-07-28 11:00:37 -07:00
|
|
|
be treated like any other Token program token type and can be useful when being
|
|
|
|
called from other programs that interact with the Token Program's interface.
|
|
|
|
|
|
|
|
Accounts containing wrapped SOL are associated with a specific Mint called the
|
2020-08-03 07:31:23 -07:00
|
|
|
"Native Mint" using the public key
|
2020-08-28 09:12:05 -07:00
|
|
|
`So11111111111111111111111111111111111111112`.
|
2020-07-28 11:00:37 -07:00
|
|
|
|
|
|
|
These accounts have a few unique behaviors
|
2020-08-03 07:31:23 -07:00
|
|
|
|
2020-07-28 11:00:37 -07:00
|
|
|
- `InitializeAccount` sets the balance of the initialized Account to the SOL
|
|
|
|
balance of the Solana account being initialized, resulting in a token balance
|
|
|
|
equal to the SOL balance.
|
|
|
|
- Transfers to and from not only modify the token balance but also transfer an
|
|
|
|
equal amount of SOL from the source account to the destination account.
|
|
|
|
- Burning is not supported
|
|
|
|
- When closing an Account the balance may be non-zero.
|
|
|
|
|
2020-09-01 18:41:05 -07:00
|
|
|
In spl-token v2, the Native Mint supply will always report 0, regardless of
|
|
|
|
how much SOL is currently wrapped.
|
|
|
|
|
2020-08-28 17:16:55 -07:00
|
|
|
### Rent-exemption
|
|
|
|
|
|
|
|
To ensure a reliable calculation of supply, a consistency valid Mint, and
|
|
|
|
consistently valid Multisig accounts all Solana accounts holding a Account,
|
|
|
|
Mint, or Multisig must contain enough SOL to be considered (rent
|
|
|
|
exempt)[https://docs.solana.com/implemented-proposals/rent]
|
|
|
|
|
2020-07-28 11:00:37 -07:00
|
|
|
### Closing accounts
|
|
|
|
|
2020-08-03 07:31:23 -07:00
|
|
|
An account may be closed using the `CloseAccount` instruction. When closing an
|
2020-07-28 11:00:37 -07:00
|
|
|
Account, all remaining SOL will be transferred to another Solana account
|
2020-08-28 17:16:55 -07:00
|
|
|
(doesn't have to be associated with the Token Program). Non-native Accounts must
|
|
|
|
have a balance of zero to be closed.
|