Skip to content
Lattice

ChainRegistryLib

Git Source

Title: ChainRegistryLib

Author: David Dada <daveproxy80@gmail.com> (https://github.com/dadadave80)

Logic + ERC-7201 storage for the Lattice chain registry: chain identities keyed by keccak256(abi.encodePacked(chainType, chainReference)) (EVM and non-EVM handled identically), an informational native-id index, per-chain gateway coverage with direct/hub-routed distinction, and addEvmChain — the one-action admin fan-out that registers an EVM chain and pushes its config into every enabled gateway adapter LIB directly (internal calls, so msg.sender stays the admin and each lib's own checkRole passes; NEVER external self-calls, which would break AccessControl).

COVERAGE AWARENESS, NOT ROUTING (issue #77 Q5): the registry is the config single-source-of-truth and the coverage authority, but adapters keep their own cheap hot-path maps — the registry NEVER sits in any adapter send path (the only cross-module reader is the OpenBridge's opt-in minDirectCoverage gate). Hub-routed coverage (e.g. the ZetaChain adapter reaching connected chains only via the ZEVM hub) NEVER counts toward directCoverageOf.

Constants

EVM_CHAIN_TYPE

The ERC-7930 chain type of eip-155 (EVM) chains.

bytes2 internal constant EVM_CHAIN_TYPE = 0x0000;

Functions

chainRegistryStorage

function chainRegistryStorage() internal pure returns (ChainRegistryStorage storage $);

Returns

NameTypeDescription
$ChainRegistryStorage

__ChainRegistry_init

Registers the IChainRegistry ERC-165 id. Called inside the diamond initializing window.

function __ChainRegistry_init() internal;

registerInterface

Writes true to the ERC-165 map slot for IChainRegistry.

function registerInterface() internal;

chainKeyOf

The chain key of any ERC-7930 chain identity.

function chainKeyOf(bytes2 chainType, bytes memory chainReference) internal pure returns (bytes32);

Parameters

NameTypeDescription
chainTypebytes2
chainReferencebytes

Returns

NameTypeDescription
<none>bytes32

chainKeyEvm

The chain key of an EVM chain (eip-155 chainType + canonical minimal big-endian reference).

function chainKeyEvm(uint256 chainId) internal pure returns (bytes32);

Parameters

NameTypeDescription
chainIduint256

Returns

NameTypeDescription
<none>bytes32

_evmChainReference

The canonical minimal big-endian (no leading zeros) ERC-7930 chain reference of chainId.

Derived by round-tripping InteroperableAddress.formatEvmV1 through InteroperableAddress.parseV1 — the ONE encoding the whole repo uses; deliberately not re-implemented here.

function _evmChainReference(uint256 chainId) private pure returns (bytes memory chainReference);

Parameters

NameTypeDescription
chainIduint256

Returns

NameTypeDescription
chainReferencebytes

isRegistered

function isRegistered(bytes32 chainKey) internal view returns (bool);

Parameters

NameTypeDescription
chainKeybytes32

Returns

NameTypeDescription
<none>bool

chainInfoOf

function chainInfoOf(bytes32 chainKey)
        internal
        view
        returns (bytes2 chainType, bytes memory chainReference, uint256 evmChainId);

Parameters

NameTypeDescription
chainKeybytes32

Returns

NameTypeDescription
chainTypebytes2
chainReferencebytes
evmChainIduint256

nativeIdsOf

function nativeIdsOf(bytes32 chainKey) internal view returns (IChainRegistry.NativeIds memory);

Parameters

NameTypeDescription
chainKeybytes32

Returns

NameTypeDescription
<none>IChainRegistry.NativeIds

gatewaysOf

function gatewaysOf(bytes32 chainKey) internal view returns (address[] memory);

Parameters

NameTypeDescription
chainKeybytes32

Returns

NameTypeDescription
<none>address[]

coverageOf

The total number of gateways covering chainKey (direct + hub-routed).

function coverageOf(bytes32 chainKey) internal view returns (uint256);

Parameters

NameTypeDescription
chainKeybytes32

Returns

NameTypeDescription
<none>uint256

directCoverageOf

The number of gateways covering chainKey DIRECTLY — hub-routed coverage never counts.

O(n) over the coverage set; n is admin-bounded small (at most one entry per local adapter).

function directCoverageOf(bytes32 chainKey) internal view returns (uint256 direct);

Parameters

NameTypeDescription
chainKeybytes32

Returns

NameTypeDescription
directuint256

registerChain

Registers a chain identity (EVM or non-EVM). Admin only. Re-register reverts ChainRegistryAlreadyRegistered — chain identities are permanent, so an explicit removeChain is deliberately absent in v1 (YAGNI; coverage entries and native ids stay mutable).

function registerChain(bytes2 chainType, bytes calldata chainReference, uint256 evmChainId) internal;

Parameters

NameTypeDescription
chainTypebytes2
chainReferencebytes
evmChainIduint256

setNativeIds

Sets the informational native ids of a registered chain. Admin only.

function setNativeIds(bytes32 chainKey, IChainRegistry.NativeIds calldata ids) internal;

Parameters

NameTypeDescription
chainKeybytes32
idsIChainRegistry.NativeIds

setGatewayCoverage

Records (covered = true, with the given hubRouted flag) or clears (covered = false) gateway's coverage of a registered chain. Admin only. Re-recording an existing gateway updates its hubRouted flag.

function setGatewayCoverage(bytes32 chainKey, address gateway, bool covered, bool hubRouted) internal;

Parameters

NameTypeDescription
chainKeybytes32
gatewayaddress
coveredbool
hubRoutedbool

addEvmChain

ONE structured admin action that adds an EVM chain everywhere: registers the chain identity, records the native ids declared by the enabled sections, fans the per-adapter config out into every ENABLED adapter lib (direct internal calls — msg.sender stays the admin, so each lib's own DEFAULT_ADMIN_ROLE check passes), then records the coverage entries. Admin only.

The fan-out writes each enabled adapter's ERC-7201 slots whether or not that adapter's facet is cut into this diamond — un-hosted slots simply go unread until such a facet is cut, so leaving a section for an un-hosted adapter disabled is the ADMIN's responsibility (no facet-existence introspection by design). Per-adapter duplicate guards (e.g. ChainSelectorAlreadyRegistered) bubble up unchanged and roll back the whole action.

function addEvmChain(IChainRegistry.AddEvmChainConfig calldata cfg) internal;

Parameters

NameTypeDescription
cfgIChainRegistry.AddEvmChainConfig

_registerChain

Registers the chain identity and returns its key. Reverts ChainRegistryEmptyChainReference on an empty reference, ChainRegistryAlreadyRegistered if the identity already exists.

FAIL-CLOSED eip-155 canonicality (review finding): an EVM chainType requires a non-zero evmChainId whose canonical minimal-big-endian reference byte-equals chainReference — a non-minimal reference (e.g. hex"000a" for chain 10) would mint a chainKey the send-time derivation can NEVER match, silently making coverage records unreachable. Non-EVM chainTypes require evmChainId == 0 (the field is meaningless there).

function _registerChain(bytes2 chainType, bytes memory chainReference, uint256 evmChainId)
        private
        returns (bytes32 chainKey);

Parameters

NameTypeDescription
chainTypebytes2
chainReferencebytes
evmChainIduint256

Returns

NameTypeDescription
chainKeybytes32

_setNativeIds

function _setNativeIds(bytes32 chainKey, IChainRegistry.NativeIds memory ids) private;

Parameters

NameTypeDescription
chainKeybytes32
idsIChainRegistry.NativeIds

_setGatewayCoverage

EVENT FIDELITY (review finding): the emitted event mirrors STORED state exactly so off-chain indexers reconstructing coverage from events cannot drift — a no-op removal (gateway was never covered) emits nothing, and the covered=false path always logs hubRouted=false (the flag is deleted, never stored).

function _setGatewayCoverage(bytes32 chainKey, address gateway, bool covered, bool hubRouted) private;

Parameters

NameTypeDescription
chainKeybytes32
gatewayaddress
coveredbool
hubRoutedbool

_registeredRecord

The record of chainKey, reverting ChainRegistryNotRegistered when it is not registered.

function _registeredRecord(bytes32 chainKey) private view returns (ChainRecord storage record);

Parameters

NameTypeDescription
chainKeybytes32

Returns

NameTypeDescription
recordChainRecord

_checkAxelarSection

Fail-closed Axelar section checks: chain7930 must be the CANONICAL chain-only ERC-7930 address of chainId (the exact bytes the Axelar adapter keys its equivalence map with — InteroperableAddress.formatEvmV1(chainId)), and remote7930 must address chainId.

function _checkAxelarSection(uint256 chainId, IChainRegistry.AxelarSection calldata section) private pure;

Parameters

NameTypeDescription
chainIduint256
sectionIChainRegistry.AxelarSection