axelar-cgp-sui

Module 0xa5::its_v0

use 0x1::ascii;
use 0x1::option;
use 0x1::string;
use 0x1::type_name;
use 0x1::vector;
use 0x2::address;
use 0x2::bag;
use 0x2::balance;
use 0x2::clock;
use 0x2::coin;
use 0x2::object;
use 0x2::table;
use 0x2::transfer;
use 0x2::tx_context;
use 0x2::url;
use 0xa0::abi;
use 0xa1::channel;
use 0xa1::gateway;
use 0xa1::message_ticket;
use 0xa2::discovery;
use 0xa5::address_tracker;
use 0xa5::coin_data;
use 0xa5::coin_info;
use 0xa5::coin_management;
use 0xa5::events;
use 0xa5::interchain_transfer_ticket;
use 0xa5::token_id;
use 0xa5::trusted_addresses;
use 0xa5::unregistered_coin_data;
use 0xa5::utils;
use 0xb0::version_control;

Struct ITS_v0

struct ITS_v0 has store
Fields
channel: channel::Channel
address_tracker: address_tracker::InterchainAddressTracker
unregistered_coin_types: table::Table<token_id::UnregisteredTokenId, type_name::TypeName>
unregistered_coins: bag::Bag
registered_coin_types: table::Table<token_id::TokenId, type_name::TypeName>
registered_coins: bag::Bag
relayer_discovery_id: object::ID
version_control: version_control::VersionControl

Constants

const DECIMALS_CAP: u8 = 9;

const EInterchainTransferHasData: vector<u8> = [105, 110, 116, 101, 114, 99, 104, 97, 105, 110, 32, 116, 114, 97, 110, 115, 102, 101, 114, 32, 119, 105, 116, 104, 32, 100, 97, 116, 97, 32, 116, 114, 121, 105, 110, 103, 32, 116, 111, 32, 98, 101, 32, 112, 114, 111, 99, 101, 115, 115, 101, 100, 32, 97, 115, 32, 97, 110, 32, 105, 110, 116, 101, 114, 99, 104, 97, 105, 110, 32, 116, 114, 97, 110, 115, 102, 101, 114];

const EInterchainTransferHasNoData: vector<u8> = [105, 110, 116, 101, 114, 99, 104, 97, 105, 110, 32, 116, 114, 97, 110, 115, 102, 101, 114, 32, 116, 114, 121, 105, 110, 103, 32, 116, 111, 32, 98, 101, 32, 112, 114, 111, 99, 99, 101, 115, 115, 101, 100, 32, 97, 115, 32, 97, 110, 32, 105, 110, 116, 101, 114, 99, 104, 97, 105, 110, 32, 116, 114, 97, 110, 115, 102, 101, 114];

const EInvalidMessageType: vector<u8> = [116, 104, 101, 32, 109, 101, 115, 115, 97, 103, 101, 32, 116, 121, 112, 101, 32, 114, 101, 99, 101, 105, 118, 101, 100, 32, 105, 115, 32, 110, 111, 116, 32, 115, 117, 112, 112, 111, 114, 116, 101, 100];

const EModuleNameDoesNotMatchSymbol: vector<u8> = [116, 104, 101, 32, 109, 111, 100, 117, 108, 101, 32, 110, 97, 109, 101, 32, 100, 111, 101, 115, 32, 110, 111, 116, 32, 109, 97, 116, 99, 104, 32, 116, 104, 101, 32, 115, 121, 109, 98, 111, 108];

const ENewerTicket: vector<u8> = [99, 97, 110, 110, 111, 116, 32, 112, 114, 111, 99, 99, 101, 115, 115, 32, 110, 101, 119, 101, 114, 32, 116, 105, 99, 107, 101, 116, 115];

