Generalized Messaging Protocol
Overview
Streamlined, simple and secure cross-chain messaging system that allows DApps to send and receive messages across networks reliably, enabling faster development and implementation of on-chain logic.
Contract Design
The contract manages cross-network message handling with secure verification to prevent double-processing and unauthorized access. It includes upgrade permissions for the owner, a list of trusted relayers, and event-driven logging to track each message's journey.
Events
The contract emits events to notify external systems about outgoing messages, helping to maintain an auditable record of cross-chain communication.
event Message(
uint256 indexed srcChainId,
bytes indexed srcAddress,
uint256 indexed connSn,
uint256 dstChainId,
bytes dstAddress,
bytes payload
);
State Variables
address public owner; // Contract owner with privileges to update configurations and relayers, (how to upgrade and manage relays safely?)
address public feeHandler; // Contract owner with privileges to update configurations and relayers, (how to upgrade and manage relays safely?)
bytes32[] public relayers; // List of authorized relayers for message verification
uint256 public connSn; // Serial number for outgoing messages, ensuring unique identification
uint256 public chainId; // Chain ID of the current contract’s chain
mapping(uint256 => mapping(uint256 => bool)) public receipts; // Tracks processed messages to prevent duplication
owner: Has authority to update contract configurations and manage authorized relayers.
relayers: Holds addresses of trusted entities that validate messages, reducing single points of failure.
connSn: A serial number for each message to uniquely identify and track outgoing messages.
nid: Represents the network ID of this contract's chain, enabling accurate identification in cross-chain operations.
receipts: Tracks processed messages per network ID to prevent repeated handling of the same message.
Fees
Fees are not coded into the contract but just accepted, that a fee has been paid is verified off chain if a fee is needed.
Functions
sendMessage
sendMessage
The sendMessage
function is responsible for dispatching messages to a specified network and address. It assigns a unique serial number (connSn) to each outgoing message, increments the connSn, and emits an event to signal the message dispatch.
function sendMessage(uint256 dstChainId, bytes dstAddress, bytes memory payload) external payable {
connSn++;
feeHandler.transfer(msg.value);
emit Message(connSn, chainID, msg.sender, dstChainId, dstAddress, payload);
}
Parameters
dstChainId: The Chain ID of the destination network.
dstAddress: The target address on the destination network.
payload: The message payload to be transmitted.
verifyMessage
verifyMessage
The verifyMessage
function validates incoming messages using signatures provided by authorized relayers. It checks the receipts
mapping to prevent processing the same message multiple times, and invokes verifySignatures
to authenticate the message’s integrity.
function verifyMessage(
uint256 srcChainId,
bytes calldata srcAddress,
uint256 connSn,
bytes memory payload,
bytes[] calldata signatures
) external {
require(!receipts[originChainId][connSn], "Message already processed");
// Mark the message as processed to prevent re-processing
receipts[originChainId][connSn] = true;
// Verify the signatures to confirm authenticity
require(
verifySignatures(connSn, originChainId, originAddress, nid, msg.sender, payload, signatures),
"Invalid signatures"
);
}
Example DApp: Using ICON GMP for Cross-Chain Messaging
Sending Messages
DApps can initiate cross-chain messages using sendMessage
in the connection contract. This allows a DApp to send a signed message to a target contract on another network, which the relayers can then verify and forward to the destination network.
function gmpAction() external {
// Application logic here
gmp.sendMessage(targetNetworkID, targetAddress, messagePayload);
}
Receiving Messages
SODAX GMP provides relayers to automatically submit messages to the designated recvMessage
endpoint. This endpoint will verify the message’s authenticity using verifyMessage
and then process it according to application-specific logic.
function recvMessage(
uint256 srcChainId,
bytes calldata srcAddress,
uint256 connSn,
bytes memory payload,
bytes[] calldata signatures
) external {
// Verify the incoming message
gmp.verifyMessage(srcChainId, srcAddress, connSn, payload, signatures);
// Application-specific logic to handle the message
}
Alternative Message Consumption
In cases where a message requires special handling (e.g., error resolution or rollback), DApps can implement alternative message interfaces. This allows for customized message processing, including recovery mechanisms or other error-handling strategies.
function revertInterface(
uint256 srcChainId,
bytes calldata srcAddress,
uint256 _onnSn,
bytes memory payload,
bytes[] calldata signatures
) external {
// Verify the message authenticity before proceeding
gmp.verifyMessage(srcChainId, srcAddress, connSn, payload, signatures);
// Implement revert or recovery logic here for special handling
}
Encoding Compliance
Last updated