The home for Hyperlane core contracts, sdk packages, and other infrastructure
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hyperlane-monorepo/solidity/contracts/mock/MockMailbox.sol

135 lines
4.0 KiB

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Versioned} from "../upgrade/Versioned.sol";
import {TypeCasts} from "../libs/TypeCasts.sol";
import {IMessageRecipient} from "../interfaces/IMessageRecipient.sol";
import {IInterchainSecurityModule, ISpecifiesInterchainSecurityModule} from "../interfaces/IInterchainSecurityModule.sol";
contract MockMailbox is Versioned {
using TypeCasts for address;
using TypeCasts for bytes32;
// Domain of chain on which the contract is deployed
// ============ Constants ============
uint32 public immutable localDomain;
uint256 public constant MAX_MESSAGE_BODY_BYTES = 2 * 2**10;
uint32 public outboundNonce = 0;
uint32 public inboundUnprocessedNonce = 0;
uint32 public inboundProcessedNonce = 0;
IInterchainSecurityModule public defaultIsm;
mapping(uint32 => MockMailbox) public remoteMailboxes;
mapping(uint256 => MockMessage) public inboundMessages;
struct MockMessage {
uint32 nonce;
uint32 origin;
address sender;
address recipient;
bytes body;
}
constructor(uint32 _domain) {
localDomain = _domain;
}
function setDefaultIsm(IInterchainSecurityModule _module) external {
defaultIsm = _module;
}
function addRemoteMailbox(uint32 _domain, MockMailbox _mailbox) external {
remoteMailboxes[_domain] = _mailbox;
}
function dispatch(
uint32 _destinationDomain,
bytes32 _recipientAddress,
bytes calldata _messageBody
) external returns (bytes32) {
require(_messageBody.length <= MAX_MESSAGE_BODY_BYTES, "msg too long");
MockMailbox _destinationMailbox = remoteMailboxes[_destinationDomain];
require(
address(_destinationMailbox) != address(0),
"Missing remote mailbox"
);
_destinationMailbox.addInboundMessage(
outboundNonce,
localDomain,
msg.sender,
_recipientAddress.bytes32ToAddress(),
_messageBody
);
outboundNonce++;
return bytes32(0);
}
function addInboundMessage(
uint32 _nonce,
uint32 _origin,
address _sender,
address _recipient,
bytes calldata _body
) external {
inboundMessages[inboundUnprocessedNonce] = MockMessage(
_nonce,
_origin,
_sender,
_recipient,
_body
);
inboundUnprocessedNonce++;
}
function processNextInboundMessage() public {
MockMessage memory _message = inboundMessages[inboundProcessedNonce];
address _recipient = _message.recipient;
IInterchainSecurityModule _ism = _recipientIsm(_recipient);
if (address(_ism) != address(0)) {
// Do not pass any metadata because we expect to
// be using TestIsms
require(_ism.verify("", _encode(_message)), "ISM verify failed");
}
IMessageRecipient(_message.recipient).handle(
_message.origin,
_message.sender.addressToBytes32(),
_message.body
);
inboundProcessedNonce++;
}
function _encode(MockMessage memory _message)
private
view
returns (bytes memory)
{
return
abi.encodePacked(
VERSION,
_message.nonce,
_message.origin,
TypeCasts.addressToBytes32(_message.sender),
localDomain,
TypeCasts.addressToBytes32(_message.recipient),
_message.body
);
}
function _recipientIsm(address _recipient)
private
view
returns (IInterchainSecurityModule)
{
try
ISpecifiesInterchainSecurityModule(_recipient)
.interchainSecurityModule()
returns (IInterchainSecurityModule _val) {
if (address(_val) != address(0)) {
return _val;
}
} catch {}
return defaultIsm;
}
}