const ENonZeroTotalSupply: vector<u8> = [116, 114, 121, 105, 110, 103, 32, 116, 111, 32, 103, 105, 118, 101, 32, 97, 32, 116, 111, 107, 101, 110, 32, 116, 104, 97, 116, 32, 104, 97, 115, 32, 104, 97, 100, 32, 115, 111, 109, 101, 32, 115, 117, 112, 112, 108, 121, 32, 97, 108, 114, 101, 97, 100, 121, 32, 109, 105, 110, 116, 101, 100];

const ENotDistributor: vector<u8> = [111, 110, 108, 121, 32, 116, 104, 101, 32, 100, 105, 115, 116, 114, 105, 98, 117, 116, 111, 114, 32, 99, 97, 110, 32, 109, 105, 110, 116];

const EUnregisteredCoin: vector<u8> = [116, 114, 121, 105, 110, 103, 32, 116, 111, 32, 102, 105, 110, 100, 32, 97, 32, 99, 111, 105, 110, 32, 116, 104, 97, 116, 32, 100, 111, 101, 115, 110, 39, 116, 32, 101, 120, 105, 115, 116];

const EUnregisteredCoinHasUrl: vector<u8> = [116, 104, 101, 32, 105, 110, 116, 101, 114, 99, 104, 97, 105, 110, 32, 116, 111, 107, 101, 110, 32, 116, 104, 97, 116, 32, 105, 115, 32, 98, 101, 105, 110, 103, 32, 114, 101, 103, 105, 115, 116, 101, 114, 101, 100, 32, 104, 97, 115, 32, 97, 32, 85, 82, 76];

const EUntrustedAddress: vector<u8> = [116, 104, 101, 32, 115, 101, 110, 100, 101, 114, 32, 116, 104, 97, 116, 32, 115, 101, 110, 116, 32, 116, 104, 105, 115, 32, 109, 101, 115, 115, 97, 103, 101, 32, 105, 115, 32, 110, 111, 116, 32, 116, 114, 117, 115, 116, 101, 100];

const EUntrustedChain: vector<u8> = [116, 104, 101, 32, 99, 104, 97, 105, 110, 32, 105, 115, 32, 110, 111, 116, 32, 116, 114, 117, 115, 116, 101, 100];

const EWrongDestination: vector<u8> = [116, 104, 101, 32, 99, 104, 97, 110, 110, 101, 108, 32, 116, 114, 121, 105, 110, 103, 32, 116, 111, 32, 114, 101, 99, 101, 105, 118, 101, 32, 116, 104, 105, 115, 32, 99, 97, 108, 108, 32, 105, 115, 32, 110, 111, 116, 32, 116, 104, 101, 32, 100, 101, 115, 116, 105, 110, 97, 116, 105, 111, 110];

const ITS_HUB_CHAIN_NAME: vector<u8> = [97, 120, 101, 108, 97, 114];

const ITS_HUB_ROUTING_IDENTIFIER: vector<u8> = [104, 117, 98];

const MESSAGE_TYPE_DEPLOY_INTERCHAIN_TOKEN: u256 = 1;

const MESSAGE_TYPE_INTERCHAIN_TRANSFER: u256 = 0;

const MESSAGE_TYPE_RECEIVE_FROM_HUB: u256 = 4;

const MESSAGE_TYPE_SEND_TO_HUB: u256 = 3;

Function new

public(friend) fun new(version_control: version_control::VersionControl, ctx: &mut tx_context::TxContext): its_v0::ITS_v0
Implementation
public(package) fun new(
    version_control: VersionControl,
    ctx: &mut TxContext,
): ITS_v0 {
    ITS_v0 {
        channel: axelar_gateway::channel::new(ctx),
        address_tracker: address_tracker::new(
            ctx,
        ),
        registered_coins: bag::new(ctx),
        registered_coin_types: table::new(ctx),
        unregistered_coins: bag::new(ctx),
        unregistered_coin_types: table::new(ctx),
        relayer_discovery_id: object::id_from_address(@0x0),
        version_control,
    }
}

Function unregistered_coin_type

