Diamond Upgrade Module
Upgrade diamond by adding, replacing, or removing facets
- Supports adding, replacing, and removing facets on a diamond.
- Emits
FacetAdded,FacetReplaced, andFacetRemovedevents for upgrade tracking. - Optionally executes a
delegatecallfor complex initialization or state manipulation. - Emits
DiamondMetadatafor tagged upgrades and associated data.
This module provides internal functions for use in your custom facets. Import it to access shared logic and storage.
Overview
This module provides core functions for managing diamond facets, enabling upgrades according to ERC-2535 and ERC-8153. It allows adding new facets, replacing existing ones, and removing facets. State changes are managed through diamond storage, ensuring visibility across all facets. Optionally, it supports delegate calls for complex initialization or state modifications during upgrades.
Storage
DiamondStorage
storage-location: erc8042:erc8153.diamond
FacetList
FacetNode
FacetReplacement
This struct is used to replace old facets with new facets.
State Variables
| Property | Type | Description |
|---|---|---|
DIAMOND_STORAGE_POSITION | bytes32 | Diamond storage slot position for this module (Value: keccak256("erc8153.diamond")) |
Functions
addFacets
Parameters:
| Property | Type | Description |
|---|---|---|
_facets | address[] | - |
at
Parameters:
| Property | Type | Description |
|---|---|---|
selectors | bytes | - |
index | uint256 | - |
getDiamondStorage
importSelectors
Parameters:
| Property | Type | Description |
|---|---|---|
_facet | address | - |
removeFacets
Parameters:
| Property | Type | Description |
|---|---|---|
_facets | address[] | - |
replaceFacets
Parameters:
| Property | Type | Description |
|---|---|---|
_replaceFacets | FacetReplacement[] | - |
upgradeDiamond
Upgrade the diamond by adding, replacing, or removing facets. Facets are added first, then replaced, then removed. These events are emitted to record changes to facets: - FacetAdded(address indexed _facet) - FacetReplaced(address indexed _oldFacet, address indexed _newFacet) - FacetRemoved(address indexed _facet) If _delegate is non-zero, the diamond performs a delegatecall to _delegate using _delegateCalldata. The DiamondDelegateCall event is emitted. The delegatecall is done to alter a diamond's state or to initialize, modify, or remove state after an upgrade. However, if _delegate is zero, no delegatecall is made and no DiamondDelegateCall event is emitted. If _tag is non-zero or if _metadata.length > 0 then the DiamondMetadata event is emitted.
Parameters:
| Property | Type | Description |
|---|---|---|
_addFacets | address[] | Facets to add. |
_replaceFacets | FacetReplacement[] | (oldFacet, newFacet) pairs, to replace old with new. |
_removeFacets | address[] | Facets to remove. |
_delegate | address | Optional contract to delegatecall (zero address to skip). |
_delegateCalldata | bytes | Optional calldata to execute on _delegate. |
_tag | bytes32 | Optional arbitrary metadata, such as release version. |
_metadata | bytes | Optional arbitrary data. |
Events
Errors
Best Practices
- Ensure that the caller possesses the necessary permissions to perform diamond upgrades.
- Carefully review the
_delegateand_delegateCalldataparameters to prevent unintended state changes or reentrancy risks during delegate calls. - Verify that facet bytecode exists at the provided addresses before attempting to add or replace them to avoid
NoBytecodeAtAddresserrors.
Integration Notes
This module interacts with the diamond's central storage, identified by DIAMOND_STORAGE_POSITION and conceptually mapped to keccak256(\"erc8153.diamond\"). It modifies the facetList within the DiamondStorage struct. Changes made through upgradeDiamond, addFacets, replaceFacets, and removeFacets are immediately visible to all facets that access this shared storage. The upgradeDiamond function orchestrates the sequence of operations: additions, then replacements, then removals.