Module 0x2::coin
Defines the Coin type - platform wide representation of fungible tokens and coins. Coin can be described as a secure wrapper around Balance type.
- Resource
Coin
- Resource
CoinMetadata
- Resource
RegulatedCoinMetadata
- Resource
TreasuryCap
- Resource
DenyCapV2
- Struct
CurrencyCreated
- Resource
DenyCap
- Constants
- Function
total_supply
- Function
treasury_into_supply
- Function
supply_immut
- Function
supply_mut
- Function
value
- Function
balance
- Function
balance_mut
- Function
from_balance
- Function
into_balance
- Function
take
- Function
put
- Function
join
- Function
split
- Function
divide_into_n
- Function
zero
- Function
destroy_zero
- Function
create_currency
- Function
create_regulated_currency_v2
- Function
mint
- Function
mint_balance
- Function
burn
- Function
deny_list_v2_add
- Function
deny_list_v2_remove
- Function
deny_list_v2_contains_current_epoch
- Function
deny_list_v2_contains_next_epoch
- Function
deny_list_v2_enable_global_pause
- Function
deny_list_v2_disable_global_pause
- Function
deny_list_v2_is_global_pause_enabled_current_epoch
- Function
deny_list_v2_is_global_pause_enabled_next_epoch
- Function
mint_and_transfer
- Function
update_name
- Function
update_symbol
- Function
update_description
- Function
update_icon_url
- Function
get_decimals
- Function
get_name
- Function
get_symbol
- Function
get_description
- Function
get_icon_url
- Function
supply
- Function
create_regulated_currency
- Function
deny_list_add
- Function
deny_list_remove
- Function
deny_list_contains
use 0x1::ascii;
use 0x1::option;
use 0x1::string;
use 0x1::type_name;
use 0x2::balance;
use 0x2::deny_list;
use 0x2::object;
use 0x2::transfer;
use 0x2::tx_context;
use 0x2::types;
use 0x2::url;
Resource Coin
A coin of type T worth value. Transferable and storable
struct Coin<T> has store, key
Fields
- id: object::UID
- balance: balance::Balance<T>
Resource CoinMetadata
Each Coin type T created through create_currency function will have a
unique instance of CoinMetadata
struct CoinMetadata<T> has store, key
Fields
- id: object::UID
- decimals: u8
- Number of decimal places the coin uses. A coin with value N and decimals D should be shown as N / 10^D E.g., a coin with value 7002 and decimals 3 should be displayed as 7.002 This is metadata for display usage only.
- name: string::String
- Name for the token
- symbol: ascii::String
- Symbol for the token
- description: string::String
- Description of the token
- icon_url: option::Option<url::Url>
- URL for the token logo
Resource RegulatedCoinMetadata
Similar to CoinMetadata, but created only for regulated coins that use the DenyList. This object is always immutable.
struct RegulatedCoinMetadata<T> has key
Fields
- id: object::UID
- coin_metadata_object: object::ID
- The ID of the coin's CoinMetadata object.
- deny_cap_object: object::ID
- The ID of the coin's DenyCap object.
Resource TreasuryCap
Capability allowing the bearer to mint and burn coins of type T. Transferable
struct TreasuryCap<T> has store, key
Fields
- id: object::UID
- total_supply: balance::Supply<T>
Resource DenyCapV2
struct DenyCapV2<T> has store, key
Fields
- id: object::UID
- allow_global_pause: bool
Struct CurrencyCreated
struct CurrencyCreated<T> has copy, drop
Fields
- decimals: u8
Resource DenyCap
Capability allowing the bearer to freeze addresses, preventing those addresses from interacting with the coin as an input to a transaction.
struct DenyCap<T> has store, key
Fields
- id: object::UID
Constants
Trying to split a coin more times than its balance allows.
const ENotEnough: u64 = 2;
The index into the deny list vector for the sui::coin::Coin type.
const DENY_LIST_COIN_INDEX: u64 = 0;
A type passed to create_supply is not a one-time witness.
const EBadWitness: u64 = 0;
const EGlobalPauseNotAllowed: u64 = 3;
Invalid arguments are passed to a function.
const EInvalidArg: u64 = 1;
Function total_supply
Return the total number of T's in circulation.
public fun total_supply<T>(cap: &coin::TreasuryCap<T>): u64
Implementation
public fun total_supply<T>(cap: &TreasuryCap<T>): u64 {
balance::supply_value(&cap.total_supply)
}
Function treasury_into_supply
Unwrap TreasuryCap getting the Supply.
Operation is irreversible. Supply cannot be converted into a TreasuryCap due to different security guarantees (TreasuryCap can be created only once for a type)
public fun treasury_into_supply<T>(treasury: coin::TreasuryCap<T>): balance::Supply<T>
Implementation
public fun treasury_into_supply<T>(treasury: TreasuryCap<T>): Supply<T> {
let TreasuryCap { id, total_supply } = treasury;
id.delete();
total_supply
}
Function supply_immut
Get immutable reference to the treasury's Supply.
public fun supply_immut<T>(treasury: &coin::TreasuryCap<T>): &balance::Supply<T>
Implementation
public fun supply_immut<T>(treasury: &TreasuryCap<T>): &Supply<T> {
&treasury.total_supply
}
Function supply_mut
Get mutable reference to the treasury's Supply.
public fun supply_mut<T>(treasury: &mut coin::TreasuryCap<T>): &mut balance::Supply<T>
Implementation
public fun supply_mut<T>(treasury: &mut TreasuryCap<T>): &mut Supply<T> {
&mut treasury.total_supply
}
Function value
Public getter for the coin's value
public fun value<T>(self: &coin::Coin<T>): u64
Function balance
Get immutable reference to the balance of a coin.
public fun balance<T>(coin: &coin::Coin<T>): &balance::Balance<T>
Function balance_mut
Get a mutable reference to the balance of a coin.
public fun balance_mut<T>(coin: &mut coin::Coin<T>): &mut balance::Balance<T>
Implementation
public fun balance_mut<T>(coin: &mut Coin<T>): &mut Balance<T> {
&mut coin.balance
}
Function from_balance
Wrap a balance into a Coin to make it transferable.
public fun from_balance<T>(balance: balance::Balance<T>, ctx: &mut tx_context::TxContext): coin::Coin<T>
Implementation
public fun from_balance<T>(balance: Balance<T>, ctx: &mut TxContext): Coin<T> {
Coin { id: object::new(ctx), balance }
}
Function into_balance
Destruct a Coin wrapper and keep the balance.
public fun into_balance<T>(coin: coin::Coin<T>): balance::Balance<T>
Implementation
Function take
Take a Coin worth of value from Balance. Aborts if value > balance.value
public fun take<T>(balance: &mut balance::Balance<T>, value: u64, ctx: &mut tx_context::TxContext): coin::Coin<T>
Implementation
Function put
Put a Coin<T> to the Balance<T>.
public fun put<T>(balance: &mut balance::Balance<T>, coin: coin::Coin<T>)
Implementation
Function join
Consume the coin c and add its value to self. Aborts if c.value + self.value > U64_MAX
public entry fun join<T>(self: &mut coin::Coin<T>, c: coin::Coin<T>)
Implementation
Function split
Split coin self to two coins, one with balance split_amount, and the remaining balance is left is self.
public fun split<T>(self: &mut coin::Coin<T>, split_amount: u64, ctx: &mut tx_context::TxContext): coin::Coin<T>
Implementation
Function divide_into_n
Split coin self into n - 1 coins with equal balances. The remainder is left in self. Return newly created coins.
public fun divide_into_n<T>(self: &mut coin::Coin<T>, n: u64, ctx: &mut tx_context::TxContext): vector<coin::Coin<T>>
Implementation
public fun divide_into_n<T>(
self: &mut Coin<T>, n: u64, ctx: &mut TxContext
): vector<Coin<T>> {
assert!(n > 0, EInvalidArg);
assert!(n <= value(self), ENotEnough);
let mut vec = vector[];
let mut i = 0;
let split_amount = value(self) / n;
while (i < n - 1) {
vec.push_back(self.split(split_amount, ctx));
i = i + 1;
};
vec
}
Function zero
Make any Coin with a zero value. Useful for placeholding bids/payments or preemptively making empty balances.
public fun zero<T>(ctx: &mut tx_context::TxContext): coin::Coin<T>
Implementation
public fun zero<T>(ctx: &mut TxContext): Coin<T> {
Coin { id: object::new(ctx), balance: balance::zero() }
}
Function destroy_zero
Destroy a coin with value zero
public fun destroy_zero<T>(c: coin::Coin<T>)
Implementation
public fun destroy_zero<T>(c: Coin<T>) {
let Coin { id, balance } = c;
id.delete();
balance.destroy_zero()
}
Function create_currency
Create a new currency type T as and return the TreasuryCap for T to the caller. Can only be called with a one-time-witness type, ensuring that there's only one TreasuryCap per T.
public fun create_currency<T: drop>(witness: T, decimals: u8, symbol: vector<u8>, name: vector<u8>, description: vector<u8>, icon_url: option::Option<url::Url>, ctx: &mut tx_context::TxContext): (coin::TreasuryCap<T>, coin::CoinMetadata<T>)
Implementation
public fun create_currency<T: drop>(
witness: T,
decimals: u8,
symbol: vector<u8>,
name: vector<u8>,
description: vector<u8>,
icon_url: Option<Url>,
ctx: &mut TxContext
): (TreasuryCap<T>, CoinMetadata<T>) {
// Make sure there's only one instance of the type T
assert!(sui::types::is_one_time_witness(&witness), EBadWitness);
(
TreasuryCap {
id: object::new(ctx),
total_supply: balance::create_supply(witness)
},
CoinMetadata {
id: object::new(ctx),
decimals,
name: string::utf8(name),
symbol: ascii::string(symbol),
description: string::utf8(description),
icon_url
}
)
}
Function create_regulated_currency_v2
public fun create_regulated_currency_v2<T: drop>(witness: T, decimals: u8, symbol: vector<u8>, name: vector<u8>, description: vector<u8>, icon_url: option::Option<url::Url>, allow_global_pause: bool, ctx: &mut tx_context::TxContext): (coin::TreasuryCap<T>, coin::DenyCapV2<T>, coin::CoinMetadata<T>)
Implementation
public fun create_regulated_currency_v2<T: drop>(
witness: T,
decimals: u8,
symbol: vector<u8>,
name: vector<u8>,
description: vector<u8>,
icon_url: Option<Url>,
allow_global_pause: bool,
ctx: &mut TxContext,
): (TreasuryCap<T>, DenyCapV2<T>, CoinMetadata<T>) {
let (treasury_cap, metadata) = create_currency(
witness,
decimals,
symbol,
name,
description,
icon_url,
ctx
);
let deny_cap = DenyCapV2 {
id: object::new(ctx),
allow_global_pause,
};
transfer::freeze_object(RegulatedCoinMetadata<T> {
id: object::new(ctx),
coin_metadata_object: object::id(&metadata),
deny_cap_object: object::id(&deny_cap),
});
(treasury_cap, deny_cap, metadata)
}
Function mint
Create a coin worth value and increase the total supply in cap accordingly.
public fun mint<T>(cap: &mut coin::TreasuryCap<T>, value: u64, ctx: &mut tx_context::TxContext): coin::Coin<T>
Implementation
public fun mint<T>(
cap: &mut TreasuryCap<T>, value: u64, ctx: &mut TxContext,
): Coin<T> {
Coin {
id: object::new(ctx),
balance: cap.total_supply.increase_supply(value)
}
}
Function mint_balance
Mint some amount of T as a Balance and increase the total supply in cap accordingly. Aborts if value + cap.total_supply >= U64_MAX
public fun mint_balance<T>(cap: &mut coin::TreasuryCap<T>, value: u64): balance::Balance<T>
Implementation
public fun mint_balance<T>(
cap: &mut TreasuryCap<T>, value: u64
): Balance<T> {
cap.total_supply.increase_supply(value)
}
Function burn
Destroy the coin c and decrease the total supply in cap accordingly.
public entry fun burn<T>(cap: &mut coin::TreasuryCap<T>, c: coin::Coin<T>): u64
Implementation
Function deny_list_v2_add
public fun deny_list_v2_add<T>(deny_list: &mut deny_list::DenyList, _deny_cap: &mut coin::DenyCapV2<T>, addr: address, ctx: &mut tx_context::TxContext)
Implementation
public fun deny_list_v2_add<T>(
deny_list: &mut DenyList,
_deny_cap: &mut DenyCapV2<T>,
addr: address,
ctx: &mut TxContext,
) {
let ty = type_name::get_with_original_ids<T>().into_string().into_bytes();
deny_list.v2_add(DENY_LIST_COIN_INDEX, ty, addr, ctx)
}
Function deny_list_v2_remove
public fun deny_list_v2_remove<T>(deny_list: &mut deny_list::DenyList, _deny_cap: &mut coin::DenyCapV2<T>, addr: address, ctx: &mut tx_context::TxContext)
Implementation
public fun deny_list_v2_remove<T>(
deny_list: &mut DenyList,
_deny_cap: &mut DenyCapV2<T>,
addr: address,
ctx: &mut TxContext,
) {
let ty = type_name::get_with_original_ids<T>().into_string().into_bytes();
deny_list.v2_remove(DENY_LIST_COIN_INDEX, ty, addr, ctx)
}
Function deny_list_v2_contains_current_epoch
public fun deny_list_v2_contains_current_epoch<T>(deny_list: &deny_list::DenyList, addr: address, ctx: &tx_context::TxContext): bool
Implementation
public fun deny_list_v2_contains_current_epoch<T>(
deny_list: &DenyList,
addr: address,
ctx: &TxContext,
): bool {
let ty = type_name::get_with_original_ids<T>().into_string().into_bytes();
deny_list.v2_contains_current_epoch(DENY_LIST_COIN_INDEX, ty, addr, ctx)
}
Function deny_list_v2_contains_next_epoch
public fun deny_list_v2_contains_next_epoch<T>(deny_list: &deny_list::DenyList, addr: address): bool
Implementation
public fun deny_list_v2_contains_next_epoch<T>(
deny_list: &DenyList,
addr: address,
): bool {
let ty = type_name::get_with_original_ids<T>().into_string().into_bytes();
deny_list.v2_contains_next_epoch(DENY_LIST_COIN_INDEX, ty, addr)
}
Function deny_list_v2_enable_global_pause
public fun deny_list_v2_enable_global_pause<T>(deny_list: &mut deny_list::DenyList, deny_cap: &mut coin::DenyCapV2<T>, ctx: &mut tx_context::TxContext)
Implementation
public fun deny_list_v2_enable_global_pause<T>(
deny_list: &mut DenyList,
deny_cap: &mut DenyCapV2<T>,
ctx: &mut TxContext,
) {
assert!(deny_cap.allow_global_pause, EGlobalPauseNotAllowed);
let ty = type_name::get_with_original_ids<T>().into_string().into_bytes();
deny_list.v2_enable_global_pause(DENY_LIST_COIN_INDEX, ty, ctx)
}
Function deny_list_v2_disable_global_pause
public fun deny_list_v2_disable_global_pause<T>(deny_list: &mut deny_list::DenyList, deny_cap: &mut coin::DenyCapV2<T>, ctx: &mut tx_context::TxContext)
Implementation
public fun deny_list_v2_disable_global_pause<T>(
deny_list: &mut DenyList,
deny_cap: &mut DenyCapV2<T>,
ctx: &mut TxContext,
) {
assert!(deny_cap.allow_global_pause, EGlobalPauseNotAllowed);
let ty = type_name::get_with_original_ids<T>().into_string().into_bytes();
deny_list.v2_disable_global_pause(DENY_LIST_COIN_INDEX, ty, ctx)
}
Function deny_list_v2_is_global_pause_enabled_current_epoch
public fun deny_list_v2_is_global_pause_enabled_current_epoch<T>(deny_list: &deny_list::DenyList, ctx: &tx_context::TxContext): bool
Implementation
public fun deny_list_v2_is_global_pause_enabled_current_epoch<T>(
deny_list: &DenyList,
ctx: &TxContext,
): bool {
let ty = type_name::get_with_original_ids<T>().into_string().into_bytes();
deny_list.v2_is_global_pause_enabled_current_epoch(DENY_LIST_COIN_INDEX, ty, ctx)
}
Function deny_list_v2_is_global_pause_enabled_next_epoch
public fun deny_list_v2_is_global_pause_enabled_next_epoch<T>(deny_list: &deny_list::DenyList): bool
Implementation
public fun deny_list_v2_is_global_pause_enabled_next_epoch<T>(
deny_list: &DenyList,
): bool {
let ty = type_name::get_with_original_ids<T>().into_string().into_bytes();
deny_list.v2_is_global_pause_enabled_next_epoch(DENY_LIST_COIN_INDEX, ty)
}
Function mint_and_transfer
Mint amount of Coin and send it to recipient. Invokes mint().
public entry fun mint_and_transfer<T>(c: &mut coin::TreasuryCap<T>, amount: u64, recipient: address, ctx: &mut tx_context::TxContext)
Implementation
public entry fun mint_and_transfer<T>(
c: &mut TreasuryCap<T>, amount: u64, recipient: address, ctx: &mut TxContext
) {
transfer::public_transfer(mint(c, amount, ctx), recipient)
}
Function update_name
Update name of the coin in CoinMetadata
public entry fun update_name<T>(_treasury: &coin::TreasuryCap<T>, metadata: &mut coin::CoinMetadata<T>, name: string::String)
Implementation
public entry fun update_name<T>(
_treasury: &TreasuryCap<T>, metadata: &mut CoinMetadata<T>, name: string::String
) {
metadata.name = name;
}
Function update_symbol
Update the symbol of the coin in CoinMetadata
public entry fun update_symbol<T>(_treasury: &coin::TreasuryCap<T>, metadata: &mut coin::CoinMetadata<T>, symbol: ascii::String)
Implementation
public entry fun update_symbol<T>(
_treasury: &TreasuryCap<T>, metadata: &mut CoinMetadata<T>, symbol: ascii::String
) {
metadata.symbol = symbol;
}
Function update_description
Update the description of the coin in CoinMetadata
public entry fun update_description<T>(_treasury: &coin::TreasuryCap<T>, metadata: &mut coin::CoinMetadata<T>, description: string::String)
Implementation
public entry fun update_description<T>(
_treasury: &TreasuryCap<T>, metadata: &mut CoinMetadata<T>, description: string::String
) {
metadata.description = description;
}
Function update_icon_url
Update the url of the coin in CoinMetadata
public entry fun update_icon_url<T>(_treasury: &coin::TreasuryCap<T>, metadata: &mut coin::CoinMetadata<T>, url: ascii::String)
Implementation
public entry fun update_icon_url<T>(
_treasury: &TreasuryCap<T>, metadata: &mut CoinMetadata<T>, url: ascii::String
) {
metadata.icon_url = option::some(url::new_unsafe(url));
}
Function get_decimals
public fun get_decimals<T>(metadata: &coin::CoinMetadata<T>): u8
Implementation
public fun get_decimals<T>(metadata: &CoinMetadata<T>): u8 {
metadata.decimals
}
Function get_name
public fun get_name<T>(metadata: &coin::CoinMetadata<T>): string::String
Implementation
public fun get_name<T>(metadata: &CoinMetadata<T>): string::String {
metadata.name
}
Function get_symbol
public fun get_symbol<T>(metadata: &coin::CoinMetadata<T>): ascii::String
Implementation
public fun get_symbol<T>(metadata: &CoinMetadata<T>): ascii::String {
metadata.symbol
}
Function get_description
public fun get_description<T>(metadata: &coin::CoinMetadata<T>): string::String
Implementation
public fun get_description<T>(metadata: &CoinMetadata<T>): string::String {
metadata.description
}
Function get_icon_url
public fun get_icon_url<T>(metadata: &coin::CoinMetadata<T>): option::Option<url::Url>
Implementation
public fun get_icon_url<T>(metadata: &CoinMetadata<T>): Option<Url> {
metadata.icon_url
}
Function supply
public fun supply<T>(treasury: &mut coin::TreasuryCap<T>): &balance::Supply<T>
Implementation
public fun supply<T>(treasury: &mut TreasuryCap<T>): &Supply<T> {
&treasury.total_supply
}
Function create_regulated_currency
This creates a new currency, via create_currency, but with an extra capability that allows for specific addresses to have their coins frozen. Those addresses cannot interact with the coin as input objects.
public fun create_regulated_currency<T: drop>(witness: T, decimals: u8, symbol: vector<u8>, name: vector<u8>, description: vector<u8>, icon_url: option::Option<url::Url>, ctx: &mut tx_context::TxContext): (coin::TreasuryCap<T>, coin::DenyCap<T>, coin::CoinMetadata<T>)
Implementation
public fun create_regulated_currency<T: drop>(
witness: T,
decimals: u8,
symbol: vector<u8>,
name: vector<u8>,
description: vector<u8>,
icon_url: Option<Url>,
ctx: &mut TxContext
): (TreasuryCap<T>, DenyCap<T>, CoinMetadata<T>) {
let (treasury_cap, metadata) = create_currency(
witness,
decimals,
symbol,
name,
description,
icon_url,
ctx
);
let deny_cap = DenyCap {
id: object::new(ctx),
};
transfer::freeze_object(RegulatedCoinMetadata<T> {
id: object::new(ctx),
coin_metadata_object: object::id(&metadata),
deny_cap_object: object::id(&deny_cap),
});
(treasury_cap, deny_cap, metadata)
}
Function deny_list_add
Adds the given address to the deny list, preventing it from interacting with the specified coin type as an input to a transaction.
public fun deny_list_add<T>(deny_list: &mut deny_list::DenyList, _deny_cap: &mut coin::DenyCap<T>, addr: address, _ctx: &mut tx_context::TxContext)
Implementation
public fun deny_list_add<T>(
deny_list: &mut DenyList,
_deny_cap: &mut DenyCap<T>,
addr: address,
_ctx: &mut TxContext
) {
let `type` =
type_name::into_string(type_name::get_with_original_ids<T>()).into_bytes();
deny_list.v1_add(
DENY_LIST_COIN_INDEX,
`type`,
addr,
)
}
Function deny_list_remove
Removes an address from the deny list. Aborts with ENotFrozen if the address is not already in the list.
public fun deny_list_remove<T>(deny_list: &mut deny_list::DenyList, _deny_cap: &mut coin::DenyCap<T>, addr: address, _ctx: &mut tx_context::TxContext)
Implementation
public fun deny_list_remove<T>(
deny_list: &mut DenyList,
_deny_cap: &mut DenyCap<T>,
addr: address,
_ctx: &mut TxContext
) {
let `type` =
type_name::into_string(type_name::get_with_original_ids<T>()).into_bytes();
deny_list.v1_remove(
DENY_LIST_COIN_INDEX,
`type`,
addr,
)
}
Function deny_list_contains
Returns true iff the given address is denied for the given coin type. It will return false if given a non-coin type.
public fun deny_list_contains<T>(deny_list: &deny_list::DenyList, addr: address): bool
Implementation
public fun deny_list_contains<T>(
deny_list: &DenyList,
addr: address,
): bool {
let name = type_name::get_with_original_ids<T>();
if (type_name::is_primitive(&name)) return false;
let `type` = type_name::into_string(name).into_bytes();
deny_list.v1_contains(DENY_LIST_COIN_INDEX, `type`, addr)
}