A significant bug has been uncovered in the Solidity programming language’s code generator that can lead to unintended memory corruption when deleting elements from in-memory byte arrays. Discovered by security researcher Shaheen Fazim on August 14, 2026, through the Ethereum Foundation’s bug bounty program, the vulnerability causes the compiler to overwrite far more data than intended. While the issue is constrained to specific compilation pipelines and precise conditions, it highlights the delicate nature of low-level memory management in smart contract development.
The core of the issue emerges when the delete operator is applied to an individual element of a bytes or string array residing in memory. Under normal expected execution, an operation like delete b[i] should clear precisely one byte of data, mirroring the explicit assignment b[i] = 0. However, due to a discrepancy in how the legacy evmasm code generation pipeline handles the deletion path compared to standard assignments, the compiler emits a full 32-byte zero write starting directly at the target element’s memory address.
Instead of clearing only the specified index, the generated bytecode zeroes out up to 31 subsequent bytes. Depending on the array’s layout and the index of the deleted element, this destructive wave either overwrites neighboring elements within the same array or spills past the boundary of the array entirely, corrupting whatever data happens to be allocated immediately afterward in EVM memory.
Scope, Severity, and Affected Versions
The Solidity development team has assigned this vulnerability a severity rating of low-to-medium on their internal scale. Several mitigating factors reduce its real-world impact. First, the bug exclusively affects the default evmasm compilation pipeline, while the modern IR (Intermediate Representation) pipeline remains entirely unaffected. Second, the use of the Solidity optimizer is neither required to trigger the bug nor capable of preventing it, as the faulty semantics are embedded directly into the generated instructions.
The vulnerable code path is deeply entrenched in the compiler’s history, predating the very first official release of Solidity. Consequently, every version of the language up to and including version 0.8.36 is affected. The issue has been officially addressed and patched in Solidity version 0.8.37.
To gauge the potential risk to deployed decentralized applications, the core team conducted a comprehensive scan of the Sourcify database, which indexes roughly 870,000 verified smart contract compilations. The search sought out the specific source code pattern capable of triggering the bug. Out of nearly a million compilations, the pattern was detected in only 17 instances, encompassing just two distinct functions. Upon closer security inspection, neither of those functions was found to be genuinely vulnerable; in both cases, the overwritten bytes were either immediately discarded or landed in harmless, unallocated memory zones. At the time of disclosure, no deployed smart contracts in the wild are known to have been compromised or affected by the bug.
Detailed Mechanics of Memory Layout and Deletion
To fully understand why the bug occurs, it is necessary to examine how Solidity manages memory allocations. In the Ethereum Virtual Machine, most data types occupy a clean, full 32-byte word. Dynamic byte arrays (bytes) and strings represent a prominent exception. In memory, a bytes array consists of an initial 32-byte length descriptor followed immediately by the raw byte data, packed tightly back-to-back without internal word-boundary gaps.
Solidity implements dynamic memory allocation by sequentially advancing the free memory pointer. Each new allocation begins precisely where the previous one terminates. Aside from necessary alignment padding, consecutive objects sit flush against one another. Because byte arrays pack their elements into single bytes, storing data into them requires single-byte write operations (mstore8) rather than full 32-byte word writes (mstore).
While the standard assignment path successfully distinguishes element widths, the delete code path in the evmasm pipeline historically defaulted to a full 32-byte word write. When a developer executes delete b[i], the compiler issues an instruction to clear 32 bytes starting at index i. Because this address rarely aligns with a clean 32-byte word boundary, the zero-fill operation spills forward.

The consequences of this spill depend heavily on whether the array is padded. Arrays created via explicit allocations like new bytes(n) or initialized from literal strings are typically padded with up to 31 zero bytes at the end so that the subsequent memory allocation starts cleanly on a word boundary. Conversely, unpadded arrays—such as those generated by bytes.concat, string.concat, and various abi.encode functions—terminate precisely where the next allocation begins, leaving zero buffer space.
When an element is deleted deep inside a padded array, the trailing padding absorbs part or all of the 32-byte zero write, preventing it from leaking into adjacent memory objects. However, when delete is invoked on any of the last 31 elements of a padded array—or on any element of an unpadded array—the zero-write wave breaches the array’s boundaries. It flows directly into whatever variable, struct, or temporary data structure was allocated next in memory.
For right-aligned values like integers, addresses, or pointers, the leading bytes of the word are overwritten. Depending on the exact number of bytes cleared, this can drastically alter numerical values, truncate addresses, or corrupt state logic in subtle, difficult-to-diagnose ways without triggering any runtime revert or compiler warning.
Practical Demonstration and Vulnerable Code Patterns
The mechanics of this vulnerability can be observed in controlled environments using standard contract patterns that rely on adjacent memory allocation. Consider a smart contract featuring two distinct functions designed to test internal array corruption and boundary leakage:
contract C
struct S uint256 x;
function clearElement() public pure returns (bytes memory)
bytes memory d = hex"0102030405";
delete d[0];
return d;
function clearLastElement() public pure returns (uint256)
bytes memory b = new bytes(32);
S memory s = S(type(uint256).max);
delete b[31];
return s.x;
When compiled and executed under the default evmasm pipeline in vulnerable compiler versions, these functions produce unexpected states. In the clearElement function, the small five-byte array occupies a single word. Invoking delete d[0] triggers a 32-byte zero write that clears index zero while simultaneously wiping out indices one through four, returning a completely zeroed byte array instead of leaving the remaining elements intact.
In the second scenario, clearLastElement, a 32-byte array b is allocated alongside a memory struct s initialized to the maximum possible uint256 value. Because the array is exactly 32 bytes long, it features no trailing padding, placing struct s immediately adjacent in memory. Executing delete b[31] causes the 32-byte clearing operation to bleed 31 bytes deep into the memory space reserved for s.x. Because integers are stored in memory with their most significant bytes first, the operation strips away the upper 31 bytes of type(uint256).max, leaving only the lowest byte intact and causing the function to erroneously return 255 instead of the maximum integer value. Substituting these delete operations with explicit assignments (d[0] = 0 and b[31] = 0) yields the correct, expected behavior across all versions.
Recommended Actions and Resolution
The discovery underscores the importance of maintaining up-to-date development toolchains in smart contract engineering. Because the vulnerability manifests silently through incorrect computational outcomes rather than explicit transaction failures or compilation errors, developers working on legacy codebases should audit their smart contracts for instances where the delete keyword is applied to individual indices of memory-based bytes or string structures.
The definitive resolution to the vulnerability is upgrading the Solidity compiler to version 0.8.37 or later. The patch corrects the code generation logic within the legacy evmasm pipeline, ensuring that the delete path consults element width specifications in the exact same manner as standard assignments. For developers unable to migrate immediately, transitioning compilation targets to the IR pipeline or ensuring that delete is avoided on individual elements of packed memory arrays serve as viable risk mitigation strategies.
The Ethereum Foundation and the Solidity core team expressed their gratitude to Shaheen Fazim for identifying the flaw through the official bug bounty ecosystem and for supplying a clear, reproducible test case that enabled a swift diagnosis and fix.

