Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use hot potato pattern to borrow cap #96

Merged
merged 18 commits into from
Aug 13, 2024
Merged
48 changes: 39 additions & 9 deletions move/operators/sources/operators.move
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ module operators::operators {
caps: Bag,
}

public struct BorrowedCap<T: key + store> {
npty marked this conversation as resolved.
Show resolved Hide resolved
cap: T
}

// ------
// Errors
// ------
Expand Down Expand Up @@ -123,15 +127,29 @@ module operators::operators {

/// Allows an approved operator to borrow a capability by its ID.
public fun borrow_cap<T: key + store>(
npty marked this conversation as resolved.
Show resolved Hide resolved
self: &Operators,
self: &mut Operators,
_operator_cap: &OperatorCap,
cap_id: ID,
ctx: &mut TxContext
): &T {
): BorrowedCap<T> {
assert!(self.operators.contains(&ctx.sender()), EOperatorNotFound);
assert!(self.caps.contains(cap_id), ECapNotFound);

&self.caps[cap_id]
BorrowedCap<T> {
cap: bag::remove(&mut self.caps, cap_id)
}
}

/// Restore a borrowed capability back to the `Operators` struct.
npty marked this conversation as resolved.
Show resolved Hide resolved
public fun restore_cap<T: key + store>(
self: &mut Operators,
_operator_cap: &OperatorCap,
cap_id: ID,
borrow_cap: BorrowedCap<T>
) {
let BorrowedCap { cap } = borrow_cap;

bag::add(&mut self.caps, cap_id, cap);
}

/// Allows an approved operator to borrow a capability by its ID.
Expand All @@ -140,11 +158,16 @@ module operators::operators {
_operator_cap: &OperatorCap,
cap_id: ID,
ctx: &mut TxContext
): &mut T {
): BorrowedCap<T> {
assert!(self.operators.contains(&ctx.sender()), EOperatorNotFound);
assert!(self.caps.contains(cap_id), ECapNotFound);

&mut self.caps[cap_id]
// &mut self.caps[cap_id]
let caps = bag::remove(&mut self.caps, cap_id);

BorrowedCap<T> {
cap: caps
}
}

/// Removes a capability from the `Operators` struct.
Expand Down Expand Up @@ -255,8 +278,13 @@ module operators::operators {
store_cap(&mut operators, &owner_cap, external_cap);
assert!(operators.caps.contains(external_id), 0);

let borrowed_cap = borrow_cap<OwnerCap>(&operators, &operator_cap, external_id, ctx);
assert!(object::id(borrowed_cap) == external_id, 1);
let borrowed_cap = borrow_cap<OwnerCap>(&mut operators, &operator_cap, external_id, ctx);
// The cap should be removed from operators when borrowed
assert!(!operators.caps.contains(external_id), 1);
// Restore the borrowed cap
restore_cap(&mut operators, &operator_cap, external_id, borrowed_cap);
// The cap should be restored to operators
assert!(operators.caps.contains(external_id), 1);

let borrowed_mut_cap = borrow_cap_mut<OwnerCap>(&mut operators, &operator_cap, external_id, ctx);
assert!(object::id(borrowed_mut_cap) == external_id, 1);
Expand Down Expand Up @@ -297,7 +325,8 @@ module operators::operators {
store_cap(&mut operators, &owner_cap, external_cap);
remove_operator(&mut operators, &owner_cap, ctx.sender());

borrow_cap<OwnerCap>(&operators, &operator_cap, external_id, ctx);
let borrowed_cap = borrow_cap<OwnerCap>(&mut operators, &operator_cap, external_id, ctx);
restore_cap(&mut operators, &operator_cap, external_id, borrowed_cap);

destroy_operator_cap(operator_cap);
destroy_owner_cap(owner_cap);
Expand All @@ -314,7 +343,8 @@ module operators::operators {

let operator_id = object::id(&operator_cap);

borrow_cap<OwnerCap>(&operators, &operator_cap, operator_id, ctx);
let borrowed_cap = borrow_cap<OwnerCap>(&mut operators, &operator_cap, operator_id, ctx);
restore_cap(&mut operators, &operator_cap, operator_id, borrowed_cap);

destroy_operator_cap(operator_cap);
destroy_owner_cap(owner_cap);
Expand Down
Loading