public(friend) fun unregistered_coin_type(self: &its_v0::ITS_v0, symbol: &ascii::String, decimals: u8): &type_name::TypeName
Implementation
public(package) fun unregistered_coin_type(
    self: &ITS_v0,
    symbol: &String,
    decimals: u8,
): &TypeName {
    let key = token_id::unregistered_token_id(symbol, decimals);

    assert!(self.unregistered_coin_types.contains(key), EUnregisteredCoin);
    &self.unregistered_coin_types[key]
}

Function registered_coin_type

public(friend) fun registered_coin_type(self: &its_v0::ITS_v0, token_id: token_id::TokenId): &type_name::TypeName
Implementation
public(package) fun registered_coin_type(
    self: &ITS_v0,
    token_id: TokenId,
): &TypeName {
    assert!(self.registered_coin_types.contains(token_id), EUnregisteredCoin);
    &self.registered_coin_types[token_id]
}

Function channel_address

public(friend) fun channel_address(self: &its_v0::ITS_v0): address
Implementation
public(package) fun channel_address(self: &ITS_v0): address {
    self.channel.to_address()
}

Function set_relayer_discovery_id

public(friend) fun set_relayer_discovery_id(self: &mut its_v0::ITS_v0, relayer_discovery: &discovery::RelayerDiscovery)
Implementation
public(package) fun set_relayer_discovery_id(
    self: &mut ITS_v0,
    relayer_discovery: &RelayerDiscovery,
) {
    self.relayer_discovery_id = object::id(relayer_discovery);
}

Function relayer_discovery_id

public(friend) fun relayer_discovery_id(self: &its_v0::ITS_v0): object::ID
Implementation
public(package) fun relayer_discovery_id(self: &ITS_v0): ID {
    self.relayer_discovery_id
}

Function set_trusted_address

public(friend) fun set_trusted_address(self: &mut its_v0::ITS_v0, chain_name: ascii::String, trusted_address: ascii::String)
Implementation
public(package) fun set_trusted_address(
    self: &mut ITS_v0,
    chain_name: String,
    trusted_address: String,
) {
    self.address_tracker.set_trusted_address(chain_name, trusted_address);
}

Function remove_trusted_address

public(friend) fun remove_trusted_address(self: &mut its_v0::ITS_v0, chain_name: ascii::String)
Implementation
public(package) fun remove_trusted_address(
    self: &mut ITS_v0,
    chain_name: String,
) {
    self.address_tracker.remove_trusted_address(chain_name);
}

Function set_trusted_addresses

public(friend) fun set_trusted_addresses(self: &mut its_v0::ITS_v0, trusted_addresses: trusted_addresses::TrustedAddresses)
Implementation
public(package) fun set_trusted_addresses(
    self: &mut ITS_v0,
    trusted_addresses: TrustedAddresses,
) {
    let (chain_names, trusted_addresses) = trusted_addresses.destroy();

    chain_names.zip_do!(
        trusted_addresses,
        |chain_name, trusted_address| self.set_trusted_address(
            chain_name,
            trusted_address,
        ),
    );
}

Function remove_trusted_addresses

public(friend) fun remove_trusted_addresses(self: &mut its_v0::ITS_v0, chain_names: vector<ascii::String>)
Implementation
public(package) fun remove_trusted_addresses(
    self: &mut ITS_v0,
    chain_names: vector<String>,
) {
    chain_names.do!(
        |chain_name| self.remove_trusted_address(
            chain_name,
        ),
    );
}

Function coin_data_mut

public(friend) fun coin_data_mut<T>(self: &mut its_v0::ITS_v0, token_id: token_id::TokenId): &mut coin_data::CoinData<T>
Implementation
public(package) fun coin_data_mut<T>(
    self: &mut ITS_v0,
    token_id: TokenId,
): &mut CoinData<T> {
    assert!(self.registered_coins.contains(token_id), EUnregisteredCoin);
    &mut self.registered_coins[token_id]
}

Function channel

