Skip to main content

Module 0x2::borrow

A simple library that enables hot-potato-locked borrow mechanics.

With Programmable transactions, it is possible to borrow a value within a transaction, use it and put back in the end. Hot-potato Borrow makes sure the object is returned and was not swapped for another one.

use 0x1::option;
use 0x2::object;
use 0x2::tx_context;

Struct Referent

An object wrapping a T and providing the borrow API.

struct Referent<T: store, key> has store
Fields
id: address
value: option::Option<T>

Struct Borrow

A hot potato making sure the object is put back once borrowed.

struct Borrow
Fields
ref: address
obj: object::ID

Constants

The Borrow does not match the Referent.

const EWrongBorrow: u64 = 0;

An attempt to swap the Referent.value with another object of the same type.

const EWrongValue: u64 = 1;

Function new

Create a new Referent struct

public fun new<T: store, key>(value: T, ctx: &mut tx_context::TxContext): borrow::Referent<T>
Implementation
public fun new<T: key + store>(value: T, ctx: &mut TxContext): Referent<T> {
    Referent {
        id: tx_context::fresh_object_address(ctx),
        value: option::some(value)
    }
}

Function borrow

Borrow the T from the Referent receiving the T and a Borrow hot potato.

public fun borrow<T: store, key>(self: &mut borrow::Referent<T>): (T, borrow::Borrow)
Implementation
public fun borrow<T: key + store>(self: &mut Referent<T>): (T, Borrow) {
    let value = self.value.extract();
    let id = object::id(&value);

    (value, Borrow {
        ref: self.id,
        obj: id
    })
}

Function put_back

Put an object and the Borrow hot potato back.

public fun put_back<T: store, key>(self: &mut borrow::Referent<T>, value: T, borrow: borrow::Borrow)
Implementation
public fun put_back<T: key + store>(self: &mut Referent<T>, value: T, borrow: Borrow) {
    let Borrow { ref, obj } = borrow;

    assert!(object::id(&value) == obj, EWrongValue);
    assert!(self.id == ref, EWrongBorrow);
    self.value.fill(value);
}

Function destroy

Unpack the Referent struct and return the value.

public fun destroy<T: store, key>(self: borrow::Referent<T>): T
Implementation
public fun destroy<T: key + store>(self: Referent<T>): T {
    let Referent { id: _, value } = self;
    value.destroy_some()
}