(a):
is_valid_delegate_for_feature(d);
```
- [Overview](#@Overview_0)
- [Usage](#@Usage_1)
- [Delegation](#@Delegation_2)
- [Struct `Cap`](#0x1_capability_Cap)
- [Struct `LinearCap`](#0x1_capability_LinearCap)
- [Resource `CapState`](#0x1_capability_CapState)
- [Resource `CapDelegateState`](#0x1_capability_CapDelegateState)
- [Constants](#@Constants_3)
- [Function `create`](#0x1_capability_create)
- [Function `acquire`](#0x1_capability_acquire)
- [Function `acquire_linear`](#0x1_capability_acquire_linear)
- [Function `validate_acquire`](#0x1_capability_validate_acquire)
- [Function `root_addr`](#0x1_capability_root_addr)
- [Function `linear_root_addr`](#0x1_capability_linear_root_addr)
- [Function `delegate`](#0x1_capability_delegate)
- [Function `revoke`](#0x1_capability_revoke)
- [Function `remove_element`](#0x1_capability_remove_element)
- [Function `add_element`](#0x1_capability_add_element)
- [Module Specification](#@Module_Specification_4)
use 0x1::error;
use 0x1::signer;
use 0x1::vector;
## Struct `Cap`
The token representing an acquired capability. Cannot be stored in memory, but copied and dropped freely.
struct Cap<Feature> has copy, drop
Fields
-
root: address
-
## Struct `LinearCap`
A linear version of a capability token. This can be used if an acquired capability should be enforced
to be used only once for an authorization.
struct LinearCap<Feature> has drop
Fields
-
root: address
-
## Resource `CapState`
An internal data structure for representing a configured capability.
struct CapState<Feature> has key
Fields
-
delegates: vector<address>
-
## Resource `CapDelegateState`
An internal data structure for representing a configured delegated capability.
struct CapDelegateState<Feature> has key
Fields
-
root: address
-
## Constants
const ECAP: u64 = 0;
const EDELEGATE: u64 = 1;
## Function `create`
Creates a new capability class, owned by the passed signer. A caller must pass a witness that
they own the Feature
type parameter.
public fun create<Feature>(owner: &signer, _feature_witness: &Feature)
Implementation
public fun create<Feature>(owner: &signer, _feature_witness: &Feature) {
let addr = signer::address_of(owner);
assert!(!exists<CapState<Feature>>(addr), error::already_exists(ECAP));
move_to<CapState<Feature>>(owner, CapState{ delegates: vector::empty() });
}
## Function `acquire`
Acquires a capability token. Only the owner of the capability class, or an authorized delegate,
can succeed with this operation. A caller must pass a witness that they own the Feature
type
parameter.
public fun acquire<Feature>(requester: &signer, _feature_witness: &Feature): capability::Cap<Feature>
Implementation
public fun acquire<Feature>(requester: &signer, _feature_witness: &Feature): Cap<Feature>
acquires CapState, CapDelegateState {
Cap<Feature>{root: validate_acquire<Feature>(requester)}
}
## Function `acquire_linear`
Acquires a linear capability token. It is up to the module which owns Feature
to decide
whether to expose a linear or non-linear capability.
public fun acquire_linear<Feature>(requester: &signer, _feature_witness: &Feature): capability::LinearCap<Feature>
Implementation
public fun acquire_linear<Feature>(requester: &signer, _feature_witness: &Feature): LinearCap<Feature>
acquires CapState, CapDelegateState {
LinearCap<Feature>{root: validate_acquire<Feature>(requester)}
}
## Function `validate_acquire`
Helper to validate an acquire. Returns the root address of the capability.
fun validate_acquire<Feature>(requester: &signer): address
Implementation
fun validate_acquire<Feature>(requester: &signer): address
acquires CapState, CapDelegateState {
let addr = signer::address_of(requester);
if (exists<CapDelegateState<Feature>>(addr)) {
let root_addr = borrow_global<CapDelegateState<Feature>>(addr).root;
// double check that requester is actually registered as a delegate
assert!(exists<CapState<Feature>>(root_addr), error::invalid_state(EDELEGATE));
assert!(vector::contains(&borrow_global<CapState<Feature>>(root_addr).delegates, &addr),
error::invalid_state(EDELEGATE));
root_addr
} else {
assert!(exists<CapState<Feature>>(addr), error::not_found(ECAP));
addr
}
}
## Function `root_addr`
Returns the root address associated with the given capability token. Only the owner
of the feature can do this.
public fun root_addr<Feature>(cap: capability::Cap<Feature>, _feature_witness: &Feature): address
Implementation
public fun root_addr<Feature>(cap: Cap<Feature>, _feature_witness: &Feature): address {
cap.root
}
## Function `linear_root_addr`
Returns the root address associated with the given linear capability token.
public fun linear_root_addr<Feature>(cap: capability::LinearCap<Feature>, _feature_witness: &Feature): address
Implementation
public fun linear_root_addr<Feature>(cap: LinearCap<Feature>, _feature_witness: &Feature): address {
cap.root
}
## Function `delegate`
Registers a delegation relation. If the relation already exists, this function does
nothing.
public fun delegate<Feature>(cap: capability::Cap<Feature>, _feature_witness: &Feature, to: &signer)
Implementation
public fun delegate<Feature>(cap: Cap<Feature>, _feature_witness: &Feature, to: &signer)
acquires CapState {
let addr = signer::address_of(to);
if (exists<CapDelegateState<Feature>>(addr)) return;
move_to(to, CapDelegateState<Feature>{root: cap.root});
add_element(&mut borrow_global_mut<CapState<Feature>>(cap.root).delegates, addr);
}
## Function `revoke`
Revokes a delegation relation. If no relation exists, this function does nothing.
public fun revoke<Feature>(cap: capability::Cap<Feature>, _feature_witness: &Feature, from: address)
Implementation
public fun revoke<Feature>(cap: Cap<Feature>, _feature_witness: &Feature, from: address)
acquires CapState, CapDelegateState
{
if (!exists<CapDelegateState<Feature>>(from)) return;
let CapDelegateState{root: _root} = move_from<CapDelegateState<Feature>>(from);
remove_element(&mut borrow_global_mut<CapState<Feature>>(cap.root).delegates, &from);
}
## Function `remove_element`
Helper to remove an element from a vector.
fun remove_element<E: drop>(v: &mut vector<E>, x: &E)
Implementation
fun remove_element<E: drop>(v: &mut vector<E>, x: &E) {
let (found, index) = vector::index_of(v, x);
if (found) {
vector::remove(v, index);
}
}
## Function `add_element`
Helper to add an element to a vector.
fun add_element<E: drop>(v: &mut vector<E>, x: E)
Implementation
fun add_element<E: drop>(v: &mut vector<E>, x: E) {
if (!vector::contains(v, &x)) {
vector::push_back(v, x)
}
}
## Module Specification
Helper specification function to check whether a capability exists at address.
fun spec_has_cap<Feature>(addr: address): bool {
exists<CapState<Feature>>(addr)
}
Helper specification function to obtain the delegates of a capability.
fun spec_delegates<Feature>(addr: address): vector<address> {
global<CapState<Feature>>(addr).delegates
}