A significant vulnerability in the Solidity code generator has been officially disclosed following a report submitted through the Ethereum Foundation’s bug bounty program. Discovered by researcher Shaheen Fazim on August 14, 2026, the defect causes the delete operator to misbehave when applied to individual elements of dynamic bytes or string arrays residing in memory. Instead of safely clearing only the targeted byte, the generated code executes a full 32-byte zero-write starting directly at the specified index. This unintended wide-scale overwrite affects internal array elements and, under specific conditions, can spill over into adjacent memory allocations, posing silent data corruption risks for smart contracts compiled using the default evmasm pipeline.
The Ethereum Foundation’s Solidity team has assessed the severity of the flaw as low-to-medium on its internal scale. The vulnerability is exclusively tied to the default evmasm compilation pipeline, leaving the modern IR (Intermediate Representation) pipeline entirely unaffected. Furthermore, the activation of the Solidity optimizer is not required for the bug to manifest, as the root issue lies directly within the fundamental code emission logic of the code generator stage itself. Historical analysis of the codebase reveals that the affected code path predates the very first official release of Solidity, meaning that all compiler versions up to and including version 0.8.36 are vulnerable. The issue has been officially resolved and patched in Solidity version 0.8.37.
To gauge the real-world impact of the discovery, developers conducted a comprehensive scan of the Sourcify database, analyzing approximately 870,000 verified smart contract compilations for the precise source code pattern capable of triggering the bug. The search identified the pattern in only 17 distinct compilations, which collectively housed just two unique functions. Further security assessments confirmed that neither of those functions was actually susceptible to malicious exploitation or destructive state corruption. As a result, no deployed smart contracts in the wild are currently known to have been compromised by the vulnerability.
Which Contracts Are Affected?
Understanding the precise conditions under which the vulnerability occurs is critical for smart contract developers reviewing their codebases. A contract is only vulnerable if it meets a specific set of operational criteria during execution. First, the compilation must utilize the default evmasm backend pipeline rather than the IR pipeline. Second, the source code must explicitly apply the delete operator to a specific element within a bytes or string array stored strictly in memory.
While checking the compiler pipeline and source code parameters can be accomplished easily through configuration files and code audits, evaluating the exact memory layout produced by the compiler requires deeper technical analysis. Consequently, security experts advise that if a contract utilizes memory-based byte arrays and applies the delete operator to indexed elements under the evmasm pipeline, it is safer to treat the contract as potentially affected rather than attempting to manually rule out complex memory proximity scenarios.
Contracts that never apply the delete operator to an element of a memory-based bytes or string type are entirely immune. Neither the activation of the optimizer nor the target Ethereum Virtual Machine (EVM) version alters how the bug manifests, because the defect is embedded directly within the emitted instructions of the code generator, and the downstream optimizer preserves these faulty semantics.
The vulnerability carries several key nuances regarding its operational scope. Only individual element deletes are affected; applying delete to an entire array via delete b triggers a completely separate and correct code path. Additionally, the array must reside in memory. Byte arrays located in storage utilize entirely distinct handling routines and remain completely unaffected, while calldata arrays cannot have the delete operator applied to them at all. Arrays whose elements occupy a full 32-word block in memory—such as bytes1[] memory—are likewise unaffected because only dynamic bytes and string types pack their internal elements back-to-back without padding.
String values are also affected by extension. Although direct usage of delete s[i] on a string memory s will fail to compile, developers frequently cast strings to bytes types—such as bytes(s)[i]—to perform index-based manipulations, which immediately triggers the identical underlying memory corruption bug.
Technical Details and Compiler Internals
To fully comprehend why the bug occurs, it is necessary to examine how Solidity manages memory allocation and data representation. Most data types in Solidity memory occupy full 32-byte words. The prominent exception is the bytes type, where a memory-allocated byte array consists of an initial 32-byte length header followed immediately by raw data packed consecutively without internal gaps. Solidity manages memory allocation sequentially by advancing a global free memory pointer, ensuring that consecutive allocations sit flush against one another, separated only by necessary word-alignment padding. Consequently, any write operation that accidentally overshoots the intended boundaries of one allocation will land directly inside the memory space of the subsequent allocation.

