language/move-stdlib/nursery/docs/Vault.md
<a name="0x1_Vault"></a>
0x1::VaultA 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. The vault supports delegation of capabilities to other signers (including revocation) as well as transfer of ownership.
<a name="@Overview_0"></a>
<a name="@Capabilities_1"></a>
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 <code>store</code> or <code>key</code> abilities, they cannot leak out of a transaction.
Example:
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<Content>(signer);
process(&read_cap)
...
fun process(cap: &Vault::ReadCap<Content>) {
let accessor = Vault::read_accessor(cap);
let content = Vault::borrow(accessor);
<< do something with <code>content: &Content</code> >>
Vault::release_read_accessor(accessor);
}
<a name="@Delegation_2"></a>
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:
Vault::new(signer, b"My Vault", Content{ ssn: 525659745 });
// Enable delegation for this vault. Only the owning signer can do this.
Vault::enable_delegation<Content>(signer);
...
// Delegate read capability to some other signer.
let delegate_cap = Vault::acquire_delegate_cap<Content>(signer);
Vault::delegate_read_cap(&delegate_cap, other_signer);
...
// Other signer can now acquire read cap
let read_cap = Vault::acquire_read_cap<Content>(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));
<a name="@Abilities_3"></a>
Currently, we require that the <code>Content</code> type of a vault has the <code>drop</code> ability in order to instantiate a capability type like <code><a href="Vault.md#0x1_Vault_ReadCap">ReadCap</a><Content></code>. 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 <code><a href="Vault.md#0x1_Vault_ReadCap">ReadCap</a><Content></code> droppable and copyable without <code>Content</code> needing the same.
ReadCapModifyCapDelegateCapTransferCapCapTypeVaultDelegateEventVaultTransferEventVaultVaultDelegatesVaultEventsVaultDelegateReadAccessorModifyAccessorread_cap_typemodify_cap_typedelegate_cap_typetransfer_cap_typenewis_delegation_enabledenable_delegationenable_eventsremove_vaultacquire_read_capacquire_modify_capacquire_delegate_capacquire_transfer_capvalidate_capread_accessorborrowrelease_read_accessormodify_accessorborrow_mutrelease_modify_accessordelegaterevokerevoke_allremove_elementadd_elementemit_delegate_eventtransfer<a name="0x1_Vault_ReadCap"></a>
ReadCapA capability to read the content of the vault. Notice that the capability cannot be stored but can be freely copied and dropped. TODO: remove <code>drop</code> on <code>Content</code> here and elsewhere once we have phantom type parameters.
<pre><code><b>struct</b> <a href="Vault.md#0x1_Vault_ReadCap">ReadCap</a><Content: drop, store> has <b>copy</b>, drop </code></pre> <details> <summary>Fields</summary> <dl> <dt> <code>vault_address: address</code> </dt> <dd> </dd> <dt> <code>authority: address</code> </dt> <dd> </dd> </dl> </details><a name="0x1_Vault_ModifyCap"></a>
ModifyCapA capability to modify the content of the vault.
<pre><code><b>struct</b> <a href="Vault.md#0x1_Vault_ModifyCap">ModifyCap</a><Content: drop, store> has <b>copy</b>, drop </code></pre> <details> <summary>Fields</summary> <dl> <dt> <code>vault_address: address</code> </dt> <dd> </dd> <dt> <code>authority: address</code> </dt> <dd> </dd> </dl> </details><a name="0x1_Vault_DelegateCap"></a>
DelegateCapA capability to delegate access to the vault.
<pre><code><b>struct</b> <a href="Vault.md#0x1_Vault_DelegateCap">DelegateCap</a><Content: drop, store> has <b>copy</b>, drop </code></pre> <details> <summary>Fields</summary> <dl> <dt> <code>vault_address: address</code> </dt> <dd> </dd> <dt> <code>authority: address</code> </dt> <dd> </dd> </dl> </details><a name="0x1_Vault_TransferCap"></a>
TransferCapA capability to transfer ownership of the vault.
<pre><code><b>struct</b> <a href="Vault.md#0x1_Vault_TransferCap">TransferCap</a><Content: drop, store> has <b>copy</b>, drop </code></pre> <details> <summary>Fields</summary> <dl> <dt> <code>vault_address: address</code> </dt> <dd> </dd> <dt> <code>authority: address</code> </dt> <dd> </dd> </dl> </details><a name="0x1_Vault_CapType"></a>
CapTypeA type describing a capability. This is used for functions like <code><a href="Vault.md#0x1_Vault_delegate">Self::delegate</a></code> where we need to specify capability types.
<pre><code><b>struct</b> <a href="Vault.md#0x1_Vault_CapType">CapType</a> has <b>copy</b>, drop, store </code></pre> <details> <summary>Fields</summary> <dl> <dt> <code>code: u8</code> </dt> <dd> </dd> </dl> </details><a name="0x1_Vault_VaultDelegateEvent"></a>
VaultDelegateEventAn event which we generate on vault access delegation or revocation if event generation is enabled.
<pre><code><b>struct</b> <a href="Vault.md#0x1_Vault_VaultDelegateEvent">VaultDelegateEvent</a> has drop, store </code></pre> <details> <summary>Fields</summary> <dl> <dt> <code>metadata: vector<u8></code> </dt> <dd> </dd> <dt> <code>vault_address: address</code> </dt> <dd> </dd> <dt> <code>authority: address</code> </dt> <dd> </dd> <dt> <code>delegate: address</code> </dt> <dd> </dd> <dt> <code>cap: <a href="Vault.md#0x1_Vault_CapType">Vault::CapType</a></code> </dt> <dd> </dd> <dt> <code>is_revoked: bool</code> </dt> <dd> </dd> </dl> </details><a name="0x1_Vault_VaultTransferEvent"></a>
VaultTransferEventAn event which we generate on vault transfer if event generation is enabled.
<pre><code><b>struct</b> <a href="Vault.md#0x1_Vault_VaultTransferEvent">VaultTransferEvent</a> has drop, store </code></pre> <details> <summary>Fields</summary> <dl> <dt> <code>metadata: vector<u8></code> </dt> <dd> </dd> <dt> <code>vault_address: address</code> </dt> <dd> </dd> <dt> <code>authority: address</code> </dt> <dd> </dd> <dt> <code>new_vault_address: address</code> </dt> <dd> </dd> </dl> </details><a name="0x1_Vault_Vault"></a>
VaultPrivate. The vault representation.
<pre><code><b>struct</b> <a href="Vault.md#0x1_Vault">Vault</a><Content: store> has key </code></pre> <details> <summary>Fields</summary> <dl> <dt> <code>content: <a href="_Option">Option::Option</a><Content></code> </dt> <dd> The content. If the option is empty, the content is currently moved into an accessor in order to work with it. </dd> </dl> </details><a name="0x1_Vault_VaultDelegates"></a>
VaultDelegatesPrivate. If the vault supports delegation, information about the delegates.
<pre><code><b>struct</b> <a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a><Content: store> has key </code></pre> <details> <summary>Fields</summary> <dl> <dt> <code>delegates: vector<address></code> </dt> <dd> The currently authorized delegates. </dd> </dl> </details><a name="0x1_Vault_VaultEvents"></a>
VaultEventsPrivate. If event generation is enabled, contains the event generators.
<pre><code><b>struct</b> <a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a><Content: store> has key </code></pre> <details> <summary>Fields</summary> <dl> <dt> <code>metadata: vector<u8></code> </dt> <dd> Metadata which identifies this vault. This information is used in events generated by this module. </dd> <dt> <code>delegate_events: <a href="_EventHandle">Event::EventHandle</a><<a href="Vault.md#0x1_Vault_VaultDelegateEvent">Vault::VaultDelegateEvent</a>></code> </dt> <dd> Event handle for vault delegation. </dd> <dt> <code>transfer_events: <a href="_EventHandle">Event::EventHandle</a><<a href="Vault.md#0x1_Vault_VaultTransferEvent">Vault::VaultTransferEvent</a>></code> </dt> <dd> Event handle for vault transfer. </dd> </dl> </details><a name="0x1_Vault_VaultDelegate"></a>
VaultDelegatePrivate. A value stored at a delegates address pointing to the owner of the vault. Also describes the capabilities granted to this delegate.
<pre><code><b>struct</b> <a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a><Content: store> has key </code></pre> <details> <summary>Fields</summary> <dl> <dt> <code>vault_address: address</code> </dt> <dd> </dd> <dt> <code>granted_caps: vector<<a href="Vault.md#0x1_Vault_CapType">Vault::CapType</a>></code> </dt> <dd> </dd> </dl> </details><a name="0x1_Vault_ReadAccessor"></a>
ReadAccessorA read accessor for the content of the vault.
<pre><code><b>struct</b> <a href="Vault.md#0x1_Vault_ReadAccessor">ReadAccessor</a><Content: drop, store> </code></pre> <details> <summary>Fields</summary> <dl> <dt> <code>content: Content</code> </dt> <dd> </dd> <dt> <code>vault_address: address</code> </dt> <dd> </dd> </dl> </details><a name="0x1_Vault_ModifyAccessor"></a>
ModifyAccessorA modify accessor for the content of the vault.
<pre><code><b>struct</b> <a href="Vault.md#0x1_Vault_ModifyAccessor">ModifyAccessor</a><Content: drop, store> </code></pre> <details> <summary>Fields</summary> <dl> <dt> <code>content: Content</code> </dt> <dd> </dd> <dt> <code>vault_address: address</code> </dt> <dd> </dd> </dl> </details><a name="@Constants_4"></a>
<a name="0x1_Vault_EACCESSOR_INCONSISTENCY"></a>
<pre><code><b>const</b> <a href="Vault.md#0x1_Vault_EACCESSOR_INCONSISTENCY">EACCESSOR_INCONSISTENCY</a>: u64 = 3; </code></pre><a name="0x1_Vault_EACCESSOR_IN_USE"></a>
<pre><code><b>const</b> <a href="Vault.md#0x1_Vault_EACCESSOR_IN_USE">EACCESSOR_IN_USE</a>: u64 = 2; </code></pre><a name="0x1_Vault_EDELEGATE"></a>
<pre><code><b>const</b> <a href="Vault.md#0x1_Vault_EDELEGATE">EDELEGATE</a>: u64 = 1; </code></pre><a name="0x1_Vault_EDELEGATE_TO_SELF"></a>
<pre><code><b>const</b> <a href="Vault.md#0x1_Vault_EDELEGATE_TO_SELF">EDELEGATE_TO_SELF</a>: u64 = 4; </code></pre><a name="0x1_Vault_EDELEGATION_NOT_ENABLED"></a>
<pre><code><b>const</b> <a href="Vault.md#0x1_Vault_EDELEGATION_NOT_ENABLED">EDELEGATION_NOT_ENABLED</a>: u64 = 5; </code></pre><a name="0x1_Vault_EEVENT"></a>
<pre><code><b>const</b> <a href="Vault.md#0x1_Vault_EEVENT">EEVENT</a>: u64 = 6; </code></pre><a name="0x1_Vault_EVAULT"></a>
<pre><code><b>const</b> <a href="Vault.md#0x1_Vault_EVAULT">EVAULT</a>: u64 = 0; </code></pre><a name="0x1_Vault_read_cap_type"></a>
read_cap_typeCreates a read capability type.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_read_cap_type">read_cap_type</a>(): <a href="Vault.md#0x1_Vault_CapType">Vault::CapType</a> </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_read_cap_type">read_cap_type</a>(): <a href="Vault.md#0x1_Vault_CapType">CapType</a> { <a href="Vault.md#0x1_Vault_CapType">CapType</a>{ code : 0 } } </code></pre> </details><a name="0x1_Vault_modify_cap_type"></a>
modify_cap_typeCreates a modify capability type.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_modify_cap_type">modify_cap_type</a>(): <a href="Vault.md#0x1_Vault_CapType">Vault::CapType</a> </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_modify_cap_type">modify_cap_type</a>(): <a href="Vault.md#0x1_Vault_CapType">CapType</a> { <a href="Vault.md#0x1_Vault_CapType">CapType</a>{ code : 1 } } </code></pre> </details><a name="0x1_Vault_delegate_cap_type"></a>
delegate_cap_typeCreates a delegate capability type.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_delegate_cap_type">delegate_cap_type</a>(): <a href="Vault.md#0x1_Vault_CapType">Vault::CapType</a> </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_delegate_cap_type">delegate_cap_type</a>(): <a href="Vault.md#0x1_Vault_CapType">CapType</a> { <a href="Vault.md#0x1_Vault_CapType">CapType</a>{ code : 2 } } </code></pre> </details><a name="0x1_Vault_transfer_cap_type"></a>
transfer_cap_typeCreates a transfer capability type.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_transfer_cap_type">transfer_cap_type</a>(): <a href="Vault.md#0x1_Vault_CapType">Vault::CapType</a> </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_transfer_cap_type">transfer_cap_type</a>(): <a href="Vault.md#0x1_Vault_CapType">CapType</a> { <a href="Vault.md#0x1_Vault_CapType">CapType</a>{ code : 3 } } </code></pre> </details><a name="0x1_Vault_new"></a>
newCreates new vault for the given signer. The vault is populated with the <code>initial_content</code>.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_new">new</a><Content: store>(owner: &signer, initial_content: Content) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_new">new</a><Content: store>(owner: &signer, initial_content: Content) { <b>let</b> addr = <a href="_address_of">Signer::address_of</a>(owner); <b>assert</b>(!<b>exists</b><<a href="Vault.md#0x1_Vault">Vault</a><Content>>(addr), <a href="_already_published">Errors::already_published</a>(<a href="Vault.md#0x1_Vault_EVAULT">EVAULT</a>)); move_to<<a href="Vault.md#0x1_Vault">Vault</a><Content>>( owner, <a href="Vault.md#0x1_Vault">Vault</a>{ content: <a href="_some">Option::some</a>(initial_content) } ) } </code></pre> </details><a name="0x1_Vault_is_delegation_enabled"></a>
is_delegation_enabledReturns <code><b>true</b></code> if the delegation functionality has been enabled. Returns <code><b>false</b></code> otherwise.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_is_delegation_enabled">is_delegation_enabled</a><Content: store>(owner: &signer): bool </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_is_delegation_enabled">is_delegation_enabled</a><Content: store>(owner: &signer): bool { <b>let</b> addr = <a href="_address_of">Signer::address_of</a>(owner); <b>assert</b>(<b>exists</b><<a href="Vault.md#0x1_Vault">Vault</a><Content>>(addr), <a href="_not_published">Errors::not_published</a>(<a href="Vault.md#0x1_Vault_EVAULT">EVAULT</a>)); <b>exists</b><<a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a><Content>>(addr) } </code></pre> </details><a name="0x1_Vault_enable_delegation"></a>
enable_delegationEnables delegation functionality for this vault. By default, vaults to not support delegation.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_enable_delegation">enable_delegation</a><Content: store>(owner: &signer) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_enable_delegation">enable_delegation</a><Content: store>(owner: &signer) { <b>assert</b>(!<a href="Vault.md#0x1_Vault_is_delegation_enabled">is_delegation_enabled</a><Content>(owner), <a href="_already_published">Errors::already_published</a>(<a href="Vault.md#0x1_Vault_EDELEGATE">EDELEGATE</a>)); move_to<<a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a><Content>>(owner, <a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a>{delegates: <a href="_empty">Vector::empty</a>()}) } </code></pre> </details><a name="0x1_Vault_enable_events"></a>
enable_eventsEnables event generation for this vault. This passed metadata is used to identify the vault in events.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_enable_events">enable_events</a><Content: store>(owner: &signer, metadata: vector<u8>) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_enable_events">enable_events</a><Content: store>(owner: &signer, metadata: vector<u8>) { <b>let</b> addr = <a href="_address_of">Signer::address_of</a>(owner); <b>assert</b>(<b>exists</b><<a href="Vault.md#0x1_Vault">Vault</a><Content>>(addr), <a href="_not_published">Errors::not_published</a>(<a href="Vault.md#0x1_Vault_EVAULT">EVAULT</a>)); <b>assert</b>(!<b>exists</b><<a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a><Content>>(addr), <a href="_already_published">Errors::already_published</a>(<a href="Vault.md#0x1_Vault_EEVENT">EEVENT</a>)); move_to<<a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a><Content>>( owner, <a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a>{ metadata, delegate_events: <a href="_new_event_handle">Event::new_event_handle</a><<a href="Vault.md#0x1_Vault_VaultDelegateEvent">VaultDelegateEvent</a>>(owner), transfer_events: <a href="_new_event_handle">Event::new_event_handle</a><<a href="Vault.md#0x1_Vault_VaultTransferEvent">VaultTransferEvent</a>>(owner), } ); } </code></pre> </details><a name="0x1_Vault_remove_vault"></a>
remove_vaultRemoves 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.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_remove_vault">remove_vault</a><Content: drop, store>(owner: &signer): Content </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_remove_vault">remove_vault</a><Content: store + drop>(owner: &signer): Content <b>acquires</b> <a href="Vault.md#0x1_Vault">Vault</a>, <a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a>, <a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a>, <a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a> { <b>let</b> addr = <a href="_address_of">Signer::address_of</a>(owner); <b>assert</b>(<b>exists</b><<a href="Vault.md#0x1_Vault">Vault</a><Content>>(addr), <a href="_not_published">Errors::not_published</a>(<a href="Vault.md#0x1_Vault_EVAULT">EVAULT</a>)); <b>let</b> <a href="Vault.md#0x1_Vault">Vault</a>{content} = move_from<<a href="Vault.md#0x1_Vault">Vault</a><Content>>(addr); <b>assert</b>(<a href="_is_some">Option::is_some</a>(&content), <a href="_invalid_state">Errors::invalid_state</a>(<a href="Vault.md#0x1_Vault_EACCESSOR_IN_USE">EACCESSOR_IN_USE</a>)); <b>if</b> (<b>exists</b><<a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a><Content>>(addr)) { <b>let</b> delegate_cap = <a href="Vault.md#0x1_Vault_DelegateCap">DelegateCap</a><Content>{vault_address: addr, authority: addr}; <a href="Vault.md#0x1_Vault_revoke_all">revoke_all</a>(&delegate_cap); }; <b>if</b> (<b>exists</b><<a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a><Content>>(addr)) { <b>let</b> <a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a>{metadata: _metadata, delegate_events, transfer_events} = move_from<<a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a><Content>>(addr); <a href="_destroy_handle">Event::destroy_handle</a>(delegate_events); <a href="_destroy_handle">Event::destroy_handle</a>(transfer_events); }; <a href="_extract">Option::extract</a>(&<b>mut</b> content) } </code></pre> </details><a name="0x1_Vault_acquire_read_cap"></a>
acquire_read_capAcquires the capability to read the vault. The passed signer must either be the owner of the vault or a delegate with appropriate access.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_acquire_read_cap">acquire_read_cap</a><Content: drop, store>(requester: &signer): <a href="Vault.md#0x1_Vault_ReadCap">Vault::ReadCap</a><Content> </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_acquire_read_cap">acquire_read_cap</a><Content: store + drop>(requester: &signer): <a href="Vault.md#0x1_Vault_ReadCap">ReadCap</a><Content> <b>acquires</b> <a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a> { <b>let</b> (vault_address, authority) = <a href="Vault.md#0x1_Vault_validate_cap">validate_cap</a><Content>(requester, <a href="Vault.md#0x1_Vault_read_cap_type">read_cap_type</a>()); <a href="Vault.md#0x1_Vault_ReadCap">ReadCap</a>{ vault_address, authority } } </code></pre> </details><a name="0x1_Vault_acquire_modify_cap"></a>
acquire_modify_capAcquires the capability to modify the vault. The passed signer must either be the owner of the vault or a delegate with appropriate access.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_acquire_modify_cap">acquire_modify_cap</a><Content: drop, store>(requester: &signer): <a href="Vault.md#0x1_Vault_ModifyCap">Vault::ModifyCap</a><Content> </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_acquire_modify_cap">acquire_modify_cap</a><Content: store + drop>(requester: &signer): <a href="Vault.md#0x1_Vault_ModifyCap">ModifyCap</a><Content> <b>acquires</b> <a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a> { <b>let</b> (vault_address, authority) = <a href="Vault.md#0x1_Vault_validate_cap">validate_cap</a><Content>(requester, <a href="Vault.md#0x1_Vault_modify_cap_type">modify_cap_type</a>()); <a href="Vault.md#0x1_Vault_ModifyCap">ModifyCap</a>{ vault_address, authority } } </code></pre> </details><a name="0x1_Vault_acquire_delegate_cap"></a>
acquire_delegate_capAcquires 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.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_acquire_delegate_cap">acquire_delegate_cap</a><Content: drop, store>(requester: &signer): <a href="Vault.md#0x1_Vault_DelegateCap">Vault::DelegateCap</a><Content> </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_acquire_delegate_cap">acquire_delegate_cap</a><Content: store + drop>(requester: &signer): <a href="Vault.md#0x1_Vault_DelegateCap">DelegateCap</a><Content> <b>acquires</b> <a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a> { <b>let</b> (vault_address, authority) = <a href="Vault.md#0x1_Vault_validate_cap">validate_cap</a><Content>(requester, <a href="Vault.md#0x1_Vault_delegate_cap_type">delegate_cap_type</a>()); <a href="Vault.md#0x1_Vault_DelegateCap">DelegateCap</a>{ vault_address, authority } } </code></pre> </details><a name="0x1_Vault_acquire_transfer_cap"></a>
acquire_transfer_capAcquires the capability to transfer the vault. The passed signer must either be the owner of the vault or a delegate with appropriate access.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_acquire_transfer_cap">acquire_transfer_cap</a><Content: drop, store>(requester: &signer): <a href="Vault.md#0x1_Vault_TransferCap">Vault::TransferCap</a><Content> </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_acquire_transfer_cap">acquire_transfer_cap</a><Content: store + drop>(requester: &signer): <a href="Vault.md#0x1_Vault_TransferCap">TransferCap</a><Content> <b>acquires</b> <a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a> { <b>let</b> (vault_address, authority) = <a href="Vault.md#0x1_Vault_validate_cap">validate_cap</a><Content>(requester, <a href="Vault.md#0x1_Vault_transfer_cap_type">transfer_cap_type</a>()); <a href="Vault.md#0x1_Vault_TransferCap">TransferCap</a>{ vault_address, authority } } </code></pre> </details><a name="0x1_Vault_validate_cap"></a>
validate_capPrivate. Validates whether a capability can be acquired by the given signer. Returns the pair of the vault address and the used authority.
<pre><code><b>fun</b> <a href="Vault.md#0x1_Vault_validate_cap">validate_cap</a><Content: drop, store>(requester: &signer, cap: <a href="Vault.md#0x1_Vault_CapType">Vault::CapType</a>): (address, address) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>fun</b> <a href="Vault.md#0x1_Vault_validate_cap">validate_cap</a><Content: store + drop>(requester: &signer, cap: <a href="Vault.md#0x1_Vault_CapType">CapType</a>): (address, address) <b>acquires</b> <a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a> { <b>let</b> addr = <a href="_address_of">Signer::address_of</a>(requester); <b>if</b> (<b>exists</b><<a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a><Content>>(addr)) { // The signer is a delegate. Check it's granted capabilities. <b>let</b> delegate = borrow_global<<a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a><Content>>(addr); <b>assert</b>(<a href="_contains">Vector::contains</a>(&delegate.granted_caps, &cap), <a href="_requires_capability">Errors::requires_capability</a>(<a href="Vault.md#0x1_Vault_EDELEGATE">EDELEGATE</a>)); (delegate.vault_address, addr) } <b>else</b> { // If it is not a delegate, it must be the owner <b>to</b> succeed. <b>assert</b>(<b>exists</b><<a href="Vault.md#0x1_Vault">Vault</a><Content>>(addr), <a href="_not_published">Errors::not_published</a>(<a href="Vault.md#0x1_Vault_EVAULT">EVAULT</a>)); (addr, addr) } } </code></pre> </details><a name="0x1_Vault_read_accessor"></a>
read_accessorCreates 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 <code><a href="Vault.md#0x1_Vault_release_read_accessor">Self::release_read_accessor</a></code>.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_read_accessor">read_accessor</a><Content: drop, store>(cap: &<a href="Vault.md#0x1_Vault_ReadCap">Vault::ReadCap</a><Content>): <a href="Vault.md#0x1_Vault_ReadAccessor">Vault::ReadAccessor</a><Content> </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_read_accessor">read_accessor</a><Content: store + drop>(cap: &<a href="Vault.md#0x1_Vault_ReadCap">ReadCap</a><Content>): <a href="Vault.md#0x1_Vault_ReadAccessor">ReadAccessor</a><Content> <b>acquires</b> <a href="Vault.md#0x1_Vault">Vault</a> { <b>let</b> content = &<b>mut</b> borrow_global_mut<<a href="Vault.md#0x1_Vault">Vault</a><Content>>(cap.vault_address).content; <b>assert</b>(<a href="_is_some">Option::is_some</a>(content), <a href="_invalid_state">Errors::invalid_state</a>(<a href="Vault.md#0x1_Vault_EACCESSOR_IN_USE">EACCESSOR_IN_USE</a>)); <a href="Vault.md#0x1_Vault_ReadAccessor">ReadAccessor</a>{ vault_address: cap.vault_address, content: <a href="_extract">Option::extract</a>(content) } } </code></pre> </details><a name="0x1_Vault_borrow"></a>
borrowReturns a reference to the content represented by a read accessor.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_borrow">borrow</a><Content: drop, store>(accessor: &<a href="Vault.md#0x1_Vault_ReadAccessor">Vault::ReadAccessor</a><Content>): &Content </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_borrow">borrow</a><Content: store + drop>(accessor: &<a href="Vault.md#0x1_Vault_ReadAccessor">ReadAccessor</a><Content>): &Content { &accessor.content } </code></pre> </details><a name="0x1_Vault_release_read_accessor"></a>
release_read_accessorReleases read accessor.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_release_read_accessor">release_read_accessor</a><Content: drop, store>(accessor: <a href="Vault.md#0x1_Vault_ReadAccessor">Vault::ReadAccessor</a><Content>) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_release_read_accessor">release_read_accessor</a><Content: store + drop>(accessor: <a href="Vault.md#0x1_Vault_ReadAccessor">ReadAccessor</a><Content>) <b>acquires</b> <a href="Vault.md#0x1_Vault">Vault</a> { <b>let</b> <a href="Vault.md#0x1_Vault_ReadAccessor">ReadAccessor</a>{ content: new_content, vault_address } = accessor; <b>let</b> content = &<b>mut</b> borrow_global_mut<<a href="Vault.md#0x1_Vault">Vault</a><Content>>(vault_address).content; // We (should be/are) able <b>to</b> prove that the below cannot happen, but we leave the assertion // here anyway for double safety. <b>assert</b>(<a href="_is_none">Option::is_none</a>(content), <a href="_internal">Errors::internal</a>(<a href="Vault.md#0x1_Vault_EACCESSOR_INCONSISTENCY">EACCESSOR_INCONSISTENCY</a>)); <a href="_fill">Option::fill</a>(content, new_content); } </code></pre> </details><a name="0x1_Vault_modify_accessor"></a>
modify_accessorCreates a modify accessor for the content in the vault based on a modify capability. This is similar like <code><a href="Vault.md#0x1_Vault_read_accessor">Self::read_accessor</a></code> but the returned accessor will allow to mutate the content.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_modify_accessor">modify_accessor</a><Content: drop, store>(cap: &<a href="Vault.md#0x1_Vault_ModifyCap">Vault::ModifyCap</a><Content>): <a href="Vault.md#0x1_Vault_ModifyAccessor">Vault::ModifyAccessor</a><Content> </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_modify_accessor">modify_accessor</a><Content: store + drop>(cap: &<a href="Vault.md#0x1_Vault_ModifyCap">ModifyCap</a><Content>): <a href="Vault.md#0x1_Vault_ModifyAccessor">ModifyAccessor</a><Content> <b>acquires</b> <a href="Vault.md#0x1_Vault">Vault</a> { <b>let</b> content = &<b>mut</b> borrow_global_mut<<a href="Vault.md#0x1_Vault">Vault</a><Content>>(cap.vault_address).content; <b>assert</b>(<a href="_is_some">Option::is_some</a>(content), <a href="_invalid_state">Errors::invalid_state</a>(<a href="Vault.md#0x1_Vault_EACCESSOR_IN_USE">EACCESSOR_IN_USE</a>)); <a href="Vault.md#0x1_Vault_ModifyAccessor">ModifyAccessor</a>{ vault_address: cap.vault_address, content: <a href="_extract">Option::extract</a>(content) } } </code></pre> </details><a name="0x1_Vault_borrow_mut"></a>
borrow_mutReturns a mutable reference to the content represented by a modify accessor.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_borrow_mut">borrow_mut</a><Content: drop, store>(accessor: &<b>mut</b> <a href="Vault.md#0x1_Vault_ModifyAccessor">Vault::ModifyAccessor</a><Content>): &<b>mut</b> Content </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_borrow_mut">borrow_mut</a><Content: store + drop>(accessor: &<b>mut</b> <a href="Vault.md#0x1_Vault_ModifyAccessor">ModifyAccessor</a><Content>): &<b>mut</b> Content { &<b>mut</b> accessor.content } </code></pre> </details><a name="0x1_Vault_release_modify_accessor"></a>
release_modify_accessorReleases a modify accessor. This will ensure that any modifications are written back to the vault.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_release_modify_accessor">release_modify_accessor</a><Content: drop, store>(accessor: <a href="Vault.md#0x1_Vault_ModifyAccessor">Vault::ModifyAccessor</a><Content>) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_release_modify_accessor">release_modify_accessor</a><Content: store + drop>(accessor: <a href="Vault.md#0x1_Vault_ModifyAccessor">ModifyAccessor</a><Content>) <b>acquires</b> <a href="Vault.md#0x1_Vault">Vault</a> { <b>let</b> <a href="Vault.md#0x1_Vault_ModifyAccessor">ModifyAccessor</a>{ content: new_content, vault_address } = accessor; <b>let</b> content = &<b>mut</b> borrow_global_mut<<a href="Vault.md#0x1_Vault">Vault</a><Content>>(vault_address).content; // We (should be/are) able <b>to</b> prove that the below cannot happen, but we leave the assertion // here anyway for double safety. <b>assert</b>(<a href="_is_none">Option::is_none</a>(content), <a href="_internal">Errors::internal</a>(<a href="Vault.md#0x1_Vault_EACCESSOR_INCONSISTENCY">EACCESSOR_INCONSISTENCY</a>)); <a href="_fill">Option::fill</a>(content, new_content); } </code></pre> </details><a name="0x1_Vault_delegate"></a>
delegateDelegates the right to acquire a capability of the given type. Delegation must have been enabled during vault creation for this to succeed.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_delegate">delegate</a><Content: drop, store>(cap: &<a href="Vault.md#0x1_Vault_DelegateCap">Vault::DelegateCap</a><Content>, to_signer: &signer, cap_type: <a href="Vault.md#0x1_Vault_CapType">Vault::CapType</a>) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_delegate">delegate</a><Content: store + drop>(cap: &<a href="Vault.md#0x1_Vault_DelegateCap">DelegateCap</a><Content>, to_signer: &signer, cap_type: <a href="Vault.md#0x1_Vault_CapType">CapType</a>) <b>acquires</b> <a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a>, <a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a>, <a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a> { <b>assert</b>( <b>exists</b><<a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a><Content>>(cap.vault_address), <a href="_invalid_state">Errors::invalid_state</a>(<a href="Vault.md#0x1_Vault_EDELEGATION_NOT_ENABLED">EDELEGATION_NOT_ENABLED</a>) ); <b>let</b> addr = <a href="_address_of">Signer::address_of</a>(to_signer); <b>assert</b>(addr != cap.vault_address, <a href="_invalid_argument">Errors::invalid_argument</a>(<a href="Vault.md#0x1_Vault_EDELEGATE_TO_SELF">EDELEGATE_TO_SELF</a>)); <b>if</b> (!<b>exists</b><<a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a><Content>>(addr)) { // Create <a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a> <b>if</b> it is not yet existing. move_to<<a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a><Content>>( to_signer, <a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a>{vault_address: cap.vault_address, granted_caps: <a href="_empty">Vector::empty</a>()} ); // Add the the delegate <b>to</b> <a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a>. <b>let</b> vault_delegates = borrow_global_mut<<a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a><Content>>(cap.vault_address); <a href="Vault.md#0x1_Vault_add_element">add_element</a>(&<b>mut</b> vault_delegates.delegates, addr); }; // Grant the capability. <b>let</b> delegate = borrow_global_mut<<a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a><Content>>(addr); <a href="Vault.md#0x1_Vault_add_element">add_element</a>(&<b>mut</b> delegate.granted_caps, *&cap_type); // Generate event <a href="Vault.md#0x1_Vault_emit_delegate_event">emit_delegate_event</a>(cap, cap_type, addr, <b>false</b>); } </code></pre> </details><a name="0x1_Vault_revoke"></a>
revokeRevokes the delegated right to acquire a capability of given type.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_revoke">revoke</a><Content: drop, store>(cap: &<a href="Vault.md#0x1_Vault_DelegateCap">Vault::DelegateCap</a><Content>, addr: address, cap_type: <a href="Vault.md#0x1_Vault_CapType">Vault::CapType</a>) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_revoke">revoke</a><Content: store + drop>(cap: &<a href="Vault.md#0x1_Vault_DelegateCap">DelegateCap</a><Content>, addr: address, cap_type: <a href="Vault.md#0x1_Vault_CapType">CapType</a>) <b>acquires</b> <a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a>, <a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a>, <a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a> { <b>assert</b>( <b>exists</b><<a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a><Content>>(cap.vault_address), <a href="_invalid_state">Errors::invalid_state</a>(<a href="Vault.md#0x1_Vault_EDELEGATION_NOT_ENABLED">EDELEGATION_NOT_ENABLED</a>) ); <b>assert</b>(<b>exists</b><<a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a><Content>>(addr), <a href="_not_published">Errors::not_published</a>(<a href="Vault.md#0x1_Vault_EDELEGATE">EDELEGATE</a>)); <b>let</b> delegate = borrow_global_mut<<a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a><Content>>(addr); <a href="Vault.md#0x1_Vault_remove_element">remove_element</a>(&<b>mut</b> delegate.granted_caps, &cap_type); // If the granted caps of this delegate drop <b>to</b> zero, remove it. <b>if</b> (<a href="_is_empty">Vector::is_empty</a>(&delegate.granted_caps)) { <b>let</b> <a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a>{ vault_address: _owner, granted_caps: _granted_caps} = move_from<<a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a><Content>>(addr); <b>let</b> vault_delegates = borrow_global_mut<<a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a><Content>>(cap.vault_address); <a href="Vault.md#0x1_Vault_remove_element">remove_element</a>(&<b>mut</b> vault_delegates.delegates, &addr); }; // Generate event. <a href="Vault.md#0x1_Vault_emit_delegate_event">emit_delegate_event</a>(cap, cap_type, addr, <b>true</b>); } </code></pre> </details><a name="0x1_Vault_revoke_all"></a>
revoke_allRevokes all delegate rights for this vault.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_revoke_all">revoke_all</a><Content: drop, store>(cap: &<a href="Vault.md#0x1_Vault_DelegateCap">Vault::DelegateCap</a><Content>) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_revoke_all">revoke_all</a><Content: store + drop>(cap: &<a href="Vault.md#0x1_Vault_DelegateCap">DelegateCap</a><Content>) <b>acquires</b> <a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a>, <a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a>, <a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a> { <b>assert</b>( <b>exists</b><<a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a><Content>>(cap.vault_address), <a href="_invalid_state">Errors::invalid_state</a>(<a href="Vault.md#0x1_Vault_EDELEGATION_NOT_ENABLED">EDELEGATION_NOT_ENABLED</a>) ); <b>let</b> delegates = &<b>mut</b> borrow_global_mut<<a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a><Content>>(cap.vault_address).delegates; <b>while</b> (!<a href="_is_empty">Vector::is_empty</a>(delegates)) { <b>let</b> addr = <a href="_pop_back">Vector::pop_back</a>(delegates); <b>let</b> <a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a>{ vault_address: _vault_address, granted_caps} = move_from<<a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a><Content>>(cap.vault_address); <b>while</b> (!<a href="_is_empty">Vector::is_empty</a>(&granted_caps)) { <b>let</b> cap_type = <a href="_pop_back">Vector::pop_back</a>(&<b>mut</b> granted_caps); <a href="Vault.md#0x1_Vault_emit_delegate_event">emit_delegate_event</a>(cap, cap_type, addr, <b>true</b>); } } } </code></pre> </details><a name="0x1_Vault_remove_element"></a>
remove_elementHelper to remove an element from a vector.
<pre><code><b>fun</b> <a href="Vault.md#0x1_Vault_remove_element">remove_element</a><E: drop>(v: &<b>mut</b> vector<E>, x: &E) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>fun</b> <a href="Vault.md#0x1_Vault_remove_element">remove_element</a><E: drop>(v: &<b>mut</b> vector<E>, x: &E) { <b>let</b> (found, index) = <a href="_index_of">Vector::index_of</a>(v, x); <b>if</b> (found) { <a href="_remove">Vector::remove</a>(v, index); } } </code></pre> </details><a name="0x1_Vault_add_element"></a>
add_elementHelper to add an element to a vector.
<pre><code><b>fun</b> <a href="Vault.md#0x1_Vault_add_element">add_element</a><E: drop>(v: &<b>mut</b> vector<E>, x: E) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>fun</b> <a href="Vault.md#0x1_Vault_add_element">add_element</a><E: drop>(v: &<b>mut</b> vector<E>, x: E) { <b>if</b> (!<a href="_contains">Vector::contains</a>(v, &x)) { <a href="_push_back">Vector::push_back</a>(v, x) } } </code></pre> </details><a name="0x1_Vault_emit_delegate_event"></a>
emit_delegate_eventEmits a delegation or revocation event if event generation is enabled.
<pre><code><b>fun</b> <a href="Vault.md#0x1_Vault_emit_delegate_event">emit_delegate_event</a><Content: drop, store>(cap: &<a href="Vault.md#0x1_Vault_DelegateCap">Vault::DelegateCap</a><Content>, cap_type: <a href="Vault.md#0x1_Vault_CapType">Vault::CapType</a>, delegate: address, is_revoked: bool) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>fun</b> <a href="Vault.md#0x1_Vault_emit_delegate_event">emit_delegate_event</a><Content: store + drop>( cap: &<a href="Vault.md#0x1_Vault_DelegateCap">DelegateCap</a><Content>, cap_type: <a href="Vault.md#0x1_Vault_CapType">CapType</a>, delegate: address, is_revoked: bool ) <b>acquires</b> <a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a> { <b>if</b> (<b>exists</b><<a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a><Content>>(cap.vault_address)) { <b>let</b> event = <a href="Vault.md#0x1_Vault_VaultDelegateEvent">VaultDelegateEvent</a>{ metadata: *&borrow_global<<a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a><Content>>(cap.vault_address).metadata, vault_address: cap.vault_address, authority: cap.authority, delegate, cap: cap_type, is_revoked }; <a href="_emit_event">Event::emit_event</a>(&<b>mut</b> borrow_global_mut<<a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a><Content>>(cap.vault_address).delegate_events, event); } } </code></pre> </details><a name="0x1_Vault_transfer"></a>
transferTransfers ownership of the vault to a new signer. All delegations are revoked before transfer, and the new owner must re-create delegates as needed.
<pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_transfer">transfer</a><Content: drop, store>(cap: &<a href="Vault.md#0x1_Vault_TransferCap">Vault::TransferCap</a><Content>, to_owner: &signer) </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="Vault.md#0x1_Vault_transfer">transfer</a><Content: store + drop>(cap: &<a href="Vault.md#0x1_Vault_TransferCap">TransferCap</a><Content>, to_owner: &signer) <b>acquires</b> <a href="Vault.md#0x1_Vault">Vault</a>, <a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a>, <a href="Vault.md#0x1_Vault_VaultDelegate">VaultDelegate</a>, <a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a> { <b>let</b> new_addr = <a href="_address_of">Signer::address_of</a>(to_owner); <b>assert</b>(!<b>exists</b><<a href="Vault.md#0x1_Vault">Vault</a><Content>>(new_addr), <a href="_already_published">Errors::already_published</a>(<a href="Vault.md#0x1_Vault_EVAULT">EVAULT</a>)); <b>assert</b>( <a href="_is_some">Option::is_some</a>(&borrow_global<<a href="Vault.md#0x1_Vault">Vault</a><Content>>(cap.vault_address).content), <a href="_invalid_state">Errors::invalid_state</a>(<a href="Vault.md#0x1_Vault_EACCESSOR_IN_USE">EACCESSOR_IN_USE</a>) ); // Revoke all delegates. <b>if</b> (<b>exists</b><<a href="Vault.md#0x1_Vault_VaultDelegates">VaultDelegates</a><Content>>(cap.vault_address)) { <b>let</b> delegate_cap = <a href="Vault.md#0x1_Vault_DelegateCap">DelegateCap</a><Content>{vault_address: cap.vault_address, authority: cap.authority }; <a href="Vault.md#0x1_Vault_revoke_all">revoke_all</a>(&delegate_cap); }; // Emit event <b>if</b> event generation is enabled. We emit the event on the <b>old</b> vault not the new one. <b>if</b> (<b>exists</b><<a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a><Content>>(cap.vault_address)) { <b>let</b> event = <a href="Vault.md#0x1_Vault_VaultTransferEvent">VaultTransferEvent</a> { metadata: *&borrow_global<<a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a><Content>>(cap.vault_address).metadata, vault_address: cap.vault_address, authority: cap.authority, new_vault_address: new_addr }; <a href="_emit_event">Event::emit_event</a>(&<b>mut</b> borrow_global_mut<<a href="Vault.md#0x1_Vault_VaultEvents">VaultEvents</a><Content>>(cap.vault_address).transfer_events, event); }; // Move the vault. move_to<<a href="Vault.md#0x1_Vault">Vault</a><Content>>(to_owner, move_from<<a href="Vault.md#0x1_Vault">Vault</a><Content>>(cap.vault_address)); } </code></pre> </details>