Accounts on Radix

With Radix Engine v2, accounts will dramatically change form from the accounts currently used on the Radix Olympia mainnet. The form of accounts described on this page will not be on the Radix mainnet until the Babylon release. Accounts created on Olympia today will be automatically migrated to the new form at Babylon release.

Unlike most blockchain platforms, an account on Radix are not simply associated with your public and private key. Instead, an account is a component, instantiated from a built-in account blueprint provided by the system which exist in the application layer. Even though accounts are implemented in the application layer, account components are unique in that they’re afforded some unique features that are not afforded to other normal components. As a result, accounts on Radix can contain resources and have special logic built into it.

Naturally, an account has an owner which controls the account, and the owner of the account is able to:

  • Lock a fee from the XRD vault that the account may hold to pay for transaction fees.

  • Manage the account by withdrawing and depositing resources.

  • Create proofs against resources that the account stores.

  • Configure which deposits the account accepts and rejects.

Furthermore, account components have a security model which employs a Role Based Access Control (RBAC) model where there are pre-configured roles which are mapped to privileged methods that only these roles have access to. These are roles to delineate who is allowed to do what with the account.

The account blueprint has two pre-configured roles by default: Owner and Securify.

  • The Owner role is given the ability to call all the privileged methods on the account (such as methods that withdraw and deposit resources or lock XRD for fee payment).

  • The Securify role is the role that can call the appropriate methods that "securifies" the account. This allows to expand the accounts authorization model and enables things like multi-factor control. More information on account securificaton is provided in the Account Securification section.

While the Owner can expand who is allowed to access their account by re-configuring the roles, by default at instantiation, both roles are associated to the owner.

The diagram below shows a complete list of the account methods and the roles that they map to, in other terms, it shows the roles that are authorized to call these methods. It also shows the mapping of the roles to the access rules. All the methods seen in the diagram below are explained in detail in the API Reference section of the document.

account tree

How the Account Component Works

Use of Radix accounts is done through calls to component methods using the transaction manifest (as with any component).

For example, a simple transfer of 10 XRD tokens from Alice’s account to Bob’s is accomplished by creating a transaction manifest that describes these steps:

  • Lock fees to pay for the transaction

  • Call the withdraw method on Alice’s account component, requesting 10 XRD

  • Take the returned tokens from the worktop and put them in a bucket

  • Pass this bucket to the try_deposit_or_x method of Bob’s account component

As long as Alice’s account does in fact have 10 XRD to withdraw (and is authorized to withdraw from that component - more on this below), the 10 XRD are returned and deposited in Bob’s account (as long as Bob’s account is not configured to deny XRD). If any of these assumptions are incorrect, the whole transaction fails.

In this way, using a Radix-style account is intuitively like getting cash from your wallet when you want to pay for something.

Account Virtualization

Accounts on Radix have two states: they can either be virtual or physical.

  • Virtual: A virtual account is an account that has no state on ledger and whose address is derived from the public key of one of the supported curves and is controlled by a signature from the associated private key.

  • Physical: A physical account is an account that has state on ledger. A physical account could have started its life as a virtual account and then became a physical account after the first interaction with the account, or it could have been created as a physical account.

    • Note that whoever performs this interaction pays a slightly higher fee for the transaction since they’re instantiating the component.

Account components can be virtualized because of a deterministic function, a virtual account address can be derived from the public key of a supported curve that is controlled by the associated private key, all without having any actual state on the ledger.

The following is the algorithm used to derive the virtual account address associated with a public key:

  • For Ecdsa Secp256k1 compress the public key, for EdDSA Ed25519 skip this step.

  • Hash the public key through Blake2b with 256 bit digests.

  • Take the last 30 bytes of the public key hash.

  • Set the first byte to 0xD1 for an Ecdsa Secp256k1 public key and 0x51 for an EdDSA Ed25519 public key.

  • Bech32m encode the above with the account_${network_specifier} HRP where the network_specifier depends on the network that the address will be used for (see addressing).

Account Metadata and Owner Keys

More to come here once we have implemented messages and owner keys for accounts.

