On August 14, 2026, security researcher Shaheen Fazim reported a significant vulnerability within the Solidity code generator via the Ethereum Foundation’s official bug bounty program. The defect centers on how the Ethereum Virtual Machine assembly (evmasm) pipeline handles memory operations when developers apply the delete operator to individual elements of bytes or string arrays residing in memory.
According to the vulnerability disclosure, utilizing the delete keyword on a specific index of a memory byte array results in the generation of faulty code that writes 32 zero bytes starting precisely at the targeted element. This behavior deviates starkly from the expected outcome, which should clear only a single byte. Instead of resetting a solitary array element, the instruction inadvertently wipes out up to 31 additional bytes following it. Depending on the array’s layout, this excessive zero-fill spills over either into subsequent indices within the same data structure or, when the deleted element sits near the tail end of the array, directly into adjacent memory allocations belonging to other variables.
Ethereum Foundation developers assigned this vulnerability a severity rating of low-to-medium on their internal evaluation scale. The issue exclusively impacts the legacy default evmasm pipeline; the modern IR (Intermediate Representation) pipeline remains entirely unaffected by the flaw. Furthermore, the invocation of the Solidity optimizer is not required to trigger the defective behavior, meaning standard compilation configurations under the default pipeline are uniformly susceptible.
An extensive retroactive investigation into the codebase history revealed that the affected code path predates the very first publicly released version of Solidity. Consequently, every version of the compiler up to and including version 0.8.36 contains the vulnerability. Solidity developers officially patched the defect in version 0.8.37, altering how the delete operation interacts with packed memory elements.
To gauge potential real-world impact prior to the patch release, maintainers scanned the Sourcify database, which catalogs roughly 870,000 verified smart contract compilations, searching specifically for the problematic source code pattern. The analysis showed that the vulnerable pattern appeared in merely 17 total compilations, encompassing only two distinct functions. A deeper security assessment confirmed that neither of those specific functions was actually compromised or capable of causing live exploits. In one instance, the corrupted bytes were subsequently discarded or overwritten by design, while the other involved an array length that could never expand sufficiently to touch vital memory. Consequently, no deployed smart contracts in the wild are known to have suffered malicious exploitation from this bug.
Understanding which smart contracts are potentially affected requires evaluating specific conditions within a codebase. A contract falls into the risk category if and only if it compiles using the legacy evmasm pipeline, targets a vulnerable compiler version spanning up to 0.8.36, and explicitly executes the delete operator on an individual element of a bytes or string array located in memory. Developers who never apply the delete keyword to individual elements of memory byte arrays or strings do not need to worry about vulnerability exposure.
The technical nuances governing this behavior stem from how Solidity manages memory allocation and data representation. Most data types in Solidity memory occupy full 32-byte words. Dynamic bytes arrays serve as a prominent exception, consisting of an initial 32-byte length descriptor followed immediately by raw data bytes packed back-to-back without internal gaps. Solidity manages memory allocation linearly by advancing a free memory pointer, meaning consecutive allocations sit directly adjacent to one another, separated only by calculated padding.
While arrays created via literals or expressions like new bytes(n) typically include up to 31 bytes of trailing padding to ensure subsequent allocations align neatly on word boundaries—referred to as padded arrays—certain operations bypass this padding. The evmasm pipeline omits trailing padding for the results of bytes.concat, string.concat, and various abi.encode functions, creating unpadded arrays whose data ends right where the next memory allocation begins.

When developers interact with byte arrays, individual elements measure a single byte wide. To modify these elements, the compiler normally emits a single-byte store instruction (mstore8) when it correctly identifies the narrow element width. However, the internal code generation path for the delete operator diverged from this standard. While the standard assignment b[i] = 0 correctly invoked a single-byte store, delete b[i] erroneously triggered a full 32-byte write starting at the element’s memory offset. Because this write begins mid-word rather than at a 32-byte boundary, it radiates forward, overwriting neighboring bytes. Because the array’s 32-byte length header preceding the data remains untouched, the array retains its original length value. Subsequent operations relying on the array contents—such as hashing via keccak256, ABI encoding, or returning data to external callers—silently consume the corrupted, zeroed-out byte sequences.
The severity and reach of this memory corruption depend heavily on the array’s length, whether it features trailing padding, and the location of the deleted index. When corruption stays contained within the array itself, every element following the deleted index, up to a maximum of 31 subsequent bytes, is wiped out. Unless those subsequent positions already contained zeroes, the array’s internal state experiences unexpected alterations upon executing the delete command.
When corruption reaches beyond the boundaries of the array, the outcome depends on the presence of padding. For padded arrays, trailing padding absorbs a portion of the 32-byte zero write. Deletions near the beginning of a padded array remain entirely internal, whereas deletions among the final 31 elements can breach the array boundary. The exact number of vulnerable tail indices depends on the array’s length modulo 32. Arrays whose lengths are exact multiples of 32 lack padding entirely, meaning deleting any of their last 31 elements will spill over into whatever variable occupies the next memory slot. Unpadded arrays are even more sensitive; deleting any of their last 31 elements—which encompasses every index for arrays shorter than 31 bytes—immediately overwrites the beginning of the subsequent memory allocation.
To illustrate the mechanics of this bug, consider a contract structured with adjacent memory declarations designed to expose both internal and external corruption pathways under the evmasm pipeline. When a developer executes a function that initializes a short byte array, deletes the initial element, and returns the array, the generated code clears not only the target index but also the subsequent bytes belonging to the same array. Similarly, if an array of length 32 is allocated immediately before a memory struct containing a large integer, deleting the final element of the array causes the 32-byte zero write to bleed into the adjacent struct. Because integers are stored in memory with their most significant bytes first, the overflow zeroes out the leading bytes of the integer, drastically altering its numerical value without triggering any runtime exceptions or compiler warnings.
Diagnosing this vulnerability in production codebases can prove challenging because the compiler emits no warning flags and execution proceeds without reverting. The failure manifests purely as corrupted return values or unexpected state alterations rather than a hard crash. Fortunately, unit tests exercising the affected paths under the evmasm pipeline generally expose the unexpected data modifications.
The official resolution deployed in Solidity version 0.8.37 corrects the discrepancy in the code generator’s delete pathway. The patch forces the compiler to consult the element’s actual width during a delete operation, matching the behavior already established by standard assignments. When clearing a packed byte array element, the compiler now correctly emits a single-byte store (mstore8) rather than a full 32-byte word store, ensuring absolute behavioral parity between delete b[i] and b[i] = 0 across both compilation pipelines.
Security teams and smart contract developers utilizing Solidity versions up to 0.8.36 are strongly encouraged to audit their codebases for memory-based bytes and string array deletions. Upgrading the compiler toolchain to version 0.8.37 or later, or transitioning compilation pipelines to the IR architecture where applicable, completely mitigates the risk of this memory corruption vulnerability.
The Ethereum Foundation expressed gratitude to Shaheen Fazim for responsibly discovering and reporting the bug through the official bug bounty channels, as well as for supplying a clear reproduction test case that expedited the engineering team’s investigation and patch deployment.

