Diamond Collision
Detects storage slot collisions between facets in EIP-2535 diamond proxy contracts, where independent facets may unknowingly share storage locations.
Diamond Collision
Overview
Remediation Guide: How to Fix Diamond Collision
The diamond collision detector identifies storage slot conflicts between facets in EIP-2535 diamond proxy architectures. In a diamond proxy, multiple “facet” contracts share the same storage context through delegatecall. If two facets declare state variables that occupy the same storage slot, writes from one facet corrupt the other facet’s data.
Sigvex analyzes the storage access patterns of each facet registered in a diamond, comparing slot usage across facets to detect overlaps.
Why This Is an Issue
Diamond proxies are designed for modularity — each facet handles a subset of functionality. However, because all facets share the diamond’s storage, they must coordinate their storage layout. Without explicit namespace separation (using the “diamond storage” or “app storage” pattern), facets developed independently will almost certainly collide at slot 0, 1, 2, etc.
The collision causes silent data corruption: a facet writing its admin variable at slot 0 overwrites another facet’s totalSupply at the same slot. This corruption may not be detected until a user observes incorrect balances or a governance action fails.
How to Resolve
// Before: Vulnerable — facets use default storage layout
contract FacetA {
uint256 public valueA; // Slot 0 — COLLIDES
}
contract FacetB {
uint256 public valueB; // Slot 0 — COLLIDES
}
// After: Fixed — diamond storage pattern with unique namespaces
library LibFacetA {
bytes32 constant STORAGE_POSITION = keccak256("diamond.facet.a.storage");
struct Storage { uint256 valueA; }
function getStorage() internal pure returns (Storage storage s) {
bytes32 pos = STORAGE_POSITION;
assembly { s.slot := pos }
}
}
Detection Methodology
- Facet identification: Identifies facet contracts registered in the diamond’s facet registry.
- Storage slot extraction: For each facet, extracts all storage slots accessed via
SLOAD/SSTORE. - Cross-facet comparison: Compares slot sets across all facet pairs, flagging any overlapping slots.
- Namespace detection: Checks whether facets use the diamond storage pattern (hashed slot positions), reducing false positives for properly namespaced facets.
Limitations
False positives:
- Facets that intentionally share storage (e.g., reading a shared
ownervariable) may be flagged. - Facets using AppStorage (a single shared struct) are intentionally sharing and should not be flagged, but may be if the pattern is not recognized.
False negatives:
- Dynamically computed slots in facets may not be fully resolved.
- Facets added after the initial deployment (via
diamondCut) require re-analysis.
Related Detectors
- Storage Collision — detects standard proxy storage collisions
- Conditional Storage Collision — detects path-dependent collisions