Configuring Account Deposit Modes and Resource Preference Map

There are two types of deposits for two different sets of callers:

  • Privileged methods such as deposit and deposit_batch which accepts all deposits and can only be called by the account owner.

  • Unprivileged methods such as try_deposit_or_abort, try_deposit_or_refund, try_deposit_batch_or_abort, and try_deposit_batch_or_refund that are reserved for third-parties who wish to deposit resources to an account.

Because privileged deposit* methods can only be called by the account owner, third-parties who wish to deposit resources to an account are required to use try_deposit* methods. The try_deposit* methods are reserved to allow account owners to configure how resources deposited to their account by third-parties are treated. As such, there are two settings that the owner of an account component can set up to configure how resources deposited are treated: the Resource Preference Map and the Account Deposit Mode.

  • The Resource Preference Map is a granular per resource configuration that account owners can specify.

  • The Account Deposit Mode is a fall-back configuration which determines how resources deposited into an account are broadly treated.

The resource preference map is the primary and first place that the account looks at when determining if a resource can be deposited or not and always supersedes configurations within the account deposit mode or any other account state.

Resource Preference Map

The account component contains a "resource preference" map in its state. This map stores the preference configuration of each specific resource and can be thought of as the “allow list” and “deny list”. Technically speaking, the resource preference map is defined in code as KeyValueStore<ResourceAddress, ResourcePreference> where each address of a resource (indicated by their ResourceAddress) is mapped to a ResourcePreference which is an enum variant of Allowed and Disallowed.

In summary:

  • If the ResourcePreference for some resource is Allowed then it is guaranteed to be deposited into the account, if the ResourcePreference for some resource is Disallowed then its guaranteed to be rejected by the account component, no other state matters.

  • A resource can not be in the “allow list” and “deny list” at the same time since a KeyValueStore does not allow for duplicate entries with the same key, thus, a resource can only be: Allowed, Disallowed, or has no entry in the resource preferences map.

The resource preference map of an account component can be configured through the set_resource_preference and remove_resource_preference methods by the owner. It’s important to note that resources are not special-cased to this resource preference mapping. Any resource can be put as a permitted resource and any resource can be put as a disallowed resource. This means even XRD can be Disallowed from being deposited into an account through unprivileged deposit methods.

Account Deposit Mode

When an account doesn’t have a specific resource configured in the resource preference map, the account component then uses a broader mechanism: account deposit mode. The account deposit mode is a default treatment of resource deposits that are not specified in the resource preference map. An account deposit mode can be configured in the following ways:

  • Accept: If the account doesn’t have a preference for a particular resource then permit the deposit of the resource.

  • Reject: If the account doesn’t have a preference for a particular resource then reject the deposit of the resource.

  • Allow Existing: If the account doesn’t have a preference for a particular resource then permit the deposit of the resource.

    • Any resource that the account has a vault for can be deposited into the account while in this mode even if the vault in the account is empty for that particular resource.

    • If the user wishes to get rid of a resource and never accept deposits of it again then they must configure that to the resource preference map.

The default deposit mode of an account can be configured through the set_default_deposit_rule method by the owner.

In summary:

  • If a resource isn’t configured in the resource preference map then the account’s default deposit mode comes into the picture which can either be Accept, Reject, or AllowExisting.

Authorized Depositors

With these account deposit configuration in mind, another feature to note is that the owner of an account can also specify authorized depositors. When owners specify authorized depositors to their account, the authorized depositors have special privileges which allows resource deposits into the account regardless of the account resource preferences and deposit mode setting. This effectively gives authorized depositors the same deposit privileges as the owner. Except of course the privileges starts and stops there and the owner can always revoke those privileges.

A small caveat is that, authorized depositors will still need to use try_deposit* methods even with their deposit privileges as the protected deposit* methods are only reserved for the owner.

