Create Fungible Tokens: Coin Standard
The Coin standard uses the sui::coin module to define fungible assets called coins that have key and store abilities. Coins support wrapping and public transfer functionality.
The Coin<T> type represents open-loop fungible tokens, denominated by their type parameter T, which is also associated with metadata that applies to all instances of Coin<T>. The sui::coin module exposes an interface over Coin<T> that treats it as fungible, meaning that a unit of T held in one instance of Coin<T> is interchangeable with any other unit of T, similar to how traditional fiat currencies operate.
The network's native coin, SUI, uses the Coin standard.
Use the Coin standard​
To create a coin, you must define the metadata, create the currency, and mint the initial supply.
Step 1: Define the metadata​
Define the metadata for the coin, including its name, description, symbol, icon URL, and decimals:
I1/silver/sources/silver.move. You probably need to run `pnpm prebuild` and restart the site.This example creates a coin with 9 decimals, the name Silver, a description, the symbol SILVER, and an icon URL for an asset stored on Walrus.
Step 2: Create the currency​
Create the coin using the coin::create_currency function:
I1/silver/sources/silver.move. You probably need to run `pnpm prebuild` and restart the site.Step 3: Mint the initial supply​
Mint the initial supply of your coin:
I1/silver/sources/silver.move. You probably need to run `pnpm prebuild` and restart the site.View the full example or learn more about the Coin Standard.
Managing coins​
Sui supports two ways to hold fungible assets: address balances and coin objects. Address balances are the recommended default for most use cases. Coin objects remain available for scenarios that require explicit object-level control.
Address balances​
Address balances provide a canonical balance for each coin type tied directly to a Sui address. Funds sent through send_funds merge automatically into a single balance per coin type, with no object management required.
Key advantages of address balances:
- No coin selection or merging logic needed.
- Stateless transaction construction without querying object states.
- Gas payment directly from SUI address balances.
- Multiple deposits merge automatically.
The TypeScript SDK (v2+) uses address balances by default. When you use coinWithBalance, the SDK draws from address balances first and falls back to coin objects only when needed. For gas payment, pass an empty array to setGasPayment to pay from your address balance.
See Address Balances Migration Guide for the full reference on using address balances, including withdrawal patterns, gas payment, sponsored transactions, and balance queries.
Coin objects​
Coin objects are address-owned objects that represent a specific amount of a given coin type. Before address balances, all funds on Sui were held as coin objects. They remain fully functional and are not deprecated.
Coin objects are useful when you need to:
- Pass a
Coin<T>or&mut Coin<T>directly to a Move function that expects one. - Hold funds inside another object (for example, in a shared escrow or liquidity pool).
- Control the exact set of objects used in a transaction.
Because coin objects are owned objects, they enable highly parallel transaction execution. Each coin is an independent object with its own version, so transactions that touch different coins can execute concurrently without contention.
For explicit coin manipulation within a PTB, use the mergeCoins command to combine multiple coin objects into one, and splitCoins to break a coin into smaller pieces. These operations are inexpensive but require you to know your coin distribution and transaction needs.
Accumulating coin objects​
It is common to accumulate many coin objects over time, especially if you receive frequent transfers. Some scenarios require merging coins into a single object. For example, if no single coin holds enough value to cover a transaction, you must merge coins first.
You can convert coin objects into an address balance at any time by calling coin::send_funds with your own address as the recipient. See Converting Existing Coins to Address Balances for instructions.
Gas smashing​
When executing a transaction, you can provide multiple coins as gas payment rather than a single coin. This feature, known as gas smashing, automatically merges the provided coins into the first coin in the payment vector. That merged coin, minus the gas budget, is then available inside the transaction for use in any command. If unused, it returns to the sender.
Gas smashing applies only to Coin<SUI> objects, because SUI is the only coin type accepted for gas payment.
You can provide as many coins as you want (up to a maximum defined in the protocol configuration). Gas smashing is a useful tool when you need to consolidate SUI coins as part of a transaction.
If you use address balance gas payment (by passing an empty gas payment array), you do not need gas smashing. Address balance gas payment removes the need to select or merge gas coins entirely.
See Gas Smashing for more details.
Concurrency​
Address balances significantly reduce concurrency challenges for most use cases. Because address balance gas payments do not require owned object inputs, you can build and sign multiple transactions without worrying about object version conflicts or locking.
When concurrency still matters​
If your transactions use coin objects (or any other owned objects) as inputs, the original concurrency constraints apply. Each owned object has a version, and the system locks it when you sign a transaction. This lock prevents using the same object in another transaction until the first one executes. Attempting to sign multiple transactions with the same owned object can result in equivocation, which makes the object unusable until the end of the epoch.
When you require heavy concurrency with coin objects, split a coin into as many coins as the number of transactions you plan to execute concurrently. Alternatively, provide different coins (through gas smashing) to each transaction. The set of coins used across concurrent transactions must have no overlap.
Recommended approach​
For most applications, use address balances for gas payment and fund transfers. Reserve coin object management for cases where a Move contract requires a Coin<T> argument or where you need explicit control over owned objects. This approach minimizes concurrency issues and simplifies transaction construction.