Skip to main content

Solidity libraries

Helpers from Recoil Link's contracts that save writing the same checks in every app. They come with the Solidity package, @recoillink/core (see Testing for installing it).

MailboxClient​

Base contract for anything that talks to a Mailbox.

import {MailboxClient} from "@recoillink/core/contracts/client/MailboxClient.sol";
Member
mailboxThe Mailbox (immutable, set in the constructor)
localDomainThis chain's domain id
onlyMailbox modifierRejects calls not coming from the Mailbox: use it on handle
hook, setHook(address)Optional custom post-dispatch hook (owner only)
interchainSecurityModule(), setInterchainSecurityModule(address)Optional custom ISM for messages to this contract (owner only); unset means the Mailbox default

MailboxClient is upgradeable-ready (OwnableUpgradeable); call _MailboxClient_initialize(hook, ism, owner) from your initializer.

Router​

MailboxClient plus a table of trusted remote contracts ("routers"), one per domain. Incoming messages from anything else are rejected before your code runs.

import {Router} from "@recoillink/core/contracts/client/Router.sol";
Member
enrollRemoteRouter(uint32 domain, bytes32 router) / enrollRemoteRouters(...)Trust a contract on another domain (owner only)
routers(uint32 domain), domains()The table
_handle(uint32 origin, bytes32 sender, bytes calldata message)Override this: called only for messages from an enrolled router
_Router_dispatch(...)Dispatch to the enrolled router on a domain

Use Router when the same app is deployed on several chains and only its own instances may talk to each other.

TypeCasts​

import {TypeCasts} from "@recoillink/core/contracts/libs/TypeCasts.sol";

bytes32 recipient = TypeCasts.addressToBytes32(recipientAddress);
address sender = TypeCasts.bytes32ToAddress(senderBytes32);

Message​

Parses the packed message (useful in custom ISMs and hooks):

id, version, nonce, origin, sender, senderAddress, destination, recipient, recipientAddress, body, and formatMessage to build one.

StandardHookMetadata​

Builds and reads the metadata passed to dispatch (see Gas and fees):

Function
overrideGasLimit(uint256)Metadata asking the gas paymaster to charge for this gas limit
overrideRefundAddress(address)Where overpayment goes
overrideMsgValue(uint256)Native value to forward on delivery
formatMetadata(msgValue, gasLimit, refundAddress, customMetadata)All fields at once
gasLimit, refundAddress, msgValue, variantRead them back
import {StandardHookMetadata} from "@recoillink/core/contracts/hooks/libs/StandardHookMetadata.sol";

bytes memory metadata = StandardHookMetadata.overrideGasLimit(200_000);
uint256 fee = mailbox.quoteDispatch(destination, recipient, body, metadata);
mailbox.dispatch{value: fee}(destination, recipient, body, metadata);

overrideGasLimit sets the refund address to msg.sender, i.e. the contract calling it.