# 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:

1. LogicSig or _stateless_ mode, used to execute Logic Signatures
2. 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](https://dev.algorand.co/reference/algorand-teal/opcodes) 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.