When the owner wants to add an authorized depositor, they may do so by calling the add_authorized_depositor method. When calling this method, the owner can specify the ResourceOrNonFungible of an existing badge that the prospective authorized depositor may have or create one for the prospective authorized depositor to receive. The ResourceOrNonFungible is an input which accepts either a ResourceAddress if the badge used is a fungible resource or a NonFungibleGlobalId if the badge used is a non-fungible resource. Once specified, the badge will not be added to the account’s list of authorized depositor and the authorized depositor must have the badge present when making privileged deposits to the account.

For example, if the authorized depositor deposits a resource that have been specified as Disallowed in the resource preference map or that the account deposit mode is set to Reject, the account does the following:

  1. Check if the badge passed is in the account’s set of authorized depositors.

  2. Assert the presence of this badge in the auth zone.

  3. Permit the deposit.

The following is a complete flow chart showing the logic to determine if a deposit is allowed or not.

account deposit flow chart

Account Securification

Owners of an account component are defined by the Owner role which is mapped to an access rule. By default, the access rule is configured to its key pairs derived from a seedphrase to control the account. Thereby, the process of securifying the account is to update the associated access rule of the Owner from its default setting to a new one which instead specifies a badge (otherwise known as an "owner badge") to control the account.

An account can be securified by calling the securify method on the account, this method returns a bucket that contains the account’s owner badge (which the Owner access rule is now updated to). This badge must then be stored somewhere, ideally in an access controller.

The securify method is only callable by the Securify role. When a virtual account is first created, the Securify role is pre-configured to also be the Owner. However, after the account has been securified the Securify role is re-configured to DenyAll, meaning it can’t ever be changed again and the method can no longer be called.

Effectively, the securification process is the process of switching from signature mode (from key pairs) to badge mode, this is because the process changes the owner’s access rule from requiring a signature to requiring a badge instead. Switching the account authorization from signature mode to badge mode offers expanded authorization configuration for the owner as detailed in this article: How Multi-Factor Radix Smart Accounts Work and What They Can Do.

The securification process is an important process for the wallet. The wallet will have a dedicated flow for securifying accounts and creating an access controller to store the account’s owner badge into. The API Reference section contains an example of a manifest that securifies an account.

API Reference

Name

create

Type

Function

Callable by

Anybody

Arguments

None

Returns

  • ComponentAddress: The component address of the account component instantiated by this function.

  • Bucket: A bucket containing the account owner badge associated with this account.

Description

Creates a new global securified allocated1 account and returns the ComponentAddress of the account and a Bucket of the account’s owner badge.

This function is used to create a new global securified allocated (non-virtual) account. It mints an owner badge and sets it as the owner role giving it the authority to call privileged methods on the account.

1The term allocated refers to an account component which started its life as a physical account.

This function will never be called by the wallet for any of the wallet flows. It is documented here for the sake of completeness only. The wallet only creates virtual accounts and none of the current flows include the use of global or local allocated (non-virtual) accounts.

Transaction Manifest

CREATE_ACCOUNT;

TAKE_ALL_FROM_WORKTOP
    Address("${account_owner_badge_address}")
    Bucket("owner_badge");

# Do something with the owner badge, ideally create an access controller and deposit
# it there.

Note that the transaction manifest above is not complete, more specifically, the account owner badge returned from the create function is not deposited anywhere in this manifest. Ideally, the account owner badge would be stored in an access controller.

Name

create_advanced

Type

Function

Callable by

Anybody

Arguments

  • owner_role - OwnerRole: The role definition of the account owner.

Returns

  • ComponentAddress: The component address of the account component instantiated by this function.

Description

Creates a new global allocated account with the owner rule specified by the caller and returns the ComponenAddress of the account component.

While the create function automatically mints an owner badge and sets that as the owner role, this function allows the caller to specify the AccessRule associated with the owner role giving the caller more freedom on who can call privileged methods on the account.

This is useful for any application where the creator of the account wishes to have some kind of an m-of-n multi-signature account, a 1-of-n account, or an account whose owner is any arbitrarily complex AccessRule. An example of where this might be used is for exchanges which might want to have an account controlled by 4-of-6 signatures to ensure that a single compromised key does not result in the loss of funds. Most users of this function do not particularly need to have the multi-factor authentication and recovery logic of an access controller.

