aere-contracts/contracts/stablecoins/MockHypMailbox.sol
Aere Network a13a649b77
Some checks are pending
contracts-ci / Install (lockfile) → compile → full test suite (push) Waiting to run
contracts-ci / PQC known-answer tests (NIST vectors) (push) Waiting to run
contracts-ci / Coverage (scoped, with artifacts) (push) Waiting to run
Initial public release
Aere Network public source. Everything here can be checked against the live
chain (chain id 2800, https://rpc.aere.network).

Scope note, stated up front rather than buried: consensus on chain 2800 is
classical secp256k1 ECDSA QBFT. The post-quantum work in this repository is at
the signature, precompile, account and transport layers. Nothing here makes the
consensus post-quantum, and no document in it should be read as claiming so.
2026-07-20 01:02:37 +03:00

80 lines
3.5 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
import "./IHypMailbox.sol";
/**
* @title MockHypMailbox — in-memory Mailbox used by the warp-route tests
* @notice Simulates Hyperlane's interchain dispatch/handle flow inside a
* single Hardhat test runner. Two mock-mailbox instances can be
* paired (setSister) so that a dispatch on instance A triggers a
* handle() call on instance B's enrolled recipient.
*
* @dev Only used in tests, never deployed to mainnet. Exposes:
* - quoteDispatch → returns a configurable flat fee
* - dispatch → forwards body to the sister Mailbox's
* recipient.handle() with origin = this.localDomain
* - localDomain → configurable per instance
*/
contract MockHypMailbox is IHypMailbox {
uint32 public override localDomain;
uint256 public fee = 0.001 ether;
MockHypMailbox public sister;
address public localRecipient; // The application contract on THIS Mailbox's chain that receives inbound messages.
event Dispatched(uint32 indexed destination, bytes32 indexed recipient, bytes body);
event Handled(uint32 indexed origin, bytes32 indexed sender, bytes body);
constructor(uint32 _localDomain) {
localDomain = _localDomain;
}
/// @notice Pair the two MockHypMailbox instances.
/// @param _sister The OTHER Mailbox (on the other "chain").
/// @param _localRecipient The application contract on OUR side that
/// should receive inbound .handle() calls.
function setSister(MockHypMailbox _sister, address _localRecipient) external {
sister = _sister;
localRecipient = _localRecipient;
}
function setFee(uint256 _fee) external { fee = _fee; }
function quoteDispatch(uint32, bytes32, bytes calldata) external view override returns (uint256) {
return fee;
}
function dispatch(
uint32 destinationDomain,
bytes32 recipientAddress,
bytes calldata messageBody
) external payable override returns (bytes32 messageId) {
require(msg.value >= fee, "MockMailbox: insufficient fee");
emit Dispatched(destinationDomain, recipientAddress, messageBody);
messageId = keccak256(abi.encode(localDomain, destinationDomain, recipientAddress, messageBody, block.timestamp));
// Delivery: msg.sender of dispatch is the application on OUR chain;
// we pass its bytes32-padded address as the `sender` field that the
// sister's recipient will check against its enrolled routers. The
// sister Mailbox actually performs the call so that recipient.handle()
// sees msg.sender == sister Mailbox (matching production behaviour).
if (address(sister) != address(0)) {
bytes32 ourSenderB32 = bytes32(uint256(uint160(msg.sender)));
sister.deliverInbound(localDomain, ourSenderB32, messageBody);
}
}
/// @dev Internal-cross-mailbox hook. Called by the SOURCE Mailbox; we
/// forward to our locally-configured recipient so it sees
/// msg.sender == us (the destination Mailbox), per production
/// Hyperlane semantics.
function deliverInbound(uint32 origin, bytes32 sender, bytes calldata body) external {
require(msg.sender == address(sister), "MockMailbox: not from sister");
require(localRecipient != address(0), "MockMailbox: no local recipient");
IHypMessageRecipient(localRecipient).handle(origin, sender, body);
emit Handled(origin, sender, body);
}
}