public(friend) fun channel(self: &its_v0::ITS_v0): &channel::Channel
Implementation
public(package) fun channel(self: &ITS_v0): &Channel {
    &self.channel
}

Function channel_mut

public(friend) fun channel_mut(self: &mut its_v0::ITS_v0): &mut channel::Channel
Implementation
public(package) fun channel_mut(self: &mut ITS_v0): &mut Channel {
    &mut self.channel
}

Function version_control

public(friend) fun version_control(self: &its_v0::ITS_v0): &version_control::VersionControl
Implementation
public(package) fun version_control(self: &ITS_v0): &VersionControl {
    &self.version_control
}

Function register_coin

public(friend) fun register_coin<T>(self: &mut its_v0::ITS_v0, coin_info: coin_info::CoinInfo<T>, coin_management: coin_management::CoinManagement<T>): token_id::TokenId
Implementation
public(package) fun register_coin<T>(
    self: &mut ITS_v0,
    coin_info: CoinInfo<T>,
    coin_management: CoinManagement<T>,
): TokenId {
    let token_id = token_id::from_coin_data(&coin_info, &coin_management);

    self.add_registered_coin(token_id, coin_management, coin_info);

    events::coin_registered<T>(
        token_id,
    );

    token_id
}

Function deploy_remote_interchain_token

public(friend) fun deploy_remote_interchain_token<T>(self: &its_v0::ITS_v0, token_id: token_id::TokenId, destination_chain: ascii::String): message_ticket::MessageTicket
Implementation
public(package) fun deploy_remote_interchain_token<T>(
    self: &ITS_v0,
    token_id: TokenId,
    destination_chain: String,
): MessageTicket {
    let coin_info = self.coin_info<T>(token_id);

    let name = coin_info.name();
    let symbol = coin_info.symbol();
    let decimals = coin_info.decimals();

    let mut writer = abi::new_writer(6);

    writer
        .write_u256(MESSAGE_TYPE_DEPLOY_INTERCHAIN_TOKEN)
        .write_u256(token_id.to_u256())
        .write_bytes(*name.as_bytes())
        .write_bytes(*symbol.as_bytes())
        .write_u256((decimals as u256))
        .write_bytes(vector::empty());

    events::interchain_token_deployment_started<T>(
        token_id,
        name,
        symbol,
        decimals,
        destination_chain,
    );

    prepare_message(self, destination_chain, writer.into_bytes())
}

Function send_interchain_transfer

public(friend) fun send_interchain_transfer<T>(self: &mut its_v0::ITS_v0, ticket: interchain_transfer_ticket::InterchainTransferTicket<T>, current_version: u64, clock: &clock::Clock): message_ticket::MessageTicket
Implementation
public(package) fun send_interchain_transfer<T>(
    self: &mut ITS_v0,
    ticket: InterchainTransferTicket<T>,
    current_version: u64,
    clock: &Clock,
): MessageTicket {
    let (
        token_id,
        balance,
        source_address,
        destination_chain,
        destination_address,
        metadata,
        version,
    ) = ticket.destroy();
    assert!(version <= current_version, ENewerTicket);

    let amount = self
        .coin_management_mut(token_id)
        .take_balance(balance, clock);
    let (_version, data) = its_utils::decode_metadata(metadata);
    let mut writer = abi::new_writer(6);

    writer
        .write_u256(MESSAGE_TYPE_INTERCHAIN_TRANSFER)
        .write_u256(token_id.to_u256())
        .write_bytes(source_address.to_bytes())
        .write_bytes(destination_address)
        .write_u256(amount)
        .write_bytes(data);

    events::interchain_transfer<T>(
        token_id,
        source_address,
        destination_chain,
        destination_address,
        amount,
        &data,
    );

    self.prepare_message(destination_chain, writer.into_bytes())
}

Function receive_interchain_transfer