This function will never be called by the wallet for any of the wallet flows. It is documented here for the sake of completeness only. The wallet only creates virtual accounts and none of the current flows include the use of global or local allocated (non-virtual) accounts.

Transaction Manifest

CREATE_ACCOUNT_ADVANCED
    Enum<OwnerRole::Updatable>(
        # Contrived example to show AccessRule configuration
        Enum<AccessRule::AllowAll>()
    );

Name

securify

Type

Method

Callable by

Securify role

Arguments

None

Returns

  • Bucket: A bucket containing the account owner badge associated with this account.

Description

Securifies the account, transitioning it from operating in signature mode to operating in badge mode.

This method securifies the account minting a new account owner badge and changing the account’s current owner access rule to a new access rule of the account owner badge and returns the minted owner badge. The returned badge then must be stored somewhere, ideally in an access controller.

This method is only callable by the Securify role. When a virtual account is first created, the Securify role requires the Owner authority. However, after the account has been securified the Securify role changes to being DenyAll such that securification can never happen again.

Transaction Manifest

CALL_METHOD
    Account("${account_component_address}")
    "securify";

TAKE_ALL_FROM_WORKTOP
    Address("${account_owner_badge_address}")
    Bucket("owner_badge");

# Do something with the owner badge, ideally create an access controller and deposit
# it there.

Note that the transaction manifest above is not complete, more specifically, the account owner badge returned from the securify method is not deposited anywhere in this manifest. Ideally, the account owner badge would be stored in an access controller.

Name

lock_fee

Type

Method

Callable by

Owner role

Arguments

  • amount - Decimal: The amount of XRD to lock for fees.

Returns

None

Description

Locks some amount of XRD in fees from the account’s XRD vault.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "lock_fee"
    Decimal("${amount_of_xrd_to_lock_for_fees}");

Name

lock_contingent_fee

Type

Method

Callable by

Owner role

Arguments

  • amount - Decimal: The amount of XRD to lock for fees.

Returns

None

Description

Locks some amount of XRD in fees from the account’s XRD vault which is contingent on the success of the transaction. If the transaction succeeds, then the locked XRD may be used for fees, if the transaction fails then the locked XRD are not used for fees.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "lock_contingent_fee"
    Decimal("${amount_of_xrd_to_lock_for_fees}");

Name

deposit

Type

Method

Callable by

Owner role

Arguments

  • bucket - Bucket: The bucket of resources to deposit into the account.

Returns

None

Description

Deposits a bucket of resources into the account.

This method is only callable by the account owner and does not do any of the checks discussed in the Account Deposit Modes section. It permits all deposits since it requires the owner authority to be present when calling it.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "deposit"
    Bucket("some_bucket");

Name

deposit_batch

Type

Method

Callable by

Owner role

Arguments

  • buckets - Vec<Bucket>: The buckets of resources to deposit into the account.

Returns

None

Description

Deposits multiple buckets of resources into the account.

This method is identical to deposit but deposits a vector of buckets instead of depositing a single bucket.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "deposit_batch"
    Expression("ENTIRE_WORKTOP");

Name

withdraw

Type

Method

Callable by

Owner role

Arguments

  • resource_address - ResourceAddress: The resource address of the resource to withdraw from the account.

  • amount - Decimal: The amount to withdraw from the account.

Returns

* Bucket: A bucket of the withdrawn resources.

Description

Withdraws resources from the account by amount.

This method withdraws a resource of the given address and amount from the account vaults and returns it in a Bucket.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "withdraw"
    Address("${resource_address}")
    Decimal("${amount}");

Name

withdraw_non_fungibles

Type

Method

Callable by

Owner role

Arguments

  • resource_address - ResourceAddress: The resource address of the resource to withdraw from the account.

  • ids - BTreeSet<NonFungibleLocalId>: The set of non-fungible local ids of the resource to withdraw from the account.

Returns

* Bucket: A bucket of the withdrawn resources.

Description

Withdraws resources from the account by NonFungibleLocalIds.

