Now we have peeked under the hood of the sui::coin
module, we can look at a simple, but complete example of creating a type of custom fungible token where there is a trusted manager that has the capability to mint and burn, similar to many ERC-20 implementations.
You can find the complete Managed Coin example contract under the example project folder.
Given what we have covered so far, this contract should be fairly easy to understand. It follows the One Time Witness pattern exactly, where the witness
resource is named MANAGED
, and automatically created by the module init
function.
The init
function then calls coin::create_currency
to get the TreasuryCap
and CoinMetadata
resources. The parameters passed into this function are the fields of the CoinMetadata
object, so include the token name, symbol, icon URL, etc.
The CoinMetadata
is immediately frozen after creation via the transfer::freeze_object
method, so that it becomes a shared immutable object that can be read by any address.
The TreasuryCap
Capability object is used as a way to control access to the mint
and burn
methods that create or destroy Coin<MANAGED>
objects respectively.
Under the fungible_tokens project folder, run:
sui client publish --gas-budget 30000
You should see console output similar to:
The two immutable objects created are respectively the package itself and the CoinMetadata
object of Managed Coin
. And the owned object passed to the transaction sender is the TreasuryCap
object of Managed Coin
.
Export the object ID's of the package object and the TreasuryCap
object to environmental variables:
export PACKAGE_ID=<package object ID from previous output>
export TREASURYCAP_ID=<treasury cap object ID from previous output>
To mint some MNG
tokens, we can use the following CLI command:
sui client call --function mint --module managed --package $PACKAGE_ID --args $TREASURYCAP_ID \"<amount to mint>\" <recipient address> --gas-budget 3000
💡Note: as of Sui binary version 0.21.0, u64
inputs must be escaped as strings, thus the above CLI command format. This might change in a future version.
Export the object ID's of the newly minted COIN<MANAGED>
object to a bash variable:
export COIN_ID=<coin object ID from previous output>
Verify that the Supply
field under the TreasuryCap<MANAGED>
object should be increased by the amount minted.
To burn an existing COIN<MANAGED>
object, we use the following CLI command:
sui client call --function burn --module managed --package $PACKAGE_ID --args $TREASURYCAP_ID $COIN_ID --gas-budget 3000
Verify that the Supply
field under the TreasuryCap<MANAGED>
object should be back to 0
.
Exercise: What other commonly used functions do fungible tokens need? You should know enough about programming in Move now to try to implement some of these functions.