Algorand Virtual Machine | Algorand Developer Portal
Algorand Virtual Machine
The AVM is a bytecode based stack interpreter that executes programs associated with Algorand transactions. TEAL is an assembly language syntax for specifying a program that is ultimately converted to AVM bytecode. These programs can be used to check the parameters of a transaction and approve the transaction as if by a signature. This use is called a Logic Signature. Starting with v2, these programs may also execute as Smart Contracts, which are often called Applications. Contract executions are invoked with explicit application call transactions.
Programs have read-only access to the transaction they are attached to, the other transactions in their atomic transaction group, and a few global values. In addition, Smart Contracts have access to limited state that is global to the application, per-account local state for each account that has opted-in to the application, and additional per-application arbitrary state in named boxes. For both types of program, approval is signaled by finishing with the stack containing a single non-zero uint64 value, though return can be used to signal an early approval which approves based only upon the top stack value being a non-zero uint64 value.
The Stack
The stack starts empty and can contain values of either uint64 or byte-arrays (byte-arrays may not exceed 4096 bytes in length). Most operations act on the stack, popping arguments from it and pushing results to it. Some operations have immediate arguments that are encoded directly into the instruction, rather than coming from the stack.
The maximum stack depth is 1000. If the stack depth is exceeded or if a byte-array element exceeds 4096 bytes, the program fails. If an opcode tries to access a position in the stack that does not exist, the operation fails. Most often, this is an attempt to access an element below the stack — the simplest example is an operation like concat which expects two arguments on the stack. If the stack has fewer than two elements, the operation fails. Some operations like frame_dig which retrieves values from subroutine parameters and proto which sets up subroutine stack frames could fail because of an attempt to access above the current stack.
Stack Types
While the stack can only store two basic types of values - uint64 and bytes - these values are often bounded, meaning they have specific ranges or limits on what they can contain. For example, a boolean value is just a uint64 that must be either 0 or 1, and an address must be exactly 32 bytes long. These limited types are named to make the documentation easier to understand and to help catch errors during program creation.
Definitions
| Name | Bound | AVM Type |
|---|---|---|
| []byte | len(x) <= 4096 | []byte |
| address | len(x) == 32 | []byte |
| any | any | |
| bigint | len(x) <= 64 | []byte |
| bool | x <= 1 | uint64 |
| boxName | 1 <= len(x) <= 64 | []byte |
| method | len(x) == 4 | []byte |
| none | none | |
| stateKey | len(x) <= 64 | []byte |
| uint64 | x <= 18446744073709551615 | uint64 |
Scratch Space
In addition to the stack there are 256 positions of scratch space. Like stack values, scratch locations may be uint64 or bytes. Scratch locations are initialized as uint64 zero. Scratch space is accessed by the load(s) and store(s) opcodes which move data from or to scratch space, respectively. Application calls may inspect the final scratch space of earlier application calls in the same group using gload(s)(s).
Versions
In order to maintain existing semantics for previously written programs, AVM code is versioned. When new opcodes are introduced, or behavior is changed, a new version is introduced. Programs carrying old versions are executed with their original semantics. In the AVM bytecode, the version is an incrementing integer, currently 12, and denoted vX throughout this document.
Execution Modes
Starting from v2, the AVM can run programs in two modes:
- LogicSig or stateless mode, used to execute Logic Signatures
- Application or stateful mode, used to execute Smart Contracts
Differences between modes include:
- Max program length (consensus parameters
LogicSigMaxSize,MaxAppTotalProgramLen&MaxExtraAppProgramPages) - Max program cost (consensus parameters
LogicSigMaxCost,MaxAppProgramCost) - Opcode availability. Refer to opcodes document for details.
- Some global values, such as
LatestTimestamp, are only available in stateful mode. - Only Applications can observe transaction effects, such as Logs or IDs allocated to ASAs or new Applications.
Execution Environment for Logic Signatures
Logic Signatures execute as part of testing a proposed transaction to see if it is valid and authorized to be committed into a block. If an authorized program executes and finishes with a single non-zero uint64 value on the stack then that program has validated the transaction it is attached to.
The program has access to data from the transaction it is attached to (txn op), any transactions in a transaction group it is part of (gtxn op), and a few global values like consensus parameters (global op). Some “Args” may be attached to a transaction being validated by a program. Args are an array of byte strings. A common pattern would be to have the key to unlock some contract as an Arg. Be aware that Logic Signature Args are recorded on the blockchain and publicly visible when the transaction is submitted to the network, even before the transaction has been included in a block. These Args are not part of the transaction ID nor of the TxGroup hash. They also cannot be read from other programs in the group of transactions.
A program can either authorize some delegated action on a normal signature-based or multisignature-based account or be wholly in charge of a contract account.
If the account has signed the program by providing a valid ed25519 signature or valid multisignature for the authorizer address on the string “Program” concatenated with the program bytecode, then the transaction is authorized as if the account had signed it, provided that the program returns true. This allows an account to hand out a signed program so that other users can carry out delegated actions which are approved by the program. Note that Logic Signature Args are not signed.
If the SHA512_256 hash of the program, prefixed by “Program”, is equal to the authorizer address of the transaction sender then this is a contract account wholly controlled by the program. No other signature is necessary or possible. The only way to execute a transaction against the contract account is for the program to approve it.
The size of a Logic Signature is defined as the length of its bytecode plus the length of all its Args. The sum of the sizes of all Smart Signatures in a group must not exceed 1000 bytes times the number of transactions in the group (1000 bytes is defined in consensus parameter LogicSigMaxSize).
Each opcode has an associated cost, usually 1, but a few slow operations have higher costs. Prior to v4, the program’s cost was estimated as the static sum of all the opcode costs in the program, whether they were actually executed or not. Beginning with v4, the program’s cost is tracked dynamically while being evaluated. If the program exceeds its budget, it fails.
The total program cost of all Logic Signatures in a group must not exceed 20,000 (consensus parameter LogicSigMaxCost) times the number of transactions in the group.