solana-program-library/docs/src/token.md

273 lines
11 KiB
Markdown
Raw Normal View History

---
title: Token Program
---
2020-07-28 11:00:37 -07:00
A Fungible Token program on the Solana blockchain.
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-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-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
[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
[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,
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
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`
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
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
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
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
The Mint may also contain a `freeze_authority` can be used to issue
`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
`None` then account freezing is permanently disabled
2020-07-28 11:00:37 -07:00
### Wrapping SOL
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
"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-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.
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
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.