mega-evme
Execute and debug EVM bytecode locally with MegaETH's gas model, tracing, and state forking.
A command-line tool for executing and debugging EVM bytecode on MegaETH specs. Similar to go-ethereum's evm command, mega-evme provides full control over the execution environment — including MegaETH-specific features like SALT bucket configuration, multidimensional resource limits, and gas detention.
Installation
cargo build --release -p mega-evme
# Binary: target/release/mega-evmePrebuilt binary
Every release also attaches a prebuilt mega-evme (Linux x86_64, built on ubuntu-24.04) and a SHA256SUMS file to its GitHub Release. Download both, verify the checksum, and make the binary executable:
sha256sum --check --ignore-missing SHA256SUMS
chmod +x mega-evme
./mega-evme --versionThe same binary is published to the MegaETH artifact registry for internal use.
Commands
Quick Start
Execute bytecode that returns the value 1:
Deploy a contract and dump the resulting state:
Fork remote state and call a contract:
Replay an on-chain transaction with execution tracing:
Global Options
These flags apply to all commands.
-v
0
N/A
Increase log verbosity (-v=error, -vv=warn, -vvv=info, -vvvv=debug, -vvvvv=trace)
--log.file <PATH>
stderr
--log-file
Write logs to a file instead of stderr
--log.no-color
false
--log-no-color
Disable colored console output
Exit codes
Every command reports its outcome through the same set of exit codes, so a pipeline can branch on the process status without parsing output.
1
execution-error
Execution or internal error: an EVM or setup failure, bad input (including a usage error), or a definitive negative answer such as an unknown transaction.
2
verification-mismatch
The run completed, but at least one replay did not reproduce its on-chain receipt or its block header.
3
rpc-failure
An RPC or transport call failed — endpoint unreachable, transport error, or an offline replay file that holds no response for a request the run had to make.
Codes 1 and 3 separate the two ways a question can go wrong: 1 means the tool answered, and the answer is negative; 3 means the question went unanswered, so retrying against a healthy endpoint may still produce a result. A state read that fails while the EVM is executing — an offline replay file without the response, or an endpoint that dies mid-transaction — belongs to 3 as well, even though it surfaces as a block execution error. A hash the endpoint itself listed in a block body but then resolves to null belongs to 3 too: the null contradicts an answer the endpoint already gave, so it describes an inconsistent endpoint (a reorg, or a load-balanced backend serving divergent views) rather than an unknown transaction. A served transaction that fails authentication belongs to 3 for the same reason: replay recomputes each fetched transaction's hash from its encoding and re-derives its sender from its signature, and an answer whose body does not match the requested hash — or whose hash field or from does not match what its own encoding proves — is the endpoint serving an inconsistent object, not an answer about the requested transaction. A block the endpoint itself resolved — the inclusion block of a mined target, its parent, or the reported latest height for a pending one — that then comes back null is the same self-contradiction and belongs to 3. Only a hash or block height the caller supplied directly stays in 1 when it resolves to null, since nothing the endpoint served claimed it existed. Authentication covers what a recomputable hash can prove: every fetched transaction body and block header is rehashed and compared against the identity it was requested under. Two inputs stay trusted because replay cannot recompute their commitment: the block body listing — the header's transactions root commits it, but rebuilding that root would need the trailing transaction bodies the walk deliberately never fetches once the last target has run — and state reads, which carry no proof at all. --verify-receipt is the cross-check for both: a forged listing or forged state changes the execution, and the divergence surfaces against the on-chain receipt as long as the receipts themselves are honestly served. --verify-block closes the listing gap for a whole block: it fetches every listed transaction and rebuilds the transactions root before the block executes, so a forged listing — one with a transaction left out, added, reordered, or emptied — surfaces as an RPC failure (3) rather than as a divergence, without trusting any served receipt. Two paths cannot be classified that way: a read that fails inside the pre-block system calls (EIP-4788 beacon root, EIP-2935 block hashes) or inside the sandboxed execution of the keyless-deploy system contract has its cause rendered into a message by the layer that raises it, so mega-evme cannot tell it from an execution failure and reports 1.
A batch run (--tx-file / --block) reports every target on its own line and then exits once for the run as a whole, ranking the failure classes it saw: any execution or internal failure exits 1, otherwise any RPC failure exits 3, otherwise any verification mismatch exits 2. A target that never replayed was also never verified, which is why an infrastructure failure outranks a mismatch.
On failure the run also prints a report: one error: <message> line per failure on stderr, plus — with --json — a structured object as the last line of stdout, so a machine-readable run never ends with empty output. A run reports more than one line when a secondary failure must not go unnoticed but does not own the exit code — an unwritable --rpc.capture-file behind an earlier replay failure, for instance. The structured object always carries the failure the exit code came from.
In batch mode that object follows the per-target lines, whose own error.kind (not_found, pending, rpc, execution) describes why one target failed and is independent of the run-level class above. A usage error is reported the same way: the argument parser prints its own report and usage block on stderr, and a --json run still ends its stdout with the object, whose message is a one-line summary of the parse failure.
New failure classes are added as new codes; the meaning of an existing code does not change.
Read more
Cookbook — Real-world recipes and worked examples.
Commands — Detailed reference for each subcommand.
Configuration — Shared options: spec selection, block environment, state management, SALT buckets.
Tracing — Execution tracing with opcode, call, and pre-state tracers.
Transaction Types — Legacy, EIP-2930, EIP-1559, EIP-7702, and Deposit transactions.
Last updated