The VM
The ESMASTe VM is a deterministic stack machine with a deliberately narrow scope. Programs are flat bytecode with a header that declares everything they may use. They have no access to randomness, to ambient authority, or to any clock except one controlled time source, so a program observes exactly what its header and inputs declare and nothing more.
Scripts
A script has two parts, a header (.header) and a body (.text). The header declares, in four segments, everything the body may use: the script public key that authentication opcodes check against (0x0 disables authentication permanently and voids any request to persist), the constant stack of 32-byte values the body refers to as c1, c2 and so on, the external stack definition, which says how the words supplied by the caller at redemption are split (ext1, ext2 and so on), and miscellaneous implementation-dependent settings such as the step budget. The body is a sequence of opcodes and their arguments. Programs shows a script in full.
The stack machine
Values live on an operand stack. A binary operation pops the top two elements, computes the result and pushes it back, always with the same operand order, for example which element is the dividend in a division. Stack instructions such as DUP1 and SWAP1 arrange operands explicitly when a program needs them in a different order.
Instructions
The instruction set covers arithmetic, a full set of comparisons, and control flow for branching and iteration. Memory operations provide scratch space for the duration of a run, storage operations provide persistent state, and transient slots follow EIP-1153 semantics, scoped per account and per transaction.
The cryptographic instructions cover exactly what the bridge needs: hashing for the digest constructions, commitment arithmetic for notes, and signature verification for authorization. Introspection is narrow. A program can see the sender, the value transferred, its own balance (BALANCE, which is always the escrow still available), and the one sanctioned time source, read through a single explicit opcode (BLOCKTIMESTAMP), which is the only environmental input in the entire machine.
Exclusions
What the machine leaves out of programs matters as much as what it includes. Each omission removes a whole class of defects, so individual programs don’t need to guard against them:
- No self-destruct, so a program can’t end its host contract early. The host self-destructs on its own, once, when the run is over, unless the script set
PERSIST. - No delegatecall, so execution can’t escape its sandbox. The only delegatecall is the host’s own, into the SingletonRunner.
- No undeclared chain reads, so a program can’t depend on state outside its declared inputs. Contracts that a script names in its constants can still be called, and statically called, from the sandboxed runner, which is how conditional options query a loan manager; a dedicated
STATICCALLopcode is in development.
Gas model
Every instruction has a cost measured by on-chain profiling rather than estimated. The rate tables ship with the toolchain and are re-measured whenever the implementation changes, because stale cost data degrades silently.
A program declares its step budget before execution. A run that would exceed it, or that reaches TRAP, reverts. Because an Ethereum transaction is atomic, nothing the run did survives, including the creation of its host contract: the escrow stays exactly where it was, to be executed again or refunded. Value movement accounts for most of a script’s cost, while computation is cheap, so a program that spends its budget on arithmetic is revealed early as badly designed.