axelar-cgp-sui

Module 0xa4::operators

use 0x1::ascii;
use 0x1::type_name;
use 0x2::bag;
use 0x2::event;
use 0x2::object;
use 0x2::transfer;
use 0x2::tx_context;
use 0x2::vec_set;

Resource OwnerCap

The OwnerCap capability representing the owner of the contract.

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

Resource OperatorCap

The OperatorCap capability representing an approved operator.

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

Resource Operators

The main Operators struct storing the capabilities and operator IDs.

struct Operators has key
Fields
id: object::UID
operators: vec_set::VecSet<address>
caps: bag::Bag

Struct Borrow

struct Borrow
Fields
id: object::ID

Struct OperatorAdded

Event emitted when a new operator is added.

struct OperatorAdded has copy, drop
Fields
operator: address

Struct OperatorRemoved

Event emitted when an operator is removed.

struct OperatorRemoved has copy, drop
Fields
operator: address

Struct CapabilityStored

Event emitted when a capability is stored.

struct CapabilityStored has copy, drop
Fields
cap_id: object::ID
cap_name: ascii::String

Struct CapabilityRemoved

Event emitted when a capability is removed.

struct CapabilityRemoved has copy, drop
Fields
cap_id: object::ID
cap_name: ascii::String

Constants

When the cap trying to restore does not match the Borrow object.

const ECapIdMismatch: vector<u8> = [116, 104, 101, 32, 73, 68, 32, 111, 102, 32, 116, 104, 101, 32, 114, 101, 116, 117, 114, 110, 101, 100, 32, 99, 97, 112, 97, 98, 105, 108, 105, 116, 121, 32, 100, 111, 101, 115, 32, 110, 111, 116, 32, 109, 97, 116, 99, 104, 32, 116, 104, 101, 32, 73, 68, 32, 105, 110, 32, 116, 104, 101, 32, 66, 111, 114, 114, 111, 119, 32, 111, 98, 106, 101, 99, 116];

When the capability is not found.

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

When the operator is not found in the set of approved operators.

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

Function init

Initializes the contract and transfers the OwnerCap to the sender.

fun init(ctx: &mut tx_context::TxContext)
Implementation
fun init(ctx: &mut TxContext) {
    transfer::share_object(Operators {
        id: object::new(ctx),
        operators: vec_set::empty(),
        caps: bag::new(ctx),
    });

    let cap = OwnerCap {
        id: object::new(ctx),
    };

    transfer::transfer(cap, ctx.sender());
}

Function add_operator

Adds a new operator by issuing an OperatorCap and storing its ID.

public fun add_operator(self: &mut operators::Operators, _: &operators::OwnerCap, new_operator: address, ctx: &mut tx_context::TxContext)
Implementation
public fun add_operator(
    self: &mut Operators,
    _: &OwnerCap,
    new_operator: address,
    ctx: &mut TxContext,
) {
    let operator_cap = OperatorCap {
        id: object::new(ctx),
    };

    transfer::transfer(operator_cap, new_operator);
    self.operators.insert(new_operator);

    event::emit(OperatorAdded {
        operator: new_operator,
    });
}

Function remove_operator

Removes an operator by ID, revoking their OperatorCap.

public fun remove_operator(self: &mut operators::Operators, _: &operators::OwnerCap, operator: address)
Implementation
public fun remove_operator(
    self: &mut Operators,
    _: &OwnerCap,
    operator: address,
) {
    self.operators.remove(&operator);

    event::emit(OperatorRemoved {
        operator,
    });
}

Function store_cap

Stores a capability in the Operators struct.

public fun store_cap<T: store, key>(self: &mut operators::Operators, _: &operators::OwnerCap, cap: T)
Implementation
public fun store_cap<T: key + store>(
    self: &mut Operators,
    _: &OwnerCap,
    cap: T,
) {
    let cap_id = object::id(&cap);
    self.caps.add(cap_id, cap);

    event::emit(CapabilityStored {
        cap_id,
        cap_name: type_name::get<T>().into_string(),
    });
}

Function loan_cap

Allows an approved operator to temporarily loan out a capability by its ID. The loaned capability must be restored by the end of the transaction.

public fun loan_cap<T: store, key>(self: &mut operators::Operators, _operator_cap: &operators::OperatorCap, cap_id: object::ID, ctx: &mut tx_context::TxContext): (T, operators::Borrow)
Implementation
public fun loan_cap<T: key + store>(
    self: &mut Operators,
    _operator_cap: &OperatorCap,
    cap_id: ID,
    ctx: &mut TxContext,
): (T, Borrow) {
    assert!(self.operators.contains(&ctx.sender()), EOperatorNotFound);
    assert!(self.caps.contains(cap_id), ECapNotFound);

    // Remove the capability from the `Operators` struct to loan it out
    let cap = self.caps.remove(cap_id);

    // Create the Borrow object which tracks the id of the cap loaned.
    let borrow_obj = Borrow {
        id: object::id(&cap),
    };

    // Return a tuple of the borrowed capability and the Borrow hot potato object
    (cap, borrow_obj)
}

Function restore_cap

Restores a previously loaned capability back to the Operators struct. This function must be called before the end of the transaction to return the loaned capability.

public fun restore_cap<T: store, key>(self: &mut operators::Operators, _operator_cap: &operators::OperatorCap, cap: T, borrow_obj: operators::Borrow)
Implementation
public fun restore_cap<T: key + store>(
    self: &mut Operators,
    _operator_cap: &OperatorCap,
    cap: T,
    borrow_obj: Borrow,
) {
    let cap_id = object::id(&cap);

    // Destroy the Borrow object and capture the id it tracks.
    let Borrow { id } = borrow_obj;

    // Make sure the Borrow object corresponds to cap returned.
    assert!(id == cap_id, ECapIdMismatch);

    // Add the capability back to the `Operators` struct
    self.caps.add(cap_id, cap);
}

Function remove_cap

Removes a capability from the Operators struct.

public fun remove_cap<T: store, key>(self: &mut operators::Operators, _: &operators::OwnerCap, cap_id: object::ID): T
Implementation
public fun remove_cap<T: key + store>(
    self: &mut Operators,
    _: &OwnerCap,
    cap_id: ID,
): T {
    event::emit(CapabilityRemoved {
        cap_id,
        cap_name: type_name::get<T>().into_string(),
    });

    self.caps.remove<ID, T>(cap_id)
}