Skip to main content
Version: Next

Accounts

The type Account provides access to accounts, Accounts are only accessed through references, which might be authorized.

Account objects provide information about and allow the management of different aspects of the account, such as account storage, keys, contracts, and capabilities.

access(all)
struct Account {

/// The address of the account.
access(all)
let address: Address

/// The FLOW balance of the default vault of this account.
access(all)
let balance: UFix64

/// The FLOW balance of the default vault of this account that is available to be moved.
access(all)
let availableBalance: UFix64

/// The storage of the account.
access(AccountMapping)
let storage: Account.Storage

/// The contracts deployed to the account.
access(AccountMapping)
let contracts: Account.Contracts

/// The keys assigned to the account.
access(AccountMapping)
let keys: Account.Keys

/// The inbox allows bootstrapping (sending and receiving) capabilities.
access(AccountMapping)
let inbox: Account.Inbox

/// The capabilities of the account.
access(AccountMapping)
let capabilities: Account.Capabilities
}

entitlement mapping AccountMapping {
include Identity

Storage -> SaveValue
Storage -> LoadValue
Storage -> CopyValue
Storage -> BorrowValue

Contracts -> AddContract
Contracts -> UpdateContract
Contracts -> RemoveContract

Keys -> AddKey
Keys -> RevokeKey

Inbox -> PublishInboxCapability
Inbox -> UnpublishInboxCapability
Inbox -> ClaimInboxCapability

Capabilities -> StorageCapabilities
Capabilities -> AccountCapabilities
}

Account access

Performing read operations

Access to an &Account means having "read access" to it. For example, the address and balance fields have the access(all) modifier, so are always accessible, which is safe because this information is public, and the fields are read-only.

Any code can get a "read-only" reference to an account (&Account) at a given address by using the built-in getAccount function:

fun getAccount(_ address: Address): &Account

Performing write operations

Access to an authorized account reference (auth(...) &Account) means having certain "write access" to it.

Entitlements authorize access to accounts. Cadence provides both coarse-grained and fine-grained entitlements, which decide what management functions are accessible on the account.

For example, the coarse-grained entitlement Storage grants access to all storage related functions, such as save and load, which save a value to storage, and load a value from storage respectively.

The fine-grained entitlement AddKey for instance, grants access to only the add function of the Account.Keys value, that is, it grants access to adding a key to the account.

An authorized account reference like auth(Storage, AddKey) &Account therefore provides read access, as well as write access to storage, and the ability to add a new key to that account.

Signed transactions can get authorized account references for each signer of the transaction that signs as an authorizer. The prepare phase of the transaction can specify exactly which entitlements it needs to perform its work.

For example, a transaction that deploys a contract to an account can be written as follows:

transaction {
prepare(signer: auth(AddContract) &Account) {
signer.contracts.add(name: "MyContract", code: [/* code */])
}
}

Here, the transaction requests an authorized reference with the AddContract entitlement. That means that the transaction is entitled to add a contract to the account, but is not able to add another key to the account, for example.

Script can get any kind of access to any account, using the built-in getAuthAccount function:

fun getAuthAccount<T: &Account>(_ address: Address): T

This function is only available in scripts. Though scripts can perform write operations, they discard their changes upon completion. Attempting to use this function outside of a script, for example in a transaction, causes a type error.

Creating an account

The Account constructor allows creating new accounts. The function requires a reference to a payer account, which should pay for the account creation.

The payer account must have enough funds to be able to create an account. If the account does not have the required funds, the program aborts.

The constructor returns a reference to the new account which has all coarse-grained account entitlements (it has the type auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account). This provides write access to all parts fo the new account, for example, storage, contracts, and keys.

fun Account(payer: auth(BorrowValue | Storage) &Account):
auth(Storage, Contracts, Keys, Inbox, Capabilities) &Account

For example, the following transaction creates a new account and has the signer of the transaction pay for it:

transaction {
prepare(signer: auth(BorrowValue) &Account) {
let account = Account(payer: signer)
}
}