ERC-5164
defines an interface that supports execution across EVM networks. This repo contains the IMessageDispatcher
and IMessageExecutor
interfaces for use with ERC-5164
compliant messengers. This repo also provides two convenience contracts that can be extended, MessageExecutor
and MessageReceiver
.
Your MessageDispatcher
should inherit from IMessageDispatcher
and implement the dispatchMessage
function. When dispatchMessage
is called, it's recommended to encode the message and transport it to its destination. Transporting a message may involve emiting a special event, storing a hash of the message, or passing it to external transport layer like a rollup's native message bridge.
Example:
contract MyMessageDispatcher is IMessageDispatcher {
function dispatchMessage(uint256 toChainId, address to, bytes calldata data) external payable returns (bytes32) {
bytes32 messageId = keccak256(abi.encode(
block.chainid,
msg.sender,
toChainId,
to,
data
));
emit MessageSent(messageId, msg.sender, toChainId, to, data);
transportLayer.transport(toChainId, messageId);
return messageId;
}
}
Your MessageExecutor
should inherit from IMessageExecutor
. Each implementation may choose how the message execution is initiated. When a messsage is executed, the ERC-5164
validation data (messageId
, fromChainId
, from
) should be appended to the message's data
payload. The provided MessageExecutor
convenience contract does this automatically when you call execute
.
Example:
contract MyMessageExecutor is MessageExecutor {
function executeMessage(
uint256 fromChainId,
address from,
address to,
bytes calldata data,
Proof memory proof
) external {
require(proof.isValid, "Invalid proof");
bytes32 messageId = keccak256(abi.encode(
fromChainId,
msg.sender,
block.chainid,
to,
data
));
_execute(messageId, fromChainId, from, to, data);
}
}
When receiving a message, inherit from MessageReceiver
to access the EIP-5164
validation data -- messageId
, from
, and fromChainId
.
Example:
contract MyContract is MessageReceiver {
event MyMessageHandleEvent {
bytes32 indexed messageId /*,
... your event params*/
}
function myFunction() external {
// Parse the cross-chain context from the call
(bytes32 messageId, address from, uint256 fromChainId) = _crossChainContext();
// Validate the cross-chain caller
require(msg.sender == hopMessageBridge, "Invalid sender");
require(from == expectedCrossChainSender, "Invalid cross-chain sender");
require(fromChainId == expectedCrossChainId, "Invalid cross-chain chainId");
// Execute your business logic
emit MyMessageHandleEvent(messageId, /* your event params */);
}
}
npm run compile