Skip to main content

Diamond Upgrade Module

Upgrade diamond by adding, replacing, or removing facets

Key Features
  • Supports adding, replacing, and removing facets on a diamond.
  • Emits FacetAdded, FacetReplaced, and FacetRemoved events for upgrade tracking.
  • Optionally executes a delegatecall for complex initialization or state manipulation.
  • Emits DiamondMetadata for tagged upgrades and associated data.
Module Usage

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

Definition
struct DiamondStorage {
mapping(bytes4 functionSelector => FacetNode) facetNodes;
FacetList facetList;
}

FacetList

Definition
struct FacetList {
bytes4 headFacetNodeId;
bytes4 tailFacetNodeId;
uint32 facetCount;
uint32 selectorCount;
}

FacetNode

Definition
struct FacetNode {
address facet;
bytes4 prevFacetNodeId;
bytes4 nextFacetNodeId;
}

FacetReplacement

This struct is used to replace old facets with new facets.

Definition
struct FacetReplacement {
address oldFacet;
address newFacet;
}

State Variables

PropertyTypeDescription
DIAMOND_STORAGE_POSITIONbytes32Diamond storage slot position for this module (Value: keccak256("erc8153.diamond"))

Functions

addFacets

function addFacets(address[] calldata _facets) ;

Parameters:

PropertyTypeDescription
_facetsaddress[]-

at

function at(bytes memory selectors, uint256 index) pure returns (bytes4 selector);

Parameters:

PropertyTypeDescription
selectorsbytes-
indexuint256-

getDiamondStorage

function getDiamondStorage() pure returns (DiamondStorage storage s);

importSelectors

function importSelectors(address _facet) view returns (bytes memory selectors);

Parameters:

PropertyTypeDescription
_facetaddress-

removeFacets

function removeFacets(address[] calldata _facets) ;

Parameters:

PropertyTypeDescription
_facetsaddress[]-

replaceFacets

function replaceFacets(FacetReplacement[] calldata _replaceFacets) ;

Parameters:

PropertyTypeDescription
_replaceFacetsFacetReplacement[]-

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.

function upgradeDiamond(
address[] calldata _addFacets,
FacetReplacement[] calldata _replaceFacets,
address[] calldata _removeFacets,
address _delegate,
bytes calldata _delegateCalldata,
bytes32 _tag,
bytes calldata _metadata
) ;

Parameters:

PropertyTypeDescription
_addFacetsaddress[]Facets to add.
_replaceFacetsFacetReplacement[](oldFacet, newFacet) pairs, to replace old with new.
_removeFacetsaddress[]Facets to remove.
_delegateaddressOptional contract to delegatecall (zero address to skip).
_delegateCalldatabytesOptional calldata to execute on _delegate.
_tagbytes32Optional arbitrary metadata, such as release version.
_metadatabytesOptional arbitrary data.

Events

Errors

Best Practices

Best Practice
  • Ensure that the caller possesses the necessary permissions to perform diamond upgrades.
  • Carefully review the _delegate and _delegateCalldata parameters 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 NoBytecodeAtAddress errors.

Integration Notes

Shared Storage

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.

Was this helpful?
Last updated:

Newsletter

Get notified about releases, feature announcements, and technical deep-dives on building smart contracts with Compose.

No spam. Unsubscribe anytime.