Skip to main content

Module 0xb::treasury

use 0x1::ascii;
use 0x1::option;
use 0x1::type_name;
use 0x1::u64;
use 0x2::address;
use 0x2::bag;
use 0x2::coin;
use 0x2::event;
use 0x2::hex;
use 0x2::object;
use 0x2::object_bag;
use 0x2::package;
use 0x2::transfer;
use 0x2::tx_context;
use 0x2::vec_map;

Struct BridgeTreasury

struct BridgeTreasury has store
Click to open
Fields

Struct BridgeTokenMetadata

struct BridgeTokenMetadata has copy, drop, store
Click to open
Fields
id: u8
decimal_multiplier: u64
notional_value: u64
native_token: bool

Struct ForeignTokenRegistration

struct ForeignTokenRegistration has store
Click to open
Fields

Struct UpdateTokenPriceEvent

struct UpdateTokenPriceEvent has copy, drop
Click to open
Fields
token_id: u8
new_price: u64

Struct NewTokenEvent

struct NewTokenEvent has copy, drop
Click to open
Fields
token_id: u8
type_name: type_name::TypeName
native_token: bool
decimal_multiplier: u64
notional_value: u64

Struct TokenRegistrationEvent

struct TokenRegistrationEvent has copy, drop
Click to open
Fields
type_name: type_name::TypeName
decimal: u8
native_token: bool

Constants

const EInvalidNotionalValue: u64 = 4;

const EInvalidUpgradeCap: u64 = 2;

const ETokenSupplyNonZero: u64 = 3;

const EUnsupportedTokenType: u64 = 1;

Function token_id

public fun token_id<T>(self: &treasury::BridgeTreasury): u8
Click to open
Implementation
public fun token_id<T>(self: &BridgeTreasury): u8 {
    let metadata = self.get_token_metadata<T>();
    metadata.id
}

Function decimal_multiplier

public fun decimal_multiplier<T>(self: &treasury::BridgeTreasury): u64
Click to open
Implementation
public fun decimal_multiplier<T>(self: &BridgeTreasury): u64 {
    let metadata = self.get_token_metadata<T>();
    metadata.decimal_multiplier
}

Function notional_value

public fun notional_value<T>(self: &treasury::BridgeTreasury): u64
Click to open
Implementation
public fun notional_value<T>(self: &BridgeTreasury): u64 {
    let metadata = self.get_token_metadata<T>();
    metadata.notional_value
}

Function register_foreign_token

public(friend) fun register_foreign_token<T>(self: &mut treasury::BridgeTreasury, tc: coin::TreasuryCap<T>, uc: package::UpgradeCap, metadata: &coin::CoinMetadata<T>)
Click to open
Implementation
public(package) fun register_foreign_token<T>(
    self: &mut BridgeTreasury,
    tc: TreasuryCap<T>,
    uc: UpgradeCap,
    metadata: &CoinMetadata<T>,
) {
    // Make sure TreasuryCap has not been minted before.
    assert!(coin::total_supply(&tc) == 0, ETokenSupplyNonZero);
    let type_name = type_name::get<T>();
    let address_bytes = hex::decode(ascii::into_bytes(type_name::get_address(&type_name)));
    let coin_address = address::from_bytes(address_bytes);
    // Make sure upgrade cap is for the Coin package
    // FIXME: add test
    assert!(
        object::id_to_address(&package::upgrade_package(&uc))
            == coin_address, EInvalidUpgradeCap
    );
    let registration = ForeignTokenRegistration {
        type_name,
        uc,
        decimal: coin::get_decimals(metadata),
    };
    self.waiting_room.add(type_name::into_string(type_name), registration);
    self.treasuries.add(type_name, tc);

    emit(TokenRegistrationEvent{
        type_name,
        decimal: coin::get_decimals(metadata),
        native_token: false
    });
}

Function add_new_token

public(friend) fun add_new_token(self: &mut treasury::BridgeTreasury, token_name: ascii::String, token_id: u8, native_token: bool, notional_value: u64)
Click to open
Implementation
public(package) fun add_new_token(
    self: &mut BridgeTreasury,
    token_name: String,
    token_id: u8,
    native_token: bool,
    notional_value: u64,
) {
    if (!native_token){
        assert!(notional_value > 0, EInvalidNotionalValue);
        let ForeignTokenRegistration{
            type_name,
            uc,
            decimal,
        } = self.waiting_room.remove<String, ForeignTokenRegistration>(token_name);
        let decimal_multiplier = 10u64.pow(decimal);
        self.supported_tokens.insert(
            type_name,
            BridgeTokenMetadata{
                id: token_id,
                decimal_multiplier,
                notional_value,
                native_token
            },
        );
        self.id_token_type_map.insert(token_id, type_name);

        // Freeze upgrade cap to prevent changes to the coin
        transfer::public_freeze_object(uc);

        emit(NewTokenEvent{
            token_id,
            type_name,
            native_token,
            decimal_multiplier,
            notional_value
        })
    } else {
        // Not implemented for V1
    }
}

Function create

public(friend) fun create(ctx: &mut tx_context::TxContext): treasury::BridgeTreasury
Click to open
Implementation
public(package) fun create(ctx: &mut TxContext): BridgeTreasury {
    BridgeTreasury {
        treasuries: object_bag::new(ctx),
        supported_tokens: vec_map::empty(),
        id_token_type_map: vec_map::empty(),
        waiting_room: bag::new(ctx),
    }
}

Function burn

public(friend) fun burn<T>(self: &mut treasury::BridgeTreasury, token: coin::Coin<T>)
Click to open
Implementation
public(package) fun burn<T>(self: &mut BridgeTreasury, token: Coin<T>) {
    let treasury = &mut self.treasuries[type_name::get<T>()];
    coin::burn(treasury, token);
}

Function mint

public(friend) fun mint<T>(self: &mut treasury::BridgeTreasury, amount: u64, ctx: &mut tx_context::TxContext): coin::Coin<T>
Click to open
Implementation
public(package) fun mint<T>(
    self: &mut BridgeTreasury,
    amount: u64,
    ctx: &mut TxContext,
): Coin<T> {
    let treasury = &mut self.treasuries[type_name::get<T>()];
    coin::mint(treasury, amount, ctx)
}

Function update_asset_notional_price

public(friend) fun update_asset_notional_price(self: &mut treasury::BridgeTreasury, token_id: u8, new_usd_price: u64)
Click to open
Implementation
public(package) fun update_asset_notional_price(
    self: &mut BridgeTreasury,
    token_id: u8,
    new_usd_price: u64,
) {
    let type_name = self.id_token_type_map.try_get(&token_id);
    assert!(type_name.is_some(), EUnsupportedTokenType);
    assert!(new_usd_price > 0, EInvalidNotionalValue);
    let type_name = type_name.destroy_some();
    let metadata = self.supported_tokens.get_mut(&type_name);
    metadata.notional_value = new_usd_price;

    emit(UpdateTokenPriceEvent {
        token_id,
        new_price: new_usd_price,
    })
}

Function get_token_metadata

fun get_token_metadata<T>(self: &treasury::BridgeTreasury): treasury::BridgeTokenMetadata
Click to open
Implementation
fun get_token_metadata<T>(self: &BridgeTreasury): BridgeTokenMetadata {
    let coin_type = type_name::get<T>();
    let metadata = self.supported_tokens.try_get(&coin_type);
    assert!(metadata.is_some(), EUnsupportedTokenType);
    metadata.destroy_some()
}