Skip to main content

Best Practices for Token Launches on Sui with Multisig Setup Guide

This guide provides detailed steps and best practices for launching new tokens on Sui, along with setting up multisig wallets for secure management.

Token launch best practices

  1. Token publishing and initial setup:
    • Use a burner wallet to perform the initial publishing and minting.
    • Transfer all minted tokens, remaining UpgradeCaps, etc., to the treasury (e.g., a multisig address).
    • Alternatively, prepare the multi-sig account first and do the publishing directly with it, as it is shown here.
    • Execute other transactions through multisig address so that the origin for these transfers is the multisig address, not the burner wallet.
  2. UpgradeCap and TreasuryCap management
    • For tokens with fixed supply:
      • Mint the entire supply at the Token Generation Event (TGE).
      • Wrap the TreasuryCap and make it unusable for certain actions (like minting) to ensure integrity.
    • For dynamic supply tokens:
      • Evaluate the need for minting based on the specific tokenomics.
      • Wrap the TreasuryCap to make it usable on certain actions under pre-defined conditions
    • Burn the token's UpgradeCap to ensure package integrity and transparency
    • For the tokenomics/staking, since it's advisable to be implemented in a separate package, we can keep the UpgradeCap
    • Multisig solution: Use a multi-signature solution to handle the TreasuryCap and UpgradeCap. Recommended multisig setups to ensure safety:
      1. Multisig (3 of 5) for UpgradeCap
        • 1 AWS KMS/ Cloud KMS
        • 2 Ledger
        • 1 Yubikey
        • 1 ZkLogin address
      2. Multisig (4 of 6) - treasury / admin cap holder
        • 1 GCP KMS
        • 1 AWS KMS
        • 2 Ledger
        • 1 Hot Wallet
        • 1 Yubikey
    • Quorum Approach: Implement a quorum approach with external voters (e.g., auditors, community) controlling upgrades.
  3. Token distribution and management
    • Minted tokens should be managed securely, through multisig accounts or other multisig wallet solutions like MSafe or StreamFlow.
    • You can use treasury management services like MPay for vesting schedules.
    • Plan for providing liquidity to Centralized Exchanges (CEXs).
  4. Coin metadata
    • Being careful on the CoinMetadata since it needs to be shared or frozen so that the coin can register to different protocols.
    • If the CoinMetadata will get frozen, ensure the image_url is served from a domain owned and controlled by the publisher

Token listing process

For Sui Wallet:

  • By default, tokens are unrecognized. Recognized tokens:
  • Appear at the top of your asset list in Sui Wallet (if balance > 0).
  • Unrecognized tokens are automatically collapsed.
  • Have a USD equivalent balance, provided this information is available via Coingecko and/or Cetus. For explorers:
  • SuiVision: Sui Request Form for Listing
  • Suiscan: Coin Submit Form for Listing

Multisig setup guide

Overview

Assuming a custom coin named $MYCOIN to be launched on Sui. The primary goals of the launch include deploying the coin on Sui mainnet, managing the treasury through a multisig account, distributing it to defined shareholders, and integrating it with Sui wallet and an explorer.

Pre-requisites

  • Sui CLI: Install the Sui Command Line Interface (CLI).
  • SUI Coin: Prepare some (~10) SUI coins for gas fees.
  • Publish Modules: Follow the setup instructions to publish your modules.

Step 1: Create Sui account

Generate Sui addresses and keys using the command:

$ sui client new-address ed25519
tip

You can also create and use a key using AWS KMS. Follow the steps to create a key using KMS key, select Asymmetric as the key type and ECC_SECG_P256K1 for the key spec. https://docs.aws.amazon.com/kms/latest/developerguide/asymm-create-key.html#create-asymmetric-keys-console

Step 2: Get keys from Sui keystore

List the signatures using:

$ sui keytool list --json

The response resembles the following, but displays actual addresses, keys, and peer IDs:

