Reuse-Sensitive CFGs in EVM Analysis
- Reuse-sensitive CFGs are formal graph models that track unique reuse contexts in EVM bytecode, eliminating spurious merges and infeasible paths.
- The methodology leverages dynamic stack emulation and taint analysis to clone basic blocks per context, resulting in high precision and recall.
- Empirical evaluations show superior performance in execution-trace coverage and vulnerability detection compared to traditional CFG approaches.
A reuse-sensitive control flow graph (CFG) is a formal structure designed to accurately represent the transfer of control in low-level bytecode systems affected by pervasive code reuse, specifically as encountered in Ethereum Virtual Machine (EVM) smart contracts. Unlike traditional reuse-insensitive CFGs, which merge code shared across different contexts into a single node, reuse-sensitive CFGs faithfully track each logical usage of a reused code snippet via the dynamic notion of a reuse context. This granularity eliminates spurious merges, loops, and infeasible paths that otherwise impede precise static analysis and downstream reasoning on EVM binaries (Wang et al., 20 May 2025).
1. Code Reuse and CFG Construction in EVM Bytecode
In EVM bytecode, indirect jumps are ubiquitous: jump targets are always popped from the stack, and compilers exploit this semantics to deduplicate sequences of instructions by sharing basic blocks (BBs) across distinct logical sites (i.e., different "pre-push" sites). A traditional or reuse-insensitive CFG is constructed by partitioning bytecode into BBs (via JUMPDEST) and computing graph edges wherever a symbolic stack state could permit a jump between blocks. Formally, if is the BB set, such a graph is , where if any stack state allows 's terminator to jump to .
This model conflates all runtime contexts, yielding CFGs that manifest "polymorphic" merge nodes, spurious loops, and excessive infeasible paths. These pathologies degrade all downstream static analyses—such as data-flow analysis and vulnerability detection—by polluting the control-flow structure with artifacts from compiler-induced code reuse (Wang et al., 20 May 2025).
A reuse-sensitive CFG introduces the notion of reuse context:
- The reuse context for basic block is the set of jump operands present on the stack just before executes, reflecting the values pre-pushed by each predecessor.
- The reuse-sensitive CFG is a directed graph , where is the universe of realized reuse contexts, and each node corresponds to executing 0 under context 1. Edges are only present between concretely observed 2 pairs, guaranteeing faithful modeling of logical code duplication and no artificial merges or loops.
2. Prevalent Patterns of Code Reuse in EVM
Empirical studies of EVM bytecode identify eight principal code-reuse patterns, falling into two major categories:
Reuse without Real Control-Flow:
- Basic fake join node
- Basic fake loop
- Sequences of fake join nodes
- Nested fake loops
Reuse Mixed with Real Control-Flow:
- Fake join node mingled with a genuine join
- Fake join node with multiple real exits
- Fake loop enclosing a real loop
- Fake loop containing real merges in the body
All patterns arise from physically shared code regions entered via disparate jump target values. These cannot be resolved statically, as the governing predicate—pre-pushed jump operand—only materializes at runtime. The presence of these patterns leads to structurally unsound reuse-insensitive CFGs, but the correct duplication of code according to reuse context eliminates these ambiguities (Wang et al., 20 May 2025).
3. Esuer: Reuse-Sensitive CFG Construction via Taint Analysis
Esuer is a tool implementing dynamic recovery of reuse-sensitive CFGs by integrating stack emulation, taint propagation, and on-the-fly basic block cloning. Its high-level workflow involves:
- Preprocessing: Linear-sweep disassembly and BB identification (split on
JUMPDEST). - CFG Recovery: BBs are explored breadth- or depth-first, with each BB potentially visited under multiple stack contexts. For each logical BB 3, Esuer maintains a set of clones 4, each tagged by its context 5, as well as snapshots of their entry (6) and exit (7) stack states.
Taint Propagation:
- Stack slots and constants (in SSA form) are mapped via 8, where 9 denotes reuse contexts.
- If 0 is a pop operand for
JUMP/JUMPIand was pre-pushed by a specific value 1, then 2. - If 3, then 4.
- Taints propagate across BB clones sharing stack-slot indices and values.
- If 0 is a pop operand for
CFG Recovery Algorithm:
- For each BB and context, Esuer clones blocks as necessary—whenever a block is entered under a new context, a new node is created.
- Edge creation and stack emulation are performed per context.
- "IsReuse" compares taint information to distinguish whether an existing clone suffices or a new clone must be created (indicating a new logical usage).
Complexity:
- Each BB may be cloned up to 5 times (6 unique contexts), so exploration is 7, with optimizations including constant-time snapshot comparison per clone, linear-time taint propagation, and early pruning.
4. Experimental Evaluation
A large-scale evaluation was performed across 10,000 real-world smart contracts compiled from Solidity and Vyper, compared against six state-of-the-art tools. Highlights include (Wang et al., 20 May 2025):
| Metric | Esuer | Best Alternative (Range) |
|---|---|---|
| Execution-trace coverage | 99.94% | – |
| Average path count | 1.0 | 5×–30× that of Esuer |
| Polymorphic jump targets | 0 | ≈11,700 (Gigahorse) |
| Precision (reuse detection) | 98.16% | – |
| Recall (reuse detection) | 96.18% | – |
| F1-score (reuse detection) | 97.02% | – |
| Success rate | 99.25% | Ethersolve 0.86s, Gigahorse 7.40s |
| Mean time/contract | 1.06s | Mythril 42.93s |
For downstream vulnerability detection on the SolidiFI bug suite:
- tx.origin misuse detector: 8
- Reentrancy detector: 9
These results underscore that Esuer's reuse-sensitive CFGs enable both superior precision (no spurious merges or infeasible paths) and high recall in security analyses.
5. Limitations and Extensions
While reuse-sensitive CFGs constructed by Esuer are highly precise for EVM bytecode, several limitations remain:
- The algorithm does not handle jumps whose targets are computed from memory or via complex stack/dataflow operations.
- Terminal BBs corresponding to
STOPorREVERTwith multiple predecessors are conservatively always cloned, potentially resulting in over-cloning at exits.
Suggested avenues for extension include the adaptation of reuse context–guided cloning to other stack- or register-based virtual machine languages (e.g., WASM, JVM), hybridization with static analyzers that track memory-based jumps, and integration of reuse-sensitive CFGs into decompilers for enhanced pseudocode readability (Wang et al., 20 May 2025).
6. Significance in Analysis and Security
Reuse-sensitive CFGs eliminate semantic ambiguities and the exponential path blow-up characteristic of reuse-insensitive approaches in EVM bytecode. By representing the logical, rather than strictly physical, duplication of code, they facilitate improved static analysis, cleaner data-flow, and more precise vulnerability detection. The light-weight nature of Esuer—using only stack emulation and taint analysis—demonstrates that full semantic fidelity to contract intent can be achieved without resorting to heavyweight SMT solving or symbolic execution (Wang et al., 20 May 2025).