Diamond Upgrade Facet
Orchestrates upgrade functionality, enabling the addition, replacement, and removal of facets.
- Manages facet lifecycle (add, replace, remove) within a diamond.
- Owner-gated upgrade entrypoint (ERC-173
owner). - Optional
delegatecallfor post-upgrade initialization/state migration. - Updates selector routing so subsequent calls dispatch to the new facet.
- Emits events for all facet changes and delegate calls.
Storage
State Variables
| Property | Type | Description |
|---|---|---|
OWNER_STORAGE_POSITION | bytes32 | Diamond storage slot position for this module (Value: keccak256("erc173.owner")) |
DIAMOND_STORAGE_POSITION | bytes32 | Diamond storage slot position for this module (Value: keccak256("erc8153.diamond")) |
Diamond Storage
Owner Storage
FacetReplacement
Functions
upgradeDiamond
Upgrade the diamond by adding, replacing, and/or removing facets.
Execution order is always: addFacets, replaceFacets, removeFacets
Then, if _delegate != address(0), the diamond performs a delegatecall with _delegateCalldata and emits DiamondDelegateCall.
Parameters:
| Property | Type | Description |
|---|---|---|
_addFacets | address[] | Facet addresses to add |
_replaceFacets | FacetReplacement[] | (oldFacet, newFacet) pairs to replace |
_removeFacets | address[] | Facet addresses to remove |
_delegate | address | Optional contract to delegatecall (address(0) to skip) |
_delegateCalldata | bytes | Optional calldata to execute on _delegate |
_tag | bytes32 | Optional arbitrary metadata, such as release version |
_metadata | bytes | Optional arbitrary metadata |
Facets must implement exportSelectors() in order to make their selectors discoverable by diamonds.
Only the exported selectors will be added to the diamond.
interface IFacet {
function exportSelectors() external pure returns (bytes memory);
}
See Facet-Based Diamond EIP-8153 for more details.
Events
Errors
Best Practices
- Ensure all diamond upgrade operations are performed by authorized accounts.
- Verify facet logic contracts are immutable and trusted before adding or replacing.
- Ensure each facet’s
exportSelectors()returns a valid packed selector list in deterministic order. - Carefully audit any optional post-upgrade
delegatecall(delegate contract + calldata).
Security Considerations
The upgradeDiamond function is critical: it mutates the diamond’s selector routing and facet linked list.
It is protected by Owner checks, and it optionally executes an unrestricted delegatecall after facet updates. Treat _delegate and _delegateCalldata as fully trusted: that code can modify diamond storage and may introduce complex control flow.