This method withdraws a resource of the given address and non-fungible local ids from the account vaults and returns it in a Bucket.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "withdraw_non_fungibles"
    Address("${resource_address}")
    Array<NonFungibleLocalId>(NonFungibleLocalId("${some_non_fungible_local_id}"));

Name

lock_fee_and_withdraw

Type

Method

Callable by

Owner role

Arguments

  • amount_to_lock - Decimal: The amount of XRD to lock for fees.

  • resource_address - ResourceAddress: The resource address of the resource to withdraw from the account.

  • amount - Decimal: The amount to withdraw from the account.

Returns

* Bucket: A bucket of the withdrawn resources.

Description

Locks some amount of XRD for fees and withdraws resources from the account by amount.

This is a composite method which calls both lock_fee and withdraw in a single call which makes this method slightly cheaper to use when we wish to lock some XRD for fees and also withdraw resources form the account.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "lock_fee_and_withdraw"
    Decimal("${amount_of_xrd_to_lock_for_fees}")
    Address("${resource_address}")
    Decimal("${amount}");

Name

lock_fee_and_withdraw_non_fungibles

Type

Method

Callable by

Owner role

Arguments

  • amount_to_lock - Decimal: The amount of XRD to lock for fees.

  • resource_address - ResourceAddress: The resource address of the resource to withdraw from the account.

  • ids - BTreeSet<NonFungibleLocalId>: The set of non-fungible local ids of the resource to withdraw from the account.

Returns

* Bucket: A bucket of the withdrawn resources.

Description

Locks some amount of XRD for fees and withdraws resources from the account by non-fungible local ids

This is a composite method which calls both lock_fee and withdraw_non_fungibles in a single call which makes this method slightly cheaper to use when we wish to lock some XRD for fees and also withdraw resources form the account.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "lock_fee_and_withdraw_non_fungibles"
    Decimal("${amount_of_xrd_to_lock_for_fees}")
    Address("${resource_address}")
    Array<NonFungibleLocalId>(NonFungibleLocalId("${some_non_fungible_local_id}"));

Name

create_proof_of_amount

Type

Method

Callable by

Owner role

Arguments

  • resource_address - ResourceAddress: The resource address of the resource to withdraw from the account.

  • amount - Decimal: The amount of the resource to create a proof of.

Returns

  • Proof: A proof of the specified quantity and resource.

Description

Creates a proof of the specified resource and amount.

This method creates a Proof of the resource and amount specified to the method and returns it.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "create_proof_of_amount"
    Address("${resource_address}")
    Decimal("${amount}");

Name

create_proof_of_amount

Type

Method

Callable by

Owner role

Arguments

  • resource_address - ResourceAddress: The resource address of the resource to withdraw from the account.

  • ids - BTreeSet<NonFungibleLocalId>: The set of non-fungible local ids of the resources to create a proof of.

Returns

  • Proof: A proof of the specified non-fungible local ids and resource.

Description

Creates a proof of the specified resource of and non-fungible local ids.

This method creates a Proof of the resource and non-fungible local ids specified to the method and returns it.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "create_proof_of_non_fungibles"
    Address("${resource_address}")
    Array<NonFungibleLocalId>(NonFungibleLocalId("${some_non_fungible_local_id}"));

Name

set_default_deposit_rule

Type

Method

Callable by

Owner role

Arguments

  • default - DefaultDepositRule: Describes how the account should deal with resources that it does not have specific rules for. This could either be Accept, Reject, or AllowExisting.

Returns

None

Description

Sets the default deposit rule of the account

This method changes the default deposit rule of the account changing the behavior of how the account handles deposits from third-parties of resources that it does not have a specific rule for.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "set_default_deposit_rule"
    Enum<DefaultDepositRule::Accept>();

A more complete manifest example of this can be found here.

Name

set_resource_preference

Type

Method

Callable by

Owner role

Arguments

  • resource_address - ResourceAddress: The address of the resource to add a resource preference for.

  • resource_preference - ResourcePreference: Describes how the account how deal with deposits of this resource. This is either Allowed, or Disallowed.

