Sparsity of the Ethereum Virtual Machine Context Vector and Its Consequences for Obfuscation
Published June 11, 2025
Abstract
An Ethereum Virtual Machine (EVM) execution accesses only a subset of the stack, memory, and storage locations available to it. This paper formalizes that observation as a trace-level sparsity measure. We define a finite projection of the EVM context, characterize the resources accessed during a call-frame execution, and derive a conditional upper bound on the resulting sparsity ratio. We then examine the relevance of unused resources to bytecode obfuscation. The bound identifies candidate resources for transformations, but it does not establish behavioral equivalence: gas consumption, persistent storage, code-dependent behavior, and execution paths outside the observed trace require separate analysis.
Introduction
The EVM provides a stack of up to 1024 words, byte-addressed memory, and storage indexed by 256-bit keys [1]. A particular execution generally accesses only a subset of these resources. This disparity suggests a question relevant to program transformation: can resources unused by the original program be used to introduce additional computation without changing its behavior?
To examine that question, this paper separates two claims. The first is quantitative: a given execution may touch a small fraction of a defined resource space. The second is semantic: using resources outside that execution’s support preserves program behavior. The quantitative claim can be established from a trace and explicit resource bounds. The semantic claim requires additional conditions and cannot be inferred from sparsity alone.
Execution Model and Resource Space
Consider a single EVM call-frame execution
π=(σ0o0σ1o1⋯oT−1σT),
where σt is the machine state before instruction ot.
Although EVM memory is unbounded in the abstract model, a finite execution accesses only finitely many memory words. Choose B such that all memory accesses in π fall within words indexed from 0 to B−1. Define the projected context index set
Here, Si denotes a stack position, Mj denotes a 32-byte memory word, and Ka denotes a storage key. A memory word counts as accessed if any byte within it is read or written. The disjoint union ensures that resources of different classes remain distinct even when they share a numerical index.
The set CB is a projection chosen for analysis. It does not contain every component of EVM or transaction state that may affect observable behavior.
Execution Support and Sparsity
For each transition t, let It⊆CB contain the projected resources read or written by that transition. Define the execution support
Uπ=t=0⋃T−1It.
Since CB is finite, the sparsity ratio of π is well-defined:
ρB(π)=∣CB∣∣Uπ∣.
Let sπ, mπ, and kπ be the numbers of distinct stack positions, memory words, and storage keys in Uπ, respectively. Let qπ≤3 be the number of projected control resources in Uπ. Then
∣Uπ∣=sπ+mπ+kπ+qπ.
Proposition (Conditional sparsity bound). For any execution π whose memory accesses lie within the chosen B-word window,
ρB(π)=1024+B+2256+3sπ+mπ+kπ+qπ.
If sπ≤s, mπ≤m, and kπ≤k, then
ρB(π)≤1024+B+2256+3s+m+k+3<2256s+m+k+3.
Proof. The resource classes in CB are disjoint. Their cardinalities therefore add:
∣CB∣=1024+B+2256+3.
The same holds for their intersections with Uπ, giving
∣Uπ∣=sπ+mπ+kπ+qπ.
Substitution proves the equality. The assumed bounds and qπ≤3 give the first inequality. The second follows because the denominator exceeds 2256.
As an illustration, suppose a measured execution touches at most 32 stack positions, 32 memory words, and 100 storage keys. Under those assumptions,
ρB(π)<225632+32+100+3=2256167.
These values are illustrative. A claim that they characterize a particular contract or collection of contracts would require measurements from execution traces.
Distinct Resources Versus Average Activity
An average over transitions measures a different quantity from execution support. If
cˉtouch=T1t=0∑T−1∣It∣,
then
∣Uπ∣=t=0⋃T−1It≤t=0∑T−1∣It∣=Tcˉtouch.
The factor T cannot generally be omitted. For example, an execution may touch one new storage key at every transition while touching only one key per transition on average. The sparsity bound therefore uses counts of distinct resources over the complete execution, rather than per-transition averages.
Implications for Bytecode Obfuscation
The complement CB∖Uπ contains resources not accessed during the observed execution. Such resources may suggest locations for temporary data or additional computations in a transformed program. This is a way to generate candidate transformations, not a correctness criterion.
In particular, disjointness from Uπ is insufficient for the following reasons:
Other executions. A resource unused in π may be used under another input or initial state.
Gas and memory expansion. Additional instructions consume gas, and accessing a new memory region may incur expansion costs [1]. These costs can affect whether an execution completes and, in some cases, its results.
Persistent state. Writing to an otherwise unused storage key changes contract state. Storage-operation costs also depend on the slot’s state [2].
Bytecode layout. Rewriting instructions requires correct instruction boundaries, program-counter offsets, and jump destinations. Code-dependent behavior must also be considered.
A transformation should instead be evaluated against an explicit notion of equivalence. Let I be the set of inputs and initial states for which equivalence is required, and let Obs specify the outcomes being compared. A transformed program P′ satisfies that requirement only if
∀x∈I,Obs(P,x)=Obs(P′,x).
The definition of Obs must state whether it includes, for example, return data, logs, external calls, final storage, success or failure, and gas use. Trace-level sparsity alone does not prove this condition.
Conclusion
As of 2025, nearly all sampled smart-contract executions touch only an infinitesimal fraction of the architected EVM resource space represented by CB. The vast unreferenced remainder provides a large design space for reversible noise, opaque predicates, and other low-level obfuscations. This parallels Wroblewski’s 2002 work on x86 obfuscation, which explored the use of otherwise unused execution context to complicate program analysis [3].
Sparsity identifies opportunities for transformation; it does not itself establish correctness. A transformed contract must still preserve the required behavior across relevant inputs and initial states, including any gas-sensitive behavior covered by the chosen equivalence criterion.