Ethereum Virtual Machine (EVM) assembler and disassembler library for working with EVM bytecode and assembly instructions
—
Convert EVM assembly language to bytecode with comprehensive support for individual instructions, multiple instruction sequences, and complete programs. Supports all Ethereum hard forks and provides both binary and hexadecimal output formats.
Assemble a single EVM instruction from its textual representation, with support for operands and program counter positioning.
def assemble_one(asmcode: str, pc: int = 0, fork: str = DEFAULT_FORK) -> Instruction:
"""
Assemble one EVM instruction from its textual representation.
Parameters:
- asmcode (str): Assembly code for one instruction (e.g., "PUSH1 0x40", "ADD")
- pc (int, optional): Program counter of the instruction. Default: 0
- fork (str, optional): Fork name. Default: DEFAULT_FORK ("istanbul")
Returns:
Instruction: An Instruction object with complete metadata
Raises:
AssembleError: If assembly fails due to invalid instruction or operand
"""Usage Examples:
from pyevmasm import assemble_one
# Simple instruction without operand
add_instr = assemble_one("ADD")
print(f"Opcode: 0x{add_instr.opcode:02x}") # 0x01
# Instruction with operand
push_instr = assemble_one("PUSH1 0x40")
print(f"Operand: 0x{push_instr.operand:x}") # 0x40
print(f"Bytes: {push_instr.bytes.hex()}") # 6040
# With program counter
jump_instr = assemble_one("JUMPI", pc=100)
print(f"PC: {jump_instr.pc}") # 100Assemble a sequence of EVM instructions from multiline assembly code, returning a generator of Instruction objects.
def assemble_all(asmcode: str, pc: int = 0, fork: str = DEFAULT_FORK):
"""
Assemble a sequence of textual representation of EVM instructions.
Parameters:
- asmcode (str): Assembly code for any number of instructions, separated by newlines
- pc (int, optional): Program counter of the first instruction. Default: 0
- fork (str, optional): Fork name. Default: DEFAULT_FORK ("istanbul")
Returns:
Generator[Instruction]: A generator of Instruction objects
Raises:
AssembleError: If assembly fails for any instruction
"""Usage Examples:
from pyevmasm import assemble_all
# Assemble multiple instructions
assembly_code = '''
PUSH1 0x80
PUSH1 0x40
MSTORE
PUSH1 0x4
CALLDATASIZE
LT
'''
instructions = list(assemble_all(assembly_code))
for instr in instructions:
print(f"{instr.pc:08x}: {instr}")
# With custom starting PC
instructions = list(assemble_all(assembly_code, pc=0x1000))
print(f"First instruction PC: 0x{instructions[0].pc:x}") # 0x1000Assemble EVM assembly code directly to binary bytecode format.
def assemble(asmcode: str, pc: int = 0, fork: str = DEFAULT_FORK) -> bytes:
"""
Assemble an EVM program to binary bytecode.
Parameters:
- asmcode (str): An EVM assembler program
- pc (int, optional): Program counter of the first instruction. Default: 0
- fork (str, optional): Fork name. Default: DEFAULT_FORK ("istanbul")
Returns:
bytes: The binary representation of the bytecode
Raises:
AssembleError: If assembly fails
"""Assemble EVM assembly code to hexadecimal string representation, the most common format for EVM bytecode.
def assemble_hex(asmcode: str, pc: int = 0, fork: str = DEFAULT_FORK) -> str:
"""
Assemble an EVM program to hexadecimal bytecode.
Parameters:
- asmcode (str): An EVM assembler program
- pc (int, optional): Program counter of the first instruction. Default: 0
- fork (str, optional): Fork name. Default: DEFAULT_FORK ("istanbul")
Returns:
str: The hex representation of the bytecode (prefixed with "0x")
Raises:
AssembleError: If assembly fails
"""Usage Examples:
from pyevmasm import assemble, assemble_hex
assembly_code = '''
PUSH1 0x60
PUSH1 0x40
MSTORE
PUSH1 0x2
PUSH2 0x100
'''
# Get binary bytecode
binary_code = assemble(assembly_code)
print(f"Binary length: {len(binary_code)} bytes")
# Get hex bytecode (most common)
hex_code = assemble_hex(assembly_code)
print(f"Hex: {hex_code}") # "0x606040526002610100"
# Can also assemble from instruction list
from pyevmasm import assemble_all
instructions = list(assemble_all(assembly_code))
hex_from_list = assemble_hex(instructions)
print(f"Same result: {hex_code == hex_from_list}") # TruePyEVMAsm supports standard EVM assembly syntax:
Different Ethereum forks support different instruction sets. PyEVMAsm handles this automatically:
from pyevmasm import assemble_hex
# This works in byzantium and later
code = assemble_hex("RETURNDATASIZE", fork="byzantium")
# This would fail in earlier forks
try:
code = assemble_hex("RETURNDATASIZE", fork="frontier")
except AssembleError:
print("RETURNDATASIZE not available in frontier fork")
# Constantinople introduced new shift operations
code = assemble_hex("SHL", fork="constantinople") # WorksInstall with Tessl CLI
npx tessl i tessl/pypi-pyevmasm