Diamond

Git Source

Author: Matter Labs

The helper library for managing the EIP-2535 diamond proxy.

Note: security-contact: security@matterlabs.dev

State Variables

DIAMOND_INIT_SUCCESS_RETURN_VALUE

Magic value that should be returned by diamond cut initialize contracts.

Used to distinguish calls to contracts that were supposed to be used as diamond initializer from other contracts.

bytes32 internal constant DIAMOND_INIT_SUCCESS_RETURN_VALUE =
  0x33774e659306e47509050e97cb651e731180a42d458212294d30751925c551a2;

DIAMOND_STORAGE_POSITION

Storage position of DiamondStorage structure.

bytes32 private constant DIAMOND_STORAGE_POSITION =
  0xc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131b;

Functions

getDiamondStorage

function getDiamondStorage()
  internal
  pure
  returns (DiamondStorage storage diamondStorage);

Returns

NameTypeDescription
diamondStorageDiamondStorageThe pointer to the storage where all specific diamond proxy parameters stored

diamondCut

Add/replace/remove any number of selectors and optionally execute a function with delegatecall

function diamondCut(DiamondCutData memory _diamondCut) internal;

Parameters

NameTypeDescription
_diamondCutDiamondCutDataDiamond's facet changes and the parameters to optional initialization delegatecall

_addFunctions

Add new functions to the diamond proxy NOTE: expect but NOT enforce that _selectors is NON-EMPTY array

function _addFunctions(
  address _facet,
  bytes4[] memory _selectors,
  bool _isFacetFreezable
) private;

_replaceFunctions

Change associated facets to already known function selectors NOTE: expect but NOT enforce that _selectors is NON-EMPTY array

function _replaceFunctions(
  address _facet,
  bytes4[] memory _selectors,
  bool _isFacetFreezable
) private;

_removeFunctions

Remove association with function and facet NOTE: expect but NOT enforce that _selectors is NON-EMPTY array

function _removeFunctions(address _facet, bytes4[] memory _selectors) private;

_saveFacetIfNew

Add address to the list of known facets if it is not on the list yet NOTE: should be called ONLY before adding a new selector associated with the address

function _saveFacetIfNew(address _facet) private;

_addOneFunction

*Add one function to the already known facet NOTE: It is expected but NOT enforced that:

  • _facet is NON-ZERO address
  • _facet is already stored address in DiamondStorage.facets
  • _selector is NOT associated by another facet*
function _addOneFunction(
  address _facet,
  bytes4 _selector,
  bool _isSelectorFreezable
) private;

_removeOneFunction

Remove one associated function with facet NOTE: It is expected but NOT enforced that _facet is NON-ZERO address

function _removeOneFunction(address _facet, bytes4 _selector) private;

_removeFacet

remove facet from the list of known facets NOTE: It is expected but NOT enforced that there are no selectors associated with _facet

function _removeFacet(address _facet) private;

_initializeDiamondCut

Delegates call to the initialization address with provided calldata

Used as a final step of diamond cut to execute the logic of the initialization for changed facets

function _initializeDiamondCut(address _init, bytes memory _calldata) private;

Events

DiamondCut

event DiamondCut(FacetCut[] facetCuts, address initAddress, bytes initCalldata);

Structs

SelectorToFacet

Utility struct that contains associated facet & meta information of selector

struct SelectorToFacet {
  address facetAddress;
  uint16 selectorPosition;
  bool isFreezable;
}

Properties

NameTypeDescription
facetAddressaddressaddress of the facet which is connected with selector
selectorPositionuint16index in FacetToSelectors.selectors array, where is selector stored
isFreezablebooldenotes whether the selector can be frozen.

FacetToSelectors

Utility struct that contains associated selectors & meta information of facet

struct FacetToSelectors {
  bytes4[] selectors;
  uint16 facetPosition;
}

Properties

NameTypeDescription
selectorsbytes4[]list of all selectors that belong to the facet
facetPositionuint16index in DiamondStorage.facets array, where is facet stored

DiamondStorage

The structure that holds all diamond proxy associated parameters

According to the EIP-2535 should be stored on a special storage key - DIAMOND_STORAGE_POSITION

struct DiamondStorage {
  mapping(bytes4 selector => SelectorToFacet selectorInfo) selectorToFacet;
  mapping(address facetAddress => FacetToSelectors facetInfo) facetToSelectors;
  address[] facets;
  bool isFrozen;
}

Properties

NameTypeDescription
selectorToFacetmapping(bytes4 selector => SelectorToFacet selectorInfo)A mapping from the selector to the facet address and its meta information
facetToSelectorsmapping(address facetAddress => FacetToSelectors facetInfo)A mapping from facet address to its selectors with meta information
facetsaddress[]The array of all unique facet addresses that belong to the diamond proxy
isFrozenboolDenotes whether the diamond proxy is frozen and all freezable facets are not accessible

FacetCut

Parameters for diamond changes that touch one of the facets

struct FacetCut {
  address facet;
  Action action;
  bool isFreezable;
  bytes4[] selectors;
}

Properties

NameTypeDescription
facetaddressThe address of facet that's affected by the cut
actionActionThe action that is made on the facet
isFreezableboolDenotes whether the facet & all their selectors can be frozen
selectorsbytes4[]An array of unique selectors that belongs to the facet address

DiamondCutData

Structure of the diamond proxy changes

struct DiamondCutData {
  FacetCut[] facetCuts;
  address initAddress;
  bytes initCalldata;
}

Properties

NameTypeDescription
facetCutsFacetCut[]The set of changes (adding/removing/replacement) of implementation contracts
initAddressaddressThe address that's delegate called after setting up new facet changes
initCalldatabytesCalldata for the delegate call to initAddress

Enums

Action

Type of change over diamond: add/replace/remove facets

enum Action {
  Add,
  Replace,
  Remove
}