On August 14, 2026, developer Shaheen Fazim identified and reported a critical vulnerability within the Solidity code generator via the Ethereum Foundation’s bug bounty program. The defect concerns how the compiler handles the delete operator when applied to an individual element of a bytes or string array located in memory. Instead of safely and precisely clearing only the specified index, the generated code incorrectly writes 32 zero bytes starting at that exact element. This unintended 32-byte zero-write spills over past the target index, wiping out up to 31 subsequent bytes either within the same array or—when the deletion occurs near the boundary of the array—leaking into adjacent, independently allocated memory structures. Interestingly, the equivalent manual assignment operation, such as b[i] = 0, remains entirely unaffected and correctly clears precisely one byte.
Ethereum Foundation maintainers assigned this vulnerability a severity rating of low-to-medium on their internal scale. Crucially, the bug is strictly isolated to the default evmasm compilation pipeline, while the newer IR (Intermediate Representation) compilation pipeline remains completely secure and unaffected. Furthermore, invoking the Solidity optimizer is neither necessary to trigger the flaw nor capable of preventing it, as the issue stems directly from the code generation phase itself, and the optimizer merely preserves the faulty semantics.
Historical analysis of the codebase reveals that the affected code path predates the very first publicly released version of Solidity. Consequently, every single version of the compiler up to and including version 0.8.36 suffers from the defect. The issue has been formally patched and resolved in Solidity version 0.8.37. To gauge potential real-world impact, developers scanned the Sourcify database, which catalogs roughly 870,000 verified smart contract compilations. The analysis uncovered the vulnerable source pattern in exactly 17 compilations, containing only two distinct functions—neither of which actually exposes real-world vulnerability under runtime conditions. At present, no deployed smart contracts are known to have suffered malicious exploitation or unintended data corruption as a result of this bug.
Which Contracts Are Affected?
A smart contract is deemed vulnerable only if a specific set of rigorous technical conditions are met simultaneously. First, the contract must be compiled using an affected version of Solidity, ranging from the earliest legacy versions up to 0.8.36. Second, the compilation must utilize the default evmasm code generation pipeline rather than the IR pipeline. Third, the source code must explicitly invoke the delete operator on an element of a memory-resident bytes or string array.
While the first two conditions can be easily verified by inspecting compiler configurations and source files, evaluating the third condition requires deep architectural reasoning regarding the exact memory layout produced by the compiler. Because memory layout optimization can be complex, developers whose code satisfies the first two criteria are strongly advised to treat their contracts as potentially affected rather than attempting to definitively rule out memory overlap. Contracts that never apply the delete keyword to an individual element of a memory-based bytes or string type face zero risk.
It is vital to understand that neither the activation of the optimizer nor the targeted Ethereum Virtual Machine version alters whether the bug manifests. The defect is structurally embedded in the bytecode emitted by the code generator. Additionally, whole-array deletions—such as executing delete b on an entire array—route through a completely different code path and execute with absolute correctness. The vulnerability is strictly confined to element-level deletions on dynamic byte arrays residing in memory.
Storage-based byte arrays utilize an entirely separate implementation pathway and remain entirely unaffected, while calldata arrays cannot have the delete operator applied to them under any circumstance. Furthermore, arrays whose elements naturally occupy a full 32-byte word in memory, such as bytes1[] memory, are completely immune; the flaw exclusively affects bytes and string types because they pack their individual byte elements tightly back-to-back without word-alignment padding. Although direct index deletion like delete s[i] is not permitted for a string memory variable, developers frequently cast strings to bytes via explicit type conversion, writing delete bytes(s)[i], which successfully triggers the exact same underlying memory corruption bug.
Technical Details
To understand why this memory corruption occurs, one must examine how Solidity manages memory allocation. Most data types in Solidity memory occupy full 32-byte words. Dynamic byte arrays (bytes) serve as a prominent exception, consisting of an initial 32-byte length descriptor followed immediately by the raw underlying data bytes packed tightly back-to-back without internal gaps. Solidity allocates memory sequentially by advancing a global free memory pointer, meaning consecutive allocations sit flush against one another. Consequently, any write operation that overruns the boundaries of one allocation spills directly into whatever data structure resides immediately afterward.

Most dynamically allocated byte arrays, such as those created using new bytes(n) or instantiated directly from literal values, are followed by up to 31 zero bytes of padding to ensure that subsequent memory allocations cleanly align on a 32-byte word boundary. These are classified as padded arrays. Conversely, the evmasm pipeline leaves certain allocations completely unpadded—specifically 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 arrays, the data ends precisely where the next memory allocation begins.
Because memory byte array elements are single bytes, updating or clearing them normally requires a single-byte store operation (mstore8) rather than a full 32-byte word store (mstore). The compiler correctly employs mstore8 for standard assignments like b[i] = 0. However, the internal implementation path for the delete operator in the evmasm pipeline fails to consult the element width, mistakenly treating the target as a standard full-word type. When delete b[i] is executed, the generated bytecode issues a full 32-byte zero write originating from the memory address of the targeted element and extending forward. Because this write starts at the specific index rather than aligning to a 32-byte word boundary, it stretches far beyond the intended byte.
The array’s length descriptor, situated safely before the data payload, remains untouched, meaning the array preserves its original length value. However, any subsequent operations that read the array’s contents—such as computing a keccak256 hash, performing ABI encoding, or returning the byte sequence to an external caller—will operate directly on the corrupted, zeroed-out memory space.
The extent of the corruption depends heavily on the index of the deleted element and how the array was initially allocated. When developers delete an element within the interior of an array, the subsequent 31 bytes within that same array are forcefully overwritten with zeros. Unless those subsequent indices already contained zero bytes, the array’s data is immediately and permanently altered.
When deletion targets one of the final 31 elements of a padded array, the trailing padding absorbs part of the 32-byte write. For arrays whose lengths leave a full 31 bytes of padding, no overflow occurs. But for arrays whose lengths are exact multiples of 32—leaving zero padding—deleting the final elements causes the zero-write to bleed directly into the subsequent memory allocation. For unpadded arrays, deleting any of the last 31 elements invariably bleeds into the next memory allocation, and for arrays shorter than 31 bytes, this includes even the very first element.
Example
A clear demonstration of this behavior involves a contract declaring adjacent memory structures. In a test contract containing functions that delete an element from a short byte array and a final element from a padded 32-byte array seated next to a structure holding a maximum-value integer, invoking the vulnerable functions under the evmasm pipeline yields corrupted outputs. For instance, clearing the first element of a five-byte array results in all five bytes being zeroed out instead of just the first. Similarly, clearing the final element of a 32-byte array overwrites the leading 31 bytes of an adjacent integer structure, drastically altering its numerical value. Replacing these delete statements with explicit assignments correctly preserves the integrity of the surrounding memory.
Severity Assessment and Remediation
The Solidity compiler emits no warnings when compiling vulnerable code, and transactions do not revert at runtime, making this bug particularly insidious to diagnose in production environments. Nevertheless, because internal array corruption typically surfaces during standard test suites that inspect modified arrays, developers have a reasonable window to catch such anomalies.
The practical likelihood of encountering catastrophic memory overwrite in real-world deployments is low, as demonstrated by the extensive Sourcify code scan. The Ethereum Foundation recommends that all developers utilizing Solidity versions up to 0.8.36 immediately upgrade their toolchains to version 0.8.37 or higher. For projects unable to upgrade immediately, developers should audit their codebases to ensure that the delete operator is never applied to individual elements of memory-based bytes or string arrays, opting instead for explicit zero-assignment statements like b[i] = 0 or transitioning compilation to the secure IR pipeline.






