Array Deletion Index
Detects unsafe array element deletion that leaves stale indices or gaps, corrupting data structures that depend on contiguous arrays.
Array Deletion Index
Overview
The array deletion index detector identifies unsafe patterns when removing elements from storage arrays. Solidity’s delete array[i] zeroes the element but does not shrink the array, leaving a gap. If code later iterates the array or uses .length to count valid entries, the zero-value gap causes incorrect behavior.
Why This Is an Issue
The delete operator on an array element sets the value to its type’s default (0 for uint, address(0) for address) but does not change array.length. Code that assumes all elements are valid will:
- Process zero-value entries as real data
- Count deleted entries in length-based loops
- Miss the actual last element if using swap-and-pop but referencing stale indices
Validator registries, token allowlists, and order books that use arrays for enumeration are commonly affected.
How to Resolve
// Before: Delete leaves gap
function remove(uint256 index) external {
delete validators[index]; // Gap at index -- length unchanged
}
// After: Swap with last element and pop
function remove(uint256 index) external {
require(index < validators.length, "Out of bounds");
validators[index] = validators[validators.length - 1];
validators.pop(); // Length reduced, no gap
}
Examples
Sample Sigvex Output
{
"detector_id": "array-deletion-index",
"severity": "medium",
"confidence": 0.85,
"description": "Storage array element deleted via 'delete' at offset 0x4a without swap-and-pop. Array length remains unchanged, leaving a zero-value gap that will be processed by subsequent iterations.",
"location": { "function": "remove(uint256)", "offset": 74 }
}
Detection Methodology
- Delete pattern detection: Identifies SSTORE of zero to array elements without corresponding length reduction.
- Iteration analysis: Checks whether the same array is iterated elsewhere in the contract.
- Swap-pop recognition: Recognizes the swap-and-pop pattern as the safe alternative and does not flag it.
Limitations
- Sparse arrays where gaps are intentional (e.g., mapping-backed virtual arrays) will be flagged.
- Order-preserving deletion (shifting all elements) is not flagged but may be gas-prohibitive for large arrays.
Related Detectors
- Unchecked Array Bounds — bounds validation
- Controlled Array Length — unbounded iteration