Accounts
Within a single workchain, the most basic information storage entity is the account.
An account is uniquely determined by its identifier.
Within the whole blockchain — the collection of workchains — the account is uniquely determined by its address: that is, when we put together the workchain identifier and its account identifier.
The account record stores account address, account balance and maybe a smart-contract state. The latter might be missing, and yet the account is able to receive basic messages.
Simplified representation of an Everscale Account
An account could be created either by a user, or by a smart-contract.
It is done by sending a message carrying a special payload to an address of the account.
In the process of its operation, an account might become frozen or deleted. This is usually the result of an account being in debt, or executing a special instruction. We depict the life-cycle of an account in Fig.
Account Lifecycle
In the beginning, the account remains in an Nonexistent state — it stores no funds and no data. Only after you send some value to the account, does it switch to the Uninit state. In that state, it is not yet very useful: it may only receive coins from the incoming messages.
The account might be initialized with a message carrying a StateInit data blob containing smart-contract code and data. In this case, with enough coins on the balance, the account becomes initialized with this smart-contract, and it is then switched into Active state.
Due to storage fees, the account balance might become negative, leading to Frozen state and even being deleted afterwards. The other option for deletion is if the smart-contract itself executes a special action. After the deletion, the account state is switched back to Nonexistent state.
Account Structure Definition
The account structure is defined as follows:
struct AccountStuff {
addr: MsgAddressInt,
storage_stat: StorageInfo,
storage: AccountStorage,
}
type Account = Option<AccountStuff>;
AccountStuff structure fields
Field | Description |
---|---|
addr | Account address |
storage_stat | Account storage use statistics |
storage | Account smart-contract storage |
Account Address
The location of an account on Everscale blockchain is represented as a two-value structure: the workchain number and the account identifier. This structure is called an account address. Hereinafter, we just call it address for greater convenience.
Addresses are defined as follows:
pub enum MsgAddressInt {
AddrStd(MsgAddrStd),
AddrVar(MsgAddrVar),
}
pub struct MsgAddrStd {
pub anycast: Option<AnycastInfo>,
pub workchain_id: i8,
pub address: AccountId,
}
pub type AccountId = SliceData;
The address may be encoded by one of the two structures: MsgAddrStd or MsgAddrVar. The latter is used to locate accounts in huge blockchains, when the standard 8-bit workchain_id is not enough, and not supported currently.
- Type SliceData denotes a binary blob encoded in a tree data structure.
- Type
i8
is an 8-bit signed integer.
MsgAddrStd structure fields
Field | Description |
---|---|
anycast | Multi-shard contracts routing information |
workchain_id | Workchain identifier |
address | Account identifier within the workchain |
Anycast-addresses are planned to be removed shortly.
Account Storage
Any account on the Everscale blockchain is being charged for occupying space on a regular basis. The fee depends on the size of data being stored, the current prices and when the last charge took place. In some circumstances, an account may also have a debt, called due payment. Most of this information is stored in the StorageInfo structure.
pub struct StorageInfo {
used: StorageUsed,
last_paid: u32,
due_payment: Option<Grams>,
}
pub struct StorageUsed {
cells: VarUInteger7,
bits: VarUInteger7,
public_cells: VarUInteger7,
}
StorageInfo structure fields
Field | Description |
---|---|
used | Blockchain storage use statistics |
last_paid | Time of the latest payment, in Unix Epoch |
due_payment | Debt of the account |
- Type Grams denotes a set of natural numbers , equipped with and operators, such that:
Here and operators are standard addition and subtraction operators in a set of integers .
- Amount of storage used by the account is encoded with StorageUsed struct.
StorageUsed structure fields
Field | Description |
---|---|
cells | Number of cells occupied by the account |
bits | Number of bits occupied by the account |
public_cells | Field is not used |
To store the data in a tree-like form, it is encoded as a series of interlinked cells. This data structure also consumes some space and it is accounted for in the cell field. The bits field refers to data size being encoded in the cells.
Account Data
The full account record is represented by several nested data structures:
- Account storage
- Account state
- Smart-contract storage called StateInit
Account Storage structure
The most outer record is the account storage. It contains the account balance and the account state. The account state may contain the smart-contract code and data, described by the structure called StateInit.
pub struct AccountStorage {
last_trans_lt: u64,
balance: CurrencyCollection,
state: AccountState,
}
AccountStorage fields
Field | Description |
---|---|
last_trans_lt | Last transaction logical time |
balance | Amount of cryptocurrency tokens available for the account |
state | Current account state |
Account State
The account state defines the mode of operation for the account, during the message being executed for that account. The Transaction Executor logic varies greatly depending on what the current account state is.
The account state may have additional data fields. See the enumeration below.
enum AccountState {
AccountUninit,
AccountActive{
init_code_hash: Option<UInt256>,
state_init: StateInit,
},
AccountFrozen{
init_code_hash: Option<UInt256>,
state_init_hash: UInt256,
},
}
The life cycle of an account is depicted on Fig.
Let us clarify the fields of enumeration items.
For AccountActive, the value stateinit defines the byte-code and data of the associated smart-contract. The field _init_code_hash defines the hash of the field state_init.code that was used at the moment of the account initialization, or at the moment of the account freeze.
In Everscale, it is possible to change the smart-contract's code on the fly using the SetCode action. However, the value init_code_hash stays unaffected.
The same holds for AccountFrozen. The value of state_init_hash defines the hash of the smart-contract state_init.code at the moment of a freeze.
Smart-Contract Storage (StateInit)
The byte-code and data of a contract are stored within a structure called StateInit. Its name may seem quite confusing. It could have been named just State. The Init part comes from the fact that this structure is also used for the initialization of an account when it is uninitialized.
pub struct StateInit {
pub split_depth: Option<Number5>,
pub special: Option<TickTock>,
pub code: Option<Cell>,
pub data: Option<Cell>,
pub library: StateInitLib,
}
split_depth field was initially devoted to large multi-shard smart-contracts, but currently it is not used.
special fields signal the fact that the smart-contract is related to the blockchain system functioning. This is related to the very small amount or contracts residing in the Masterchain, i.e. Elector, Config, Giver, etc. There is a special logic to executing messages destined for those contracts.
code and data fields encodes the current byte-code and data of a contract. Here, data denote values of contract's variables.
library used to encode the code libraries the contract may refer to from its code. This mechanism is deprecated.