Skip to main content

Purpose and Scope

This page provides detailed information about the Ethereum Virtual Machine (EVM) execution layer in StableNet, focusing on the interpreter architecture, opcode execution mechanics, jump tables, gas metering, and contract call handling.
For details on how transactions enter the execution pipeline, see Transaction Lifecycle.
For the state transition model that wraps EVM execution, see State Transitions and Gas.
For StableNet-specific gas pricing policies, see Gas Fee Policy.

EVM Architecture

The EVM is implemented as a stack-based virtual machine that executes bytecode and manages state changes.
Its core consists of several major structures.
Architecture Overview: EVM Component Hierarchy

EVM Structure

The EVM struct contains all context required for execution.
FieldTypePurpose
ContextBlockContextBlock-level information (coinbase, gas limit, block number, timestamp, etc.)
TxContextTxContextTransaction-level information (origin, gas price, blob hashes)
StateDBStateDBInterface for account and storage state
depthintCurrent call stack depth (max 1024)
chainConfig*params.ChainConfigChain configuration
chainRulesparams.RulesFork rules for the current block
ConfigConfigVM configuration (tracer, ExtraEips, NoBaseFee, etc.)
interpreter*EVMInterpreterBytecode interpreter
abortatomic.BoolAsynchronous abort flag
callGasTempuint64Temporary gas calculation space for CALL-family opcodes

EVMInterpreter Structure

The interpreter executes bytecode using a jump table.
FieldTypePurpose
evm*EVMReference to the parent EVM
table*JumpTableArray defining 256 opcodes
hashercrypto.KeccakStateHash instance for KECCAK256 opcode
hasherBufcommon.HashHash output buffer
readOnlyboolSTATICCALL mode flag
returnData[]byteReturn data from the most recent call

ScopeContext Structure

ScopeContext holds execution resources scoped to a single call.
It is created per contract execution and passed to all opcode execution functions, providing access to the stack and memory.

Interpreter Loop

The core execution loop of EVMInterpreter.Run() processes bytecode instructions one by one. Interpreter Loop Execution Flow

Stack and Memory Management

The EVM uses a stack for operands during execution and an expandable memory for data storage.

Stack Implementation

The Stack is a bounded array of 256-bit integers.
ComponentDescription
Structure[]uint256.Int, maximum size 1024
Poolsync.Pool for reuse across calls
Operationspush, pop, peek, swap, dup
ValidationChecked before each opcode execution
Before executing each opcode, the stack guarantees:
  • stack.len() >= operation.minStack
  • stack.len() <= operation.maxStack

Memory Implementation

Memory is a byte array that expands in 32-byte words.
ComponentDescription
Storage[]byte
Gas TrackingCumulative expansion cost tracked via lastGasCost
OperationsSet, Set32, Resize, GetPtr, GetCopy
Cost Model3 * words + words² / 512
Memory expansion gas calculation:
newMemSizeWords = (newMemSize + 31) / 32
newTotalFee = 3 * newMemSizeWords + newMemSizeWords² / 512
expansionCost = newTotalFee - lastGasCost

Major Execution Steps

  1. Initialization
    • Increase call depth
    • Set readOnly if STATICCALL
    • Reset returnData
    • Create new Stack and Memory
    • Construct ScopeContext
  2. Fetch Opcode
    • Load opcode at the program counter
  3. Stack Validation
    • Check for underflow and overflow
  4. Gas Consumption
    • Deduct fixed gas
    • Compute dynamic gas if required
    • Apply memory expansion gas
  5. Execution
    • Invoke the opcode execution function
  6. Program Counter Update
    • Increment pc unless a JUMP-family opcode is executed

Jump Table and Opcodes

The jump table maps 256 opcodes to execution functions, gas costs, and stack requirements.
Different instruction sets are selected depending on the active fork.

Instruction Sets by Fork

Instruction SetForkFeatures
frontierFrontierBase opcodes
homesteadHomesteadDELEGATECALL
byzantiumByzantiumSTATICCALL, REVERT
constantinopleConstantinopleCREATE2
istanbulIstanbulGas repricing
berlinBerlinEIP-2929
londonLondonBASEFEE
shanghaiShanghaiPUSH0
cancunCancunBLOB-related opcodes
anzeonAnzeonLondon + Shanghai + partial Cancun (blob excluded)
The jump table is selected in NewEVMInterpreter() based on chain rules.

Contract Calls

The EVM supports CALL, DELEGATECALL, STATICCALL, CREATE, and CREATE2.

Key Handling During Calls

  • Maximum call depth: 1024
  • Anzeon: value transfer destination restrictions
  • Blacklist checks
  • State snapshot creation and rollback on error
  • Tracer event invocation

Precompiled Contracts

AddressContractPurpose
0x01ecrecoverECDSA recovery
0x02sha256Hashing
0x03ripemd160Hashing
0x04identityData copy
0x05modexpModular exponentiation
0x06–0x08bn256Pairing operations
0x09blake2FCompression
0xb00001blsPoPAnzeon BLS Proof-of-Possession

Native Manager Contracts (Anzeon)

StableNet provides native Go-implemented contracts for system-level operations.
AddressContractPurpose
0xb00002NativeCoinManagerDirect balance manipulation
0xb00003AccountManagerAccount extra-data management
These are integrated into the normal CALL flow and interact directly with StateDB.

Gas Metering

Gas is calculated across the following stages:
  • Intrinsic gas
  • Memory expansion gas
  • Opcode dynamic gas
  • Post-execution refunds
Refund caps:
  • Pre-London: gasUsed / 2
  • London+: gasUsed / 5

Error Handling

Error TypeBehaviorExample
ConsensusTransaction invalidErrNonceTooLow
ExecutionConsume all gasErrOutOfGas
RevertRoll back state, partial gas refundErrExecutionReverted
InternalShould not occurErrGasUintOverflow
The REVERT opcode rolls back state changes while preserving return data.