[
{
"alias": "elegant-sphene",
"suiAddress": "<SUI-ADDRESS-1>",
"publicBase64Key": "<PUBLIC-KEY-1>",
"keyScheme": "ed25519",
"flag": 0,
"peerId": "<PEER-ID-1>"
},
{
"alias": "inspiring-topaz",
"suiAddress": "<SUI-ADDRESS-2>",
"publicBase64Key": "<PUBLIC-KEY-2>",
"keyScheme": "ed25519",
"flag": 0,
"peerId": "<PEER-ID-2>"
},
{
"alias": "amazing-emerald",
"suiAddress": "<SUI-ADDRESS-3>",
"publicBase64Key": "<PUBLIC-KEY-3>",
"keyScheme": "ed25519",
"flag": 0,
"peerId": "<PEER-ID-3>"
}
]
info

Get a public key from AWS KMS. Execute runGetPublicKey on the following script to get a public key on the format of Sui. https://gist.github.com/1-4200/3fbd79da289a54d3687326c61823e689#file-kms-sigining-ts-L264. Do not forget to declare the necessary AWS-related environment variables to run the script.

Step 3: Create and set multisig address

To create a multisig address, input a list of public keys to use for the multisig address and a list of their corresponding weights and the threshold (replacing <VARIABLES> with actual values).

info

A setup of two out of three signers is typically considered secure. However, to strengthen security measures, we suggest diversifying the types of signers involved. Including additional types such as a cloud signer, like AWS KMS, can provide enhanced protection, especially for long-term usage. Solely relying on hot wallet keys for multisig may entail security risks.

Generate a multisig address using:

$ sui keytool multi-sig-address --pks <PUBLIC-KEY-ED25519> <PUBLIC-KEY-ED25519> <PUBLIC-KEY-ED25519> --weights 1 1 1 --threshold 2 --json

The response resembles the following:

{
"multisigAddress": "<MULTISIG-ADDRESS>",
"multisig": [
{
"address": "<SUI-ADDRESS-1>",
"publicBase64Key": "<PUBLIC-KEY-1>",
"weight": 1
},
{
"address": "<SUI-ADDRESS-2>",
"publicBase64Key": "<PUBLIC-KEY-2>",
"weight": 1
},
{
"address": "<SUI-ADDRESS-3>",
"publicBase64Key": "<PUBLIC-KEY-3>",
"weight": 1
}
]
}

Set multisig address as active

sui client switch --address <MULTISIG-ADDRESS>

Step 4: Transfer SUI coin to multisig address

Transfer a certain amount of SUI Coins for gas fees from your Sui Wallet, Sui CLI, CEX or any other account to a multisig address. Check if the multisig address has the amount you transferred.

$ sui client gas --json
[
{
"gasCoinId": "0xa8eaedaaa86e3d7bef2d844b22252e24e0bd83289b24970f831c4ec127f888be",
"mistBalance": 4000000000,
"suiBalance": "4.00"
}
]

Step 5: Serialize publish transaction for publishing your modules

Navigate to the repository directory and serialize the publish transaction:

cd <path-to-repo>
sui client publish --serialize-unsigned-transaction

The response resembles the following:

UPDATING GIT DEPENDENCY https://github.com/MystenLabs/sui.git
INCLUDING DEPENDENCY Sui
INCLUDING DEPENDENCY MoveStdlib
BUILDING <your_project_name>
Successfully verified dependencies on-chain against source.
<TX-BYTES>

Step 6: Sign the transaction

Sign the transaction with ≥k keys:

$ sui keytool sign --address <SUI-ADDRESS-1> --data <TX_BYTES> --json
{
"suiAddress": "<SUI-ADDRESS-1>",
"rawTxData": "<TX-BYTES>",
...
"suiSignature": "<SIGNATURE-1>"
}
$ sui keytool sign --address <SUI-ADDRESS-2> --data <TX_BYTES> --json
{
"suiAddress": "<SUI-ADDRESS-2>",
"rawTxData": "<TX-BYTES>",
...
"suiSignature": "<SIGNATURE-2>"
}
info

Sign the transaction with AWS KMS key. If you wish to include addresses generated by AWS KMS in your multisig, create a signature through the script below on runSignTxBytes. https://gist.github.com/1-4200/3fbd79da289a54d3687326c61823e689#file-kms-sigining-ts-L263 Do not forget to declare the necessary environment variables (AWS-related, TX_BYTES) to run the script.

