// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; // ============ Internal Imports ============ import {IInterchainGasPaymaster} from "../interfaces/IInterchainGasPaymaster.sol"; import {IInterchainSecurityModule} from "../interfaces/IInterchainSecurityModule.sol"; import {IHyperlaneConnectionClient} from "../interfaces/IHyperlaneConnectionClient.sol"; import {IMailbox} from "../interfaces/IMailbox.sol"; // ============ External Imports ============ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; abstract contract HyperlaneConnectionClient is OwnableUpgradeable, IHyperlaneConnectionClient { // ============ Mutable Storage ============ IMailbox public mailbox; // Interchain Gas Paymaster contract. The relayer associated with this contract // must be willing to relay messages dispatched from the current Mailbox contract, // otherwise payments made to the paymaster will not result in relayed messages. IInterchainGasPaymaster public interchainGasPaymaster; IInterchainSecurityModule public interchainSecurityModule; uint256[48] private __GAP; // gap for upgrade safety // ============ Events ============ /** * @notice Emitted when a new mailbox is set. * @param mailbox The address of the mailbox contract */ event MailboxSet(address indexed mailbox); /** * @notice Emitted when a new Interchain Gas Paymaster is set. * @param interchainGasPaymaster The address of the Interchain Gas Paymaster. */ event InterchainGasPaymasterSet(address indexed interchainGasPaymaster); event InterchainSecurityModuleSet(address indexed module); // ============ Modifiers ============ /** * @notice Only accept messages from an Hyperlane Mailbox contract */ modifier onlyMailbox() { require(msg.sender == address(mailbox), "!mailbox"); _; } /** * @notice Only accept addresses that at least have contract code */ modifier onlyContract(address _contract) { require(Address.isContract(_contract), "!contract"); _; } // ======== Initializer ========= function __HyperlaneConnectionClient_initialize(address _mailbox) internal onlyInitializing { _setMailbox(_mailbox); __Ownable_init(); } function __HyperlaneConnectionClient_initialize( address _mailbox, address _interchainGasPaymaster ) internal onlyInitializing { _setInterchainGasPaymaster(_interchainGasPaymaster); __HyperlaneConnectionClient_initialize(_mailbox); } function __HyperlaneConnectionClient_initialize( address _mailbox, address _interchainGasPaymaster, address _interchainSecurityModule ) internal onlyInitializing { _setInterchainSecurityModule(_interchainSecurityModule); __HyperlaneConnectionClient_initialize( _mailbox, _interchainGasPaymaster ); } function __HyperlaneConnectionClient_initialize( address _mailbox, address _interchainGasPaymaster, address _interchainSecurityModule, address _owner ) internal onlyInitializing { _setMailbox(_mailbox); _setInterchainGasPaymaster(_interchainGasPaymaster); _setInterchainSecurityModule(_interchainSecurityModule); _transferOwnership(_owner); } // ============ External functions ============ /** * @notice Sets the address of the application's Mailbox. * @param _mailbox The address of the Mailbox contract. */ function setMailbox(address _mailbox) external virtual onlyOwner { _setMailbox(_mailbox); } /** * @notice Sets the address of the application's InterchainGasPaymaster. * @param _interchainGasPaymaster The address of the InterchainGasPaymaster contract. */ function setInterchainGasPaymaster(address _interchainGasPaymaster) external virtual onlyOwner { _setInterchainGasPaymaster(_interchainGasPaymaster); } function setInterchainSecurityModule(address _module) external virtual onlyOwner { _setInterchainSecurityModule(_module); } // ============ Internal functions ============ /** * @notice Sets the address of the application's InterchainGasPaymaster. * @param _interchainGasPaymaster The address of the InterchainGasPaymaster contract. */ function _setInterchainGasPaymaster(address _interchainGasPaymaster) internal onlyContract(_interchainGasPaymaster) { interchainGasPaymaster = IInterchainGasPaymaster( _interchainGasPaymaster ); emit InterchainGasPaymasterSet(_interchainGasPaymaster); } /** * @notice Modify the contract the Application uses to validate Mailbox contracts * @param _mailbox The address of the mailbox contract */ function _setMailbox(address _mailbox) internal onlyContract(_mailbox) { mailbox = IMailbox(_mailbox); emit MailboxSet(_mailbox); } function _setInterchainSecurityModule(address _module) internal { require( _module == address(0) || Address.isContract(_module), "!contract" ); interchainSecurityModule = IInterchainSecurityModule(_module); emit InterchainSecurityModuleSet(_module); } }