Algorand Ledger State Guide
Algorand Ledger State Guide
Abstract
Algorand replicates a state and the state’s history between protocol
participants. This state and its history is called the Algorand Ledger.
Contents
1 Overview 2
1.1 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 States . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2 Round 5
3 Genesis Identifier 5
4 Genesis Hash 6
6 Timestamp 7
7 Cryptographic Seed 7
8 Reward State 7
9 Account State 8
9.1 Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
9.1.1 Key/Value Stores . . . . . . . . . . . . . . . . . . . . . . . 10
9.1.2 State Schemas . . . . . . . . . . . . . . . . . . . . . . . . 10
9.1.3 Boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
9.2 Assets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
10 Participation Updates 13
1
12 Light Block Header Commitment 13
16 Transactions 15
16.0.1 Payment Transaction . . . . . . . . . . . . . . . . . . . . . 16
16.0.2 Key Registration Transaction . . . . . . . . . . . . . . . . 17
16.0.3 Application Call Transaction . . . . . . . . . . . . . . . . 18
16.0.4 Asset Configuration Transaction . . . . . . . . . . . . . . 19
16.0.5 Asset Transfer Transaction . . . . . . . . . . . . . . . . . 19
16.0.6 Asset Freeze Transaction . . . . . . . . . . . . . . . . . . 20
16.1 State proof transaction . . . . . . . . . . . . . . . . . . . . . . . . 20
16.2 Authorization and Signatures . . . . . . . . . . . . . . . . . . . . 21
16.3 ApplyData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
16.3.1 State Deltas . . . . . . . . . . . . . . . . . . . . . . . . . . 23
16.4 Transaction Sequences, Sets, and Tails . . . . . . . . . . . . . . . 24
16.5 Transaction Groups . . . . . . . . . . . . . . . . . . . . . . . . . 25
16.6 Asset Transaction Semantics . . . . . . . . . . . . . . . . . . . . 26
16.7 ApplicationCall Transaction Semantics . . . . . . . . . . . . . . . 28
16.7.1 Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
16.7.2 Application Stateful Execution Semantics . . . . . . . . . 30
16.8 Validity and State Changes . . . . . . . . . . . . . . . . . . . . . 31
17 Previous Hash 33
18 Multisignature 33
1 Overview
1.1 Parameters
The Algorand Ledger is parameterized by the following values:
• tδ , the maximum difference between successive timestamps. Currently
defined as 25 seconds.
• Tmax , the length of the transaction tail. Currently defined as 1000.
• Bmax , the maximum number of transaction bytes in a block. Currently
defined as 5,242,880.
• bmin , the minimum balance for any address. Currently defined as 100,000
microAlgos.
• fmin , the minimum processing fee for any transaction. Currently defined
as 1000 microAlgos.
2
• Vmax , the maximum length of protocol version strings. Currently defined
as 128.
• Nmax , the maximum length of a transaction note string. Currently defined
as 1024 bytes.
• Gmax , the maximum number of transactions allowed in a transaction
group. Currently defined as 16.
• τ , the number of votes needed to execute a protocol upgrade. Currently
defined as 9000.
• δd , the number of rounds over with an upgrade proposal is open. Currently
defined as 10,000.
• δxmin and δxmax , the minimum and maximum number of rounds needed
to prepare for an upgrade. Currently respectively defined as 10,000 and
150,000.
• δx , the default number of rounds needed to prepare for an upgrade. Cur-
rently defined as 140,000.
• ωr , the rate at which the reward rate is refreshed. Currently defined as
500,000.
• A, the size of an earning unit. Currently defined as 1,000,000 microAlgos.
• Several parameters for state proofs; namely: (current values provided in
the “State Proof Tracking” section)
– δSP , the number of rounds between state proofs.
– δSP B , the delay (lookback) in rounds for online participant informa-
tion committed to in the block header for state proofs.
– NSP , the maximum number of online accounts that are included in
the Vector commitment of state proofs participants.
– KQSP , the security parameter for state proof.
– fSP , the fraction of participants that are proven to have signed by a
state proof.
1.2 States
A ledger is a sequence of states which comprise the common information es-
tablished by some instantiation of the Algorand protocol. A ledger is identified
by a string called the genesis identifier, as well as a genesis hash that crypto-
graphically commits to the starting state of the ledger. Each state consists of
the following components:
• The round of the state, which indexes into the ledger’s sequence of states.
• The genesis identifier and genesis hash, which identify the ledger to which
the state belongs.
• The current protocol version and the upgrade state.
• A timestamp, which is informational and identifies when the state was first
proposed.
• A seed, which is a source of randomness used to establish consensus on
3
the next state.
• The current reward state, which describes the policy at which incentives
are distributed to participants.
• The current account state, which holds account balances and keys for all
stakeholding addresses.
– One component of this state is the transaction tail, which caches the
transaction sets (see below) in the last Tmax blocks.
• The current box state, which holds mappings from (app id, name) tuples
to box contents of arbitrary bytes.
1.3 Blocks
A block is a data structure which specifies the transition between states. The
data in a block is divided between the block header and its block body. The block
header contains the following components:
• The block’s round, which matches the round of the state it is transitioning
into. (The block with round 0 is special in that this block specifies not
a transition but rather the entire initial state, which is called the genesis
state. This block is correspondingly called the genesis block.) The round
is stored under msgpack key rnd.
• The block’s genesis identifier and genesis hash, which match the genesis
identifier and hash of the states it transitions between. The genesis identi-
fier is stored under msgpack key gen, and the genesis hash is stored under
msgpack key gh.
• The block’s upgrade vote, which results in the new upgrade state. The
block also duplicates the upgrade state of the state it transitions into.
The msgpack representation of the components of the upgrade vote are
described in detail below.
• The block’s timestamp, which matches the timestamp of the state it tran-
sitions into. The timestamp is stored under msgpack key ts.
• The block’s seed, which matches the seed of the state it transitions into.
The seed is stored under msgpack key seed.
• The block’s reward updates, which results in the new reward state. The
block also duplicates the reward state of the state it transitions into. The
msgpack representation of the components of the reward updates are de-
scribed in detail below.
• A cryptographic commitment to the block’s transaction sequence, de-
scribed below, stored under msgpack key txn.
• A cryptographic commitment, using SHA256 hash function, to the block’s
transaction sequence, described below, stored under msgpack key txn256.
4
• The block’s previous hash, which is the cryptographic hash of the previous
block in the sequence. (The previous hash of the genesis block is 0.) The
previous hash is stored under msgpack key prev.
• The block’s transaction counter, which is the total number of transactions
issued prior to this block. This count starts from the first block with a
protocol version that supported the transaction counter. The counter is
stored in msgpack field tc.
• The block’s expired participation accounts, which contains an optional slice
of public keys of accounts. These accounts are expected to have their
participation key expire by the end of the round (or was expired before
the current round). The msgpack representation of the components are
described in detail below. The slice is stored in msgpack key partupdrmv.
The block’s expired participation accounts slice is valid as long as the participa-
tion keys of all the accounts in the slice are expired by the end of the round or
were expired before, the accounts themselves would have been online at the end
of the round if they were not included in the slice, and the number of elements
in the slice is less or equal to 32. A block proposer may not include all such
accounts in the slice and may even omit the slice completely.
The block body is the block’s transaction sequence, which describes the sequence
of updates (transactions) to the account state and box state.
A block is valid if each component is also valid. (The genesis block is always
valid). Applying a valid block to a state produces a new state by updating each
of its components. The rest of this document defines block validity and state
transitions by describing them for each component.
2 Round
The round or round number is a 64-bit unsigned integer which indexes into the
sequence of states and blocks. The round r of each block is one greater than the
round of the previous block. Given a ledger, the round of a block exclusively
identifies it.
The rest of this document describes components of states and blocks with respect
to some implicit ledger. Thus, the round exclusively describes some component,
and we denote the round of a component with a subscript. For instance, the
timestamp of state/block r is denoted tr .
3 Genesis Identifier
The genesis identifier is a short string that identifies an instance of a ledger.
The genesis identifier of a valid block is the identifier of the block in the previous
round. In other words, GenesisIDr+1 = GenesisIDr .
5
4 Genesis Hash
The genesis hash is a cryptographic hash of the genesis configuration, used to
unambiguously identify an instance of the ledger.
The genesis hash is set in the genesis block (or the block at which an upgrade to
a protocol supporting GenesisHash occurs), and must be preserved identically
in all subsequent blocks.
6
• xr+1 is
– 0 if r = x′r or both r = sr and sr + b < τ ,
– r + δd + δ if vr′ is the empty string and vr is not the empty string
(where δ = δx if xr = 0 and δ = xr if xr ̸= 0), and
– x′r otherwise.
6 Timestamp
The timestamp is a 64-bit signed integer. The timestamp is purely informational
and states when a block was first proposed, expressed in the number of seconds
since [Link] Thursday, 1 January 1970 (UTC).
The timestamp tr+1 of a block in round r is valid if:
• tr = 0 or
• tr+1 > tr and tr+1 < tr + tδ .
7 Cryptographic Seed
The seed is a 256-bit integer. Seeds are validated and updated according to
the specification of the Algorand Byzantine Fault Tolerance protocol. The Seed
procedure specified there returns the seed from the desired round.
8 Reward State
The reward state consists of three 64-bit unsigned integers: the total amount of
money distributed to each earning unit since the genesis state Tr , the amount
of money to be distributed to each earning unit at the next round Rr , and the
amount of money left over after distribution Br∗ .
The reward state depends on the Ipool , the address of the incentive pool, and
the functions Stake(r, Ipool ) and RewardUnits(r). These are defined as part of
the Account State below.
Informally, every ωr rounds, the rate Rr is updated such that rewards given over
the next ωr rounds will drain the incentive pool, leaving it with the minimum
balance bmin . The rewards residue Br∗ is the amount of leftover rewards that
should have been given in the previous round but could not be evenly divided
among all reward units. The residue carries over into the rewards to be given in
the next round. The actual draining of the incentive pool account is described
in the Validity and State Changes section further below.
More formally, let Z = RewardUnits(r). Given a reward state (Tr , Rr , Br∗ ), the
∗
new reward state is (Tr+1 , Rr+1 , Br+1 ) where
Stake(r,Ipool )−Br∗ −bmin
j k
• Rr+1 = ωr if Rr ≡ 0 mod ωr ; Rr+1 = Rr otherwise,
7
• Tr+1 = Tr + RZr if Z ̸= 0; Tr+1 = Tr otherwise, and
∗
• Br+1 = (Br∗ + Rr ) mod Z if Z ̸= 0; Br+1
∗
= Br∗ otherwise.
A valid block’s reward state matches the expected reward state.
9 Account State
The balances are a set of mappings from addresses, 256-bit integers, to balance
records. A balance record contains the following fields: the account raw balance,
the account status, the account rewards base and total awarded amount, the
account spending key, and the account participation keys.
The account raw balance aI is a 64-bit unsigned integer which determines how
much money the address has.
The account rewards base a′I and total awarded amount a∗I are 64-bit unsigned
integers.
Combined with the account balance, the reward base and total awarded amount
are used to distribute rewards to accounts lazily. The account stake is a function
which maps a given account and round to the account’s balance in that round
and is defined as follows:
ja k
I
Stake(r, I) = aI + (Tr − a′I )
A
unless pi = 2 (see below), in which case:
Stake(r, I) = aI .
8
the account’s address) as their authorization address. This is described in the
Authorization and Signatures section below.
The account’s participation keys pk are defined in Algorand’s specification of
participation keys.
An account’s participation keys and voting stake from a recent round is returned
by the Record procedure in the Byzantine Agreement Protocol.
There exist two special addresses: Ipool , the address of the incentive pool, and
If , the address of the fee sink. For both of these accounts, pI = 2.
9.1 Applications
Each account can create applications, each named by a globally-unique inte-
ger (the application ID). Applications are associated with a set of application
parameters, which can be encoded as a msgpack struct:
• A mutable Stateful “Approval” program (ApprovalProgram), whose re-
sult determines whether or not an ApplicationCall transaction refer-
ring to this application ID is to be allowed. This program executes for
all ApplicationCall transactions referring to this application ID ex-
cept for those whose OnCompletion == ClearState, in which case the
ClearStateProgram is executed instead. This program may modify local
or global state associated with this application. This field is encoded with
msgpack field approv.
For Version 3 or lower programs, the cost of the program as determined
by the Stateful Check function must not exceed 700.
For Version 4 or higher programs, the cost of the program during execution
must not exceed 700.
• A mutable Stateful “Clear State” program (ClearStateProgram), exe-
cuted when an opted-in user forcibly removes the local application state
associated with this application from their account data. This happens
when an ApplicationCall transaction referring to this application ID is
executed with OnCompletion == ClearState. This program, when exe-
cuted, is not permitted to cause the transaction to fail. This program may
modify local or global state associated with this application. This field is
encoded with msgpack field clearp.
For Version 3 or lower programs, the cost of the program as determined
by the Stateful Check function must not exceed 700.
For Version 4 or higher programs, the cost of the program during execution
must not exceed 700.
• An immutable “global state schema” (GlobalStateSchema), which sets a
limit on the size of the global Key/Value Store that may be associated
9
with this application (see “State Schemas”). This field is encoded with
msgpack field gsch.
The maximum number of values that this schema may permit is 64.
• An immutable “local state schema” (LocalStateSchema), which sets a
limit on the size of a Key/Value Store that this application will allocate in
the account data of an account that has opted in (see “State Schemas”).
This field is encoded with msgpack field lsch.
The maximum number of values that this schema may permit is 16.
• An immutable “extra pages” value (ExtraProgramPages), which limits
the total size of the programs of the application. The sum of the
lengths of ApprovalProgram and ClearStateProgram may not exceed
2048*(1+ExtraProgramPages) bytes. This field is encoded with msgpack
field epp and may not exceed 3. This ExtraProgramPages field is taken
into account on application update as well.
• The “global state” (GlobalState) associated with this application, stored
as a Key/Value Store. This field is encoded with msgpack field gs.
Each application created increases the minimum balance requirements of the
creator by 100,000 microalgos, plus the GlobalStateSchema Minimum Balance
contribution.
Each application opted in to increases the minimum balance requirements of the
opting-in account by 100,000 microalgos plus the LocalStateSchema Minimum
Balance contribution.
10
[Link] App Minimum Balance Changes
When an account opts in to an application or creates an application, the min-
imum balance requirements for that account increases. The minimum balance
requirement is decreased equivalently when an account closes out or deletes an
app.
When opting in to an application, there is a base minimum balance increase of
100,000 microalgos. There is an additional minimum balance increase based on
the LocalStateSchema for that application, described by following formula:
28500 * [Link] + 50000 * [Link] microalgos.
When creating an application, there is a base minimum balance increase of
100,000 microalgos. There is an additional minimum balance increase of 100000
* ExtraProgramPages microalgos. Finally, there is an additional minimum bal-
ance increase based on the GlobalStateSchema for that application, described
by the following formula:
28500 * [Link] + 50000 * [Link] microalgos.
9.1.3 Boxes
The box store is an associative array mapping keys of type (uint64 x byte-array)
to values of type byte-array. The key is a pair in which the first value corresponds
to an existing (or previously existing) application ID, and the second is a box
name, 1 to 64 bytes in length. The value is a byte-array of length not greater
than 32,768. Unlike global/local state keys, an empty array is not a valid box
name. However, empty box names may appear in transactions to increase the
I/O budget (see below).
When an application executes an opcode that creates or destroys a box, the
minimum balance of the associated application account (whose address is the
hash of the application ID) is modified. When a box with name n and size
s is created, the minimum balance requirement is raised by 2500 + 400 *
(len(n)+s). When the box is destroyed, the minimum balance is decremented
by the same amount.
9.2 Assets
Each account can create assets, named by a globally-unique integer (the asset
ID). Assets are associated with a set of asset parameters, which can be encoded
as a msgpack struct:
• The total number of units of the asset that have been created, encoded
with msgpack field t. This value must be between 0 and 264 − 1.
• The number of digits after the decimal place to be used when displaying
the asset, encoded with msgpack field dc. A value of 0 represents an asset
that is not divisible, while a value of 1 represents an asset divisible into
11
into tenths, 2 into hundredths, and so on. This value must be between 0
and and 19 (inclusive) (264 − 1 is 20 decimal digits).
• Whether holdings of that asset are frozen by default, a boolean flag en-
coded with msgpack field df.
• A string representing the unit name of the asset for display to the user,
encoded with msgpack field un. This field does not uniquely identify an
asset; multiple assets can have the same unit name. The maximum length
of this field is 8 bytes.
• A string representing the name of the asset for display to the user, encoded
with msgpack field an. As above, this does not uniquely identify an asset.
The maximum length of this field is 32 bytes.
• A string representing a URL that provides further description of the asset,
encoded with msgpack field au. As above, this does not uniquely identify
an asset. The maximum length of this field is 96 bytes.
• A 32-byte hash specifying a commitment to asset-specific metadata, en-
coded with msgpack field am. As above, this does not uniquely identify an
asset.
• An address of a manager account, encoded with msgpack field m. The
manager address is used to update the addresses in the asset parameters
using an asset configuration transaction.
• An address of a reserve account, encoded with msgpack field r. The
reserve address is not used in the protocol, and is used purely by client
software for user display purposes.
• An address of a freeze account, encoded with msgpack field f. The freeze
address is used to issue asset freeze transactions.
• An address of a clawback account, encoded with msgpack field c. The
clawback address is used to issue asset transfer transactions from arbitrary
source addresses.
Parameters for assets created by an account are stored alongside the account
state, denoted by a pair (address, asset ID).
Accounts can create and hold any number of assets. An account must hold
every asset that it created (even if it holds 0 units of that asset), until that
asset is destroyed. An account’s asset holding is simply a map from asset IDs to
an integer value indicating how many units of that asset is held by the account
and a boolean flag indicating if the holding is frozen or unfrozen. An account
that holds any asset cannot be closed.
12
10 Participation Updates
Participation updates contains a single list of addresses of accounts which have
been deemed to be expired. An account is said to be expired when the last valid
vote round in its participation key is strictly less than the current round that
is being processed. Once included in this list, an account will be marked offline
as part of applying the block changes to the ledger.
13
14 State Proof Tracking
Each block header keeps track of the state needed to construct, validate, and
record state proofs.
This tracking data is stored in a map under the msgpack key spt in the block
header. The map is indexed by the type of the state proof; at the moment, only
type 0 is supported. In the future, other types of state proofs might be added.
For type 0, KQSP = 256, fSP is 232 ∗ 30/100 (as the numerator of a fraction
out of 232 ), NSP = 1024, δSP = 256 and δSP B = 16 .
The value of the tracking data is a msgpack map with three elements:
• Under key n, the next expected round of a state proof that should be
formed. When upgrading from an earlier consensus protocol to a protocol
that supports state proofs, the n field is set to the lowest value such that
n is a multiple of δSP and so that the n is at least the first round of the
new protocol (supporting state proofs) plus δSP B + δSP . This field is set
in every block.
• Under key v, the root of the Vector commitment to an array of participants
that are eligible to vote in the state proof at round δSP from the current
block. Only blocks whose round number is a multiple of δSP have a non-
zero v field.
• Under key t, the total online stake at round δSP (with pending rewards).
The participants committed to by the Vector commitment are chosen in a spe-
cific fashion:
• First off, because it takes some time to collect all of the online participants
(more than the target assembly time for a block), the set of participants
and total online non-expired stake appearing in a commitment in block at
round r are actually based on the account state from round r − δSP B .
• The participants are sorted by the number of microAlgos they currently
hold (including any pending rewards). This enables more compact proofs
of pseudorandomly-chosen participants weighted by their microAlgo hold-
ings. Only accounts in the online state are included in this list of partici-
pants.
• To limit the worst-case size of this Vector commitment, the array of par-
ticipants contains just the top NSP participants. Efficiently computing
the top NSP accounts by their algo balance is difficult in the presence of
pending rewards. Thus, to make this top-NSP calculation more efficient,
we choose the top accounts based on a normalized balance, denoted below
by nI .
The normalized balance is a hypothetical balance: Consider an account
I with current balance aI . If an account had balance nI in the genesis
block, and did not perform any transactions since then, then its balance by
14
the current round (when rewards are included) will be aI , except perhaps
due to rounding effects. In more detail, let r be the last round in which
a transaction touched account I (and therefore all pending rewards were
added to it). Consider the following quantities, as defined in the Account
State:
– The raw balance aI of account I at round r is its total balance on
that round.
– The rewards base a′I is meant to capture the total rewards that were
allocated to all accounts upto round r, expressed as a fraction of the
total stake (with limited precision as described below).
Given these two quantities, the normalized balance of an online account
I is aI /(1 + a′I ). For example, if the total amount of rewards distributed
upto round r is 20% of the total stake, then the normalized balance is
aI /1.2.
To limit the required precision in this calculation, the system uses a param-
eter ru that specifies the rewards-earning unit, namely accounts only earn
rewards for a whole number of ru microAlgos. (Currently ru = 1, 000, 000,
so the rewards-earning unit is one Algo.)
The parameter a′I above is an integer such that a′I /ru is the desired frac-
tion, rounded down to precision of 1/ru. The normalized balance is com-
puted as nI = ⌊aI · ru/(a′I + ru)⌋.
16 Transactions
Just as a block represents a transition between two ledger states, a transaction
Tx represents a transition between two account states. A transaction contains
the following fields:
• The transaction type TxType, which is a short string that indicates the
type of a transaction. The following transaction types are supported:
15
– Transaction type pay corresponds to a payment transaction.
– Transaction type keyreg corresponds to a key registration transac-
tion.
– Transaction type acfg corresponds to an asset configuration trans-
action.
– Transaction type axfer corresponds to an asset transfer transaction.
– Transaction type afrz corresponds to an asset freeze transaction.
– Transaction type appl corresponds to an application call transaction.
• The sender I, which is an address which identifies the account that au-
thorized the transaction.
• The fee f , which is a 64-bit integer that specifies the processing fee the
sender pays to execute the transaction.
• The first valid r1 and last valid r2 for which the transaction may be
executed.
• The lease x, which is an optional 256-bit integer specifying mutual exclu-
sion. If x ̸= 0 (i.e., x is set) and this transaction is confirmed, then this
transaction prevents another transaction from the same sender and with
the lease set to the same value from being confirmed until r2 is confirmed.
• The genesis identifier GenesisID of the ledger for which this transaction
is valid. The GenesisID is optional.
• The genesis hash GenesisHash of the ledger for which this transaction is
valid. The GenesisHash is required.
• The group grp, an optional 32-byte hash whose meaning is described in
the Transaction Groups section below.
• The rekey to address RekeyTo, a 32-byte string. If nonzero, the transaction
will set the sender account’s spending key to this value. (If the RekeyTo
address matches the sender address, then the spending key is instead set
to zero.)
• The note N , a sequence of bytes with length at most Nmax which contains
arbitrary data.
16
• The closing address I0 , which is an optional address that collects all re-
maining funds in the account after the transfer to the receiver.
17
16.0.3 Application Call Transaction
An application call transaction additionally has the following fields:
• The ID of the application being called, encoded as msgpack field apid. If
the ID is zero, this transaction is creating an application.
• An OnCompletion type, which may specify an additional effect of this
transaction on the application’s state in the sender or application creator’s
account data. This field is encoded as msgpack field apan, and may take
on one of the following values:
– NoOpOC (value 0): Only execute the ApprovalProgram associated
with this application ID, with no additional effects.
– OptInOC (value 1): Before executing the ApprovalProgram, allocate
local state for this application into the sender’s account data.
– CloseOutOC (value 2): After executing the ApprovalProgram, clear
any local state for this application out of the sender’s account data.
– ClearStateOC (value 3): Don’t execute the ApprovalProgram, and
instead execute the ClearStateProgram (which may not reject this
transaction). Additionally, clear any local state for this application
out of the sender’s account data as in CloseOutOC.
– UpdateApplicationOC (value 4): After executing the ApprovalProgram,
replace the ApprovalProgram and ClearStateProgram associated
with this application ID with the programs specified in this
transaction.
– DeleteApplicationOC (value 5): After executing the ApprovalProgram,
delete the application parameters from the account data of the ap-
plication’s creator.
• Application arguments, encoded as msgpack field apaa. These arguments
are a slice of byte slices. There must be no more than 16 app arguments,
and the sum of their lengths in bytes must not exceed 2048.
• Accounts besides the Sender whose local states may be referred to by the
executing ApprovalProgram or ClearStateProgram. These accounts are
referred to by their addresses, and this field is encoded as msgpack field
apat. The maximum number of addresses in this field is 4.
• Application IDs, besides the application whose ApprovalProgram or
ClearStateProgram is executing, that the executing program may read
global state from. This field is encoded as msgpack field apfa. The
maximum number of entries in this field is 8.
• Asset IDs that the executing program may read asset parameters from.
This field is encoded as msgpack field apas. The maximum number of
entries in this field is 8.
• Box references that the executing program or any other program in the
same group may access for reading or modification when the reference
18
matches the running programs app ID. This field is encoded as msgpack
field apbx, each element of which is encoded as a msgpack object contain-
ing an index (i) and name (n). The maximum number of entries in this
field is 8. The index (i) is a 1-based index in the ForeignApps (apfa)
array. A 0 index is interpreted as the application ID of this transaction
(apid, or the ID that is allocated for the created app when apid is 0).
• Local state schema, encoded as msgpack field apls. This field is only used
during application creation, and sets bounds on the size of the local state
for users who opt in to this application.
• Global state schema, encoded as msgpack field apgs. This field is only
used during application creation, and sets bounds on the size of the global
state associated with this application.
• Extra program pages, encoded as msgpack field apep. This field is only
used during application creation, and requests an increased maximum size
for the approval and clear state programs.
• Approval program, encoded as msgpack field apap. This field is used
for both application creation and updates, and sets the corresponding
application’s ApprovalProgram.
• Clear state program, encoded as msgpack field apsu. This field is used
for both application creation and updates, and sets the corresponding
application’s ClearStateProgram.
– The Approval program and the Clear state program must have the
same version number if either is 6 or higher.
Furthermore, the sum of the number of Accounts in apat, Application IDs in
apfa, Asset IDs in apas, and Box References in apbx is limited to 8.
19
• The source address for the asset transfer (non-zero iff this is a clawback),
encoded as msgpack field asnd.
• The destination address for the asset transfer, encoded as msgpack field
arcv.
• The address to which all remaining asset units should be transferred to
close out this account’s holdings of this asset, encoded as msgpack field
aclose.
20
validity), given the state proof message, the state proof fields extracted from the
transaction. In addition, the verifier should also be given a trusted commitment
to the participant array and Proven Weight value. The trusted data should be
taken from the on-chain data at the relevant round.
To encourage the formation of shorter state proof, the rule for validity of state
proof transactions is dependent on the first valid fv round number in the trans-
action. In particular, the signed weight of a state proof must be:
• Equal to the total online stake, TotalWeight, if the first valid round num-
ber on the transaction is no greater than the proof’s sprnd plus δSP /2.
• At least P rovenW eight+(T otalW eight−P rovenW eight)∗Of f set/(δSP /2),
if the first valid round number on the transaction is the proof’s sprnd
plus δSP /2 + Of f set.
• At least the minimum weight being proven by the proof, ProvenWeight, if
the first valid round number on the transaction is no less than the proof’s
sprnd plus δSP .
Where ProvenWeight = (TotalWeight * fSP ) / 2ˆ32
When a state proof transaction is applied to the state, the next expected state
proof round for that type of state proof is incremented by δSP .
A node should be able to verify state proof transaction at any point in time
(even if fv is greater than next expected state proof round in the block header).
21
• A valid multisignature (msig) is an object containing the following fields
and which hashes to the authorizer address as described in the Multisig-
nature section:
– The subsig array of subsignatures each consisting of a signer address
and a 64-byte signature of the transaction. Note, multisignature
transaction must contain all signer’s addresses in the subsig array
even if the transaction has not been signed by that address.
– The threshold thr that is a minimum number of signatures required.
– The multisignature version v (current value is 1).
• A valid logic-signed transaction’s signature is the lsig object containing
the following fields:
– The logic l which is versioned bytecode. (See TEAL documentation)
– An optional single signature sig of 64 bytes valid for the authorizer
address of the transaction which has signed the bytes in l.
– An optional multisignature msig from the authorizer address over the
bytes in l.
– An optional array of byte strings arg which are arguments supplied
to the program in l. (arg bytes are not covered by sig or msig)
The logic signature is valid if exactly one of sig or msig is a valid signature
of the program by the authorizer address of the transaction, or if neither
sig nor msig is set and the hash of the program is equal to the authorizer
address. Also the program must execute and finish with a single non-
zero value on the stack. See TEAL documentation for details on program
execution.
16.3 ApplyData
Each transaction is associated with some information about how it is applied
to the account state. This information is called ApplyData, and contains the
following fields:
• The closing amount, ClosingAmount, which specifies how many microalgos
were transferred to the closing address, and is encoded as “ca” in msgpack.
• The asset closing amount, AssetClosingAmount, which specifies how many
of the asset units were transferred to the closing address. It is encoded as
“aca” in msgpack.
• The amount of rewards distributed to each of the accounts touched by this
transaction. There are three fields (“rs”, “rr”, and “rc” keys in msgpack
encoding), representing the amount of rewards distributed to the sender,
receiver, and closing addresses respectively. The fields have integer values
representing microalgos. If any of the accounts are the same (e.g., the
22
sender and recipient are the same), then that account received the sum of
the respective reward distributions (i.e., “rs” plus “rr”); in the reference
implementation, one of these two fields will be zero in that case.
• If this is an ApplicationCall transaction, the EvalDelta associ-
ated with the successful execution of the corresponding application’s
ApprovalProgram or ClearStateProgram. The EvalDelta, encoded as
msgpack field dt, contains the following fields:
– A GlobalDelta, encoding changes to the global state of the called
application, encoded as msgpack field gd.
∗ gd is a StateDelta.
– Zero or more LocalDeltas, encoding changes to some local states
associated with the called application, encoded as msgpack field ld.
∗ ld maps an “account offset” to a StateDelta. Account offset 0
is the transaction’s sender. Account offsets 1 and greater refer to
the account specified at that offset minus one in the transaction’s
Accounts slice. An account would have its LocalDeltas changes
as long as there is at least a single change in that set.
– Zero or more Logs encoded in an array lg, recording the arguments
to each call of the log opcode in the called application. The order of
the entries follows the execution order of the log invocations. The
maximum total number of log calls is 32, and the total size of all
logged bytes is limited to 1024. No Logs are included if a Clear state
program fails.
– Zero or more InnerTxns, encoded in an array itx. Each element of
itx records a successful inner transaction. Each element will con-
tain the transaction fields, encoded under txn, in the same way that
the top-level transaction is encoded, recursively, including ApplyData
that applies to the inner transaction.
∗ The recursive depth of inner transactions is limited 8.
∗ Up to 16 InnerTxns may be present in version 5. In version 6,
the count of all inner transactions across the transaction group
must not exceed 256.
∗ InnerTxns are limited to pay, axfer, acfg, and afrz transactions
in programs before version 6. Version 6 also allows keyreg and
appl.
∗ A ClearStateProgram execution may not have any InnerTxns.
23
• Action, encoded as msgpack field at, which specifies how the value for
this key has changed. It has three possible values:
– SetUintAction (value = 1), indicating that the value for this key
should be set to the value delta’s Uint field.
– SetBytesAction (value = 2), indicating that the value for this key
should be set to the value delta’s Bytes field.
– DeleteAction (value = 3), indicating that the value for this key
should be deleted.
• Bytes, encoded as msgpack field bs, which specifies a byte slice value to
set.
• Uint, encoded as msgpack field ui, which specifies a 64-bit unsigned inte-
ger value to set.
. The txid value is the 32-byte transaction identifier. The stibhash value is
a 32-byte hash of the signed transaction and ApplyData for the transaction,
hashed with the domain-separation prefix STIB, and encoded as follows:
• Transactions in a block are encoded in a slightly different way than stan-
dalone transactions, for efficiency:
If a transaction contains a GenesisID value, then (1) it must match the
block’s GenesisID, (2) the transaction’s GenesisID value must be omitted
from the transaction’s msgpack encoding in the block, and (3) the trans-
action’s msgpack encoding in the block must indicate the GenesisID value
was omitted by including a key “hgi” with the boolean value true.
Since transactions must include a GenesisHash value, the GenesisHash
value of each transaction in a block must match the block’s GenesisHash,
and the GenesisHash value is omitted from the transaction as encoded in
a block.
• Transactions in a block are also augmented with the ApplyData that re-
flect how that transaction applied to the account state.
The transaction commitment for a block covers the transaction encodings with
the changes described above. Individual transaction signatures cover the original
encoding of transactions as standalone.
In addtion to transaction commitment, each block will also contains SHA256
transaction commitment. It can allow a verifier which does not support
24
SHA512_256 function to verify proof of membership on transcation. In order
to consturct this commitment we use Vector Commitment. The leaves in the
Vector Commitment tree are hashed as
. Where:
• txidSha256 = SHA256(TX || transcation)
• txidSha256 = SHA256(STIB || signed transaction || ApplyData)
The vector commitment uses SHA256 for internal nodes as well.
A valid transaction sequence contains no duplicates: each transaction in the
transaction sequence appears exactly once. We can call the set of these transac-
tions the transaction set. (For convenience, we may also write TxSeqr to refer
unambiguously to this set.) For a block to be valid, its transaction sequence
must be valid (i.e., no duplicate transactions may appear there).
All transactions have a size in bytes. The size of the transaction Tx is denoted
|Tx|. For a block to be valid, the sum of the sizes of each transaction in a
transaction sequence must be at most Bmax ; in other words,
X
|Tx| ≤ Bmax .
Tx∈TxSeqr
The transaction tail for a given round r is a set produced from the union of the
transaction identifiers of each transaction in the last Tmax transaction sets and
is used to detect duplicate transactions. In other words,
[
TxTailr = {Hash(Tx)|Tx ∈ TxSeqs }.
r−Tmax ≤s≤r−1
The transaction tail is part of the ledger state but is distinct from the account
state and is not committed to in the block.
25
wanting to require transaction A to confirm if and only if transactions B and C
confirm can take the hashes of transactions A, B, and C (without the “Group”
field set), hash them together, and set the “Group” field of all three transactions
to that hash before signing them. A group may contain no more than Gmax
transactions.
More formally, when evaluating a block, consider the ith and (i+1)th transaction
in the payset to belong to the same transaction group if the “Group” fields of
the two transactions are equal and nonzero. The block may now be viewed
as an ordered sequence of transaction groups, where each transaction group is
a contiguous sublist of the payset consisting of one or more transactions with
equal “Group” field. For each transaction group where the transactions have
nonzero “Group”, compute the TxGroup hash as follows:
• Take the hash of each transaction in the group but with its “Group” field
omitted.
• Hash this ordered list of hashes – more precisely, hash the canonical msg-
pack encoding of a struct with a field “txlist” containing the list of hashes,
using “TG” as domain separation prefix.
If the TxGroup hash of any transaction group in a block does not match the
“Group” field of the transactions in that group (and that “Group” field is
nonzero), then the block is invalid. Additionally, if a block contains a transac-
tion group of more than Gmax transactions, the block is invalid.
If the sum of the fees paid by the transactions in a transaction group is less than
fmin times the number of transactions in the group, then the block is invalid.
If the sum of the lengths of the boxes denoted by the box references in a trans-
action group exceeds 1,024 times the total number of box referencess in the
transaction group, then the block is invalid. Call this limit the I/O Budget for
the group. Box references with an empty name are counted toward the total
number of references, but add nothing to the sum of lengths.
If the sum of the lengths of the boxes modified (by creation or modification)
in a transaction group exceeds the I/O Budget of the group at any time dur-
ing evaluation (see ApplicationCall Transaction Semantics), then the block is
invalid.
Beyond the TxGroup, MinFee, and Box size checks, each transaction in a group
is evaluated separately and must be valid on its own, as described below in the
Validity and State Changes section. For example, an account with balance 50
could not spend 100 in transaction A and afterward receive 500 in transaction
B, even if transactions A and B are in the same group, because transaction A
would leave the account with a negative balance.
26
• If the asset ID is zero, create a new asset with an ID corresponding to one
plus this transaction’s unique counter value. The transaction’s counter
value is the transaction counter field from the block header plus the posi-
tional index of this transaction in the block (starting from 0).
On asset creation, the asset parameters for the created asset are stored
in the creator’s account under the newly allocated asset ID. The creating
account also allocates space to hold asset units of the newly allocated
asset. All units of the newly created asset (i.e., the total specified in
the parameters) are held by the creator. When the creator holding is
initialized it ignores the default freeze flag and is always initialized to
unfrozen.
• If the asset ID is non-zero, the transaction must be issued by the manager
of the asset (based on the asset’s current parameters). A zero manager
address means no such transaction can be issued.
If the parameters are omitted (the zero value), the asset is destroyed. This
is allowed only if the creator holds all of the units of that asset (i.e., equal
to the total in the parameters).
If the parameters are not omitted, any non-zero key in the asset’s current
parameters (as stored in the asset creator’s account) is updated to the key
specified in the asset parameters. This applies to the manager, reserve,
freeze, and clawback keys. Once a key is set to zero, it cannot be updated.
Other parameters are immutable.
An asset transfer transaction has the following semantics:
• If the asset source field is non-zero, the transaction must be issued by the
asset’s clawback account, and this transaction can neither allocate nor
close out holdings of an asset (i.e., the asset close-to field must not be
specified, and the source account must already have allocated space to
store holdings of the asset in question). In this clawback case, freezes are
bypassed on both the source and destination of this transfer.
If the asset source field is zero, the asset source is assumed to be the
transaction’s sender, and freezes are not bypassed.
• If the transfer amount is 0, the transaction allocates space in the sender’s
account to store the asset ID. The holdings are initialized with a zero
number of units of that asset, and the default freeze flag from the asset’s
parameters. Space cannot be allocated for asset IDs that have never been
created, or that have been destroyed, at the time of space allocation. Space
can remain allocated, however, after the asset is destroyed.
• The transaction moves the specified number of units of the asset from
the source to the destination. If either account is frozen, and freezes are
not bypassed, the transaction fails to execute. If either account does not
have any space allocated to hold units of this asset, the transaction fails
27
to execute. If the source account has fewer than the specified number of
units of that asset, the transaction fails to execute.
• If the asset close-to field is specified, the transaction transfers all remaining
units of the asset to the close-to address. If the close-to address is not the
creator address, then neither the sender account’s holdings of this asset nor
the close-to address’s holdings can be frozen; otherwise, the transaction
fails to execute. Closing to the asset creator is always allowed, even if
the source and/or creator account’s holdings are frozen. If the sender or
close-to address does not have allocated space for the asset in question,
the transaction fails to execute. After transferring all outstanding units
of the asset, space for the asset is deallocated from the sender account.
An asset freeze transaction has the following semantics:
• If the transaction is not issued by the freeze address in the specified asset’s
parameters, the transaction fails to execute.
• If the specified asset does not exist in the specified account, the transaction
fails to execute.
• The freeze flag of the specified asset in the specified account is updated
to the flag value from the freeze transaction.
When an asset transaction allocates space in an account for an asset, whether by
creation or opt-in, the sender’s minimum balance requirement is incremented by
100,000 microalgos. When the space is deallocated, whether by asset destruc-
tion or asset-close-to, the balance requirement of the sender is decremented by
100,000 microalgos.
16.7.1 Procedure
1. • If the application ID specified by the transaction is zero, create a new
application with ID equal to one plus the system transaction counter
(this is the same ID selection algorithm as used by Assets).
When creating an application, the application parameters speci-
fied by the transaction (ApprovalProgram, ClearStateProgram,
GlobalStateSchema, LocalStateSchema, and ExtraProgramPages)
are allocated into the sender’s account data, keyed by the new
application ID.
28
Continue to step 2.
• If the application ID specified by the transaction is nonzero, continue
to step 2.
2. • If OnCompletion == ClearState, then:
– Check if the transaction’s sender is opted in to this application
ID. If not, FAIL.
– Check if the application parameters still exist in the creator’s
account data.
∗ If the application does not exist, delete the sender’s local
state for this application (marking them as no longer opted
in), and SUCCEED.
∗ If the application does exist, continue to step 3.
• If the OnCompletion != ClearState, continue to step 4.
3. • Execute the ClearStateProgram.
– If the program execution returns PASS == true, apply the lo-
cal/global/box key/value store deltas generated by the program’s
execution.
– If the program execution returns PASS == false, do not apply
any local/global/box key/value store deltas generated by the pro-
gram’s execution.
• Delete the sender’s local state for this application (marking them as
no longer opted in). SUCCEED.
4. • If OnCompletion == OptIn, then at this point during execution we
will allocate a local key/value store for the sender for this application
ID, marking the sender as opted in.
Continue to step 5.
5. • Execute the ApprovalProgram.
– If the program execution returns PASS == true, apply any lo-
cal/global key/value store deltas generated by the program’s ex-
ecution. Continue to step 6.
– If the program execution returns PASS == false, FAIL.
6. • If OnCompletion == NoOp
– SUCCEED.
• If OnCompletion == OptIn
– This was handled above. SUCCEED.
• If OnCompletion == CloseOut
– Check if the transaction’s sender is opted in to this application
ID. If not, FAIL.
– Delete the sender’s local state for this application (marking them
as no longer opted in). SUCCEED.
• If OnCompletion == ClearState
– This was handled above (unreachable).
29
• If OnCompletion == DeleteApplication
– Delete the application’s parameters from the creator’s account
data. (Note: this does not affect any local state). SUCCEED.
• If OnCompletion == UpdateApplication
– If an existing program is version 4 or higher, and the supplied
program is a downgrade from the existing version FAIL
– Update the Approval and ClearState programs for this
application according to the programs specified in this
ApplicationCall transaction. The new programs are not
executed in this transaction. SUCCEED.
30
4 or later, asset balances may only be read for assets whose parameters
are also available.
• Only available boxes may be accessed. An attempt to access any other
box will cause the program exection to fail.
• Boxes may not be accessed by an app’s ClearStateProgram.
31
– If I0 ̸= 0 then aρ+1,I = a′ρ+1,I = a∗ρ+1,I = pρ+1,I = pkρ+1,I = 0;
– otherwise,
∗ aρ+1,I = Stake(ρ + 1, I) − a − f if I ′ ̸= I and aρ+1,I = Stake(ρ +
1, I) − f otherwise.
∗ a′ρ+1,I = Tr+1 .
aρ,I
∗ a∗ρ+1,I = a∗ρ,I + (Tr+1 − a′ρ,I ) A .
∗ If TxType is “pay”, then pkρ+1,I = pkρ,I and pρ+1,I = pρ,I
∗ Otherwise (i.e., if TxType is “keyreg”),
· pkρ+1,I = pk
· pρ+1,I = 0 if pk = 0 and nonpart = false
· pρ+1,I = 2 if pk = 0 and nonpart = true
· pρ+1,I = 1 if pk ̸= 0.
• For I ′ if I ̸= I ′ and either I ′ ̸= 0 or a ̸= 0:
– aρ+1,I ′ = Stake(ρ + 1, I ′ ) + a.
– a′ρ+1,I ′ = Tr+1 .
a ′
– a∗ρ+1,I ′ = a∗ρ,I ′ + (Tr+1 − a′ρ,I ′ ) ρ,I
A .
• For I0 if I0 ̸= 0:
– aρ+1,I0 = Stake(ρ + 1, I0 ) + Stake(ρ + 1, I) − a − f .
– a′ρ+1,I0 = Tr+1 .
a
– a∗ρ+1,I0 = a∗ρ,I0 + (Tr+1 − a′ρ,I0 ) ρ,I A
0
.
• For all other I ∗ ̸= I, the account state is identical to that in view ρ.
For asset transaction types (asset configuration, asset transfer, and asset freeze),
account state is updated based on the reference logic described in Asset Trans-
action Semantics.
Additionally, for all types of transactions, if the RekeyTo address of the trans-
action is nonzero and does not match the transaction sender address, then the
transaction sender account’s spending key is set to the RekeyTo address. If the
RekeyTo address of the transaction does match the transaction sender address,
then the transaction sender account’s spending key is set to zero.
The final intermediate account ρk state changes the balance of the incentive
pool as follows:
32
17 Previous Hash
The previous hash is a cryptographic hash of the previous block header in the
sequence of blocks. The sequence of previous hashes in each block header forms
an authenticated, linked-list of the reversed sequence.
Let Br represent the block header in round r, and let H be some cryptographic
function. Then the previous hash Prevr+1 in the block for round r + 1 is
Prevr+1 = H(Br ).
18 Multisignature
Multisignature term describes a special multisignature address, signing and val-
idation procedures. In contrast with a regular account address that may be
understood as a public key, multisignature address is a hash of a constant string
identifier for multisignature, version, threshold, and all addresses used for mul-
tisignature address creation:
33