Skip to main content

MetaRegistry

MetaRegistry is a supplementary contract that stores Node Operator metadata and defines operator groups used by CuratedModule for weighted stake allocation. A group assigns shares to its module Node Operators and can reference operators in external staking modules. The registry calculates each grouped Node Operator's effective allocation weight from its Accounting bond curve and its share within the group. Operators outside a group have zero allocation weight.

The contract also stores each Node Operator's name and description and can restrict further metadata edits by the operator owner.

State Variables

MANAGE_OPERATOR_GROUPS_ROLE

bytes32 public constant MANAGE_OPERATOR_GROUPS_ROLE = keccak256("MANAGE_OPERATOR_GROUPS_ROLE")

SET_OPERATOR_INFO_ROLE

bytes32 public constant SET_OPERATOR_INFO_ROLE = keccak256("SET_OPERATOR_INFO_ROLE")

SET_BOND_CURVE_WEIGHT_ROLE

bytes32 public constant SET_BOND_CURVE_WEIGHT_ROLE = keccak256("SET_BOND_CURVE_WEIGHT_ROLE")

NO_GROUP_ID

uint256 public constant NO_GROUP_ID = 0

MODULE

ICuratedModule public immutable MODULE

ACCOUNTING

IAccounting public immutable ACCOUNTING

STAKING_ROUTER

IStakingRouter public immutable STAKING_ROUTER

MAX_BP

uint256 internal constant MAX_BP = 10000

EXTERNAL_STAKE_PER_VALIDATOR

uint256 internal constant EXTERNAL_STAKE_PER_VALIDATOR = 32 ether

MAX_NAME_LENGTH

uint256 internal constant MAX_NAME_LENGTH = 256

MAX_DESCRIPTION_LENGTH

uint256 internal constant MAX_DESCRIPTION_LENGTH = 1024

META_REGISTRY_STORAGE_LOCATION

bytes32 private constant META_REGISTRY_STORAGE_LOCATION =
0xa7ec41e1a061c67796a04fcd9cc7cab9545b0a750beebc54139d9ed9d2251c00

Functions

constructor

constructor(address module) ;

initialize

Initialize the registry.

function initialize(address admin) external initializer;

Parameters

NameTypeDescription
adminaddressAddress to receive DEFAULT_ADMIN_ROLE.

getInitializedVersion

Returns the initialized version of the contract.

function getInitializedVersion() external view returns (uint64);

setOperatorMetadataAsAdmin

Set or update metadata for a node operator (callable by SET_OPERATOR_INFO_ROLE).

function setOperatorMetadataAsAdmin(uint256 nodeOperatorId, OperatorMetadata calldata metadata)
external
onlyRole(SET_OPERATOR_INFO_ROLE);

Parameters

NameTypeDescription
nodeOperatorIduint256Node operator ID.
metadataOperatorMetadataMetadata payload to persist.

setOperatorMetadataAsOwner

Set or update metadata by the node operator owner.

Reverts if module does not support IBaseModule interface.

function setOperatorMetadataAsOwner(uint256 nodeOperatorId, string calldata name, string calldata description)
external;

Parameters

NameTypeDescription
nodeOperatorIduint256Node operator ID.
namestringDisplay name.
descriptionstringLong description.

createOrUpdateOperatorGroup

Create a new operator group or update an existing one.

Creating is allowed only when groupId == NO_GROUP_ID.

function createOrUpdateOperatorGroup(uint256 groupId, OperatorGroup calldata groupInfo)
external
onlyRole(MANAGE_OPERATOR_GROUPS_ROLE);

Parameters

NameTypeDescription
groupIduint256Group ID to update, or NO_GROUP_ID to create.
groupInfoOperatorGroupGroup definition.

setBondCurveWeight

Set base weight for the bond curve ID (callable by SET_BOND_CURVE_WEIGHT_ROLE).

Effective weights for operators using the curve will not be updated automatically. refreshOperatorWeight() must be called for the affected operators to update their effective weights.

function setBondCurveWeight(uint256 curveId, uint256 weight) external onlyRole(SET_BOND_CURVE_WEIGHT_ROLE);

Parameters

NameTypeDescription
curveIduint256Bond curve ID.
weightuint256Base allocation weight.

refreshOperatorWeight

Trigger the operator weight update routine in the registry.

function refreshOperatorWeight(uint256 nodeOperatorId) external;

Parameters

NameTypeDescription
nodeOperatorIduint256Node operator ID to trigger the update for.

getOperatorMetadata

Get metadata for a node operator.

function getOperatorMetadata(uint256 nodeOperatorId) external view returns (OperatorMetadata memory metadata);

Parameters

NameTypeDescription
nodeOperatorIduint256Node operator ID.

Returns

NameTypeDescription
metadataOperatorMetadataStored metadata struct.

getOperatorGroup

Fetch an operator group by ID.

function getOperatorGroup(uint256 groupId) external view returns (OperatorGroup memory groupInfo);

Parameters

NameTypeDescription
groupIduint256Group ID to fetch.

Returns

NameTypeDescription
groupInfoOperatorGroupGroup definition.

getOperatorGroupsCount

Returns total operator groups count.

function getOperatorGroupsCount() external view returns (uint256 count);

getNodeOperatorGroupId

Get Node Operator group ID (returns NO_GROUP_ID if the operator is not in any group).

function getNodeOperatorGroupId(uint256 nodeOperatorId) external view returns (uint256 operatorGroupId);

Parameters

NameTypeDescription
nodeOperatorIduint256Node operator ID to query.

Returns

NameTypeDescription
operatorGroupIduint256Group ID.

getExternalOperatorGroupId

Get External Operator group ID (returns NO_GROUP_ID if the operator is not in any group).

