---
title: Reuse-Sensitive CFGs in EVM Analysis
url: https://www.emergentmind.com/topics/reuse-sensitive-control-flow-graphs
type: topic
---

# Reuse-Sensitive CFGs in EVM Analysis

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 [2505.14437].

## 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 $B$ is the BB set, such a graph is $G_\mathrm{ins}=(B, E_\mathrm{ins})$, where $(b \to b') \in E_\mathrm{ins}$ if any stack state allows $b$'s terminator to jump to $b'$.

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 [2505.14437].

A reuse-sensitive CFG introduces the notion of reuse context:
- The reuse context for basic block $b$ is the set of jump operands present on the stack just before $b$ executes, reflecting the values pre-pushed by each predecessor.
- The reuse-sensitive CFG is a directed graph $G_\mathrm{sen}=(B \times C, E_\mathrm{sen})$, where $C$ is the universe of realized reuse contexts, and each node $(b, c)$ corresponds to executing $b$ under context $c$. Edges are only present between concretely observed $(b, c)$ 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:**
1. Basic fake join node
2. Basic fake loop
3. Sequences of fake join nodes
4. Nested fake loops

**Reuse Mixed with Real Control-Flow:**
5. Fake join node mingled with a genuine join
6. Fake join node with multiple real exits
7. Fake loop enclosing a real loop
8. 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 [2505.14437].

## 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 $b$, Esuer maintains a set of clones $\{b[c_1], b[c_2],\ldots\}$, each tagged by its context $c_i$, as well as snapshots of their entry ($S_\mathrm{start}$) and exit ($S_\mathrm{end}$) stack states.

**Taint Propagation:**
- Stack slots and constants (in SSA form) are mapped via $\tau : V \rightarrow \mathcal{P}(C)$, where $C$ denotes reuse contexts.
  1. If $v$ is a pop operand for `JUMP/JUMPI` and was pre-pushed by a specific value $k$, then $\tau(v) \supseteq \{k\}$.
  2. If $x = \text{op}(y_1,\ldots, y_n)$, then $\tau(x) = \bigcup \tau(y_i)$.
  3. Taints propagate across BB clones sharing stack-slot indices and values.

**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 $k$ times ($k$ unique contexts), so exploration is $O(|B| \cdot k)$, 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 [2505.14437]:

| 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: $F_1 = 99.97\%$
- Reentrancy detector: $F_1 = 99.67\%$

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 `STOP` or `REVERT` with 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 [2505.14437].

## 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 [2505.14437].

Source: https://www.emergentmind.com/topics/reuse-sensitive-control-flow-graphs