public(friend) fun receive_interchain_transfer<T>(self: &mut its_v0::ITS_v0, approved_message: channel::ApprovedMessage, clock: &clock::Clock, ctx: &mut tx_context::TxContext)
Implementation
public(package) fun receive_interchain_transfer<T>(
    self: &mut ITS_v0,
    approved_message: ApprovedMessage,
    clock: &Clock,
    ctx: &mut TxContext,
) {
    let (source_chain, payload, message_id) = self.decode_approved_message(
        approved_message,
    );
    let mut reader = abi::new_reader(payload);
    assert!(
        reader.read_u256() == MESSAGE_TYPE_INTERCHAIN_TRANSFER,
        EInvalidMessageType,
    );

    let token_id = token_id::from_u256(reader.read_u256());
    let source_address = reader.read_bytes();
    let destination_address = address::from_bytes(reader.read_bytes());
    let amount = reader.read_u256();
    let data = reader.read_bytes();

    assert!(data.is_empty(), EInterchainTransferHasData);

    let coin = self
        .coin_management_mut(token_id)
        .give_coin<T>(amount, clock, ctx);

    transfer::public_transfer(coin, destination_address);

    events::interchain_transfer_received<T>(
        message_id,
        token_id,
        source_chain,
        source_address,
        destination_address,
        amount,
        &b"",
    );
}

Function receive_interchain_transfer_with_data

public(friend) fun receive_interchain_transfer_with_data<T>(self: &mut its_v0::ITS_v0, approved_message: channel::ApprovedMessage, channel: &channel::Channel, clock: &clock::Clock, ctx: &mut tx_context::TxContext): (ascii::String, vector<u8>, vector<u8>, coin::Coin<T>)
Implementation
public(package) fun receive_interchain_transfer_with_data<T>(
    self: &mut ITS_v0,
    approved_message: ApprovedMessage,
    channel: &Channel,
    clock: &Clock,
    ctx: &mut TxContext,
): (String, vector<u8>, vector<u8>, Coin<T>) {
    let (source_chain, payload, message_id) = self.decode_approved_message(
        approved_message,
    );
    let mut reader = abi::new_reader(payload);
    assert!(
        reader.read_u256() == MESSAGE_TYPE_INTERCHAIN_TRANSFER,
        EInvalidMessageType,
    );

    let token_id = token_id::from_u256(reader.read_u256());

    let source_address = reader.read_bytes();
    let destination_address = address::from_bytes(reader.read_bytes());
    let amount = reader.read_u256();
    let data = reader.read_bytes();

    assert!(destination_address == channel.to_address(), EWrongDestination);
    assert!(!data.is_empty(), EInterchainTransferHasNoData);

    let coin = self.coin_management_mut(token_id).give_coin(amount, clock, ctx);

    events::interchain_transfer_received<T>(
        message_id,
        token_id,
        source_chain,
        source_address,
        destination_address,
        amount,
        &data,
    );

    (source_chain, source_address, data, coin)
}

Function receive_deploy_interchain_token

public(friend) fun receive_deploy_interchain_token<T>(self: &mut its_v0::ITS_v0, approved_message: channel::ApprovedMessage)
Implementation
public(package) fun receive_deploy_interchain_token<T>(
    self: &mut ITS_v0,
    approved_message: ApprovedMessage,
) {
    let (_, payload, _) = self.decode_approved_message(approved_message);
    let mut reader = abi::new_reader(payload);
    assert!(
        reader.read_u256() == MESSAGE_TYPE_DEPLOY_INTERCHAIN_TOKEN,
        EInvalidMessageType,
    );

    let token_id = token_id::from_u256(reader.read_u256());
    let name = string::utf8(reader.read_bytes());
    let symbol = ascii::string(reader.read_bytes());
    let remote_decimals = (reader.read_u256() as u8);
    let distributor_bytes = reader.read_bytes();
    let decimals = if (remote_decimals > DECIMALS_CAP) DECIMALS_CAP
    else remote_decimals;
    let (treasury_cap, mut coin_metadata) = self.remove_unregistered_coin<T>(
        token_id::unregistered_token_id(&symbol, decimals),
    );

    treasury_cap.update_name(&mut coin_metadata, name);

    let mut coin_management = coin_management::new_with_cap<T>(treasury_cap);
    let coin_info = coin_info::from_metadata<T>(coin_metadata, remote_decimals);

    if (distributor_bytes.length() > 0) {
        let distributor = address::from_bytes(distributor_bytes);
        coin_management.add_distributor(distributor);
    };

    self.add_registered_coin<T>(token_id, coin_management, coin_info);
}

