Types
IConceroRouter.MessageRequest
This request is the single source of truth for pricing, receipt packing, relayer selection, and verifier setup.
// From @concero/contracts/interfaces/IConceroRouter.sol
struct MessageRequest {
/// @notice Which chain the message should be delivered to.
/// @dev Concero uses chain selectors (not chain IDs) to route delivery.
uint24 dstChainSelector;
/// @notice How many source-chain block confirmations you want to wait for before the message
/// is considered safe enough to deliver (reorg protection).
/// @dev Set based on your security needs: higher confirmations = safer, but slower delivery.
uint64 srcBlockConfirmations;
/// @notice Which token you pay fees in.
/// @dev Use address(0) for native; ERC20 support depends on selected relayer/verifier libs.
address feeToken;
/// @notice The relayer module you want to deliver this message.
/// @dev This is a per-message choice. If the user selects a relayer, only that relayer
/// (per its own rules) is expected/allowed to submit the delivery.
address relayerLib;
/// @notice Which verifier modules you want to use to attest/verify this message.
/// @dev You choose the security model per message by choosing these modules.
address[] validatorLibs;
/// @notice Configuration for each verifier module.
/// @dev One config per verifier lib (must match validatorLibs length).
/// Typical examples: verifier gas limits, thresholds, or module-specific params.
bytes[] validatorConfigs;
/// @notice Relayer-specific configuration for this message.
/// @dev Optional opaque bytes interpreted only by the chosen relayer implementation.
/// Examples: service tier, delivery options, custom routing hints (depends on relayer).
bytes relayerConfig;
/// @notice Destination-specific execution parameters.
/// @dev For EVM destinations this defines:
/// - who should be called on the destination (receiver)
/// - how much gas to give that call (gasLimit)
/// This is what makes the message actually executable on the target chain.
bytes dstChainData;
/// @notice The message data that will be delivered to the destination chain.
/// @dev This is arbitrary bytes. Concero does not impose a format here:
/// - it can be raw bytes (e.g. "hello")
/// - it can be an ABI-encoded struct
/// - it can be a custom serialization your app understands
/// The destination-side receiver decides how to interpret it.
bytes payload;
}MessageReceipt
Message receipt is packed bytes, encoded by MessageCodec.
// From @concero/contracts/common/libraries/MessageCodec.sol
bytes messageReceipt;
// Encoded by MessageCodec.toMessageReceiptBytes(...)
// [0] : version (uint8)
// [1:4] : srcChainSelector (uint24)
// [4:7] : dstChainSelector (uint24)
// [7:39] : nonce (bytes32)
// [39:42] : srcChainData length (uint24)
// [42:..] : srcChainData = sender (address) + srcBlockConfirmations (uint64)
// [...] : dstChainData length + dstChainData
// [...] : relayerConfig length + relayerConfig
// [...] : validatorConfigs (flattened bytes[])
// [...] : internalValidatorConfigs (flattened bytes[])
// [...] : payload length + payloadEvmDstChainData
EvmDstChainData is packed bytes, encoded by MessageCodec.
[0:20] receiver (address)
[20:24] dstGasLimit (uint32)Use MessageCodec to encode and decode EVM destination chain data:
bytes memory encodedDstChainData = MessageCodec.encodeEvmDstChainData(receiver, gasLimit); // Encode
(address receiver, uint32 gasLimit) = MessageCodec.decodeEvmDstChainData(dstChainData); // Decode