Step 7: Combine signature

Combine the signatures using:

$ sui keytool multi-sig-combine-partial-sig --pks <PUBLIC-KEY-1> <PUBLIC-KEY-2> <PUBLIC-KEY-3> --weights 1 1 1 --threshold 2 --sigs <SIGNATURE-1> <SIGNATURE-2>

multisig address: <MULTISIG-ADDRESS> # Informational
multisig parsed: <HUMAN-READABLE-STRUCT> # Informational
multisig serialized: <SERIALIZED-MULTISIG>

You need only the signatures of the participating signers whose sum of weights >=k. You must provide all public keys and their weights, and the threshold that defined the multisig address.

Step 8: Execute the transaction

Execute the transaction using the combined signature:

$ sui client execute-signed-tx --tx-bytes <TX_BYTES> --signatures <SERIALIZED-MULTISIG> --json
Click to open

Example output of the execute-signed-tx command.

{
"digest": "LyCucbaARVLcCL8EPb27Bk5zWAjghdqAc5jVaeEmSSU",
"transaction": {
"data": {
"messageVersion": "v1",
"transaction": {
"kind": "ProgrammableTransaction",
"inputs": [
{
"type": "pure",
"valueType": "address",
"value": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68"
}
],
"transactions": [
{
"Publish": [
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x0000000000000000000000000000000000000000000000000000000000000002"
]
},
{
"TransferObjects": [
[
{
"Result": 0
}
],
{
"Input": 0
}
]
}
]
},
"sender": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68",
"gasData": {
"payment": [
{
"objectId": "0x0610d6a78501b689300e5d1fc785667f729edd75675ed0b5f9391cee9152aded",
"version": 2,
"digest": "ZZrGvm4qqhs11w5iARTqmxvEwyvg6d12dSC2Ew1CY5y"
}
],
"owner": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68",
"price": "1000",
"budget": "21980400"
}
},
"txSignatures": [
"AIPLM4AVdyMChc5iThoOd37T3LR6u7XLQQuqx2HZcIcwIWvPZaCwDDWxOO87l+xt0e4wxS9cKW+ZGY1gwKm9hwGgoGXnNiF3adQSrq4+y8KWkCWmum6jpYnGZvYQ4FB8Vg=="
]
},
"effects": {
"messageVersion": "v1",
"status": {
"status": "success"
},
"executedEpoch": "1",
"gasUsed": {
"computationCost": "1000000",
"storageCost": "19980400",
"storageRebate": "978120",
"nonRefundableStorageFee": "9880"
},
"modifiedAtVersions": [
{
"objectId": "0x0610d6a78501b689300e5d1fc785667f729edd75675ed0b5f9391cee9152aded",
"sequenceNumber": "2"
}
],
"transactionDigest": "LyCucbaARVLcCL8EPb27Bk5zWAjghdqAc5jVaeEmSSU",
"created": [
{
"owner": "Immutable",
"reference": {
"objectId": "0x00e0ebe33cd95b7084acc08c56e3b93df2f2f847545b83eb5cd00e638eb0b800",
"version": 1,
"digest": "21WwdEYAUapR4UmPF3A8wWaqnsmXBUfLmMxb6ehzu83u"
}
},
{
"owner": "Immutable",
"reference": {
"objectId": "0x2ce11233569304f64f96c3dbf8a1aeb99a0d2d420f0a84092166ac5d50d6087f",
"version": 3,
"digest": "CKFPxn81q8GxQsaQq3T5LNWtE6enQQ1mmwdLRUe2ntrw"
}
},
{
"owner": "Immutable",
"reference": {
"objectId": "0x6b0feae03901037f3db1f18b694b5d18197e74906579823b9958cbdbf6f87278",
"version": 3,
"digest": "2UpNB69ZBqR9GsQJqfz4jyc5yx9FEvTFsLMEiHK4kJFi"
}
},
{
"owner": {
"AddressOwner": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68"
},
"reference": {
"objectId": "0x6fbd871137808ba4ea610fa302fa0943c83f67a8f5a6b0468ff3288303392c57",
"version": 3,
"digest": "fdBKCwEEqxk5MwjsVpZ4SwYMkV6ehTEtXjGHbikKYsF"
}
},
{
"owner": "Immutable",
"reference": {
"objectId": "0x737cad1d42af9a3ce80d737b1eca05faa8f040667ce63c7b8b785beb8eee0cc9",
"version": 3,
"digest": "CMStx1LeqCBRsajPx4v4fp7FSDW4NMYsk1jnx1nuQXEj"
}
},
{
"owner": {
"AddressOwner": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68"
},
"reference": {
"objectId": "0xdc3a30681099a3121adb4d6a6a1ab0901872bccf040b699acb8fa5b3897bc3f6",
"version": 3,
"digest": "GxkGYWT6GvZapMm8phePSTYiAENwfqzcdbUMNjTJbabS"
}
},
{
"owner": {
"AddressOwner": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68"
},
"reference": {
"objectId": "0xf7c9802c55fccd299b68d201f68d3c7165fe0040d30aa6b01f889ce024f132f4",
"version": 3,
"digest": "AN9tG1omyRPaKEtsPh3S9iwnThWFuvMgsXsp9oZsGqXK"
}
}
],
"mutated": [
{
"owner": {
"AddressOwner": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68"
},
"reference": {
"objectId": "0x0610d6a78501b689300e5d1fc785667f729edd75675ed0b5f9391cee9152aded",
"version": 3,
"digest": "AyA5SNDgF9J1YabEzhFsgEcFbUpNReWs6G7GfR7z9kuZ"
}
}
],
"gasObject": {
"owner": {
"AddressOwner": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68"
},
"reference": {
"objectId": "0x0610d6a78501b689300e5d1fc785667f729edd75675ed0b5f9391cee9152aded",
"version": 3,
"digest": "AyA5SNDgF9J1YabEzhFsgEcFbUpNReWs6G7GfR7z9kuZ"
}
},
"dependencies": [
"43xRGMCLDNyNxfCCRwyTd5A9d1JEXMqgjR73rSdxP5pp",
"9YFcEEL2UYQpC8jujNzT2Y4cskrbSpTn9VZftEv5xFa9"
]
},
"events": [],
"objectChanges": [
{
"type": "mutated",
"sender": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68",
"owner": {
"AddressOwner": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68"
},
"objectType": "0x2::coin::Coin<0x2::sui::SUI>",
"objectId": "0x0610d6a78501b689300e5d1fc785667f729edd75675ed0b5f9391cee9152aded",
"version": "3",
"previousVersion": "2",
"digest": "AyA5SNDgF9J1YabEzhFsgEcFbUpNReWs6G7GfR7z9kuZ"
},
{
"type": "published",
"packageId": "0x00e0ebe33cd95b7084acc08c56e3b93df2f2f847545b83eb5cd00e638eb0b800",
"version": "1",
"digest": "21WwdEYAUapR4UmPF3A8wWaqnsmXBUfLmMxb6ehzu83u",
"modules": [
"e4c"
]
},
{
"type": "created",
"sender": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68",
"owner": "Immutable",
"objectType": "0x2::coin::CoinMetadata<0x00e0ebe33cd95b7084acc08c56e3b93df2f2f847545b83eb5cd00e638eb0b800::e4c::E4C>",
"objectId": "0x2ce11233569304f64f96c3dbf8a1aeb99a0d2d420f0a84092166ac5d50d6087f",
"version": "3",
"digest": "CKFPxn81q8GxQsaQq3T5LNWtE6enQQ1mmwdLRUe2ntrw"
},
{
"type": "created",
"sender": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68",
"owner": "Immutable",
"objectType": "0x2::coin::RegulatedCoinMetadata<0x00e0ebe33cd95b7084acc08c56e3b93df2f2f847545b83eb5cd00e638eb0b800::e4c::E4C>",
"objectId": "0x6b0feae03901037f3db1f18b694b5d18197e74906579823b9958cbdbf6f87278",
"version": "3",
"digest": "2UpNB69ZBqR9GsQJqfz4jyc5yx9FEvTFsLMEiHK4kJFi"
},
{
"type": "created",
"sender": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68",
"owner": {
"AddressOwner": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68"
},
"objectType": "0x2::coin::DenyCap<0x00e0ebe33cd95b7084acc08c56e3b93df2f2f847545b83eb5cd00e638eb0b800::e4c::E4C>",
"objectId": "0x6fbd871137808ba4ea610fa302fa0943c83f67a8f5a6b0468ff3288303392c57",
"version": "3",
"digest": "fdBKCwEEqxk5MwjsVpZ4SwYMkV6ehTEtXjGHbikKYsF"
},
{
"type": "created",
"sender": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68",
"owner": "Immutable",
"objectType": "0x00e0ebe33cd95b7084acc08c56e3b93df2f2f847545b83eb5cd00e638eb0b800::e4c::E4CTotalSupply",
"objectId": "0x737cad1d42af9a3ce80d737b1eca05faa8f040667ce63c7b8b785beb8eee0cc9",
"version": "3",
"digest": "CMStx1LeqCBRsajPx4v4fp7FSDW4NMYsk1jnx1nuQXEj"
},
{
"type": "created",
"sender": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68",
"owner": {
"AddressOwner": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68"
},
"objectType": "0x2::coin::Coin<0x00e0ebe33cd95b7084acc08c56e3b93df2f2f847545b83eb5cd00e638eb0b800::e4c::E4C>",
"objectId": "0xdc3a30681099a3121adb4d6a6a1ab0901872bccf040b699acb8fa5b3897bc3f6",
"version": "3",
"digest": "GxkGYWT6GvZapMm8phePSTYiAENwfqzcdbUMNjTJbabS"
},
{
"type": "created",
"sender": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68",
"owner": {
"AddressOwner": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68"
},
"objectType": "0x2::package::UpgradeCap",
"objectId": "0xf7c9802c55fccd299b68d201f68d3c7165fe0040d30aa6b01f889ce024f132f4",
"version": "3",
"digest": "AN9tG1omyRPaKEtsPh3S9iwnThWFuvMgsXsp9oZsGqXK"
}
],
"balanceChanges": [
{
"owner": {
"AddressOwner": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68"
},
"coinType": "0x2::sui::SUI",
"amount": "-20002280"
},
{
"owner": {
"AddressOwner": "0x51b53d828382b39c820694f4c601d1f413e68b1d963e735aef6637fe270d4d68"
},
"coinType": "0x00e0ebe33cd95b7084acc08c56e3b93df2f2f847545b83eb5cd00e638eb0b800::e4c::E4C",
"amount": "100000000000"
}
],
"confirmedLocalExecution": true
}