For most standard byte arrays created via keywords like new bytes(n) or initialized from literal values, the compiler appends up to 31 zero bytes of padding so that any subsequent memory allocation begins neatly on a clean 32-byte word boundary. These are referred to as padded arrays. However, the evmasm pipeline deliberately omits padding for the results of bytes.concat, string.concat, and various abi.encode variants including abi.encodePacked, abi.encodeWithSelector, abi.encodeWithSignature, and abi.encodeCall. In these unpadded allocations, the data ends precisely where the next allocation begins, heightening the risk of cross-allocation memory contamination.
When dealing with narrower data types in memory, alignment rules dictate positioning. Left-aligned types like bytesN begin at the first byte of a word, whereas right-aligned types such as integers, addresses, memory pointers, and array length headers sit at the end of a word with leading zero bytes. Because dynamic byte array elements are individual bytes, storing data into a byte array represents a rare scenario where memory writes cannot simply rely on full-word operations. The compiler ordinarily handles this by emitting a single-byte store instruction (mstore8) whenever it recognizes the precise element width, except along the flawed deletion code path.
The root cause of the vulnerability lies within the divergence of the delete implementation. When a developer writes delete x, the compiler is designed to assign the zero value corresponding to that type, meaning delete b[i] should be functionally identical to the standard assignment b[i] = 0. Both operations ultimately culminate in a write operation to the element’s designated location. However, within the vulnerable evmasm pipeline, these two code paths utilize completely distinct internal store routines.
While standard assignments properly factor in the single-byte element width and emit a precise mstore8 instruction, the delete path incorrectly treats the target as a full word. This results in the emission of a 32-byte zero write starting directly at the location of the deleted element. Because this write begins at an indexed byte offset rather than aligned to a clean 32-byte word boundary, it stretches forward by a full 32 bytes, overwriting everything in its path. Because the initial 32-byte length header of the array is located before the data payload, it remains untouched, allowing the array to retain its original length indicator. Consequently, any subsequent operations relying on the array contents—such as computing cryptographic hashes via keccak256, performing ABI encoding, or returning data to an external caller—will silently process corrupted, zeroed-out memory bytes. Meanwhile, the modern IR pipeline utilizes a unified store routine for both assignments and deletions, remaining completely immune to the defect.
The physical reach of the runaway zero-write depends heavily on the index of the deleted element and the presence of allocation padding. When deleting an element deep inside a padded array, the trailing padding bytes absorb a portion of the write. For instance, arrays whose lengths are exact multiples of 32 contain zero padding, meaning that deleting any of the final 31 elements will cause the 32-byte zero write to breach the array boundaries and overwrite the beginning of whatever memory allocation sits directly after it. For unpadded arrays generated by concatenation or encoding functions, deleting any of the final 31 elements—or even the very first element if the array itself is short—will immediately spill over into subsequent memory.
Practical Demonstration and Impact Assessment
To illustrate the mechanics of the vulnerability, security researchers provided a concrete contract example demonstrating both internal array corruption and external memory spillover. In scenarios involving internal array corruption, deleting an element near the beginning of a short array clears not only that specific byte but also wipes out up to 31 subsequent bytes within the same data structure. In scenarios involving external memory spillover, an array allocated immediately before a complex data structure—such as a memory struct containing a large integer—will experience a partial overwrite of that adjacent struct when an element near the tail end of the array is deleted.
Observed testing confirms that while an explicit assignment like b[i] = 0 correctly modifies only the targeted byte, using delete b[i] on vulnerable compiler versions propagates unexpected zeroes across adjacent memory. Because integers are stored with their most significant bytes first, overwriting the leading bytes of a maxed-out integer variable drastically alters its numerical value, turning a high-scale numeric boundary into a small integer without triggering any compiler warnings or runtime reversion exceptions.
Despite the technical severity of arbitrary memory overwrites, the practical likelihood of exploitation remains low. The bug persisted undetected throughout the multi-year history of the language, and database scans confirmed that the vulnerable code pattern is exceptionally rare in production environments. Furthermore, in the few instances where the pattern was identified, the overwritten bytes were either immediately discarded or positioned in unallocated memory spaces where no critical application state could be damaged.
The Solidity development team has fully resolved the vulnerability in version 0.8.37 by modifying the compiler’s delete code path to correctly consult element widths. The compiler now emits the proper single-byte store instruction (mstore8) during element deletions, ensuring that delete b[i] and b[i] = 0 behave identically across all compilation pipelines. Developers maintaining active codebases utilizing affected compiler versions are strongly encouraged to upgrade their toolchains to Solidity 0.8.37 or later, and to audit any memory-intensive byte array manipulation routines that make use of the delete operator.