Function give_unregistered_coin

public(friend) fun give_unregistered_coin<T>(self: &mut its_v0::ITS_v0, treasury_cap: coin::TreasuryCap<T>, coin_metadata: coin::CoinMetadata<T>)
Implementation
public(package) fun give_unregistered_coin<T>(
    self: &mut ITS_v0,
    treasury_cap: TreasuryCap<T>,
    mut coin_metadata: CoinMetadata<T>,
) {
    assert!(treasury_cap.total_supply() == 0, ENonZeroTotalSupply);
    assert!(
        coin::get_icon_url(&coin_metadata).is_none(),
        EUnregisteredCoinHasUrl,
    );

    treasury_cap.update_description(&mut coin_metadata, string::utf8(b""));

    let decimals = coin_metadata.get_decimals();
    let symbol = coin_metadata.get_symbol();

    let module_name = type_name::get_module(&type_name::get<T>());
    assert!(
        &module_name == &its_utils::module_from_symbol(&symbol),
        EModuleNameDoesNotMatchSymbol,
    );

    let token_id = token_id::unregistered_token_id(&symbol, decimals);

    self.add_unregistered_coin<T>(token_id, treasury_cap, coin_metadata);

    events::unregistered_coin_received<T>(
        token_id,
        symbol,
        decimals,
    );
}

Function mint_as_distributor

public(friend) fun mint_as_distributor<T>(self: &mut its_v0::ITS_v0, channel: &channel::Channel, token_id: token_id::TokenId, amount: u64, ctx: &mut tx_context::TxContext): coin::Coin<T>
Implementation
public(package) fun mint_as_distributor<T>(
    self: &mut ITS_v0,
    channel: &Channel,
    token_id: TokenId,
    amount: u64,
    ctx: &mut TxContext,
): Coin<T> {
    let coin_management = self.coin_management_mut<T>(token_id);
    let distributor = channel.to_address();

    assert!(coin_management.is_distributor(distributor), ENotDistributor);

    coin_management.mint(amount, ctx)
}

Function mint_to_as_distributor

public(friend) fun mint_to_as_distributor<T>(self: &mut its_v0::ITS_v0, channel: &channel::Channel, token_id: token_id::TokenId, to: address, amount: u64, ctx: &mut tx_context::TxContext)
Implementation
public(package) fun mint_to_as_distributor<T>(
    self: &mut ITS_v0,
    channel: &Channel,
    token_id: TokenId,
    to: address,
    amount: u64,
    ctx: &mut TxContext,
) {
    let coin_management = self.coin_management_mut<T>(token_id);
    let distributor = channel.to_address();

    assert!(coin_management.is_distributor(distributor), ENotDistributor);

    let coin = coin_management.mint(amount, ctx);

    transfer::public_transfer(coin, to);
}

Function burn_as_distributor

public(friend) fun burn_as_distributor<T>(self: &mut its_v0::ITS_v0, channel: &channel::Channel, token_id: token_id::TokenId, coin: coin::Coin<T>)
Implementation
public(package) fun burn_as_distributor<T>(
    self: &mut ITS_v0,
    channel: &Channel,
    token_id: TokenId,
    coin: Coin<T>,
) {
    let coin_management = self.coin_management_mut<T>(token_id);
    let distributor = channel.to_address();

    assert!(coin_management.is_distributor<T>(distributor), ENotDistributor);

    coin_management.burn(coin.into_balance());
}

Function coin_data

