# Module `0x1::vault` A module which implements secure memory (called a *vault*) of some content which can only be operated on if authorized by a signer. Authorization is managed by [*capabilities*](https://en.wikipedia.org/wiki/Capability-based_security). The vault supports delegation of capabilities to other signers (including revocation) as well as transfer of ownership. ## Overview ### Capabilities Capabilities are unforgeable tokens which represent the right to perform a particular operation on the vault. To acquire a capability instance, authentication via a signer is needed. This signer must either be the owner of the vault, or someone the capability has been delegated to. Once acquired, a capability can be passed to other functions to perform the operation it enables. Specifically, those called functions do not need to have access to the original signer. This is a key property of capability based security as it prevents granting more rights to code than needed. Capability instances are unforgeable because they are localized to transactions. They can only be created by functions of this module, and as they do not have the Move language store or key abilities, they cannot leak out of a transaction. Example: ```move struct Content has store { ssn: u64 } ... // Create new vault vault::new(signer, b"My Vault", Content{ ssn: 525659745 }); ... // Obtain a read capability let read_cap = vault::acquire_read_cap(signer); process(&read_cap) ... fun process(cap: &vault::ReadCap) { let accessor = vault::read_accessor(cap); let content = vault::borrow(accessor); << do something with content: &Content >> vault::release_read_accessor(accessor); } ``` ### Delegation Delegation provides the option to delegate the right to acquire a vault capability to other signers than the owner of the vault. Delegates still need to authenticate themselves using their signer, similar as the owner does. All security arguments for owners apply also to delegates. Delegation can be revoked removing previously granted rights from a delegate. Delegation can be configured to be transitive by granting the right to acquire a delegation capability to delegates, which can then further delegate access rights. By default, when a vault is created, it does not support delegation. The owner of the vault needs to explicitly enable delegation. This allows to create vaults which are not intended for delegation and one does not need to worry about its misuse. Example: ```move vault::new(signer, b"My Vault", Content{ ssn: 525659745 }); // Enable delegation for this vault. Only the owning signer can do this. vault::enable_delegation(signer); ... // Delegate read capability to some other signer. let delegate_cap = vault::acquire_delegate_cap(signer); vault::delegate_read_cap(&delegate_cap, other_signer); ... // Other signer can now acquire read cap let read_cap = vault::acquire_read_cap(other_signer); ... // The granted capability can be revoked. There is no need to have the other signer for this. vault::revoke_read_cap(&delegate_cap, signer::address_of(other_signer)); ``` ### Abilities Currently, we require that the Content type of a vault has the drop ability in order to instantiate a capability type like ReadCap<Content>. Without this, capabilities themselves would need to have an explicit release function, which makes little sense as they are pure values. We expect the Move language to have 'phantom type parameters' or similar features added, which will allows us to have ReadCap<Content> droppable and copyable without Content needing the same. - [Overview](#@Overview_0) - [Capabilities](#@Capabilities_1) - [Delegation](#@Delegation_2) - [Abilities](#@Abilities_3) - [Struct `ReadCap`](#0x1_vault_ReadCap) - [Struct `ModifyCap`](#0x1_vault_ModifyCap) - [Struct `DelegateCap`](#0x1_vault_DelegateCap) - [Struct `TransferCap`](#0x1_vault_TransferCap) - [Struct `CapType`](#0x1_vault_CapType) - [Struct `VaultDelegateEvent`](#0x1_vault_VaultDelegateEvent) - [Struct `VaultTransferEvent`](#0x1_vault_VaultTransferEvent) - [Resource `Vault`](#0x1_vault_Vault) - [Resource `VaultDelegates`](#0x1_vault_VaultDelegates) - [Resource `VaultEvents`](#0x1_vault_VaultEvents) - [Resource `VaultDelegate`](#0x1_vault_VaultDelegate) - [Struct `ReadAccessor`](#0x1_vault_ReadAccessor) - [Struct `ModifyAccessor`](#0x1_vault_ModifyAccessor) - [Constants](#@Constants_4) - [Function `read_cap_type`](#0x1_vault_read_cap_type) - [Function `modify_cap_type`](#0x1_vault_modify_cap_type) - [Function `delegate_cap_type`](#0x1_vault_delegate_cap_type) - [Function `transfer_cap_type`](#0x1_vault_transfer_cap_type) - [Function `new`](#0x1_vault_new) - [Function `is_delegation_enabled`](#0x1_vault_is_delegation_enabled) - [Function `enable_delegation`](#0x1_vault_enable_delegation) - [Function `enable_events`](#0x1_vault_enable_events) - [Function `remove_vault`](#0x1_vault_remove_vault) - [Function `acquire_read_cap`](#0x1_vault_acquire_read_cap) - [Function `acquire_modify_cap`](#0x1_vault_acquire_modify_cap) - [Function `acquire_delegate_cap`](#0x1_vault_acquire_delegate_cap) - [Function `acquire_transfer_cap`](#0x1_vault_acquire_transfer_cap) - [Function `validate_cap`](#0x1_vault_validate_cap) - [Function `read_accessor`](#0x1_vault_read_accessor) - [Function `borrow`](#0x1_vault_borrow) - [Function `release_read_accessor`](#0x1_vault_release_read_accessor) - [Function `modify_accessor`](#0x1_vault_modify_accessor) - [Function `borrow_mut`](#0x1_vault_borrow_mut) - [Function `release_modify_accessor`](#0x1_vault_release_modify_accessor) - [Function `delegate`](#0x1_vault_delegate) - [Function `revoke`](#0x1_vault_revoke) - [Function `revoke_all`](#0x1_vault_revoke_all) - [Function `remove_element`](#0x1_vault_remove_element) - [Function `add_element`](#0x1_vault_add_element) - [Function `emit_delegate_event`](#0x1_vault_emit_delegate_event) - [Function `transfer`](#0x1_vault_transfer)
use 0x1::error;
use 0x1::event;
use 0x1::option;
use 0x1::signer;
use 0x1::vector;
## Struct `ReadCap` A capability to read the content of the vault. Notice that the capability cannot be stored but can be freely copied and dropped. TODO: remove drop on Content here and elsewhere once we have phantom type parameters.
struct ReadCap<Content: drop, store> has copy, drop
Fields
vault_address: address
authority: address
## Struct `ModifyCap` A capability to modify the content of the vault.
struct ModifyCap<Content: drop, store> has copy, drop
Fields
vault_address: address
authority: address
## Struct `DelegateCap` A capability to delegate access to the vault.
struct DelegateCap<Content: drop, store> has copy, drop
Fields
vault_address: address
authority: address
## Struct `TransferCap` A capability to transfer ownership of the vault.
struct TransferCap<Content: drop, store> has copy, drop
Fields
vault_address: address
authority: address
## Struct `CapType` A type describing a capability. This is used for functions like Self::delegate where we need to specify capability types.
struct CapType has copy, drop, store
Fields
code: u8
## Struct `VaultDelegateEvent` An event which we generate on vault access delegation or revocation if event generation is enabled.
struct VaultDelegateEvent has drop, store
Fields
metadata: vector<u8>
vault_address: address
authority: address
delegate: address
cap: vault::CapType
is_revoked: bool
## Struct `VaultTransferEvent` An event which we generate on vault transfer if event generation is enabled.
struct VaultTransferEvent has drop, store
Fields
metadata: vector<u8>
vault_address: address
authority: address
new_vault_address: address
## Resource `Vault` Private. The vault representation.
struct Vault<Content: store> has key
Fields
content: option::Option<Content>
The content. If the option is empty, the content is currently moved into an accessor in order to work with it.
## Resource `VaultDelegates` Private. If the vault supports delegation, information about the delegates.
struct VaultDelegates<Content: store> has key
Fields
delegates: vector<address>
The currently authorized delegates.
## Resource `VaultEvents` Private. If event generation is enabled, contains the event generators.
struct VaultEvents<Content: store> has key
Fields
metadata: vector<u8>
Metadata which identifies this vault. This information is used in events generated by this module.
delegate_events: event::EventHandle<vault::VaultDelegateEvent>
Event handle for vault delegation.
transfer_events: event::EventHandle<vault::VaultTransferEvent>
Event handle for vault transfer.
## Resource `VaultDelegate` Private. A value stored at a delegates address pointing to the owner of the vault. Also describes the capabilities granted to this delegate.
struct VaultDelegate<Content: store> has key
Fields
vault_address: address
granted_caps: vector<vault::CapType>
## Struct `ReadAccessor` A read accessor for the content of the vault.
struct ReadAccessor<Content: drop, store>
Fields
content: Content
vault_address: address
## Struct `ModifyAccessor` A modify accessor for the content of the vault.
struct ModifyAccessor<Content: drop, store>
Fields
content: Content
vault_address: address
## Constants
const EDELEGATE: u64 = 1;
const EACCESSOR_INCONSISTENCY: u64 = 3;
const EACCESSOR_IN_USE: u64 = 2;
const EDELEGATE_TO_SELF: u64 = 4;
const EDELEGATION_NOT_ENABLED: u64 = 5;
const EEVENT: u64 = 6;
const EVAULT: u64 = 0;
## Function `read_cap_type` Creates a read capability type.
public fun read_cap_type(): vault::CapType
Implementation
public fun read_cap_type(): CapType { CapType{ code : 0 } }
## Function `modify_cap_type` Creates a modify capability type.
public fun modify_cap_type(): vault::CapType
Implementation
public fun modify_cap_type(): CapType { CapType{ code : 1 } }
## Function `delegate_cap_type` Creates a delegate capability type.
public fun delegate_cap_type(): vault::CapType
Implementation
public fun delegate_cap_type(): CapType { CapType{ code : 2 } }
## Function `transfer_cap_type` Creates a transfer capability type.
public fun transfer_cap_type(): vault::CapType
Implementation
public fun transfer_cap_type(): CapType { CapType{ code : 3 } }
## Function `new` Creates new vault for the given signer. The vault is populated with the initial_content.
public fun new<Content: store>(owner: &signer, initial_content: Content)
Implementation
public fun new<Content: store>(owner: &signer,  initial_content: Content) {
    let addr = signer::address_of(owner);
    assert!(!exists<Vault<Content>>(addr), error::already_exists(EVAULT));
    move_to<Vault<Content>>(
        owner,
        Vault{
            content: option::some(initial_content)
        }
    )
}
## Function `is_delegation_enabled` Returns true if the delegation functionality has been enabled. Returns false otherwise.
public fun is_delegation_enabled<Content: store>(owner: &signer): bool
Implementation
public fun is_delegation_enabled<Content: store>(owner: &signer): bool {
    let addr = signer::address_of(owner);
    assert!(exists<Vault<Content>>(addr), error::not_found(EVAULT));
    exists<VaultDelegates<Content>>(addr)
}
## Function `enable_delegation` Enables delegation functionality for this vault. By default, vaults to not support delegation.
public fun enable_delegation<Content: store>(owner: &signer)
Implementation
public fun enable_delegation<Content: store>(owner: &signer) {
    assert!(!is_delegation_enabled<Content>(owner), error::already_exists(EDELEGATE));
    move_to<VaultDelegates<Content>>(owner, VaultDelegates{delegates: vector::empty()})
}
## Function `enable_events` Enables event generation for this vault. This passed metadata is used to identify the vault in events.
public fun enable_events<Content: store>(owner: &signer, metadata: vector<u8>)
Implementation
public fun enable_events<Content: store>(owner: &signer, metadata: vector<u8>) {
    let addr = signer::address_of(owner);
    assert!(exists<Vault<Content>>(addr), error::not_found(EVAULT));
    assert!(!exists<VaultEvents<Content>>(addr), error::already_exists(EEVENT));
    move_to<VaultEvents<Content>>(
        owner,
        VaultEvents{
            metadata,
            delegate_events: event::new_event_handle<VaultDelegateEvent>(owner),
            transfer_events: event::new_event_handle<VaultTransferEvent>(owner),
        }
    );
}
## Function `remove_vault` Removes a vault and all its associated data, returning the current content. In order for this to succeed, there must be no active accessor for the vault.
public fun remove_vault<Content: drop, store>(owner: &signer): Content
Implementation
public fun remove_vault<Content: store + drop>(owner: &signer): Content
acquires Vault, VaultDelegates, VaultDelegate, VaultEvents {
    let addr = signer::address_of(owner);
    assert!(exists<Vault<Content>>(addr), error::not_found(EVAULT));
    let Vault{content} = move_from<Vault<Content>>(addr);
    assert!(option::is_some(&content), error::invalid_state(EACCESSOR_IN_USE));

    if (exists<VaultDelegates<Content>>(addr)) {
        let delegate_cap = DelegateCap<Content>{vault_address: addr, authority: addr};
        revoke_all(&delegate_cap);
    };
    if (exists<VaultEvents<Content>>(addr)) {
        let VaultEvents{metadata: _metadata, delegate_events, transfer_events} =
            move_from<VaultEvents<Content>>(addr);
        event::destroy_handle(delegate_events);
        event::destroy_handle(transfer_events);
    };

    option::extract(&mut content)
}
## Function `acquire_read_cap` Acquires the capability to read the vault. The passed signer must either be the owner of the vault or a delegate with appropriate access.
public fun acquire_read_cap<Content: drop, store>(requester: &signer): vault::ReadCap<Content>
Implementation
public fun acquire_read_cap<Content: store + drop>(requester: &signer): ReadCap<Content>
acquires VaultDelegate {
    let (vault_address, authority) = validate_cap<Content>(requester, read_cap_type());
    ReadCap{ vault_address, authority }
}
## Function `acquire_modify_cap` Acquires the capability to modify the vault. The passed signer must either be the owner of the vault or a delegate with appropriate access.
public fun acquire_modify_cap<Content: drop, store>(requester: &signer): vault::ModifyCap<Content>
Implementation
public fun acquire_modify_cap<Content: store + drop>(requester: &signer): ModifyCap<Content>
acquires VaultDelegate {
    let (vault_address, authority) = validate_cap<Content>(requester, modify_cap_type());
    ModifyCap{ vault_address, authority }
}
## Function `acquire_delegate_cap` Acquires the capability to delegate access to the vault. The passed signer must either be the owner of the vault or a delegate with appropriate access.
public fun acquire_delegate_cap<Content: drop, store>(requester: &signer): vault::DelegateCap<Content>
Implementation
public fun acquire_delegate_cap<Content: store + drop>(requester: &signer): DelegateCap<Content>
acquires VaultDelegate {
    let (vault_address, authority) = validate_cap<Content>(requester, delegate_cap_type());
    DelegateCap{ vault_address, authority }
}
## Function `acquire_transfer_cap` Acquires the capability to transfer the vault. The passed signer must either be the owner of the vault or a delegate with appropriate access.
public fun acquire_transfer_cap<Content: drop, store>(requester: &signer): vault::TransferCap<Content>
Implementation
public fun acquire_transfer_cap<Content: store + drop>(requester: &signer): TransferCap<Content>
acquires VaultDelegate {
    let (vault_address, authority) = validate_cap<Content>(requester, transfer_cap_type());
    TransferCap{ vault_address, authority }
}
## Function `validate_cap` Private. Validates whether a capability can be acquired by the given signer. Returns the pair of the vault address and the used authority.
fun validate_cap<Content: drop, store>(requester: &signer, cap: vault::CapType): (address, address)
Implementation
fun validate_cap<Content: store + drop>(requester: &signer, cap: CapType): (address, address)
acquires VaultDelegate {
    let addr = signer::address_of(requester);
    if (exists<VaultDelegate<Content>>(addr)) {
        // The signer is a delegate. Check it's granted capabilities.
        let delegate = borrow_global<VaultDelegate<Content>>(addr);
        assert!(vector::contains(&delegate.granted_caps, &cap), error::permission_denied(EDELEGATE));
        (delegate.vault_address, addr)
    } else {
        // If it is not a delegate, it must be the owner to succeed.
        assert!(exists<Vault<Content>>(addr), error::not_found(EVAULT));
        (addr, addr)
    }
}
## Function `read_accessor` Creates a read accessor for the content in the vault based on a read capability. Only one accessor (whether read or modify) for the same vault can exist at a time, and this function will abort if one is in use. An accessor must be explicitly released using Self::release_read_accessor.
public fun read_accessor<Content: drop, store>(cap: &vault::ReadCap<Content>): vault::ReadAccessor<Content>
Implementation
public fun read_accessor<Content: store + drop>(cap: &ReadCap<Content>): ReadAccessor<Content>
acquires Vault {
    let content = &mut borrow_global_mut<Vault<Content>>(cap.vault_address).content;
    assert!(option::is_some(content), error::invalid_state(EACCESSOR_IN_USE));
    ReadAccessor{ vault_address: cap.vault_address, content: option::extract(content) }
}
## Function `borrow` Returns a reference to the content represented by a read accessor.
public fun borrow<Content: drop, store>(accessor: &vault::ReadAccessor<Content>): &Content
Implementation
public fun borrow<Content: store + drop>(accessor: &ReadAccessor<Content>): &Content {
    &accessor.content
}
## Function `release_read_accessor` Releases read accessor.
public fun release_read_accessor<Content: drop, store>(accessor: vault::ReadAccessor<Content>)
Implementation
public fun release_read_accessor<Content: store + drop>(accessor: ReadAccessor<Content>)
acquires Vault {
    let ReadAccessor{ content: new_content, vault_address } = accessor;
    let content = &mut borrow_global_mut<Vault<Content>>(vault_address).content;
    // We (should be/are) able to prove that the below cannot happen, but we leave the assertion
    // here anyway for double safety.
    assert!(option::is_none(content), error::internal(EACCESSOR_INCONSISTENCY));
    option::fill(content, new_content);
}
## Function `modify_accessor` Creates a modify accessor for the content in the vault based on a modify capability. This is similar like Self::read_accessor but the returned accessor will allow to mutate the content.
public fun modify_accessor<Content: drop, store>(cap: &vault::ModifyCap<Content>): vault::ModifyAccessor<Content>
Implementation
public fun modify_accessor<Content: store + drop>(cap: &ModifyCap<Content>): ModifyAccessor<Content>
acquires Vault {
    let content = &mut borrow_global_mut<Vault<Content>>(cap.vault_address).content;
    assert!(option::is_some(content), error::invalid_state(EACCESSOR_IN_USE));
    ModifyAccessor{ vault_address: cap.vault_address, content: option::extract(content) }
}
## Function `borrow_mut` Returns a mutable reference to the content represented by a modify accessor.
public fun borrow_mut<Content: drop, store>(accessor: &mut vault::ModifyAccessor<Content>): &mut Content
Implementation
public fun borrow_mut<Content: store + drop>(accessor: &mut ModifyAccessor<Content>): &mut Content {
    &mut accessor.content
}
## Function `release_modify_accessor` Releases a modify accessor. This will ensure that any modifications are written back to the vault.
public fun release_modify_accessor<Content: drop, store>(accessor: vault::ModifyAccessor<Content>)
Implementation
public fun release_modify_accessor<Content: store + drop>(accessor: ModifyAccessor<Content>)
acquires Vault {
    let ModifyAccessor{ content: new_content, vault_address } = accessor;
    let content = &mut borrow_global_mut<Vault<Content>>(vault_address).content;
    // We (should be/are) able to prove that the below cannot happen, but we leave the assertion
    // here anyway for double safety.
    assert!(option::is_none(content), error::internal(EACCESSOR_INCONSISTENCY));
    option::fill(content, new_content);
}
## Function `delegate` Delegates the right to acquire a capability of the given type. Delegation must have been enabled during vault creation for this to succeed.
public fun delegate<Content: drop, store>(cap: &vault::DelegateCap<Content>, to_signer: &signer, cap_type: vault::CapType)
Implementation
public fun delegate<Content: store + drop>(cap: &DelegateCap<Content>, to_signer: &signer, cap_type: CapType)
acquires VaultDelegates, VaultDelegate, VaultEvents {
    assert!(
        exists<VaultDelegates<Content>>(cap.vault_address),
        error::invalid_state(EDELEGATION_NOT_ENABLED)
    );

    let addr = signer::address_of(to_signer);
    assert!(addr != cap.vault_address, error::invalid_argument(EDELEGATE_TO_SELF));

    if (!exists<VaultDelegate<Content>>(addr)) {
        // Create VaultDelegate if it is not yet existing.
        move_to<VaultDelegate<Content>>(
            to_signer,
            VaultDelegate{vault_address: cap.vault_address, granted_caps: vector::empty()}
        );
        // Add the the delegate to VaultDelegates.
        let vault_delegates = borrow_global_mut<VaultDelegates<Content>>(cap.vault_address);
        add_element(&mut vault_delegates.delegates, addr);
    };

    // Grant the capability.
    let delegate = borrow_global_mut<VaultDelegate<Content>>(addr);
    add_element(&mut delegate.granted_caps, *&cap_type);

    // Generate event
    emit_delegate_event(cap, cap_type, addr, false);
}
## Function `revoke` Revokes the delegated right to acquire a capability of given type.
public fun revoke<Content: drop, store>(cap: &vault::DelegateCap<Content>, addr: address, cap_type: vault::CapType)
Implementation
public fun revoke<Content: store + drop>(cap: &DelegateCap<Content>, addr: address, cap_type: CapType)
acquires VaultDelegates, VaultDelegate, VaultEvents {
    assert!(
        exists<VaultDelegates<Content>>(cap.vault_address),
        error::invalid_state(EDELEGATION_NOT_ENABLED)
    );
    assert!(exists<VaultDelegate<Content>>(addr), error::not_found(EDELEGATE));

    let delegate = borrow_global_mut<VaultDelegate<Content>>(addr);
    remove_element(&mut delegate.granted_caps, &cap_type);

    // If the granted caps of this delegate drop to zero, remove it.
    if (vector::is_empty(&delegate.granted_caps)) {
        let VaultDelegate{ vault_address: _owner, granted_caps: _granted_caps} =
            move_from<VaultDelegate<Content>>(addr);
        let vault_delegates = borrow_global_mut<VaultDelegates<Content>>(cap.vault_address);
        remove_element(&mut vault_delegates.delegates, &addr);
    };

    // Generate event.
    emit_delegate_event(cap, cap_type, addr, true);
}
## Function `revoke_all` Revokes all delegate rights for this vault.
public fun revoke_all<Content: drop, store>(cap: &vault::DelegateCap<Content>)
Implementation
public fun revoke_all<Content: store + drop>(cap: &DelegateCap<Content>)
acquires VaultDelegates, VaultDelegate, VaultEvents {
    assert!(
        exists<VaultDelegates<Content>>(cap.vault_address),
        error::invalid_state(EDELEGATION_NOT_ENABLED)
    );
    let delegates = &mut borrow_global_mut<VaultDelegates<Content>>(cap.vault_address).delegates;
    while (!vector::is_empty(delegates)) {
        let addr = vector::pop_back(delegates);
        let VaultDelegate{ vault_address: _vault_address, granted_caps} =
            move_from<VaultDelegate<Content>>(cap.vault_address);
        while (!vector::is_empty(&granted_caps)) {
            let cap_type = vector::pop_back(&mut granted_caps);
            emit_delegate_event(cap, cap_type, addr, true);
        }
    }
}
## 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)
    }
}
## Function `emit_delegate_event` Emits a delegation or revocation event if event generation is enabled.
fun emit_delegate_event<Content: drop, store>(cap: &vault::DelegateCap<Content>, cap_type: vault::CapType, delegate: address, is_revoked: bool)
Implementation
fun emit_delegate_event<Content: store + drop>(
       cap: &DelegateCap<Content>,
       cap_type: CapType,
       delegate: address,
       is_revoked: bool
) acquires VaultEvents {
    if (exists<VaultEvents<Content>>(cap.vault_address)) {
        let event = VaultDelegateEvent{
            metadata: *&borrow_global<VaultEvents<Content>>(cap.vault_address).metadata,
            vault_address: cap.vault_address,
            authority: cap.authority,
            delegate,
            cap: cap_type,
            is_revoked
        };
        event::emit_event(&mut borrow_global_mut<VaultEvents<Content>>(cap.vault_address).delegate_events, event);
    }
}
## Function `transfer` Transfers ownership of the vault to a new signer. All delegations are revoked before transfer, and the new owner must re-create delegates as needed.
public fun transfer<Content: drop, store>(cap: &vault::TransferCap<Content>, to_owner: &signer)
Implementation
public fun transfer<Content: store + drop>(cap: &TransferCap<Content>, to_owner: &signer)
acquires Vault, VaultEvents, VaultDelegate, VaultDelegates {
    let new_addr = signer::address_of(to_owner);
    assert!(!exists<Vault<Content>>(new_addr), error::already_exists(EVAULT));
    assert!(
        option::is_some(&borrow_global<Vault<Content>>(cap.vault_address).content),
        error::invalid_state(EACCESSOR_IN_USE)
    );

    // Revoke all delegates.
    if (exists<VaultDelegates<Content>>(cap.vault_address)) {
        let delegate_cap = DelegateCap<Content>{vault_address: cap.vault_address, authority: cap.authority };
        revoke_all(&delegate_cap);
    };

    // Emit event if event generation is enabled. We emit the event on the old vault not the new one.
    if (exists<VaultEvents<Content>>(cap.vault_address)) {
        let event = VaultTransferEvent {
            metadata: *&borrow_global<VaultEvents<Content>>(cap.vault_address).metadata,
            vault_address: cap.vault_address,
            authority: cap.authority,
            new_vault_address: new_addr
        };
        event::emit_event(&mut borrow_global_mut<VaultEvents<Content>>(cap.vault_address).transfer_events, event);
    };

    // Move the vault.
    move_to<Vault<Content>>(to_owner, move_from<Vault<Content>>(cap.vault_address));
}