// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import "../stablecoins/IHypMailbox.sol"; /** * @title MockWarpMailboxV3 — faithful stand-in for AereMailboxV3's external * surface used by AereWarpRouteV3 tests. Not for mainnet. * * @dev Mirrors the real AereMailboxV3 behaviour the router depends on: * - quoteDispatch(uint32,bytes32,bytes) returns a configurable fee. * - dispatch(...) requires msg.value >= fee, keeps the fee, refunds any * excess to msg.sender (exactly like AereMailboxV3._dispatch), records * the call, returns a v3-style messageId. * - mockDeliver(...) lets a test drive an inbound handle() so the * recipient sees msg.sender == this mailbox (like process()). */ contract MockWarpMailboxV3 is IHypMailbox { uint32 public override localDomain; uint256 public feeAmount = 0.001 ether; // Recorded from the last dispatch — asserted by tests. uint32 public lastDestination; bytes32 public lastRecipient; bytes public lastBody; uint256 public lastFeePaid; bytes32 public lastMessageId; uint32 public dispatchNonce; event Dispatched(uint32 indexed destination, bytes32 indexed recipient, bytes body, uint256 feePaid); constructor(uint32 _localDomain) { localDomain = _localDomain; } function setFee(uint256 f) external { feeAmount = f; } function quoteDispatch(uint32, bytes32, bytes calldata) external view override returns (uint256) { return feeAmount; } function dispatch( uint32 destination, bytes32 recipient, bytes calldata body ) external payable override returns (bytes32) { require(msg.value >= feeAmount, "MockWarpMailboxV3: insufficient fee"); lastDestination = destination; lastRecipient = recipient; lastBody = body; lastFeePaid = feeAmount; bytes32 id = keccak256(abi.encodePacked(localDomain, dispatchNonce, destination, recipient, body)); dispatchNonce += 1; lastMessageId = id; emit Dispatched(destination, recipient, body, feeAmount); uint256 excess = msg.value - feeAmount; if (excess > 0) { (bool ok, ) = msg.sender.call{value: excess}(""); require(ok, "MockWarpMailboxV3: refund failed"); } return id; } /// @notice Test-only inbound delivery: call recipient.handle so it sees /// msg.sender == this mailbox. function mockDeliver( address recipient, uint32 origin, bytes32 sender, bytes calldata body ) external { IHypMessageRecipient(recipient).handle(origin, sender, body); } receive() external payable {} } /** * @title MockWarpIGPV3 — minimal AereIGPV3 quoting surface for the router's * quoteGasPayment() transparency view test. */ contract MockWarpIGPV3 { function quoteGasPayment(uint32, uint256 gasLimit) external pure returns (uint256) { // Deterministic: 1 gwei of AERE per unit of destination gas. return gasLimit * 1e9; } }