Skip to content

Latest commit

 

History

History
956 lines (532 loc) · 31.9 KB

coin.md

File metadata and controls

956 lines (532 loc) · 31.9 KB

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

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 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>

Struct CurrencyCreated

Emitted when new currency is created through the create_currency call. Contains currency metadata for off-chain discovery. Type parameter T matches the one in Coin<T>

struct CurrencyCreated<T> has copy, drop
Fields
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.

Constants

For when trying to split a coin more times than its balance allows.

const ENotEnough: u64 = 2;

For when a type passed to create_supply is not a one-time witness.

const EBadWitness: u64 = 0;

For when 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;
    object::delete(id);
    total_supply
}

Function supply

Get immutable reference to the treasury's 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 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
Implementation
public fun value<T>(self: &Coin<T>): u64 {
    balance::value(&self.balance)
}

Function balance

Get immutable reference to the balance of a coin.

public fun balance<T>(coin: &coin::Coin<T>): &balance::Balance<T>
Implementation
public fun balance<T>(coin: &Coin<T>): &Balance<T> {
    &coin.balance
}

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.

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.

Implementation
public fun into_balance<T>(coin: Coin<T>): Balance<T> {
    let Coin { id, balance } = coin;
    object::delete(id);
    balance
}

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
public fun take<T>(
    balance: &mut Balance<T>, value: u64, ctx: &mut TxContext,
): Coin<T> {
    Coin {
        id: object::new(ctx),
        balance: balance::split(balance, value)
    }
}

Function put

Put a Coin<T> to the Balance<T>.

public fun put<T>(balance: &mut balance::Balance<T>, coin: coin::Coin<T>)
Implementation
public fun put<T>(balance: &mut Balance<T>, coin: Coin<T>) {
    balance::join(balance, into_balance(coin));
}

Function keep

Transfer c to the sender of the current transaction

public fun keep<T>(c: coin::Coin<T>, ctx: &tx_context::TxContext)
Implementation
public fun keep<T>(c: Coin<T>, ctx: &TxContext) {
    transfer::transfer(c, tx_context::sender(ctx))
}

Function join

Consume the coin c and add its value to self. Aborts if c.value + self.value > U64_MAX

public fun join<T>(self: &mut coin::Coin<T>, c: coin::Coin<T>)
Implementation
public entry fun join<T>(self: &mut Coin<T>, c: Coin<T>) {
    let Coin { id, balance } = c;
    object::delete(id);
    balance::join(&mut self.balance, balance);
}

Function join_vec

Join everything in coins with self

public fun join_vec<T>(self: &mut coin::Coin<T>, coins: vector<coin::Coin<T>>)
Implementation
public entry fun join_vec<T>(self: &mut Coin<T>, coins: vector<Coin<T>>) {
    let i = 0;
    let len = vector::length(&coins);
    while (i < len) {
        let coin = vector::remove(&mut coins, i);
        join(self, coin);
        i = i + 1
    };
    // safe because we've drained the vector
    vector::destroy_empty(coins)
}

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;
    object::delete(id);
    balance::destroy_zero(balance)
}

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 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, ctx: &mut tx_context::TxContext): coin::TreasuryCap<T>
Implementation
public fun create_currency<T: drop>(
    witness: T,
    decimals: u8,
    ctx: &mut TxContext
): TreasuryCap<T> {
    // Make sure there's only one instance of the type T
    assert!(sui::types::is_one_time_witness(&witness), EBadWitness);

    // Emit Currency metadata as an event.
    event::emit(CurrencyCreated<T> {
        decimals
    });

    TreasuryCap {
        id: object::new(ctx),
        total_supply: balance::create_supply(witness)
    }
}

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: balance::increase_supply(&mut cap.total_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> {
    balance::increase_supply(&mut cap.total_supply, value)
}

Function burn

Destroy the coin c and decrease the total supply in cap accordingly.

public fun burn<T>(cap: &mut coin::TreasuryCap<T>, c: coin::Coin<T>): u64
Implementation
public fun burn<T>(cap: &mut TreasuryCap<T>, c: Coin<T>): u64 {
    let Coin { id, balance } = c;
    object::delete(id);
    balance::decrease_supply(&mut cap.total_supply, balance)
}

Function mint_and_transfer

Mint amount of Coin and send it to recipient. Invokes mint().

public 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::transfer(mint(c, amount, ctx), recipient)
}

Function burn_

Burn a Coin and reduce the total_supply. Invokes burn().

public fun burn_<T>(c: &mut coin::TreasuryCap<T>, coin: coin::Coin<T>)
Implementation
public entry fun burn_<T>(c: &mut TreasuryCap<T>, coin: Coin<T>) {
    burn(c, coin);
}

Function split_and_transfer

Send amount units of c to recipient Aborts with EVALUE if amount is greater than or equal to amount

public fun split_and_transfer<T>(c: &mut coin::Coin<T>, amount: u64, recipient: address, ctx: &mut tx_context::TxContext)
Implementation
public entry fun split_and_transfer<T>(
    c: &mut Coin<T>, amount: u64, recipient: address, ctx: &mut TxContext
) {
    transfer::transfer(take(&mut c.balance, amount, ctx), recipient)
}

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)
Implementation
public entry fun split<T>(self: &mut Coin<T>, split_amount: u64, ctx: &mut TxContext) {
    transfer::transfer(
        take(&mut self.balance, split_amount, ctx),
        tx_context::sender(ctx)
    )
}

Function split_n_to_vec

Split coin self into n coins with equal balances. If the balance is not evenly divisible by n, the remainder is left in self. Return newly created coins.

public fun split_n_to_vec<T>(self: &mut coin::Coin<T>, n: u64, ctx: &mut tx_context::TxContext): vector<coin::Coin<T>>
Implementation
public fun split_n_to_vec<T>(self: &mut Coin<T>, n: u64, ctx: &mut TxContext): vector<Coin<T>> {
    assert!(n > 0, EInvalidArg);
    assert!(n <= balance::value(&self.balance), ENotEnough);
    let vec = vector::empty<Coin<T>>();
    let i = 0;
    let split_amount = balance::value(&self.balance) / n;
    while (i < n - 1) {
        vector::push_back(&mut vec, take(&mut self.balance, split_amount, ctx));
        i = i + 1;
    };
    vec
}

Function split_n

Split coin self into n coins with equal balances. If the balance is not evenly divisible by n, the remainder is left in self.

public fun split_n<T>(self: &mut coin::Coin<T>, n: u64, ctx: &mut tx_context::TxContext)
Implementation
public entry fun split_n<T>(self: &mut Coin<T>, n: u64, ctx: &mut TxContext) {
    let vec: vector<Coin<T>> = split_n_to_vec(self, n, ctx);
    let i = 0;
    let len = vector::length(&vec);
    while (i < len) {
        transfer::transfer(vector::pop_back(&mut vec), tx_context::sender(ctx));
        i = i + 1;
    };
    vector::destroy_empty(vec);
}

Function split_vec

Split coin self into multiple coins, each with balance specified in split_amounts. Remaining balance is left in self.

public fun split_vec<T>(self: &mut coin::Coin<T>, split_amounts: vector<u64>, ctx: &mut tx_context::TxContext)
Implementation
public entry fun split_vec<T>(self: &mut Coin<T>, split_amounts: vector<u64>, ctx: &mut TxContext) {
    let i = 0;
    let len = vector::length(&split_amounts);
    while (i < len) {
        split(self, *vector::borrow(&split_amounts, i), ctx);
        i = i + 1;
    };
}