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/isms/routing/DomainRoutingIsm.sol

121 lines
3.9 KiB

// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;
// ============ External Imports ============
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
// ============ Internal Imports ============
import {AbstractRoutingIsm} from "./AbstractRoutingIsm.sol";
import {IInterchainSecurityModule} from "../../interfaces/IInterchainSecurityModule.sol";
import {Message} from "../../libs/Message.sol";
import {TypeCasts} from "../../libs/TypeCasts.sol";
import {EnumerableMapExtended} from "../../libs/EnumerableMapExtended.sol";
/**
* @title DomainRoutingIsm
*/
contract DomainRoutingIsm is AbstractRoutingIsm, OwnableUpgradeable {
using EnumerableMapExtended for EnumerableMapExtended.UintToBytes32Map;
using Message for bytes;
using TypeCasts for bytes32;
using TypeCasts for address;
using Address for address;
// ============ Mutable Storage ============
EnumerableMapExtended.UintToBytes32Map internal _modules;
// ============ Events ============
/**
* @notice Emitted when a module is set for a domain
* @param domain The origin domain.
* @param module The ISM to use.
*/
event ModuleSet(uint32 indexed domain, address module);
// ============ External Functions ============
/**
* @param _owner The owner of the contract.
*/
function initialize(address _owner) public initializer {
__Ownable_init();
_transferOwnership(_owner);
}
/**
* @notice Sets the ISMs to be used for the specified origin domains
* @param _owner The owner of the contract.
* @param _domains The origin domains
* @param __modules The ISMs to use to verify messages
*/
function initialize(
address _owner,
uint32[] calldata _domains,
IInterchainSecurityModule[] calldata __modules
) public initializer {
__Ownable_init();
require(_domains.length == __modules.length, "length mismatch");
uint256 _length = _domains.length;
for (uint256 i = 0; i < _length; ++i) {
_set(_domains[i], address(__modules[i]));
}
_transferOwnership(_owner);
}
/**
* @notice Sets the ISM to be used for the specified origin domain
* @param _domain The origin domain
* @param _module The ISM to use to verify messages
*/
function set(uint32 _domain, IInterchainSecurityModule _module)
external
onlyOwner
{
_set(_domain, address(_module));
}
function domains() external view returns (uint256[] memory) {
return _modules.keys();
}
function modules(uint32 origin)
public
view
virtual
returns (IInterchainSecurityModule)
{
(bool contained, bytes32 _module) = _modules.tryGet(origin);
require(contained, "No ISM found for origin domain");
return IInterchainSecurityModule(_module.bytes32ToAddress());
}
// ============ Public Functions ============
/**
* @notice Returns the ISM responsible for verifying _message
* @dev Can change based on the content of _message
* @param _message Formatted Hyperlane message (see Message.sol).
* @return module The ISM to use to verify _message
*/
function route(bytes calldata _message)
public
view
override
returns (IInterchainSecurityModule)
{
return modules(_message.origin());
}
// ============ Internal Functions ============
/**
* @notice Sets the ISM to be used for the specified origin domain
* @param _domain The origin domain
* @param _module The ISM to use to verify messages
*/
function _set(uint32 _domain, address _module) internal {
require(_module.isContract(), "!contract");
_modules.set(_domain, _module.addressToBytes32());
emit ModuleSet(_domain, _module);
}
}