function getExternalOperatorGroupId(ExternalOperator calldata op) external view returns (uint256 operatorGroupId);

Parameters

NameTypeDescription
opExternalOperatorExternal operator.

Returns

NameTypeDescription
operatorGroupIduint256Group ID.

getBondCurveWeight

Returns base weight for the bond curve ID.

function getBondCurveWeight(uint256 curveId) external view returns (uint256 weight);

Parameters

NameTypeDescription
curveIduint256Bond curve ID.

Returns

NameTypeDescription
weightuint256Base allocation weight.

getNodeOperatorWeight

Returns effective weight for the node operator.

Returns the cached effective weight.

function getNodeOperatorWeight(uint256 nodeOperatorId) external view returns (uint256 weight);

Parameters

NameTypeDescription
nodeOperatorIduint256Node operator ID to query.

Returns

NameTypeDescription
weightuint256Effective allocation weight.

getNodeOperatorWeightAndExternalStake

Returns effective weight and external stake for the node operator.

Returns (0, 0) if the operator is not in a group.

function getNodeOperatorWeightAndExternalStake(uint256 nodeOperatorId)
external
view
returns (uint256 weight, uint256 externalStake);

Parameters

NameTypeDescription
nodeOperatorIduint256Node operator ID to query.

Returns

NameTypeDescription
weightuint256Effective allocation weight.
externalStakeuint256External stake amount in wei.

getOperatorWeights

Returns allocation weights for the given node operators.

function getOperatorWeights(uint256[] calldata nodeOperatorIds)
external
view
returns (uint256[] memory operatorWeights);

Parameters

NameTypeDescription
nodeOperatorIdsuint256[]Node operator IDs to query.

Returns

NameTypeDescription
operatorWeightsuint256[]Weights aligned with nodeOperatorIds.

_createGroup

function _createGroup(OperatorGroup calldata groupInfo) internal;

_updateGroup

function _updateGroup(uint256 groupId, OperatorGroup calldata groupInfo) internal;

_storeGroupData

function _storeGroupData(uint256 groupId, OperatorGroup calldata groupInfo) internal;

_resetGroup

function _resetGroup(uint256 groupId) internal;

_setGroupName

function _setGroupName(uint256 groupId, string calldata name) internal;

_storeSubOperators

function _storeSubOperators(uint256 groupId, SubNodeOperator[] calldata subNodeOperators) internal;

_storeExternalOperators

function _storeExternalOperators(uint256 groupId, ExternalOperator[] calldata externalOperators) internal;

_refreshOperatorWeight

noId should be a part of group with groupId.

function _refreshOperatorWeight(uint256 groupId, uint256 noId) internal;

_setEffectiveWeight

function _setEffectiveWeight(uint256 nodeOperatorId, uint256 newWeight) internal returns (uint256 oldWeight);

_storeOperatorMetadata

function _storeOperatorMetadata(uint256 nodeOperatorId, OperatorMetadata memory metadata) internal;

_checkExternalOperatorExistsTypeNOR

function _checkExternalOperatorExistsTypeNOR(ExternalOperator memory op) internal;

_getOrCacheModuleAddress

Returns the module address for moduleId, resolving from STAKING_ROUTER on cache miss.

function _getOrCacheModuleAddress(uint8 moduleId) internal returns (address addr);

_getLatestEffectiveWeight

function _getLatestEffectiveWeight(uint256 nodeOperatorId, uint256 share) internal view returns (uint256);

_getOperatorBaseWeight

function _getOperatorBaseWeight(uint256 nodeOperatorId) internal view returns (uint256);

_getCachedModuleAddress

Returns the cached module address. Reverts if the address was never resolved via _getOrCacheModuleAddress.

function _getCachedModuleAddress(uint8 moduleId) internal view returns (address addr);

_onlyExistingOperator

function _onlyExistingOperator(address module, uint256 nodeOperatorId) internal view;

_nodeOperatorExists

function _nodeOperatorExists(address module, uint256 nodeOperatorId) internal view returns (bool);

_nodeOperatorOwner

function _nodeOperatorOwner(address module, uint256 nodeOperatorId) internal view returns (address);

_totalExternalStake

function _totalExternalStake(ExternalOperator[] storage externalOperators)
internal
view
returns (uint256 totalExternalStake);

_getOperatorExternalStakeTypeNOR

function _getOperatorExternalStakeTypeNOR(ExternalOperator memory op) internal view returns (uint256 stake);

_storage

function _storage() internal pure returns (MetaRegistryStorage storage $);

Structs

CachedOperatorGroup

struct CachedOperatorGroup {
string name;
uint64[] subNodeOperatorIds;
ExternalOperator[] externalOperators;
}

GroupIndex

struct GroupIndex {
mapping(uint256 nodeOperatorId => uint256 groupId) groupIdByOperatorId;
mapping(bytes32 externalKey => uint256 groupId) groupIdByExternalKey;
mapping(uint256 nodeOperatorId => uint16 share) shareByOperatorId;
}

EffectiveWeightCache

struct EffectiveWeightCache {
// Invariant: operators outside any group must have zero cached effective weight.
mapping(uint256 nodeOperatorId => uint256 weight) operatorEffectiveWeight;
mapping(uint256 groupId => uint256 weight) groupEffectiveWeightSum;
}

MetaRegistryStorage

Note: storage-location: erc7201:MetaRegistry

struct MetaRegistryStorage {
mapping(uint256 curveId => uint256 weight) bondCurveWeight;
mapping(uint256 groupId => CachedOperatorGroup) groups;
GroupIndex groupIndex;
EffectiveWeightCache effectiveWeightCache;
mapping(uint256 nodeOperatorId => OperatorMetadata) operatorMetadata;
mapping(uint256 moduleId => address moduleAddress) moduleAddressCache;
uint256 groupsCount;
}