fun coin_data<T>(self: &its_v0::ITS_v0, token_id: token_id::TokenId): &coin_data::CoinData<T>
Implementation
fun coin_data<T>(self: &ITS_v0, token_id: TokenId): &CoinData<T> {
    assert!(self.registered_coins.contains(token_id), EUnregisteredCoin);
    &self.registered_coins[token_id]
}

Function coin_info

fun coin_info<T>(self: &its_v0::ITS_v0, token_id: token_id::TokenId): &coin_info::CoinInfo<T>
Implementation
fun coin_info<T>(self: &ITS_v0, token_id: TokenId): &CoinInfo<T> {
    coin_data<T>(self, token_id).coin_info()
}

Function is_trusted_address

fun is_trusted_address(self: &its_v0::ITS_v0, source_chain: ascii::String, source_address: ascii::String): bool
Implementation
fun is_trusted_address(
    self: &ITS_v0,
    source_chain: String,
    source_address: String,
): bool {
    self.address_tracker.is_trusted_address(source_chain, source_address)
}

Function coin_management_mut

fun coin_management_mut<T>(self: &mut its_v0::ITS_v0, token_id: token_id::TokenId): &mut coin_management::CoinManagement<T>
Implementation
fun coin_management_mut<T>(
    self: &mut ITS_v0,
    token_id: TokenId,
): &mut CoinManagement<T> {
    let coin_data: &mut CoinData<T> = &mut self.registered_coins[token_id];
    coin_data.coin_management_mut()
}

Function add_unregistered_coin

fun add_unregistered_coin<T>(self: &mut its_v0::ITS_v0, token_id: token_id::UnregisteredTokenId, treasury_cap: coin::TreasuryCap<T>, coin_metadata: coin::CoinMetadata<T>)
Implementation
fun add_unregistered_coin<T>(
    self: &mut ITS_v0,
    token_id: UnregisteredTokenId,
    treasury_cap: TreasuryCap<T>,
    coin_metadata: CoinMetadata<T>,
) {
    self
        .unregistered_coins
        .add(
            token_id,
            unregistered_coin_data::new(
                treasury_cap,
                coin_metadata,
            ),
        );

    let type_name = type_name::get<T>();
    add_unregistered_coin_type(self, token_id, type_name);
}

Function remove_unregistered_coin

fun remove_unregistered_coin<T>(self: &mut its_v0::ITS_v0, token_id: token_id::UnregisteredTokenId): (coin::TreasuryCap<T>, coin::CoinMetadata<T>)
Implementation
fun remove_unregistered_coin<T>(
    self: &mut ITS_v0,
    token_id: UnregisteredTokenId,
): (TreasuryCap<T>, CoinMetadata<T>) {
    let unregistered_coins: UnregisteredCoinData<T> = self
        .unregistered_coins
        .remove(token_id);
    let (treasury_cap, coin_metadata) = unregistered_coins.destroy();

    remove_unregistered_coin_type(self, token_id);

    (treasury_cap, coin_metadata)
}

Function trusted_address

fun trusted_address(self: &its_v0::ITS_v0, chain_name: ascii::String): ascii::String
Implementation
fun trusted_address(self: &ITS_v0, chain_name: String): String {
    *self.address_tracker.trusted_address(chain_name)
}

Function add_unregistered_coin_type

fun add_unregistered_coin_type(self: &mut its_v0::ITS_v0, token_id: token_id::UnregisteredTokenId, type_name: type_name::TypeName)
Implementation
fun add_unregistered_coin_type(
    self: &mut ITS_v0,
    token_id: UnregisteredTokenId,
    type_name: TypeName,
) {
    self.unregistered_coin_types.add(token_id, type_name);
}

Function remove_unregistered_coin_type

fun remove_unregistered_coin_type(self: &mut its_v0::ITS_v0, token_id: token_id::UnregisteredTokenId): type_name::TypeName
Implementation
fun remove_unregistered_coin_type(
    self: &mut ITS_v0,
    token_id: UnregisteredTokenId,
): TypeName {
    self.unregistered_coin_types.remove(token_id)
}

