Ethereum Virtual Machine (EVM) assembler and disassembler library for working with EVM bytecode and assembly instructions
—
Rich instruction metadata and semantic analysis capabilities for EVM instruction inspection. The Instruction class provides comprehensive information about EVM opcodes including stack effects, memory/storage access patterns, control flow analysis, and gas costs.
The core representation of EVM instructions with complete metadata and semantic analysis capabilities.
class Instruction:
"""
Represents an EVM instruction with complete metadata and analysis capabilities.
This class provides comprehensive information about EVM opcodes including
basic properties, stack effects, memory/storage access patterns, and
semantic classification for program analysis.
"""
def __init__(self, opcode: int, name: str, operand_size: int,
pops: int, pushes: int, fee: int, description: str,
operand: int = None, pc: int = 0):
"""
Initialize an EVM instruction.
Parameters:
- opcode (int): The opcode value (0x00-0xFF)
- name (str): Instruction name/mnemonic base (e.g., "PUSH", "DUP")
- operand_size (int): Immediate operand size in bytes (0 for no operand)
- pops (int): Number of items popped from the stack
- pushes (int): Number of items pushed to the stack
- fee (int): Basic gas fee for the instruction
- description (str): Textual description of the instruction
- operand (int, optional): Immediate operand value
- pc (int, optional): Program counter of this instruction
"""
def parse_operand(self, buf) -> None:
"""
Parse an operand from a buffer.
Parameters:
- buf (iterator): A buffer/iterator of bytes
Raises:
ParseError: If not enough data for decoding operand
"""Core instruction identification and metadata properties.
class Instruction:
@property
def opcode(self) -> int:
"""The opcode as an integer (0x00-0xFF)."""
@property
def name(self) -> str:
"""The instruction name/mnemonic (long form, e.g., 'PUSH1', 'DUP2')."""
@property
def mnemonic(self) -> str:
"""Alias for name property."""
@property
def description(self) -> str:
"""Colloquial description of the instruction."""
@property
def semantics(self) -> str:
"""Canonical semantics (short name, e.g., 'PUSH', 'DUP')."""Usage Examples:
from pyevmasm import disassemble_one
# Analyze a PUSH1 instruction
instr = disassemble_one(b'\x60\x40') # PUSH1 0x40
print(f"Opcode: 0x{instr.opcode:02x}") # 0x60
print(f"Name: {instr.name}") # PUSH1
print(f"Semantics: {instr.semantics}") # PUSH
print(f"Description: {instr.description}") # Place 1 byte item on stack.
# Analyze a DUP instruction
instr = disassemble_one(b'\x81') # DUP2
print(f"Name: {instr.name}") # DUP2
print(f"Semantics: {instr.semantics}") # DUPProperties for analyzing instruction operands and immediate values.
class Instruction:
@property
def operand_size(self) -> int:
"""The immediate operand size in bytes."""
@property
def has_operand(self) -> bool:
"""True if the instruction uses an immediate operand."""
@property
def operand(self) -> int:
"""The immediate operand value (getter/setter)."""
@operand.setter
def operand(self, value: int) -> None:
"""Set the operand value with validation."""
@property
def size(self) -> int:
"""Size of the encoded instruction (1 + operand_size)."""
@property
def bytes(self) -> bytes:
"""Encoded instruction as bytes."""Usage Examples:
from pyevmasm import assemble_one, disassemble_one
# Instructions with operands
push_instr = assemble_one("PUSH2 0x1234")
print(f"Has operand: {push_instr.has_operand}") # True
print(f"Operand size: {push_instr.operand_size}") # 2
print(f"Operand value: 0x{push_instr.operand:x}") # 0x1234
print(f"Total size: {push_instr.size}") # 3 (1 + 2)
print(f"Bytes: {push_instr.bytes.hex()}") # 611234
# Instructions without operands
add_instr = assemble_one("ADD")
print(f"Has operand: {add_instr.has_operand}") # False
print(f"Size: {add_instr.size}") # 1Properties for analyzing stack effects and stack-based operations.
class Instruction:
@property
def pops(self) -> int:
"""Number of words popped from the stack."""
@property
def pushes(self) -> int:
"""Number of words pushed to the stack."""
@property
def uses_stack(self) -> bool:
"""True if the instruction reads/writes from/to the stack."""
@property
def reads_from_stack(self) -> bool:
"""True if the instruction reads from stack."""
@property
def writes_to_stack(self) -> bool:
"""True if the instruction writes to the stack."""Usage Examples:
from pyevmasm import disassemble_one
# Stack effects analysis
add_instr = disassemble_one(b'\x01') # ADD
print(f"Pops: {add_instr.pops}") # 2 (pops two values)
print(f"Pushes: {add_instr.pushes}") # 1 (pushes result)
print(f"Net stack: {add_instr.pushes - add_instr.pops}") # -1
push_instr = disassemble_one(b'\x60\x01') # PUSH1 0x01
print(f"Pops: {push_instr.pops}") # 0
print(f"Pushes: {push_instr.pushes}") # 1
# Stack usage detection
print(f"ADD uses stack: {add_instr.uses_stack}") # True
print(f"ADD reads stack: {add_instr.reads_from_stack}") # True
print(f"PUSH writes stack: {push_instr.writes_to_stack}") # TrueProperties for analyzing memory and storage access patterns.
class Instruction:
@property
def writes_to_memory(self) -> bool:
"""True if the instruction writes to memory."""
@property
def reads_from_memory(self) -> bool:
"""True if the instruction reads from memory."""
@property
def writes_to_storage(self) -> bool:
"""True if the instruction writes to storage."""
@property
def reads_from_storage(self) -> bool:
"""True if the instruction reads from storage."""Usage Examples:
from pyevmasm import disassemble_one
# Memory operations
mstore_instr = disassemble_one(b'\x52') # MSTORE
print(f"Writes memory: {mstore_instr.writes_to_memory}") # True
mload_instr = disassemble_one(b'\x51') # MLOAD
print(f"Reads memory: {mload_instr.reads_from_memory}") # True
# Storage operations
sstore_instr = disassemble_one(b'\x55') # SSTORE
print(f"Writes storage: {sstore_instr.writes_to_storage}") # True
sload_instr = disassemble_one(b'\x54') # SLOAD
print(f"Reads storage: {sload_instr.reads_from_storage}") # TrueProperties for analyzing program control flow and execution patterns.
class Instruction:
@property
def is_terminator(self) -> bool:
"""True if the instruction is a basic block terminator."""
@property
def is_endtx(self) -> bool:
"""True if the instruction is a transaction terminator."""
@property
def is_starttx(self) -> bool:
"""True if the instruction is a transaction initiator."""
@property
def is_branch(self) -> bool:
"""True if the instruction is a jump."""Usage Examples:
from pyevmasm import disassemble_one
# Control flow analysis
jump_instr = disassemble_one(b'\x56') # JUMP
print(f"Is branch: {jump_instr.is_branch}") # True
print(f"Is terminator: {jump_instr.is_terminator}") # True
jumpi_instr = disassemble_one(b'\x57') # JUMPI
print(f"Is branch: {jumpi_instr.is_branch}") # True
return_instr = disassemble_one(b'\xf3') # RETURN
print(f"Is end tx: {return_instr.is_endtx}") # True
print(f"Is terminator: {return_instr.is_terminator}") # True
call_instr = disassemble_one(b'\xf1') # CALL
print(f"Is start tx: {call_instr.is_starttx}") # TrueProperties for classifying instructions by their semantic purpose and EVM specification categories.
class Instruction:
@property
def group(self) -> str:
"""Instruction classification as per the Ethereum Yellow Paper."""
@property
def is_arithmetic(self) -> bool:
"""True if the instruction is an arithmetic operation."""
@property
def is_environmental(self) -> bool:
"""True if the instruction accesses environmental data."""
@property
def is_system(self) -> bool:
"""True if the instruction is a system operation."""
@property
def uses_block_info(self) -> bool:
"""True if the instruction accesses block information."""Usage Examples:
from pyevmasm import disassemble_one
# Semantic classification
add_instr = disassemble_one(b'\x01') # ADD
print(f"Group: {add_instr.group}") # Stop and Arithmetic Operations
print(f"Is arithmetic: {add_instr.is_arithmetic}") # True
caller_instr = disassemble_one(b'\x33') # CALLER
print(f"Group: {caller_instr.group}") # Environmental Information
print(f"Is environmental: {caller_instr.is_environmental}") # True
timestamp_instr = disassemble_one(b'\x42') # TIMESTAMP
print(f"Uses block info: {timestamp_instr.uses_block_info}") # TrueProperties for analyzing gas costs and execution fees.
class Instruction:
@property
def fee(self) -> int:
"""The basic gas fee of the instruction."""Usage Examples:
from pyevmasm import disassemble_one
# Gas cost analysis
add_instr = disassemble_one(b'\x01') # ADD
print(f"Gas cost: {add_instr.fee}") # 3
sstore_instr = disassemble_one(b'\x55') # SSTORE (varies by fork)
print(f"Gas cost: {sstore_instr.fee}") # 0 (complex gas calculation)
# Gas costs vary by fork
balance_istanbul = disassemble_one(b'\x31', fork="istanbul")
balance_frontier = disassemble_one(b'\x31', fork="frontier")
print(f"BALANCE gas (istanbul): {balance_istanbul.fee}") # 700
print(f"BALANCE gas (frontier): {balance_frontier.fee}") # 20Properties for managing instruction positioning within programs.
class Instruction:
@property
def pc(self) -> int:
"""Program counter location of this instruction."""
@pc.setter
def pc(self, value: int) -> None:
"""Set the program counter location."""Usage Examples:
from pyevmasm import assemble_one
# Program counter management
instr = assemble_one("PUSH1 0x40", pc=100)
print(f"PC: {instr.pc}") # 100
# Modify PC
instr.pc = 200
print(f"New PC: {instr.pc}") # 200Install with Tessl CLI
npx tessl i tessl/pypi-pyevmasm