Skip to content
Lattice

CrosschainLinkLib

Git Source

Title: CrosschainLinkLib

Authors: David Dada <daveproxy80@gmail.com> (https://github.com/dadadave80), Adapted for EIP-2535 from OpenZeppelin CrosschainLinked + ERC7786Recipient v5.6.1 (https://github.com/OpenZeppelin/openzeppelin-contracts)

(https://github.com/OpenZeppelin/openzeppelin-contracts/tree/5fd1781b1454fd1ef8e722282f86f9293cacf256/contracts/crosschain).

Logic + ERC-7201 storage for the CrosschainLink facet: an ERC-7786 send + receive endpoint with a per-chain (gateway, counterpart) link registry and tag-routed inbound handlers.

Divergence from OZ: ERC-7786's receiveMessage is a single Diamond selector, so this one library authenticates AND dispatches (OZ leaves _processMessage to a subclass). Dispatch is by the payload's leading 4-byte tag → a registered handler. Unlike OZ's ERC7786Recipient (which trusts the gateway for at-most-once delivery), this adds defensive receiveId replay protection because a Diamond may authorize more than one gateway (uniqueness is only guaranteed per-gateway).

Functions

crosschainLinkStorage

Returns the ERC-7201 storage struct for CrosschainLink.

function crosschainLinkStorage() internal pure returns (CrosschainLinkStorage storage $);

Returns

NameTypeDescription
$CrosschainLinkStorage

Registers the ICrosschainLink ERC-165 interface.

Must be called between preInitializer / postInitializer.

function __CrosschainLink_init() internal;

registerInterface

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

function registerInterface() internal;

Returns the gateway and counterpart registered for a chain-only interoperable address.

function getLink(bytes memory chain) internal view returns (address gateway, bytes memory counterpart);

Parameters

NameTypeDescription
chainbytes

Returns

NameTypeDescription
gatewayaddress
counterpartbytes

getHandler

Returns the handler registered for a message tag (zero if none).

function getHandler(bytes4 tag) internal view returns (address);

Parameters

NameTypeDescription
tagbytes4

Returns

NameTypeDescription
<none>address

isProcessed

Returns whether a receiveId from a given gateway has already been processed.

Keyed per-gateway (ERC-7786 only guarantees receiveId uniqueness for the calling gateway).

function isProcessed(address gateway, bytes32 receiveId) internal view returns (bool);

Parameters

NameTypeDescription
gatewayaddress
receiveIdbytes32

Returns

NameTypeDescription
<none>bool

receiveMessage

Authenticates, de-duplicates, and dispatches an inbound ERC-7786 message.

Checks-effects-interactions: receiveId is marked used (effect) BEFORE the handler call (interaction); a reverting handler rolls that back, keeping the message retryable.

function receiveMessage(bytes32 receiveId, bytes calldata sender, bytes calldata payload)
        internal
        returns (bytes4);

Parameters

NameTypeDescription
receiveIdbytes32
senderbytes
payloadbytes

Returns

NameTypeDescription
<none>bytes4The ERC-7786 magic value IERC7786Recipient.receiveMessage.selector (0x2432ef26).

Registers (or overrides) the gateway + counterpart for the counterpart's source chain.

Caller must hold DEFAULT_ADMIN_ROLE.

function setLink(address gateway, bytes calldata counterpart, bool allowOverride) internal;

Parameters

NameTypeDescription
gatewayaddress
counterpartbytes
allowOverridebool

setHandler

Registers a handler for inbound messages whose payload starts with tag (zero to clear).

Caller must hold DEFAULT_ADMIN_ROLE.

function setHandler(bytes4 tag, address handler) internal;

Parameters

NameTypeDescription
tagbytes4
handleraddress

sendMessage

Sends a message to the counterpart registered for chain via its ERC-7786 gateway.

Caller must hold DEFAULT_ADMIN_ROLE. Admin entrypoint for ad-hoc messages (e.g. governance signalling); handler/bridge logic uses the un-gated sendToCounterpart directly.

function sendMessage(bytes calldata chain, bytes calldata payload, bytes[] calldata attributes)
        internal
        returns (bytes32);

Parameters

NameTypeDescription
chainbytes
payloadbytes
attributesbytes[]

Returns

NameTypeDescription
<none>bytes32

sendToCounterpart

Sends a message to the counterpart registered for chain via its ERC-7786 gateway.

NO access control — callable only from in-Diamond facet logic (it is internal). Bridge handlers call this; their own token mechanics (burn/lock the caller's funds) are the gate. External callers can only reach the gated sendMessage selector, never this directly.

function sendToCounterpart(bytes memory chain, bytes memory payload, bytes[] memory attributes)
        internal
        returns (bytes32);

Parameters

NameTypeDescription
chainbytes
payloadbytes
attributesbytes[]

Returns

NameTypeDescription
<none>bytes32

_isAuthorizedGateway

Whether instance is the registered gateway AND sender is the registered counterpart for the source chain encoded in sender.

function _isAuthorizedGateway(address instance, bytes calldata sender) private view returns (bool);

Parameters

NameTypeDescription
instanceaddress
senderbytes

Returns

NameTypeDescription
<none>bool

_extractChain

Reduces a full interoperable address to its "chain-only" form (drops the address part).

function _extractChain(bytes memory self) private pure returns (bytes memory);

Parameters

NameTypeDescription
selfbytes

Returns

NameTypeDescription
<none>bytes