Function add_registered_coin_type

fun add_registered_coin_type(self: &mut its_v0::ITS_v0, token_id: token_id::TokenId, type_name: type_name::TypeName)
Implementation
fun add_registered_coin_type(
    self: &mut ITS_v0,
    token_id: TokenId,
    type_name: TypeName,
) {
    self.registered_coin_types.add(token_id, type_name);
}

Function add_registered_coin

fun add_registered_coin<T>(self: &mut its_v0::ITS_v0, token_id: token_id::TokenId, coin_management: coin_management::CoinManagement<T>, coin_info: coin_info::CoinInfo<T>)
Implementation
fun add_registered_coin<T>(
    self: &mut ITS_v0,
    token_id: TokenId,
    mut coin_management: CoinManagement<T>,
    coin_info: CoinInfo<T>,
) {
    coin_management.set_scaling(coin_info.scaling());
    self
        .registered_coins
        .add(
            token_id,
            coin_data::new(
                coin_management,
                coin_info,
            ),
        );

    let type_name = type_name::get<T>();
    add_registered_coin_type(self, token_id, type_name);
}

Function prepare_message

Send a payload to a destination chain. The destination chain needs to have a trusted address.

fun prepare_message(self: &its_v0::ITS_v0, destination_chain: ascii::String, payload: vector<u8>): message_ticket::MessageTicket
Implementation
fun prepare_message(
    self: &ITS_v0,
    mut destination_chain: String,
    mut payload: vector<u8>,
): MessageTicket {
    let mut destination_address = self.trusted_address(destination_chain);

    // Prevent sending directly to the ITS Hub chain. This is not supported yet,
    // so fail early to prevent the user from having their funds stuck.
    assert!(
        destination_chain.into_bytes() != ITS_HUB_CHAIN_NAME,
        EUntrustedChain,
    );

    // Check whether the ITS call should be routed via ITS hub for this
    // destination chain
    if (destination_address.into_bytes() == ITS_HUB_ROUTING_IDENTIFIER) {
        let mut writer = abi::new_writer(3);
        writer.write_u256(MESSAGE_TYPE_SEND_TO_HUB);
        writer.write_bytes(destination_chain.into_bytes());
        writer.write_bytes(payload);
        payload = writer.into_bytes();
        destination_chain = ascii::string(ITS_HUB_CHAIN_NAME);
        destination_address = self.trusted_address(destination_chain);
    };

    gateway::prepare_message(
        &self.channel,
        destination_chain,
        destination_address,
        payload,
    )
}

Function decode_approved_message

Decode an approved call and check that the source chain is trusted.

fun decode_approved_message(self: &its_v0::ITS_v0, approved_message: channel::ApprovedMessage): (ascii::String, vector<u8>, ascii::String)
Implementation
fun decode_approved_message(
    self: &ITS_v0,
    approved_message: ApprovedMessage,
): (String, vector<u8>, String) {
    let (mut source_chain, message_id, source_address, mut payload) = self
        .channel
        .consume_approved_message(approved_message);

    assert!(
        self.is_trusted_address(source_chain, source_address),
        EUntrustedAddress,
    );

    let mut reader = abi::new_reader(payload);
    if (reader.read_u256() == MESSAGE_TYPE_RECEIVE_FROM_HUB) {
        assert!(
            source_chain.into_bytes() == ITS_HUB_CHAIN_NAME,
            EUntrustedChain,
        );

        source_chain = ascii::string(reader.read_bytes());
        payload = reader.read_bytes();

        assert!(
            self.trusted_address(source_chain).into_bytes() == ITS_HUB_ROUTING_IDENTIFIER,
            EUntrustedChain,
        );
    } else {
        assert!(
            source_chain.into_bytes() != ITS_HUB_CHAIN_NAME,
            EUntrustedChain,
        );
    };

    (source_chain, payload, message_id)
}