Module iota::coin
Defines the Coin type - platform wide representation of fungible
tokens and coins. Coin can be described as a secure wrapper around
Balance type.
use iota::address;
use iota::bag;
use iota::balance;
use iota::config;
use iota::deny_list;
use iota::dynamic_field;
use iota::dynamic_object_field;
use iota::event;
use iota::hex;
use iota::object;
use iota::transfer;
use iota::tx_context;
use iota::types;
use iota::url;
use std::address;
use std::ascii;
use std::bcs;
use std::option;
use std::string;
use std::type_name;
use std::vector;
Module Functions
pub 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: std::option::Option<iota::url::Url>, ctx: &mut iota::tx_context::TxContext): (iota::coin::TreasuryCap<T>, iota::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!(iota::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,
},
)
}
pub create_regulated_currency_v1
This creates a new currency, via create_currency, but with an extra capability that
allows for specific addresses to have their coins frozen. When an address is added to the
deny list, it is immediately unable to interact with the currency's coin as input objects.
Additionally at the start of the next epoch, they will be unable to receive the currency's
coin.
The allow_global_pause flag enables an additional API that will cause all addresses to
be denied. Note however, that this doesn't affect per-address entries of the deny list and
will not change the result of the "contains" APIs.
public fun create_regulated_currency_v1<T: drop>(witness: T, decimals: u8, symbol: vector<u8>, name: vector<u8>, description: vector<u8>, icon_url: std::option::Option<iota::url::Url>, allow_global_pause: bool, ctx: &mut iota::tx_context::TxContext): (iota::coin::TreasuryCap<T>, iota::coin::DenyCapV1<T>, iota::coin::CoinMetadata<T>)
Implementation
public fun create_regulated_currency_v1<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>, DenyCapV1<T>, CoinMetadata<T>) {
let (treasury_cap, metadata) = create_currency(
witness,
decimals,
symbol,
name,
description,
icon_url,
ctx,
);
let deny_cap = DenyCapV1 {
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)
}
pub deny_list_v1_add
Adds the given address to the deny list, preventing it from interacting with the specified coin type as an input to a transaction. Additionally at the start of the next epoch, the address will be unable to receive objects of this coin type.
public fun deny_list_v1_add<T>(deny_list: &mut iota::deny_list::DenyList, _deny_cap: &mut iota::coin::DenyCapV1<T>, addr: address, ctx: &mut iota::tx_context::TxContext)
Implementation
public fun deny_list_v1_add<T>(
deny_list: &mut DenyList,
_deny_cap: &mut DenyCapV1<T>,
addr: address,
ctx: &mut TxContext,
) {
let ty = type_name::get_with_original_ids<T>().into_string().into_bytes();
deny_list.add(DENY_LIST_COIN_INDEX, ty, addr, ctx)
}
pub deny_list_v1_contains_current_epoch
Check if the deny list contains the given address for the current epoch. Denied addresses in the current epoch will be unable to receive objects of this coin type.
public fun deny_list_v1_contains_current_epoch<T>(deny_list: &iota::deny_list::DenyList, addr: address, ctx: &iota::tx_context::TxContext): bool
Implementation
public fun deny_list_v1_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.contains_current_epoch(DENY_LIST_COIN_INDEX, ty, addr, ctx)
}
pub deny_list_v1_contains_next_epoch
Check if the deny list contains the given address for the next epoch. Denied addresses in the next epoch will immediately be unable to use objects of this coin type as inputs. At the start of the next epoch, the address will be unable to receive objects of this coin type.
public fun deny_list_v1_contains_next_epoch<T>(deny_list: &iota::deny_list::DenyList, addr: address): bool
Implementation
public fun deny_list_v1_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.contains_next_epoch(DENY_LIST_COIN_INDEX, ty, addr)
}
pub deny_list_v1_disable_global_pause
Disable the global pause for the given coin type. This will immediately allow all addresses to resume using objects of this coin type as inputs. However, receiving objects of this coin type will still be paused until the start of the next epoch.
public fun deny_list_v1_disable_global_pause<T>(deny_list: &mut iota::deny_list::DenyList, deny_cap: &mut iota::coin::DenyCapV1<T>, ctx: &mut iota::tx_context::TxContext)
Implementation
public fun deny_list_v1_disable_global_pause<T>(
deny_list: &mut DenyList,
deny_cap: &mut DenyCapV1<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.disable_global_pause(DENY_LIST_COIN_INDEX, ty, ctx)
}
pub deny_list_v1_enable_global_pause
Enable the global pause for the given coin type. This will immediately prevent all addresses from using objects of this coin type as inputs. At the start of the next epoch, all addresses will be unable to receive objects of this coin type.
public fun deny_list_v1_enable_global_pause<T>(deny_list: &mut iota::deny_list::DenyList, deny_cap: &mut iota::coin::DenyCapV1<T>, ctx: &mut iota::tx_context::TxContext)
Implementation
public fun deny_list_v1_enable_global_pause<T>(
deny_list: &mut DenyList,
deny_cap: &mut DenyCapV1<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.enable_global_pause(DENY_LIST_COIN_INDEX, ty, ctx)
}
pub deny_list_v1_is_global_pause_enabled_current_epoch
Check if the global pause is enabled for the given coin type in the current epoch.
public fun deny_list_v1_is_global_pause_enabled_current_epoch<T>(deny_list: &iota::deny_list::DenyList, ctx: &iota::tx_context::TxContext): bool
Implementation
public fun deny_list_v1_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.is_global_pause_enabled_current_epoch(DENY_LIST_COIN_INDEX, ty, ctx)
}
pub deny_list_v1_is_global_pause_enabled_next_epoch
Check if the global pause is enabled for the given coin type in the next epoch.
public fun deny_list_v1_is_global_pause_enabled_next_epoch<T>(deny_list: &iota::deny_list::DenyList): bool
Implementation
public fun deny_list_v1_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.is_global_pause_enabled_next_epoch(DENY_LIST_COIN_INDEX, ty)
}
pub deny_list_v1_remove
Removes an address from the deny list. Similar to deny_list_v1_add, the effect for input
objects will be immediate, but the effect for receiving objects will be delayed until the
next epoch.
public fun deny_list_v1_remove<T>(deny_list: &mut iota::deny_list::DenyList, _deny_cap: &mut iota::coin::DenyCapV1<T>, addr: address, ctx: &mut iota::tx_context::TxContext)
Implementation
public fun deny_list_v1_remove<T>(
deny_list: &mut DenyList,
_deny_cap: &mut DenyCapV1<T>,
addr: address,
ctx: &mut TxContext,
) {
let ty = type_name::get_with_original_ids<T>().into_string().into_bytes();
deny_list.remove(DENY_LIST_COIN_INDEX, ty, addr, ctx)
}
pub from_balance
Wrap a balance into a Coin to make it transferable.
public fun from_balance<T>(balance: iota::balance::Balance<T>, ctx: &mut iota::tx_context::TxContext): iota::coin::Coin<T>
Implementation
public fun from_balance<T>(balance: Balance<T>, ctx: &mut TxContext): Coin<T> {
Coin { id: object::new(ctx), balance }
}
pub put
Put a Coin<T> to the Balance<T>.
public fun put<T>(balance: &mut iota::balance::Balance<T>, coin: iota::coin::Coin<T>)
Implementation
pub take
Take a Coin worth of value from Balance.
Aborts if value > balance.value
public fun take<T>(balance: &mut iota::balance::Balance<T>, value: u64, ctx: &mut iota::tx_context::TxContext): iota::coin::Coin<T>
Implementation
pub zero
Make any Coin with a zero value. Useful for placeholding bids/payments or preemptively making empty balances.
public fun zero<T>(ctx: &mut iota::tx_context::TxContext): iota::coin::Coin<T>
Implementation
public fun zero<T>(ctx: &mut TxContext): Coin<T> {
Coin { id: object::new(ctx), balance: balance::zero() }
}
Structs
struct Coin
A coin of type T worth value. Transferable and storable
public struct Coin<phantom T> has key, store
Fields
pub balance
Get immutable reference to the balance of a coin.
public fun balance<T>(coin: &iota::coin::Coin<T>): &iota::balance::Balance<T>
pub balance_mut
Get a mutable reference to the balance of a coin.
public fun balance_mut<T>(coin: &mut iota::coin::Coin<T>): &mut iota::balance::Balance<T>
Implementation
public fun balance_mut<T>(coin: &mut Coin<T>): &mut Balance<T> {
&mut coin.balance
}
pub destroy_zero
Destroy a coin with value zero
public fun destroy_zero<T>(c: iota::coin::Coin<T>)
Implementation
public fun destroy_zero<T>(c: Coin<T>) {
let Coin { id, balance } = c;
id.delete();
balance.destroy_zero()
}
pub 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 iota::coin::Coin<T>, n: u64, ctx: &mut iota::tx_context::TxContext): vector<iota::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
}
pub into_balance
Destruct a Coin wrapper and keep the balance.
public fun into_balance<T>(coin: iota::coin::Coin<T>): iota::balance::Balance<T>
Implementation
pub 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 iota::coin::Coin<T>, split_amount: u64, ctx: &mut iota::tx_context::TxContext): iota::coin::Coin<T>
Implementation
pub value
Public getter for the coin's value
public fun value<T>(self: &iota::coin::Coin<T>): u64
pub entry 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 iota::coin::Coin<T>, c: iota::coin::Coin<T>)
Implementation
struct CoinMetadata
Each Coin type T created through create_currency function will have a
unique instance of CoinMetadata<T> that stores the metadata for this coin type.
public struct CoinMetadata<phantom T> has key, store
Fields
id: iota::object::UIDdecimals: u8Number of decimal places the coin uses. A coin with
valueN anddecimalsD should be shown as N / 10^D E.g., a coin withvalue7002 and decimals 3 should be displayed as 7.002 This is metadata for display usage only.name: std::string::StringName for the token
symbol: std::ascii::StringSymbol for the token
description: std::string::StringDescription of the token
icon_url: std::option::Option<iota::url::Url>URL for the token logo
pub get_decimals
public fun get_decimals<T>(metadata: &iota::coin::CoinMetadata<T>): u8
Implementation
public fun get_decimals<T>(metadata: &CoinMetadata<T>): u8 {
metadata.decimals
}
pub get_description
public fun get_description<T>(metadata: &iota::coin::CoinMetadata<T>): std::string::String
Implementation
public fun get_description<T>(metadata: &CoinMetadata<T>): string::String {
metadata.description
}
pub get_icon_url
public fun get_icon_url<T>(metadata: &iota::coin::CoinMetadata<T>): std::option::Option<iota::url::Url>
Implementation
public fun get_icon_url<T>(metadata: &CoinMetadata<T>): Option<Url> {
metadata.icon_url
}
pub get_name
public fun get_name<T>(metadata: &iota::coin::CoinMetadata<T>): std::string::String
Implementation
public fun get_name<T>(metadata: &CoinMetadata<T>): string::String {
metadata.name
}
pub get_symbol
public fun get_symbol<T>(metadata: &iota::coin::CoinMetadata<T>): std::ascii::String
Implementation
public fun get_symbol<T>(metadata: &CoinMetadata<T>): ascii::String {
metadata.symbol
}
struct RegulatedCoinMetadata
Similar to CoinMetadata, but created only for regulated coins that use the DenyList. This object is always immutable.
public struct RegulatedCoinMetadata<phantom T> has key
Fields
id: iota::object::UIDcoin_metadata_object: iota::object::IDThe ID of the coin's CoinMetadata object.
deny_cap_object: iota::object::IDThe ID of the coin's DenyCap object.
struct TreasuryCap
Capability allowing the bearer to mint and burn
coins of type T. Transferable
public struct TreasuryCap<phantom T> has key, store
Fields
pub mint
Create a coin worth value and increase the total supply
in cap accordingly.
public fun mint<T>(cap: &mut iota::coin::TreasuryCap<T>, value: u64, ctx: &mut iota::tx_context::TxContext): iota::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),
}
}
pub 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 iota::coin::TreasuryCap<T>, value: u64): iota::balance::Balance<T>
Implementation
public fun mint_balance<T>(cap: &mut TreasuryCap<T>, value: u64): Balance<T> {
cap.total_supply.increase_supply(value)
}
pub supply_immut
Get immutable reference to the treasury's Supply.
public fun supply_immut<T>(treasury: &iota::coin::TreasuryCap<T>): &iota::balance::Supply<T>
Implementation
public fun supply_immut<T>(treasury: &TreasuryCap<T>): &Supply {
&treasury.total_supply
}
pub supply_mut
Get mutable reference to the treasury's Supply.
public fun supply_mut<T>(treasury: &mut iota::coin::TreasuryCap<T>): &mut iota::balance::Supply<T>
Implementation
public fun supply_mut<T>(treasury: &mut TreasuryCap<T>): &mut Supply<T> {
&mut treasury.total_supply
}
pub total_supply
Return the total number of T's in circulation.
public fun total_supply<T>(cap: &iota::coin::TreasuryCap<T>): u64
Implementation
public fun total_supply<T>(cap: &TreasuryCap<T>): u64 {
balance::supply_value(&cap.total_supply)
}
pub 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: iota::coin::TreasuryCap<T>): iota::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
}
pub entry burn
Destroy the coin c and decrease the total supply in cap
accordingly.
public entry fun burn<T>(cap: &mut iota::coin::TreasuryCap<T>, c: iota::coin::Coin<T>): u64
Implementation
public entry fun burn<T>(cap: &mut TreasuryCap<T>, c: Coin<T>): u64 {
let Coin { id, balance } = c;
id.delete();
cap.total_supply.decrease_supply(balance)
}
pub entry mint_and_transfer
Mint amount of Coin and send it to recipient. Invokes mint().
public entry fun mint_and_transfer<T>(c: &mut iota::coin::TreasuryCap<T>, amount: u64, recipient: address, ctx: &mut iota::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)
}
pub entry update_description
Update the description of the coin in CoinMetadata
public entry fun update_description<T>(_treasury: &iota::coin::TreasuryCap<T>, metadata: &mut iota::coin::CoinMetadata<T>, description: std::string::String)
Implementation
public entry fun update_description<T>(
_treasury: &TreasuryCap<T>,
metadata: &mut CoinMetadata<T>,
description: string::String,
) {
metadata.description = description;
}
pub entry update_icon_url
Update the url of the coin in CoinMetadata
public entry fun update_icon_url<T>(_treasury: &iota::coin::TreasuryCap<T>, metadata: &mut iota::coin::CoinMetadata<T>, url: std::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));
}
pub entry update_name
Update name of the coin in CoinMetadata
public entry fun update_name<T>(_treasury: &iota::coin::TreasuryCap<T>, metadata: &mut iota::coin::CoinMetadata<T>, name: std::string::String)
Implementation
public entry fun update_name<T>(
_treasury: &TreasuryCap<T>,
metadata: &mut CoinMetadata<T>,
name: string::String,
) {
metadata.name = name;
}
pub entry update_symbol
Update the symbol of the coin in CoinMetadata
public entry fun update_symbol<T>(_treasury: &iota::coin::TreasuryCap<T>, metadata: &mut iota::coin::CoinMetadata<T>, symbol: std::ascii::String)
Implementation
public entry fun update_symbol<T>(
_treasury: &TreasuryCap<T>,
metadata: &mut CoinMetadata<T>,
symbol: ascii::String,
) {
metadata.symbol = symbol;
}
struct DenyCapV1
Capability allowing the bearer to deny addresses from using the currency's coins--
immediately preventing those addresses from interacting with the coin as an input to a
transaction and at the start of the next preventing them from receiving the coin.
If allow_global_pause is true, the bearer can enable a global pause that behaves as if
all addresses were added to the deny list.
public struct DenyCapV1<phantom T> has key, store
Fields
id: iota::object::UIDallow_global_pause: bool
Constants
err EBadWitness
A type passed to create_supply is not a one-time witness.
const EBadWitness: u64 = 0;
err EInvalidArg
Invalid arguments are passed to a function.
const EInvalidArg: u64 = 1;
err ENotEnough
Trying to split a coin more times than its balance allows.
const ENotEnough: u64 = 2;
err EGlobalPauseNotAllowed
const EGlobalPauseNotAllowed: u64 = 3;
const DENY_LIST_COIN_INDEX
The index into the deny list vector for the iota::coin::Coin type.
const DENY_LIST_COIN_INDEX: u64 = 0;