Returns

None

Description

Sets the resource preference of a resource.

This method sets and overrides the preference of the resource in the account.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "set_resource_preference"
    Address("${resource_address}")
    Enum<ResourcePreference::Allowed>();

A more complete manifest example of this can be found here.

Name

remove_resource_preference

Type

Method

Callable by

Owner role

Arguments

  • resource_address - ResourceAddress: The address of the resource to add a resource preference for.

Returns

None

Description

Removes the preference of a resource making it use the default deposit rule instead. If no preference for this resource exists then nothing happens.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "remove_resource_preference"
    Address("${resource_address}");

A more complete manifest example of this can be found here.

Name

add_authorized_depositor

Type

Method

Callable by

Owner role

Arguments

  • badge - ResourceOrNonFungible: The badge of the authorized depositor to add specified as a ResourceOrNonFungible.

Returns

None

Description

Adds an authorized depositor badge to the set of authorized depositors.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "add_authorized_depositor"
    Enum<ResourceOrNonFungible::Resource>(Address("${resource_address}"));

A more complete manifest example of this can be found here.

Name

remove_authorized_depositor

Type

Method

Callable by

Owner role

Arguments

  • badge - ResourceOrNonFungible: The badge of the authorized depositor to remove specified as a ResourceOrNonFungible.

Returns

None

Description

Removes an authorized depositor badge to the set of authorized depositors.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "remove_authorized_depositor"
    Enum<ResourceOrNonFungible::Resource>(Address("${resource_address}"));

A more complete manifest example of this can be found here.

Name

try_deposit_or_refund

Type

Method

Callable by

Owner role

Arguments

  • bucket - Bucket: The bucket of resources to attempt to deposit into the account.

  • authorized_depositor_badge - Option<ResourceOrNonFungible>: An optional parameter of authorized depositor badge to use for this deposit. If specified, then it will be checked and used if the deposit can’t go through without it.

Returns

* Option<Bucket>: An optional bucket of resources. This is Some if the deposit failed and the bucket is being returned and None if the deposit succeeded.

Description

Attempts to deposit resources in the account, refunds them returns them if the deposit fails.

This method attempts to deposit a bucket of resources into the account, if the account is configured to disallow deposits of this resource then they’re returned and refunded back as a bucket.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "try_deposit_or_refund"
    Bucket("some_bucket")
    None;

Name

try_deposit_batch_or_refund

Type

Method

Callable by

Anybody

Arguments

  • buckets - Vec<Bucket>: The buckets to attempt to deposit into the account.

  • authorized_depositor_badge - Option<ResourceOrNonFungible>: An optional parameter of authorized depositor badge to use for this deposit. If specified, then it will be checked and used if the deposit can’t go through without it.

Returns

  • Vec<Bucket>: A vector of buckets which is empty if all the resources could be deposited and has the same length as the arguments if any of the resources could not be deposited.

Description

Attempts to deposit buckets of resources into the account and refunds all of them if any of them can’t be deposited.

This method attempts to deposit buckets of resources into the account, if the account is configured to disallow deposit of any the resources then they’re all returned and refunded back as buckets.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "try_deposit_batch_or_abort"
    Expression("ENTIRE_WORKTOP")
    None;

Name

try_deposit_batch_or_abort

Type

Method

Callable by

Anybody

Arguments

  • buckets - Vec<Bucket>: The buckets to attempt to deposit into the account.

  • authorized_depositor_badge - Option<ResourceOrNonFungible>: An optional parameter of authorized depositor badge to use for this deposit. If specified, then it will be checked and used if the deposit can’t go through without it.

Returns

None

Description

Attempts to deposit buckets of resources into the account aborts the transaction if any of them can’t be deposited.

This method attempts to deposit buckets of resources into the account, if the account is configured to disallow deposit of any the resources then the transaction aborts.

Transaction Manifest

CALL_METHOD
    Address("${account_component_address}")
    "try_deposit_batch_or_abort"
    Expression("ENTIRE_WORKTOP")
    None;