Solidity

Diamond Proxy

A diamond proxy is an EIP-2535 upgradeable proxy pattern that routes function selectors to multiple facet contracts.

One proxy address can expose functions from many implementation contracts called facets.

Diamond Proxy Explained in Detail

A diamond proxy routes calls by function selector to facet contracts. Each facet contains part of the system's logic, while the diamond proxy keeps the stable address and usually stores shared state.

The pattern is standardized by EIP-2535 and is often used for modular systems with many functions or frequent upgrades.

Smart contract example

The critical upgrade operation is commonly called diamondCut. It can add, replace, or remove selector-to-facet mappings.

If an attacker can call diamondCut, they can replace privileged selectors, remove safety checks, or redirect user-facing functions to malicious facets.

Diamond Proxy in Auditing

Diamonds expand the normal upgradeable proxy attack surface. Auditors must review selector routing, facet permissions, shared storage, initialization, and upgrade governance across the whole diamond, not one implementation contract at a time.

Facet separation does not imply storage separation. Many facets operate on the same proxy storage through delegatecall.

Red flags in code

  • diamondCut is weakly protected or callable through an unexpected path.

  • Facets use inconsistent access control for related privileged functions.

  • Selector collisions or replacement behavior are not documented.

  • Shared storage layouts use unclear namespaces or overlapping slots.

  • Removed selectors leave stale assumptions in other facets.

How to test or review it

  • Map every function selector to its current facet.

  • Test diamondCut as owner, governance, non-owner, and malicious facet callers.

  • Review function selector collisions and replacement rules.

  • Compare storage namespaces used by all facets.

  • Verify loupe functions or inspection tooling match deployed selector mappings.

Sources