// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; // ============ Internal Imports ============ import {IInterchainGasPaymaster} from "@hyperlane-xyz/core/interfaces/IInterchainGasPaymaster.sol"; import {IOutbox} from "@hyperlane-xyz/core/interfaces/IOutbox.sol"; import {IAbacusConnectionManager} from "@hyperlane-xyz/core/interfaces/IAbacusConnectionManager.sol"; // ============ External Imports ============ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; abstract contract AbacusConnectionClient is OwnableUpgradeable { // ============ Mutable Storage ============ IAbacusConnectionManager public abacusConnectionManager; // Interchain Gas Paymaster contract. The relayer associated with this contract // must be willing to relay messages dispatched from the current Outbox contract, // otherwise payments made to the paymaster will not result in relayed messages. IInterchainGasPaymaster public interchainGasPaymaster; uint256[48] private __GAP; // gap for upgrade safety // ============ Events ============ /** * @notice Emitted when a new abacusConnectionManager is set. * @param abacusConnectionManager The address of the abacusConnectionManager contract */ event AbacusConnectionManagerSet(address indexed abacusConnectionManager); /** * @notice Emitted when a new Interchain Gas Paymaster is set. * @param interchainGasPaymaster The address of the Interchain Gas Paymaster. */ event InterchainGasPaymasterSet(address indexed interchainGasPaymaster); // ============ Modifiers ============ /** * @notice Only accept messages from an Abacus Inbox contract */ modifier onlyInbox() { require(_isInbox(msg.sender), "!inbox"); _; } // ======== Initializer ========= function __AbacusConnectionClient_initialize( address _abacusConnectionManager ) internal onlyInitializing { _setAbacusConnectionManager(_abacusConnectionManager); __Ownable_init(); } function __AbacusConnectionClient_initialize( address _abacusConnectionManager, address _interchainGasPaymaster ) internal onlyInitializing { _setInterchainGasPaymaster(_interchainGasPaymaster); __AbacusConnectionClient_initialize(_abacusConnectionManager); } // ============ External functions ============ /** * @notice Sets the address of the application's AbacusConnectionManager. * @param _abacusConnectionManager The address of the AbacusConnectionManager contract. */ function setAbacusConnectionManager(address _abacusConnectionManager) external virtual onlyOwner { _setAbacusConnectionManager(_abacusConnectionManager); } /** * @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); } // ============ Internal functions ============ /** * @notice Sets the address of the application's InterchainGasPaymaster. * @param _interchainGasPaymaster The address of the InterchainGasPaymaster contract. */ function _setInterchainGasPaymaster(address _interchainGasPaymaster) internal { interchainGasPaymaster = IInterchainGasPaymaster( _interchainGasPaymaster ); emit InterchainGasPaymasterSet(_interchainGasPaymaster); } /** * @notice Modify the contract the Application uses to validate Inbox contracts * @param _abacusConnectionManager The address of the abacusConnectionManager contract */ function _setAbacusConnectionManager(address _abacusConnectionManager) internal { abacusConnectionManager = IAbacusConnectionManager( _abacusConnectionManager ); emit AbacusConnectionManagerSet(_abacusConnectionManager); } /** * @notice Get the local Outbox contract from the abacusConnectionManager * @return The local Outbox contract */ function _outbox() internal view returns (IOutbox) { return abacusConnectionManager.outbox(); } /** * @notice Determine whether _potentialInbox is an enrolled Inbox from the abacusConnectionManager * @return True if _potentialInbox is an enrolled Inbox */ function _isInbox(address _potentialInbox) internal view returns (bool) { return abacusConnectionManager.isInbox(_potentialInbox); } /** * @notice Get the local domain from the abacusConnectionManager * @return The local domain */ function _localDomain() internal view virtual returns (uint32) { return abacusConnectionManager.localDomain(); } }