Skip to main content

Diamond Upgrade Facet

Diamond upgrade and management facet

Key Features
  • Manages facet lifecycle (add, replace, remove) within a diamond.
  • Supports optional delegatecall for post-upgrade operations.
  • Emits events for all facet changes and delegate calls.
  • Provides selector discovery mechanism via exportSelectors.

Overview

This facet provides core diamond upgrade functionality, enabling the addition, replacement, and removal of facets. It orchestrates these operations through the diamond proxy and can optionally perform delegate calls for initialization or state modification. The facet also supports exporting its selectors for discovery.

Storage

OwnerStorage

Definition
struct OwnerStorage {
address owner;
}

FacetNode

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

FacetList

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

DiamondStorage

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

FacetReplacement

Definition
struct FacetReplacement {
address oldFacet;
address newFacet;
}

State Variables

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

Functions

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
) external;

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.

exportSelectors

Exports the function selectors of the DiamondUpgradeFacet This function is use as a selector discovery mechanism for diamonds

function exportSelectors() external pure returns (bytes memory);

Returns:

PropertyTypeDescription
-bytesselectors The exported function selectors of the DiamondUpgradeFacet

Events

Errors

Best Practices

Best Practice
  • Ensure all diamond upgrade operations are performed by authorized accounts.
  • Verify facet logic contracts have correct bytecode before adding or replacing.
  • Safely manage the delegatecall functionality for initialization or state modification after an upgrade.

Security Considerations

Security

The upgradeDiamond function is critical and must be protected by robust access control to prevent unauthorized modifications. The facet uses delegatecall, which requires careful validation of the _delegate address and _delegateCalldata to prevent reentrancy or unintended state changes. Input validation for facet addresses and selector data is crucial. Potential risks include OwnerUnauthorizedAccount, NoSelectorsForFacet, NoBytecodeAtAddress, and DelegateCallReverted errors if inputs are invalid or delegate calls fail.

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.