Module sui::coin_registry
Defines the system object for managing coin data in a central registry. This module provides a centralized way to store and manage metadata for all currencies in the Sui ecosystem, including their supply information, regulatory status, and metadata capabilities.
- Struct CoinRegistry
- Struct ExtraField
- Struct CurrencyKey
- Struct LegacyMetadataKey
- Struct MetadataCap
- Struct Borrow
- Struct Currency
- Struct CurrencyInitializer
- Enum SupplyState
- Enum RegulatedState
- Enum MetadataCapState
- Constants
- Function new_currency
- Function new_currency_with_otw
- Function claim_metadata_cap
- Function make_regulated
- Function make_supply_fixed_init
- Function make_supply_burn_only_init
- Function make_supply_fixed
- Function make_supply_burn_only
- Function finalize
- Function finalize_and_delete_metadata_cap
- Function finalize_registration
- Function delete_metadata_cap
- Function burn
- Function burn_balance
- Function set_name
- Function set_description
- Function set_icon_url
- Function set_treasury_cap_id
- Function migrate_legacy_metadata
- Function update_from_legacy_metadata
- Function delete_migrated_legacy_metadata
- Function migrate_regulated_state_by_metadata
- Function migrate_regulated_state_by_cap
- Function borrow_legacy_metadata
- Function return_borrowed_legacy_metadata
- Function decimals
- Function name
- Function symbol
- Function description
- Function icon_url
- Function is_metadata_cap_claimed
- Function is_metadata_cap_deleted
- Function metadata_cap_id
- Function treasury_cap_id
- Function deny_cap_id
- Function is_supply_fixed
- Function is_supply_burn_only
- Function is_regulated
- Function total_supply
- Function exists
- Function is_migrated_from_legacy
- Function to_legacy_metadata
- Function create
- Macro function finalize_impl
- Macro function migrate_legacy_metadata_impl
- Macro function is_ascii_printable
use std::address;
use std::ascii;
use std::bcs;
use std::internal;
use std::option;
use std::string;
use std::type_name;
use std::u128;
use std::vector;
use sui::accumulator;
use sui::accumulator_settlement;
use sui::address;
use sui::bag;
use sui::balance;
use sui::bcs;
use sui::coin;
use sui::config;
use sui::deny_list;
use sui::derived_object;
use sui::dynamic_field;
use sui::dynamic_object_field;
use sui::event;
use sui::funds_accumulator;
use sui::hash;
use sui::hex;
use sui::object;
use sui::party;
use sui::protocol_config;
use sui::table;
use sui::transfer;
use sui::tx_context;
use sui::types;
use sui::url;
use sui::vec_map;
use sui::vec_set;
Struct CoinRegistry
System object found at address 0xc that stores coin data for all registered coin types. This is a shared object that acts as a central registry for coin metadata, supply information, and regulatory status.
public struct CoinRegistry has key
Fields
- id: sui::object::UID
Struct ExtraField
Store only object that enables more flexible coin data registration, allowing for additional fields to be added without changing the Currency structure.
public struct ExtraField has store
Fields
- 0: std::type_name::TypeName
- 1: vector<u8>
Struct CurrencyKey
Key used to derive addresses when creating Currency<T> objects.
public struct CurrencyKey<phantom T> has copy, drop, store
Struct LegacyMetadataKey
Key used to store the legacy CoinMetadata for a Currency.
public struct LegacyMetadataKey has copy, drop, store
Struct MetadataCap
Capability object that gates metadata (name, description, icon_url, symbol) changes in the Currency. It can only be created (or claimed) once, and can be deleted to prevent changes to the Currency metadata.
public struct MetadataCap<phantom T> has key, store
Fields
- id: sui::object::UID
Struct Borrow
Potato callback for the legacy CoinMetadata borrowing.
public struct Borrow<phantom T>
Struct Currency
Currency stores metadata such as name, symbol, decimals, icon_url and description, as well as supply states (optional) and regulatory status.
public struct Currency<phantom T> has key
Fields
- id: sui::object::UID
- decimals: u8
- Number of decimal places the coin uses for display purposes.
- name: std::string::String
- Human-readable name for the coin.
- symbol: std::string::String
- Short symbol/ticker for the coin.
- description: std::string::String
- Detailed description of the coin.
- icon_url: std::string::String
- URL for the coin's icon/logo.
- supply: std::option::Option<sui::coin_registry::SupplyState<T>>
-
Current supply state of the coin (fixed supply or unknown).
Note: We're using Option because SupplyState does not have drop, meaning we cannot swap out its value at a later state. - regulated: sui::coin_registry::RegulatedState
- Regulatory status of the coin (regulated with deny cap or unknown)
- treasury_cap_id: std::option::Option<sui::object::ID>
- ID of the treasury cap for this coin type, if registered.
- metadata_cap_id: sui::coin_registry::MetadataCapState
- ID of the metadata capability for this coin type, if claimed.
- extra_fields: sui::vec_map::VecMap<std::string::String, sui::coin_registry::ExtraField>
- Additional fields for extensibility.
Struct CurrencyInitializer
Hot potato wrapper to enforce registration after "new_currency" data creation.
Destroyed in the finalize call and either transferred to the CoinRegistry
(in case of an OTW registration) or shared directly (for dynamically created
currencies).
public struct CurrencyInitializer<phantom T>
Fields
- currency: sui::coin_registry::Currency<T>
- extra_fields: sui::bag::Bag
- is_otw: bool
Enum SupplyState
Supply state marks the type of Currency Supply, which can be
- Fixed: no minting or burning;
- BurnOnly: no minting, burning is allowed;
- Unknown: flexible (supply is controlled by its TreasuryCap);
public enum SupplyState<phantom T> has store
Variants
- Variant Fixed
- Coin has a fixed supply with the given Supply object.
- 0: sui::balance::Supply<T>
- Variant BurnOnly
- Coin has a supply that can ONLY decrease.
- 0: sui::balance::Supply<T>
- Variant Unknown
- Supply information is not yet known or registered.
Enum RegulatedState
Regulated state of a coin type.
- Regulated: DenyCap exists or a RegulatedCoinMetadata used to mark currency as regulated;
- Unregulated: the currency was created without deny list;
- Unknown: the regulatory status is unknown.
public enum RegulatedState has copy, drop, store
Variants
- Variant Regulated
- Coin is regulated with a deny cap for address restrictions. allow_global_pause is None if the information is unknown (has not been migrated from DenyCapV2).
- cap: sui::object::ID
- allow_global_pause: std::option::Option<bool>
- variant: u8
- Variant Unregulated
- The coin has been created without deny list.
- Variant Unknown
-
Regulatory status is unknown.
Result of a legacy migration for that coin (from coin.move constructors)
Enum MetadataCapState
State of the MetadataCap for a single Currency.
public enum MetadataCapState has copy, drop, store
Variants
- Variant Claimed
- The metadata cap has been claimed.
- Variant Unclaimed
- The metadata cap has not been claimed.
- Variant Deleted
- The metadata cap has been claimed and then deleted.
Constants
Metadata cap already claimed
#[error]
const EMetadataCapAlreadyClaimed: vector<u8> = b"Metadata cap already claimed";
Only the system address can create the registry
#[error]
const ENotSystemAddress: vector<u8> = b"Only the system can create the registry.";
Currency for this coin type already exists
#[error]
const ECurrencyAlreadyExists: vector<u8> = b"Currency for this coin type already exists.";
Attempt to set the deny list state permissionlessly while it has already been set.
#[error]
const EDenyListStateAlreadySet: vector<u8> = b"Cannot set the deny list state as it has already been set.";
Attempt to update Currency with legacy metadata after the MetadataCap has been claimed. Updates are only allowed if the MetadataCap has not yet been claimed or deleted.
#[error]
const ECannotUpdateManagedMetadata: vector<u8> = b"Cannot update metadata whose MetadataCap has already been claimed";
Attempt to set the symbol to a non-ASCII printable character
#[error]
const EInvalidSymbol: vector<u8> = b"Symbol has to be ASCII printable";
#[error]
const EDenyCapAlreadyCreated: vector<u8> = b"Cannot claim the deny cap twice";
Attempt to migrate legacy metadata for a Currency that already exists.
#[error]
const ECurrencyAlreadyRegistered: vector<u8> = b"Currency already registered";
#[error]
const EEmptySupply: vector<u8> = b"Supply cannot be empty";
#[error]
const ESupplyNotBurnOnly: vector<u8> = b"Cannot burn on a non burn-only supply";
#[error]
const EInvariantViolation: vector<u8> = b"Code invariant violation";
#[error]
const EDeletionNotSupported: vector<u8> = b"Deleting legacy metadata is not supported";
#[error]
const ENotOneTimeWitness: vector<u8> = b"Type is expected to be OTW";
#[error]
const EBorrowLegacyMetadata: vector<u8> = b"Cannot borrow legacy metadata for migrated currency";
#[error]
const EDuplicateBorrow: vector<u8> = b"Attempt to return duplicate borrowed CoinMetadata";
Incremental identifier for regulated coin versions in the deny list.
We start from 0 in the new system, which aligns with the state of DenyCapV2.
const REGULATED_COIN_VERSION: u8 = 0;
Marker used in metadata to indicate that the currency is not migrated.
const NEW_CURRENCY_MARKER: vector<u8> = vector[105, 115, 95, 110, 101, 119, 95, 99, 117, 114, 114, 101, 110, 99, 121];
Function new_currency
Creates a new currency.
Note: This constructor has no long term difference from new_currency_with_otw.
This can be called from the module that defines T any time after it has been published.
public fun new_currency<T: key>(registry: &mut sui::coin_registry::CoinRegistry, decimals: u8, symbol: std::string::String, name: std::string::String, description: std::string::String, icon_url: std::string::String, ctx: &mut sui::tx_context::TxContext): (sui::coin_registry::CurrencyInitializer<T>, sui::coin::TreasuryCap<T>)
Function new_currency_with_otw
Creates a new currency with using an OTW as proof of uniqueness.
This is a two-step operation:
- Currency is constructed in the init function and sent to the CoinRegistry;
- Currency is promoted to a shared object in the finalize_registration call;
public fun new_currency_with_otw<T: drop>(otw: T, decimals: u8, symbol: std::string::String, name: std::string::String, description: std::string::String, icon_url: std::string::String, ctx: &mut sui::tx_context::TxContext): (sui::coin_registry::CurrencyInitializer<T>, sui::coin::TreasuryCap<T>)
Function claim_metadata_cap
Claim a MetadataCap for a coin type.
Only allowed from the owner of TreasuryCap, and only once.
Aborts if the MetadataCap has already been claimed.
Deleted MetadataCap cannot be reclaimed.
public fun claim_metadata_cap<T>(currency: &mut sui::coin_registry::Currency<T>, _: &sui::coin::TreasuryCap<T>, ctx: &mut sui::tx_context::TxContext): sui::coin_registry::MetadataCap<T>
Function make_regulated
Allows converting a currency, on init, to regulated, which creates a DenyCapV2 object, and a denylist entry. Sets regulated state to Regulated.
This action is irreversible.
public fun make_regulated<T>(init: &mut sui::coin_registry::CurrencyInitializer<T>, allow_global_pause: bool, ctx: &mut sui::tx_context::TxContext): sui::coin::DenyCapV2<T>
Function make_supply_fixed_init
Initializer function to make the supply fixed.
Aborts if Supply is 0 to enforce minting during initialization.
public fun make_supply_fixed_init<T>(init: &mut sui::coin_registry::CurrencyInitializer<T>, cap: sui::coin::TreasuryCap<T>)
Function make_supply_burn_only_init
Initializer function to make the supply burn-only.
Aborts if Supply is 0 to enforce minting during initialization.
public fun make_supply_burn_only_init<T>(init: &mut sui::coin_registry::CurrencyInitializer<T>, cap: sui::coin::TreasuryCap<T>)
Function make_supply_fixed
Freeze the supply by destroying the TreasuryCap and storing it in the Currency.
public fun make_supply_fixed<T>(currency: &mut sui::coin_registry::Currency<T>, cap: sui::coin::TreasuryCap<T>)
Function make_supply_burn_only
Make the supply BurnOnly by giving up the TreasuryCap, and allowing burning of Coins through the Currency.
public fun make_supply_burn_only<T>(currency: &mut sui::coin_registry::Currency<T>, cap: sui::coin::TreasuryCap<T>)
Function finalize
Finalize the coin initialization, returning MetadataCap
public fun finalize<T>(builder: sui::coin_registry::CurrencyInitializer<T>, ctx: &mut sui::tx_context::TxContext): sui::coin_registry::MetadataCap<T>
Function finalize_and_delete_metadata_cap
Does the same as finalize, but also deletes the MetadataCap after finalization.
public fun finalize_and_delete_metadata_cap<T>(builder: sui::coin_registry::CurrencyInitializer<T>, ctx: &mut sui::tx_context::TxContext)
Function finalize_registration
The second step in the "otw" initialization of coin metadata, that takes in the Currency<T> that was transferred from init, and transforms it in to a "derived address" shared object.
Can be performed by anyone.
public fun finalize_registration<T>(registry: &mut sui::coin_registry::CoinRegistry, currency: sui::transfer::Receiving<sui::coin_registry::Currency<T>>, _ctx: &mut sui::tx_context::TxContext)
Function delete_metadata_cap
Delete the metadata cap making further updates of Currency metadata impossible.
This action is IRREVERSIBLE, and the MetadataCap can no longer be claimed.
public fun delete_metadata_cap<T>(currency: &mut sui::coin_registry::Currency<T>, cap: sui::coin_registry::MetadataCap<T>)
Function burn
Burn the Coin if the Currency has a BurnOnly supply state.
public fun burn<T>(currency: &mut sui::coin_registry::Currency<T>, coin: sui::coin::Coin<T>)
Function burn_balance
Burn the Balance if the Currency has a BurnOnly supply state.
public fun burn_balance<T>(currency: &mut sui::coin_registry::Currency<T>, balance: sui::balance::Balance<T>)
Function set_name
Update the name of the Currency.
public fun set_name<T>(currency: &mut sui::coin_registry::Currency<T>, _: &sui::coin_registry::MetadataCap<T>, name: std::string::String)
Function set_description
Update the description of the Currency.
public fun set_description<T>(currency: &mut sui::coin_registry::Currency<T>, _: &sui::coin_registry::MetadataCap<T>, description: std::string::String)
Function set_icon_url
Update the icon URL of the Currency.
public fun set_icon_url<T>(currency: &mut sui::coin_registry::Currency<T>, _: &sui::coin_registry::MetadataCap<T>, icon_url: std::string::String)
Function set_treasury_cap_id
Register the treasury cap ID for a migrated Currency. All currencies created with new_currency or new_currency_with_otw have their treasury cap ID set during initialization.
public fun set_treasury_cap_id<T>(currency: &mut sui::coin_registry::Currency<T>, cap: &sui::coin::TreasuryCap<T>)
Function migrate_legacy_metadata
Register CoinMetadata in the CoinRegistry. This can happen only once, if the Currency did not exist yet. Further updates are possible through update_from_legacy_metadata.
public fun migrate_legacy_metadata<T>(registry: &mut sui::coin_registry::CoinRegistry, legacy: &sui::coin::CoinMetadata<T>, _ctx: &mut sui::tx_context::TxContext)
Function update_from_legacy_metadata
Update Currency from CoinMetadata if the MetadataCap is not claimed. After the MetadataCap is claimed, updates can only be made through set_* functions.
public fun update_from_legacy_metadata<T>(currency: &mut sui::coin_registry::Currency<T>, legacy: &sui::coin::CoinMetadata<T>)
Function delete_migrated_legacy_metadata
public fun delete_migrated_legacy_metadata<T>(_: &mut sui::coin_registry::Currency<T>, _: sui::coin::CoinMetadata<T>)
Function migrate_regulated_state_by_metadata
Allow migrating the regulated state by access to RegulatedCoinMetadata frozen object.
This is a permissionless operation which can be performed only once.
public fun migrate_regulated_state_by_metadata<T>(currency: &mut sui::coin_registry::Currency<T>, metadata: &sui::coin::RegulatedCoinMetadata<T>)
Function migrate_regulated_state_by_cap
Mark regulated state by showing the DenyCapV2 object for the Currency.
public fun migrate_regulated_state_by_cap<T>(currency: &mut sui::coin_registry::Currency<T>, cap: &sui::coin::DenyCapV2<T>)
Function borrow_legacy_metadata
Borrow the legacy CoinMetadata from a new Currency. To preserve the ID of the legacy CoinMetadata, we create it on request and then store it as a dynamic field for future borrows.
Borrow<T> ensures that the CoinMetadata is returned in the same transaction.
public fun borrow_legacy_metadata<T>(currency: &mut sui::coin_registry::Currency<T>, ctx: &mut sui::tx_context::TxContext): (sui::coin::CoinMetadata<T>, sui::coin_registry::Borrow<T>)
Function return_borrowed_legacy_metadata
Return the borrowed CoinMetadata and the Borrow potato to the Currency.
Note to self: Borrow requirement prevents deletion through this method.
public fun return_borrowed_legacy_metadata<T>(currency: &mut sui::coin_registry::Currency<T>, legacy: sui::coin::CoinMetadata<T>, borrow: sui::coin_registry::Borrow<T>, _ctx: &mut sui::tx_context::TxContext)
Function decimals
Get the number of decimal places for the coin type.
public fun decimals<T>(currency: &sui::coin_registry::Currency<T>): u8
Function name
Get the human-readable name of the coin.
public fun name<T>(currency: &sui::coin_registry::Currency<T>): std::string::String
Function symbol
Get the symbol/ticker of the coin.
public fun symbol<T>(currency: &sui::coin_registry::Currency<T>): std::string::String
Function description
Get the description of the coin.
public fun description<T>(currency: &sui::coin_registry::Currency<T>): std::string::String
Function icon_url
Get the icon URL for the coin.
public fun icon_url<T>(currency: &sui::coin_registry::Currency<T>): std::string::String
Function is_metadata_cap_claimed
Check if the metadata capability has been claimed for this Currency type.
public fun is_metadata_cap_claimed<T>(currency: &sui::coin_registry::Currency<T>): bool
Function is_metadata_cap_deleted
Check if the metadata capability has been deleted for this Currency type.
public fun is_metadata_cap_deleted<T>(currency: &sui::coin_registry::Currency<T>): bool
Function metadata_cap_id
Get the metadata cap ID, or none if it has not been claimed.
public fun metadata_cap_id<T>(currency: &sui::coin_registry::Currency<T>): std::option::Option<sui::object::ID>
Function treasury_cap_id
Get the treasury cap ID for this coin type, if registered.
public fun treasury_cap_id<T>(currency: &sui::coin_registry::Currency<T>): std::option::Option<sui::object::ID>
Function deny_cap_id
Get the deny cap ID for this coin type, if it's a regulated coin.
Returns None if:
- The Currency is not regulated;
- The Currency is migrated from legacy, and its regulated state has not been set;
public fun deny_cap_id<T>(currency: &sui::coin_registry::Currency<T>): std::option::Option<sui::object::ID>
Function is_supply_fixed
Check if the supply is fixed.
public fun is_supply_fixed<T>(currency: &sui::coin_registry::Currency<T>): bool
Function is_supply_burn_only
Check if the supply is burn-only.
public fun is_supply_burn_only<T>(currency: &sui::coin_registry::Currency<T>): bool
Function is_regulated
Check if the currency is regulated.
public fun is_regulated<T>(currency: &sui::coin_registry::Currency<T>): bool
Function total_supply
Get the total supply for the Currency<T> if the Supply is in fixed or burn-only state. Returns None if the SupplyState is Unknown.
public fun total_supply<T>(currency: &sui::coin_registry::Currency<T>): std::option::Option<u64>
Function exists
Check if coin data exists for the given type T in the registry.
public fun exists<T>(registry: &sui::coin_registry::CoinRegistry): bool
Function is_migrated_from_legacy
Whether the currency is migrated from legacy.
fun is_migrated_from_legacy<T>(currency: &sui::coin_registry::Currency<T>): bool
Function to_legacy_metadata
Create a new legacy CoinMetadata from a Currency.
fun to_legacy_metadata<T>(currency: &sui::coin_registry::Currency<T>, ctx: &mut sui::tx_context::TxContext): sui::coin::CoinMetadata<T>
Function create
Create and share the singleton CoinRegistry -- this function is
called exactly once, during the upgrade epoch.
Only the system address (0x0) can create the registry.
fun create(ctx: &sui::tx_context::TxContext)
Macro function finalize_impl
Internal macro to keep implementation between build and test modes.
macro fun finalize_impl<$T>($builder: sui::coin_registry::CurrencyInitializer<$T>, $ctx: &mut sui::tx_context::TxContext): (sui::coin_registry::Currency<$T>, sui::coin_registry::MetadataCap<$T>)
Macro function migrate_legacy_metadata_impl
Internal macro to keep implementation between build and test modes.
macro fun migrate_legacy_metadata_impl<$T>($registry: &mut sui::coin_registry::CoinRegistry, $legacy: &sui::coin::CoinMetadata<$T>): sui::coin_registry::Currency<$T>
Macro function is_ascii_printable
Nit: consider adding this function to std::string in the future.
macro fun is_ascii_printable($s: &std::string::String): bool