0xa4::operators
OwnerCap
OperatorCap
Operators
Borrow
OperatorAdded
OperatorRemoved
CapabilityStored
CapabilityRemoved
init
add_operator
remove_operator
store_cap
loan_cap
restore_cap
remove_cap
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;
OwnerCap
The OwnerCap
capability representing the owner of the contract.
struct OwnerCap has store, key
id: object::UID
OperatorCap
The OperatorCap
capability representing an approved operator.
struct OperatorCap has store, key
id: object::UID
Operators
The main Operators
struct storing the capabilities and operator IDs.
struct Operators has key
id: object::UID
operators: vec_set::VecSet<address>
caps: bag::Bag
Borrow
struct Borrow
id: object::ID
OperatorAdded
Event emitted when a new operator is added.
struct OperatorAdded has copy, drop
operator: address
OperatorRemoved
Event emitted when an operator is removed.
struct OperatorRemoved has copy, drop
operator: address
CapabilityStored
Event emitted when a capability is stored.
struct CapabilityStored has copy, drop
cap_id: object::ID
cap_name: ascii::String
CapabilityRemoved
Event emitted when a capability is removed.
struct CapabilityRemoved has copy, drop
cap_id: object::ID
cap_name: ascii::String
When the cap trying to restore does not match the Borrow object.
#[error]
const ECapIdMismatch: vector<u8> = b"the ID of the returned capability does not match the ID in the Borrow object";
When the capability is not found.
#[error]
const ECapNotFound: vector<u8> = b"the given capability id does not exist";
When the operator is not found in the set of approved operators.
#[error]
const EOperatorNotFound: vector<u8> = b"the sender is not an operator";
init
Initializes the contract and transfers the OwnerCap
to the sender.
fun init(ctx: &mut tx_context::TxContext)
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());
}
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)
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,
});
}
remove_operator
Removes an operator by ID, revoking their OperatorCap
.
public fun remove_operator(self: &mut operators::Operators, _: &operators::OwnerCap, operator: address)
public fun remove_operator(
self: &mut Operators,
_: &OwnerCap,
operator: address,
) {
self.operators.remove(&operator);
event::emit(OperatorRemoved {
operator,
});
}
store_cap
Stores a capability in the Operators
struct.
public fun store_cap<T: store, key>(self: &mut operators::Operators, _: &operators::OwnerCap, cap: T)
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(),
});
}
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)
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)
}
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)
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);
}
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
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)
}