Skip to main content

Transferable Witness

The transferable witness pattern is based on a combination of capability and witness patterns. Because you should be careful with the witness pattern, you should allow only authorized users to spawn it (ideally only once). Some scenarios, however, require type authorization by module X to be used in another module Y. Or, possibly, there's a case where authorization should be performed after some time.

For these rather rare scenarios, a storable witness is a good solution.

module examples::transferable_witness {

/// Witness now has a `store` that allows us to store it inside a wrapper.
public struct WITNESS has store, drop {}


/// Carries the witness type. Can be used only once to get a Witness.
public struct WitnessCarrier has key { id: UID, witness: WITNESS }


/// Send a `WitnessCarrier` to the module publisher.
fun init(ctx: &mut TxContext) {
transfer::transfer(
WitnessCarrier { id: object::new(ctx), witness: WITNESS {} },
tx_context::sender(ctx)
)
}


/// Unwrap a carrier and get the inner WITNESS type.
public fun get_witness(carrier: WitnessCarrier): WITNESS {
let WitnessCarrier { id, witness } = carrier;
object::delete(id);
witness
}
}