axelar-cgp-sui

Module 0xa9::operators

use 0x1::option;
use 0x2::coin;
use 0x2::object;
use 0x2::transfer;
use 0x2::tx_context;
use 0xa1::channel;
use 0xa4::operators;
use 0xa5::interchain_token_service;
use 0xa5::token_id;

Resource MultiMinter

struct MultiMinter has key
Fields
id: object::UID
distributor_cap: option::Option<channel::Channel>
operator_cap: option::Option<operators::OperatorCap>
distributor_cap_id: option::Option<object::ID>

Resource OwnerCap

struct OwnerCap has store, key
Fields
id: object::UID

Function init

fun init(ctx: &mut tx_context::TxContext)
Implementation
fun init(ctx: &mut TxContext) {
    transfer::share_object(MultiMinter {
        id: object::new(ctx),
        distributor_cap: option::none(),
        operator_cap: option::none(),
        distributor_cap_id: option::none(),
    });

    transfer::public_transfer(
        OwnerCap {
            id: object::new(ctx),
        },
        ctx.sender(),
    );
}

Function mint

Requirements: Only ITS and this package need to have mint capability over the Coin simultaneously. Setup: When registering the coin with ITS, the TreasuryCap is provided to ITS, and ITS returns a distributor Channel capability, along with TreasuryCapReclaimer that can reclaim the treasury cap to stop bridging. The Distributor Channel cap allows an additional action to mint the coin. This should be stored in this package’s object by calling the add_distributor_cap._owner_cap

mint_as_distributor can be called by this package to mint the coin.

public fun mint<T>(self: &operators::MultiMinter, its: &mut interchain_token_service::InterchainTokenService, token_id: token_id::TokenId, amount: u64, ctx: &mut tx_context::TxContext): coin::Coin<T>
Implementation
public fun mint<T>(self: &MultiMinter, its: &mut InterchainTokenService, token_id: TokenId, amount: u64, ctx: &mut TxContext): Coin<T> {
    let coin = its.mint_as_distributor<T>(self.distributor_cap.borrow(), token_id, amount, ctx);
    coin
}

Function add_distributor_cap

After registering the coin with ITS, store the distributor Channel capability here.

public fun add_distributor_cap(self: &mut operators::MultiMinter, _owner_cap: &operators::OwnerCap, distributor_cap: channel::Channel)
Implementation
public fun add_distributor_cap(self: &mut MultiMinter, _owner_cap: &OwnerCap, distributor_cap: Channel) {
    self.distributor_cap.fill(distributor_cap);
}

Function remove_distributor_cap

Acquire the distributor Channel capability from the MultiMinter object.

public fun remove_distributor_cap(self: &mut operators::MultiMinter, _owner_cap: &operators::OwnerCap): channel::Channel
Implementation
public fun remove_distributor_cap(self: &mut MultiMinter, _owner_cap: &OwnerCap): Channel {
    self.distributor_cap.extract()
}

Function mint_as_operator

Requirements: ITS, this package, and other addresses need to have mint capability over the Coin simultaneously. Setup: This is a more demanding requirement and thus the Operators contract can be used to give multiple operators the ability to mint. When registering the coin with ITS, the TreasuryCap is provided to ITS, and ITS returns a distributor Channel capability, along with TreasuryCapReclaimer that can reclaim the treasury cap to stop bridging. The Distributor Channel cap allows an additional action to mint the coin.

An instance of the Operators contract needs to be deployed. The Channel capability then needs to be stored by calling store_cap. The OperatorCap needs to be stored by calling add_operator_cap, along with Channel capability ID.

Now, using the OperatorCap, the Channel cap can be loaned from the Operators contract. Then, it can be used to mint the coin via ITS, and the loaned Channel cap can be returned to the Operators contract atomically.

public fun mint_as_operator<T>(self: &mut operators::MultiMinter, its: &mut interchain_token_service::InterchainTokenService, operators: &mut operators::Operators, token_id: token_id::TokenId, amount: u64, ctx: &mut tx_context::TxContext): coin::Coin<T>
Implementation
public fun mint_as_operator<T>(
    self: &mut MultiMinter,
    its: &mut InterchainTokenService,
    operators: &mut Operators,
    token_id: TokenId,
    amount: u64,
    ctx: &mut TxContext,
): Coin<T> {
    let (distributor_cap, borrow) = operators.loan_cap<Channel>(self.operator_cap.borrow(), *self.distributor_cap_id.borrow(), ctx);
    let coin = its.mint_as_distributor<T>(&distributor_cap, token_id, amount, ctx);
    operators.restore_cap(self.operator_cap.borrow(), distributor_cap, borrow);
    coin
}

Function add_operator_cap

Store the OperatorCap capability that was given by the Operators contract.

public fun add_operator_cap(self: &mut operators::MultiMinter, _owner_cap: &operators::OwnerCap, operator_cap: operators::OperatorCap, distributor_cap_id: object::ID)
Implementation
public fun add_operator_cap(self: &mut MultiMinter, _owner_cap: &OwnerCap, operator_cap: OperatorCap, distributor_cap_id: ID) {
    self.distributor_cap_id.fill(distributor_cap_id);
    self.operator_cap.fill(operator_cap);
}

Function remove_operator_cap

Acquire the OperatorCap capability from the MultiMinter object.

public fun remove_operator_cap(self: &mut operators::MultiMinter, _owner_cap: &operators::OwnerCap): operators::OperatorCap
Implementation
public fun remove_operator_cap(self: &mut MultiMinter, _owner_cap: &OwnerCap): OperatorCap {
    let _ = self.distributor_cap_id.extract();
    self.operator_cap.extract()
}