Coin distribution

Distribute $MYCOIN coins from the multisig address to shareholders and CEXs as needed.

Serialize transactions

Serialize any transaction like the transfer transaction and follow the same process from Step 6. This section demonstrates how to use an object that belongs to a multisig address and serialize a transfer to be signed. The tx_bytes value can be any serialized transaction data where the sender is the multisig address. Use the --serialize-unsigned-transaction flag for supported commands in sui client -h (publish, upgrade, call, transfer, transfer-sui, pay, pay-all-sui, pay-sui, split, merge-coin) to output the Base64 encoded transaction bytes.

sui client transfer --to <SUI-ADDRESS> --object-id <OBJECT-ID> --gas-budget <GAS-AMOUNT> --serialize-unsigned-transaction

Raw tx_bytes to execute: <TX_BYTES>

The go-to checklist for coin launch

The go-to checklist for coin launch is a comprehensive and easy-to-follow checklist designed to ensure a smooth and successful launch of a coin on Sui blockchain.

Coin deployment and distribution

Set up a local Sui deployment environment

Determine how to manage accounts that will hold coin-related key objects

Get a certain amount of SUI coins to pay for the gas needed to deploy

Prepare a reliable RPC gateway for transaction execution and querying

Implement the coin distribution logic (fair launch, presale, airdrop, etc.)

Prepare the token distribution plan and whitelists (if applicable)

Set up a token sale platform or distribution mechanism (if applicable)

Integration and listing

Integrate the coin with popular Sui-based wallets to be listed as a recognized

Apply for recognition on popular explorers as an approved coin

Apply for listing on decentralized exchanges (DEXs)

Explore centralized exchanges (CEXs) listings