Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- MerkleTreeHook
- Optimization enabled
- true
- Compiler version
- v0.8.19+commit.7dd6d404
- Optimization runs
- 999999
- EVM Version
- default
- Verified at
- 2024-11-06T11:09:39.529557Z
Constructor Arguments
0x00000000000000000000000033db966328ea213b0f76ef96ca368ab37779f065
Arg [0] (address) : 0x33db966328ea213b0f76ef96ca368ab37779f065
contracts/hooks/MerkleTreeHook.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /*@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ HYPERLANE @@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@*/ import {MerkleLib} from "../libs/Merkle.sol"; import {Message} from "../libs/Message.sol"; import {MailboxClient} from "../client/MailboxClient.sol"; import {Indexed} from "../libs/Indexed.sol"; import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol"; import {AbstractPostDispatchHook} from "./libs/AbstractPostDispatchHook.sol"; import {StandardHookMetadata} from "./libs/StandardHookMetadata.sol"; contract MerkleTreeHook is AbstractPostDispatchHook, MailboxClient, Indexed { using Message for bytes; using MerkleLib for MerkleLib.Tree; using StandardHookMetadata for bytes; // An incremental merkle tree used to store outbound message IDs. MerkleLib.Tree internal _tree; event InsertedIntoTree(bytes32 messageId, uint32 index); constructor(address _mailbox) MailboxClient(_mailbox) {} // count cannot exceed 2**TREE_DEPTH, see MerkleLib.sol function count() public view returns (uint32) { return uint32(_tree.count); } function root() public view returns (bytes32) { return _tree.root(); } function tree() public view returns (MerkleLib.Tree memory) { return _tree; } function latestCheckpoint() external view returns (bytes32, uint32) { return (root(), count() - 1); } // ============ External Functions ============ /// @inheritdoc IPostDispatchHook function hookType() external pure override returns (uint8) { return uint8(IPostDispatchHook.Types.MERKLE_TREE); } // ============ Internal Functions ============ /// @inheritdoc AbstractPostDispatchHook function _postDispatch( bytes calldata, /*metadata*/ bytes calldata message ) internal override { require(msg.value == 0, "MerkleTreeHook: no value expected"); // ensure messages which were not dispatched are not inserted into the tree bytes32 id = message.id(); require(_isLatestDispatched(id), "message not dispatching"); uint32 index = count(); _tree.insert(id); emit InsertedIntoTree(id, index); } /// @inheritdoc AbstractPostDispatchHook function _quoteDispatch( bytes calldata, /*metadata*/ bytes calldata /*message*/ ) internal pure override returns (uint256) { return 0; } }
@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
@openzeppelin/contracts/utils/Address.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
contracts/PackageVersioned.sol
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; /** * @title PackageVersioned * @notice Package version getter for contracts **/ abstract contract PackageVersioned { // GENERATED CODE - DO NOT EDIT string public constant PACKAGE_VERSION = "5.7.0"; }
contracts/client/MailboxClient.sol
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; /*@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ HYPERLANE @@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@*/ // ============ Internal Imports ============ import {IMailbox} from "../interfaces/IMailbox.sol"; import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol"; import {IInterchainSecurityModule} from "../interfaces/IInterchainSecurityModule.sol"; import {Message} from "../libs/Message.sol"; import {PackageVersioned} from "../PackageVersioned.sol"; // ============ External Imports ============ import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; abstract contract MailboxClient is OwnableUpgradeable, PackageVersioned { using Message for bytes; event HookSet(address _hook); event IsmSet(address _ism); IMailbox public immutable mailbox; uint32 public immutable localDomain; IPostDispatchHook public hook; IInterchainSecurityModule public interchainSecurityModule; uint256[48] private __GAP; // gap for upgrade safety // ============ Modifiers ============ modifier onlyContract(address _contract) { require( Address.isContract(_contract), "MailboxClient: invalid mailbox" ); _; } modifier onlyContractOrNull(address _contract) { require( Address.isContract(_contract) || _contract == address(0), "MailboxClient: invalid contract setting" ); _; } /** * @notice Only accept messages from an Hyperlane Mailbox contract */ modifier onlyMailbox() { require( msg.sender == address(mailbox), "MailboxClient: sender not mailbox" ); _; } constructor(address _mailbox) onlyContract(_mailbox) { mailbox = IMailbox(_mailbox); localDomain = mailbox.localDomain(); _transferOwnership(msg.sender); } /** * @notice Sets the address of the application's custom hook. * @param _hook The address of the hook contract. */ function setHook( address _hook ) public virtual onlyContractOrNull(_hook) onlyOwner { hook = IPostDispatchHook(_hook); emit HookSet(_hook); } /** * @notice Sets the address of the application's custom interchain security module. * @param _module The address of the interchain security module contract. */ function setInterchainSecurityModule( address _module ) public onlyContractOrNull(_module) onlyOwner { interchainSecurityModule = IInterchainSecurityModule(_module); emit IsmSet(_module); } // ======== Initializer ========= function _MailboxClient_initialize( address _hook, address _interchainSecurityModule, address _owner ) internal onlyInitializing { __Ownable_init(); setHook(_hook); setInterchainSecurityModule(_interchainSecurityModule); _transferOwnership(_owner); } function _isLatestDispatched(bytes32 id) internal view returns (bool) { return mailbox.latestDispatchedId() == id; } function _isDelivered(bytes32 id) internal view returns (bool) { return mailbox.delivered(id); } }
contracts/hooks/libs/AbstractPostDispatchHook.sol
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; /*@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ HYPERLANE @@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@*/ // ============ Internal Imports ============ import {StandardHookMetadata} from "./StandardHookMetadata.sol"; import {IPostDispatchHook} from "../../interfaces/hooks/IPostDispatchHook.sol"; import {PackageVersioned} from "../../PackageVersioned.sol"; /** * @title AbstractPostDispatch * @notice Abstract post dispatch hook supporting the current global hook metadata variant. */ abstract contract AbstractPostDispatchHook is IPostDispatchHook, PackageVersioned { using StandardHookMetadata for bytes; // ============ External functions ============ /// @inheritdoc IPostDispatchHook function supportsMetadata( bytes calldata metadata ) public pure virtual override returns (bool) { return metadata.length == 0 || metadata.variant() == StandardHookMetadata.VARIANT; } /// @inheritdoc IPostDispatchHook function postDispatch( bytes calldata metadata, bytes calldata message ) external payable override { require( supportsMetadata(metadata), "AbstractPostDispatchHook: invalid metadata variant" ); _postDispatch(metadata, message); } /// @inheritdoc IPostDispatchHook function quoteDispatch( bytes calldata metadata, bytes calldata message ) public view override returns (uint256) { require( supportsMetadata(metadata), "AbstractPostDispatchHook: invalid metadata variant" ); return _quoteDispatch(metadata, message); } // ============ Internal functions ============ /** * @notice Post dispatch hook implementation. * @param metadata The metadata of the message being dispatched. * @param message The message being dispatched. */ function _postDispatch( bytes calldata metadata, bytes calldata message ) internal virtual; /** * @notice Quote dispatch hook implementation. * @param metadata The metadata of the message being dispatched. * @param message The message being dispatched. * @return The quote for the dispatch. */ function _quoteDispatch( bytes calldata metadata, bytes calldata message ) internal view virtual returns (uint256); }
contracts/hooks/libs/StandardHookMetadata.sol
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; /*@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ HYPERLANE @@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@*/ /** * Format of metadata: * * [0:2] variant * [2:34] msg.value * [34:66] Gas limit for message (IGP) * [66:86] Refund address for message (IGP) * [86:] Custom metadata */ library StandardHookMetadata { struct Metadata { uint16 variant; uint256 msgValue; uint256 gasLimit; address refundAddress; } uint8 private constant VARIANT_OFFSET = 0; uint8 private constant MSG_VALUE_OFFSET = 2; uint8 private constant GAS_LIMIT_OFFSET = 34; uint8 private constant REFUND_ADDRESS_OFFSET = 66; uint256 private constant MIN_METADATA_LENGTH = 86; uint16 public constant VARIANT = 1; /** * @notice Returns the variant of the metadata. * @param _metadata ABI encoded standard hook metadata. * @return variant of the metadata as uint8. */ function variant(bytes calldata _metadata) internal pure returns (uint16) { if (_metadata.length < VARIANT_OFFSET + 2) return 0; return uint16(bytes2(_metadata[VARIANT_OFFSET:VARIANT_OFFSET + 2])); } /** * @notice Returns the specified value for the message. * @param _metadata ABI encoded standard hook metadata. * @param _default Default fallback value. * @return Value for the message as uint256. */ function msgValue( bytes calldata _metadata, uint256 _default ) internal pure returns (uint256) { if (_metadata.length < MSG_VALUE_OFFSET + 32) return _default; return uint256(bytes32(_metadata[MSG_VALUE_OFFSET:MSG_VALUE_OFFSET + 32])); } /** * @notice Returns the specified gas limit for the message. * @param _metadata ABI encoded standard hook metadata. * @param _default Default fallback gas limit. * @return Gas limit for the message as uint256. */ function gasLimit( bytes calldata _metadata, uint256 _default ) internal pure returns (uint256) { if (_metadata.length < GAS_LIMIT_OFFSET + 32) return _default; return uint256(bytes32(_metadata[GAS_LIMIT_OFFSET:GAS_LIMIT_OFFSET + 32])); } /** * @notice Returns the specified refund address for the message. * @param _metadata ABI encoded standard hook metadata. * @param _default Default fallback refund address. * @return Refund address for the message as address. */ function refundAddress( bytes calldata _metadata, address _default ) internal pure returns (address) { if (_metadata.length < REFUND_ADDRESS_OFFSET + 20) return _default; return address( bytes20( _metadata[REFUND_ADDRESS_OFFSET:REFUND_ADDRESS_OFFSET + 20] ) ); } /** * @notice Returns any custom metadata. * @param _metadata ABI encoded standard hook metadata. * @return Custom metadata. */ function getCustomMetadata( bytes calldata _metadata ) internal pure returns (bytes calldata) { if (_metadata.length < MIN_METADATA_LENGTH) return _metadata[0:0]; return _metadata[MIN_METADATA_LENGTH:]; } /** * @notice Formats the specified gas limit and refund address into standard hook metadata. * @param _msgValue msg.value for the message. * @param _gasLimit Gas limit for the message. * @param _refundAddress Refund address for the message. * @param _customMetadata Additional metadata to include in the standard hook metadata. * @return ABI encoded standard hook metadata. */ function formatMetadata( uint256 _msgValue, uint256 _gasLimit, address _refundAddress, bytes memory _customMetadata ) internal pure returns (bytes memory) { return abi.encodePacked( VARIANT, _msgValue, _gasLimit, _refundAddress, _customMetadata ); } /** * @notice Formats the specified gas limit and refund address into standard hook metadata. * @param _msgValue msg.value for the message. * @return ABI encoded standard hook metadata. */ function overrideMsgValue( uint256 _msgValue ) internal view returns (bytes memory) { return formatMetadata(_msgValue, uint256(0), msg.sender, ""); } /** * @notice Formats the specified gas limit and refund address into standard hook metadata. * @param _gasLimit Gas limit for the message. * @return ABI encoded standard hook metadata. */ function overrideGasLimit( uint256 _gasLimit ) internal view returns (bytes memory) { return formatMetadata(uint256(0), _gasLimit, msg.sender, ""); } /** * @notice Formats the specified refund address into standard hook metadata. * @param _refundAddress Refund address for the message. * @return ABI encoded standard hook metadata. */ function overrideRefundAddress( address _refundAddress ) internal pure returns (bytes memory) { return formatMetadata(uint256(0), uint256(0), _refundAddress, ""); } }
contracts/interfaces/IInterchainSecurityModule.sol
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; interface IInterchainSecurityModule { enum Types { UNUSED, ROUTING, AGGREGATION, LEGACY_MULTISIG, MERKLE_ROOT_MULTISIG, MESSAGE_ID_MULTISIG, NULL, // used with relayer carrying no metadata CCIP_READ, ARB_L2_TO_L1, WEIGHTED_MERKLE_ROOT_MULTISIG, WEIGHTED_MESSAGE_ID_MULTISIG, OP_L2_TO_L1 } /** * @notice Returns an enum that represents the type of security model * encoded by this ISM. * @dev Relayers infer how to fetch and format metadata. */ function moduleType() external view returns (uint8); /** * @notice Defines a security model responsible for verifying interchain * messages based on the provided metadata. * @param _metadata Off-chain metadata provided by a relayer, specific to * the security model encoded by the module (e.g. validator signatures) * @param _message Hyperlane encoded interchain message * @return True if the message was verified */ function verify( bytes calldata _metadata, bytes calldata _message ) external returns (bool); } interface ISpecifiesInterchainSecurityModule { function interchainSecurityModule() external view returns (IInterchainSecurityModule); }
contracts/interfaces/IMailbox.sol
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; import {IInterchainSecurityModule} from "./IInterchainSecurityModule.sol"; import {IPostDispatchHook} from "./hooks/IPostDispatchHook.sol"; interface IMailbox { // ============ Events ============ /** * @notice Emitted when a new message is dispatched via Hyperlane * @param sender The address that dispatched the message * @param destination The destination domain of the message * @param recipient The message recipient address on `destination` * @param message Raw bytes of message */ event Dispatch( address indexed sender, uint32 indexed destination, bytes32 indexed recipient, bytes message ); /** * @notice Emitted when a new message is dispatched via Hyperlane * @param messageId The unique message identifier */ event DispatchId(bytes32 indexed messageId); /** * @notice Emitted when a Hyperlane message is processed * @param messageId The unique message identifier */ event ProcessId(bytes32 indexed messageId); /** * @notice Emitted when a Hyperlane message is delivered * @param origin The origin domain of the message * @param sender The message sender address on `origin` * @param recipient The address that handled the message */ event Process( uint32 indexed origin, bytes32 indexed sender, address indexed recipient ); function localDomain() external view returns (uint32); function delivered(bytes32 messageId) external view returns (bool); function defaultIsm() external view returns (IInterchainSecurityModule); function defaultHook() external view returns (IPostDispatchHook); function requiredHook() external view returns (IPostDispatchHook); function latestDispatchedId() external view returns (bytes32); function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody ) external payable returns (bytes32 messageId); function quoteDispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody ) external view returns (uint256 fee); function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata body, bytes calldata defaultHookMetadata ) external payable returns (bytes32 messageId); function quoteDispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody, bytes calldata defaultHookMetadata ) external view returns (uint256 fee); function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata body, bytes calldata customHookMetadata, IPostDispatchHook customHook ) external payable returns (bytes32 messageId); function quoteDispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody, bytes calldata customHookMetadata, IPostDispatchHook customHook ) external view returns (uint256 fee); function process( bytes calldata metadata, bytes calldata message ) external payable; function recipientIsm( address recipient ) external view returns (IInterchainSecurityModule module); }
contracts/interfaces/hooks/IPostDispatchHook.sol
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; /*@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ HYPERLANE @@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@*/ interface IPostDispatchHook { enum Types { UNUSED, ROUTING, AGGREGATION, MERKLE_TREE, INTERCHAIN_GAS_PAYMASTER, FALLBACK_ROUTING, ID_AUTH_ISM, PAUSABLE, PROTOCOL_FEE, LAYER_ZERO_V1, RATE_LIMITED, ARB_L2_TO_L1, OP_L2_TO_L1 } /** * @notice Returns an enum that represents the type of hook */ function hookType() external view returns (uint8); /** * @notice Returns whether the hook supports metadata * @param metadata metadata * @return Whether the hook supports metadata */ function supportsMetadata( bytes calldata metadata ) external view returns (bool); /** * @notice Post action after a message is dispatched via the Mailbox * @param metadata The metadata required for the hook * @param message The message passed from the Mailbox.dispatch() call */ function postDispatch( bytes calldata metadata, bytes calldata message ) external payable; /** * @notice Compute the payment required by the postDispatch call * @param metadata The metadata required for the hook * @param message The message passed from the Mailbox.dispatch() call * @return Quoted payment for the postDispatch call */ function quoteDispatch( bytes calldata metadata, bytes calldata message ) external view returns (uint256); }
contracts/libs/Indexed.sol
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; contract Indexed { uint256 public immutable deployedBlock; constructor() { deployedBlock = block.number; } }
contracts/libs/Merkle.sol
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; // work based on eth2 deposit contract, which is used under CC0-1.0 uint256 constant TREE_DEPTH = 32; uint256 constant MAX_LEAVES = 2 ** TREE_DEPTH - 1; /** * @title MerkleLib * @author Celo Labs Inc. * @notice An incremental merkle tree modeled on the eth2 deposit contract. **/ library MerkleLib { /** * @notice Struct representing incremental merkle tree. Contains current * branch and the number of inserted leaves in the tree. **/ struct Tree { bytes32[TREE_DEPTH] branch; uint256 count; } /** * @notice Inserts `_node` into merkle tree * @dev Reverts if tree is full * @param _node Element to insert into tree **/ function insert(Tree storage _tree, bytes32 _node) internal { require(_tree.count < MAX_LEAVES, "merkle tree full"); _tree.count += 1; uint256 size = _tree.count; for (uint256 i = 0; i < TREE_DEPTH; i++) { if ((size & 1) == 1) { _tree.branch[i] = _node; return; } _node = keccak256(abi.encodePacked(_tree.branch[i], _node)); size /= 2; } // As the loop should always end prematurely with the `return` statement, // this code should be unreachable. We assert `false` just to be safe. assert(false); } /** * @notice Calculates and returns`_tree`'s current root given array of zero * hashes * @param _zeroes Array of zero hashes * @return _current Calculated root of `_tree` **/ function rootWithCtx( Tree storage _tree, bytes32[TREE_DEPTH] memory _zeroes ) internal view returns (bytes32 _current) { uint256 _index = _tree.count; for (uint256 i = 0; i < TREE_DEPTH; i++) { uint256 _ithBit = (_index >> i) & 0x01; bytes32 _next = _tree.branch[i]; if (_ithBit == 1) { _current = keccak256(abi.encodePacked(_next, _current)); } else { _current = keccak256(abi.encodePacked(_current, _zeroes[i])); } } } /// @notice Calculates and returns`_tree`'s current root function root(Tree storage _tree) internal view returns (bytes32) { return rootWithCtx(_tree, zeroHashes()); } /// @notice Returns array of TREE_DEPTH zero hashes /// @return _zeroes Array of TREE_DEPTH zero hashes function zeroHashes() internal pure returns (bytes32[TREE_DEPTH] memory _zeroes) { _zeroes[0] = Z_0; _zeroes[1] = Z_1; _zeroes[2] = Z_2; _zeroes[3] = Z_3; _zeroes[4] = Z_4; _zeroes[5] = Z_5; _zeroes[6] = Z_6; _zeroes[7] = Z_7; _zeroes[8] = Z_8; _zeroes[9] = Z_9; _zeroes[10] = Z_10; _zeroes[11] = Z_11; _zeroes[12] = Z_12; _zeroes[13] = Z_13; _zeroes[14] = Z_14; _zeroes[15] = Z_15; _zeroes[16] = Z_16; _zeroes[17] = Z_17; _zeroes[18] = Z_18; _zeroes[19] = Z_19; _zeroes[20] = Z_20; _zeroes[21] = Z_21; _zeroes[22] = Z_22; _zeroes[23] = Z_23; _zeroes[24] = Z_24; _zeroes[25] = Z_25; _zeroes[26] = Z_26; _zeroes[27] = Z_27; _zeroes[28] = Z_28; _zeroes[29] = Z_29; _zeroes[30] = Z_30; _zeroes[31] = Z_31; } /** * @notice Calculates and returns the merkle root for the given leaf * `_item`, a merkle branch, and the index of `_item` in the tree. * @param _item Merkle leaf * @param _branch Merkle proof * @param _index Index of `_item` in tree * @return _current Calculated merkle root **/ function branchRoot( bytes32 _item, bytes32[TREE_DEPTH] memory _branch, // cheaper than calldata indexing uint256 _index ) internal pure returns (bytes32 _current) { _current = _item; for (uint256 i = 0; i < TREE_DEPTH; i++) { uint256 _ithBit = (_index >> i) & 0x01; // cheaper than calldata indexing _branch[i*32:(i+1)*32]; bytes32 _next = _branch[i]; if (_ithBit == 1) { _current = keccak256(abi.encodePacked(_next, _current)); } else { _current = keccak256(abi.encodePacked(_current, _next)); } } } /** * @notice Calculates and returns the merkle root as if the index is * the topmost leaf in the tree. * @param _item Merkle leaf * @param _branch Merkle proof * @param _index Index of `_item` in tree * @dev Replaces siblings greater than the index (right subtrees) with zeroes. * @return _current Calculated merkle root **/ function reconstructRoot( bytes32 _item, bytes32[TREE_DEPTH] memory _branch, // cheaper than calldata indexing uint256 _index ) internal pure returns (bytes32 _current) { _current = _item; bytes32[TREE_DEPTH] memory _zeroes = zeroHashes(); for (uint256 i = 0; i < TREE_DEPTH; i++) { uint256 _ithBit = (_index >> i) & 0x01; // cheaper than calldata indexing _branch[i*32:(i+1)*32]; if (_ithBit == 1) { _current = keccak256(abi.encodePacked(_branch[i], _current)); } else { // remove right subtree from proof _current = keccak256(abi.encodePacked(_current, _zeroes[i])); } } } // keccak256 zero hashes bytes32 internal constant Z_0 = hex"0000000000000000000000000000000000000000000000000000000000000000"; bytes32 internal constant Z_1 = hex"ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5"; bytes32 internal constant Z_2 = hex"b4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30"; bytes32 internal constant Z_3 = hex"21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85"; bytes32 internal constant Z_4 = hex"e58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344"; bytes32 internal constant Z_5 = hex"0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d"; bytes32 internal constant Z_6 = hex"887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968"; bytes32 internal constant Z_7 = hex"ffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83"; bytes32 internal constant Z_8 = hex"9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af"; bytes32 internal constant Z_9 = hex"cefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0"; bytes32 internal constant Z_10 = hex"f9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5"; bytes32 internal constant Z_11 = hex"f8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892"; bytes32 internal constant Z_12 = hex"3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c"; bytes32 internal constant Z_13 = hex"c1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb"; bytes32 internal constant Z_14 = hex"5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc"; bytes32 internal constant Z_15 = hex"da7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d2"; bytes32 internal constant Z_16 = hex"2733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981f"; bytes32 internal constant Z_17 = hex"e1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a"; bytes32 internal constant Z_18 = hex"5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0"; bytes32 internal constant Z_19 = hex"b46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0"; bytes32 internal constant Z_20 = hex"c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2"; bytes32 internal constant Z_21 = hex"f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd9"; bytes32 internal constant Z_22 = hex"5a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e377"; bytes32 internal constant Z_23 = hex"4df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652"; bytes32 internal constant Z_24 = hex"cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef"; bytes32 internal constant Z_25 = hex"0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d"; bytes32 internal constant Z_26 = hex"b8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d0"; bytes32 internal constant Z_27 = hex"838c5655cb21c6cb83313b5a631175dff4963772cce9108188b34ac87c81c41e"; bytes32 internal constant Z_28 = hex"662ee4dd2dd7b2bc707961b1e646c4047669dcb6584f0d8d770daf5d7e7deb2e"; bytes32 internal constant Z_29 = hex"388ab20e2573d171a88108e79d820e98f26c0b84aa8b2f4aa4968dbb818ea322"; bytes32 internal constant Z_30 = hex"93237c50ba75ee485f4c22adf2f741400bdf8d6a9cc7df7ecae576221665d735"; bytes32 internal constant Z_31 = hex"8448818bb4ae4562849e949e17ac16e0be16688e156b5cf15e098c627c0056a9"; }
contracts/libs/Message.sol
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; import {TypeCasts} from "./TypeCasts.sol"; /** * @title Hyperlane Message Library * @notice Library for formatted messages used by Mailbox **/ library Message { using TypeCasts for bytes32; uint256 private constant VERSION_OFFSET = 0; uint256 private constant NONCE_OFFSET = 1; uint256 private constant ORIGIN_OFFSET = 5; uint256 private constant SENDER_OFFSET = 9; uint256 private constant DESTINATION_OFFSET = 41; uint256 private constant RECIPIENT_OFFSET = 45; uint256 private constant BODY_OFFSET = 77; /** * @notice Returns formatted (packed) Hyperlane message with provided fields * @dev This function should only be used in memory message construction. * @param _version The version of the origin and destination Mailboxes * @param _nonce A nonce to uniquely identify the message on its origin chain * @param _originDomain Domain of origin chain * @param _sender Address of sender as bytes32 * @param _destinationDomain Domain of destination chain * @param _recipient Address of recipient on destination chain as bytes32 * @param _messageBody Raw bytes of message body * @return Formatted message */ function formatMessage( uint8 _version, uint32 _nonce, uint32 _originDomain, bytes32 _sender, uint32 _destinationDomain, bytes32 _recipient, bytes calldata _messageBody ) internal pure returns (bytes memory) { return abi.encodePacked( _version, _nonce, _originDomain, _sender, _destinationDomain, _recipient, _messageBody ); } /** * @notice Returns the message ID. * @param _message ABI encoded Hyperlane message. * @return ID of `_message` */ function id(bytes memory _message) internal pure returns (bytes32) { return keccak256(_message); } /** * @notice Returns the message version. * @param _message ABI encoded Hyperlane message. * @return Version of `_message` */ function version(bytes calldata _message) internal pure returns (uint8) { return uint8(bytes1(_message[VERSION_OFFSET:NONCE_OFFSET])); } /** * @notice Returns the message nonce. * @param _message ABI encoded Hyperlane message. * @return Nonce of `_message` */ function nonce(bytes calldata _message) internal pure returns (uint32) { return uint32(bytes4(_message[NONCE_OFFSET:ORIGIN_OFFSET])); } /** * @notice Returns the message origin domain. * @param _message ABI encoded Hyperlane message. * @return Origin domain of `_message` */ function origin(bytes calldata _message) internal pure returns (uint32) { return uint32(bytes4(_message[ORIGIN_OFFSET:SENDER_OFFSET])); } /** * @notice Returns the message sender as bytes32. * @param _message ABI encoded Hyperlane message. * @return Sender of `_message` as bytes32 */ function sender(bytes calldata _message) internal pure returns (bytes32) { return bytes32(_message[SENDER_OFFSET:DESTINATION_OFFSET]); } /** * @notice Returns the message sender as address. * @param _message ABI encoded Hyperlane message. * @return Sender of `_message` as address */ function senderAddress( bytes calldata _message ) internal pure returns (address) { return sender(_message).bytes32ToAddress(); } /** * @notice Returns the message destination domain. * @param _message ABI encoded Hyperlane message. * @return Destination domain of `_message` */ function destination( bytes calldata _message ) internal pure returns (uint32) { return uint32(bytes4(_message[DESTINATION_OFFSET:RECIPIENT_OFFSET])); } /** * @notice Returns the message recipient as bytes32. * @param _message ABI encoded Hyperlane message. * @return Recipient of `_message` as bytes32 */ function recipient( bytes calldata _message ) internal pure returns (bytes32) { return bytes32(_message[RECIPIENT_OFFSET:BODY_OFFSET]); } /** * @notice Returns the message recipient as address. * @param _message ABI encoded Hyperlane message. * @return Recipient of `_message` as address */ function recipientAddress( bytes calldata _message ) internal pure returns (address) { return recipient(_message).bytes32ToAddress(); } /** * @notice Returns the message body. * @param _message ABI encoded Hyperlane message. * @return Body of `_message` */ function body( bytes calldata _message ) internal pure returns (bytes calldata) { return bytes(_message[BODY_OFFSET:]); } }
contracts/libs/TypeCasts.sol
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; library TypeCasts { // alignment preserving cast function addressToBytes32(address _addr) internal pure returns (bytes32) { return bytes32(uint256(uint160(_addr))); } // alignment preserving cast function bytes32ToAddress(bytes32 _buf) internal pure returns (address) { require( uint256(_buf) <= uint256(type(uint160).max), "TypeCasts: bytes32ToAddress overflow" ); return address(uint160(uint256(_buf))); } }
Compiler Settings
{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata"],"":["ast"]}},"optimizer":{"runs":999999,"enabled":true},"libraries":{}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_mailbox","internalType":"address"}]},{"type":"event","name":"HookSet","inputs":[{"type":"address","name":"_hook","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"type":"uint8","name":"version","internalType":"uint8","indexed":false}],"anonymous":false},{"type":"event","name":"InsertedIntoTree","inputs":[{"type":"bytes32","name":"messageId","internalType":"bytes32","indexed":false},{"type":"uint32","name":"index","internalType":"uint32","indexed":false}],"anonymous":false},{"type":"event","name":"IsmSet","inputs":[{"type":"address","name":"_ism","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"PACKAGE_VERSION","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"count","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedBlock","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IPostDispatchHook"}],"name":"hook","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"hookType","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IInterchainSecurityModule"}],"name":"interchainSecurityModule","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"},{"type":"uint32","name":"","internalType":"uint32"}],"name":"latestCheckpoint","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"localDomain","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IMailbox"}],"name":"mailbox","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"postDispatch","inputs":[{"type":"bytes","name":"metadata","internalType":"bytes"},{"type":"bytes","name":"message","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"quoteDispatch","inputs":[{"type":"bytes","name":"metadata","internalType":"bytes"},{"type":"bytes","name":"message","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"root","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setHook","inputs":[{"type":"address","name":"_hook","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setInterchainSecurityModule","inputs":[{"type":"address","name":"_module","internalType":"address"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsMetadata","inputs":[{"type":"bytes","name":"metadata","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct MerkleLib.Tree","components":[{"type":"bytes32[32]","name":"branch","internalType":"bytes32[32]"},{"type":"uint256","name":"count","internalType":"uint256"}]}],"name":"tree","inputs":[]}]
Contract Creation Code
0x60e06040523480156200001157600080fd5b5060405162001bc838038062001bc8833981016040819052620000349162000176565b80806001600160a01b0381163b620000925760405162461bcd60e51b815260206004820152601e60248201527f4d61696c626f78436c69656e743a20696e76616c6964206d61696c626f780000604482015260640160405180910390fd5b6001600160a01b03821660808190526040805163234d8e3d60e21b81529051638d3638f4916004808201926020929091908290030181865afa158015620000dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001039190620001a8565b63ffffffff1660a052620001173362000124565b50504360c05250620001d0565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000602082840312156200018957600080fd5b81516001600160a01b0381168114620001a157600080fd5b9392505050565b600060208284031215620001bb57600080fd5b815163ffffffff81168114620001a157600080fd5b60805160a05160c0516119c1620002076000396000610242015260006102840152600081816103880152610ce601526119c16000f3fe6080604052600436106101445760003560e01c8063907c0f92116100c0578063e445e7dd11610074578063ebf0c71711610059578063ebf0c7171461042e578063f2fde38b14610443578063fd54b2281461046357600080fd5b8063e445e7dd146103d7578063e5320bb9146103fe57600080fd5b8063aaccd230116100a5578063aaccd23014610356578063d5438eae14610376578063de523cf3146103aa57600080fd5b8063907c0f92146102d157806393c448471461030057600080fd5b8063715018a61161011757806382ea7bfe116100fc57806382ea7bfe146102305780638d3638f4146102725780638da5cb5b146102a657600080fd5b8063715018a6146101c95780637f5a7c7b146101de57600080fd5b806306661abd14610149578063086011b9146101745780630e72cc06146101895780633dfd3873146101a9575b600080fd5b34801561015557600080fd5b5060b7545b60405163ffffffff90911681526020015b60405180910390f35b6101876101823660046114d9565b610485565b005b34801561019557600080fd5b506101876101a4366004611545565b610532565b3480156101b557600080fd5b506101876101c4366004611545565b61067b565b3480156101d557600080fd5b506101876107bc565b3480156101ea57600080fd5b5060655461020b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161016b565b34801561023c57600080fd5b506102647f000000000000000000000000000000000000000000000000000000000000000081565b60405190815260200161016b565b34801561027e57600080fd5b5061015a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102b257600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff1661020b565b3480156102dd57600080fd5b506102e66107d0565b6040805192835263ffffffff90911660208301520161016b565b34801561030c57600080fd5b506103496040518060400160405280600581526020017f352e372e3000000000000000000000000000000000000000000000000000000081525081565b60405161016b9190611582565b34801561036257600080fd5b506102646103713660046114d9565b6107f8565b34801561038257600080fd5b5061020b7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103b657600080fd5b5060665461020b9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103e357600080fd5b506103ec61089b565b60405160ff909116815260200161016b565b34801561040a57600080fd5b5061041e6104193660046115ee565b6108a5565b604051901515815260200161016b565b34801561043a57600080fd5b506102646108ca565b34801561044f57600080fd5b5061018761045e366004611545565b6108d6565b34801561046f57600080fd5b5061047861098d565b60405161016b9190611630565b61048f84846108a5565b610520576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4162737472616374506f73744469737061746368486f6f6b3a20696e76616c6960448201527f64206d657461646174612076617269616e74000000000000000000000000000060648201526084015b60405180910390fd5b61052c848484846109dc565b50505050565b8073ffffffffffffffffffffffffffffffffffffffff81163b15158061056c575073ffffffffffffffffffffffffffffffffffffffff8116155b6105f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d61696c626f78436c69656e743a20696e76616c696420636f6e74726163742060448201527f73657474696e67000000000000000000000000000000000000000000000000006064820152608401610517565b610600610b7a565b606680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091556040519081527fc47cbcc588c67679e52261c45cc315e56562f8d0ccaba16facb9093ff9498799906020015b60405180910390a15050565b8073ffffffffffffffffffffffffffffffffffffffff81163b1515806106b5575073ffffffffffffffffffffffffffffffffffffffff8116155b610741576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d61696c626f78436c69656e743a20696e76616c696420636f6e74726163742060448201527f73657474696e67000000000000000000000000000000000000000000000000006064820152608401610517565b610749610b7a565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091556040519081527f4eab7b127c764308788622363ad3e9532de3dfba7845bd4f84c125a22544255a9060200161066f565b6107c4610b7a565b6107ce6000610bfb565b565b6000806107db6108ca565b60016107e660b75490565b6107f091906116a2565b915091509091565b600061080485856108a5565b610890576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4162737472616374506f73744469737061746368486f6f6b3a20696e76616c6960448201527f64206d657461646174612076617269616e7400000000000000000000000000006064820152608401610517565b600095945050505050565b600060035b905090565b60008115806108c1575060016108bb8484610c72565b61ffff16145b90505b92915050565b60006108a06097610cc3565b6108de610b7a565b73ffffffffffffffffffffffffffffffffffffffff8116610981576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610517565b61098a81610bfb565b50565b610995611451565b60408051610440810180835290916097918391820190839060209082845b8154815260200190600101908083116109b3575050509183525050602091820154910152919050565b3415610a6a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4d65726b6c6554726565486f6f6b3a206e6f2076616c7565206578706563746560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610517565b6000610aab83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610cd692505050565b9050610ab681610ce1565b610b1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f6d657373616765206e6f74206469737061746368696e670000000000000000006044820152606401610517565b6000610b2760b75490565b9050610b34609783610d7a565b6040805183815263ffffffff831660208201527f253a3a04cab70d47c1504809242d9350cd81627b4f1d50753e159cf8cd76ed33910160405180910390a1505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146107ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610517565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000610c7f8160026116c6565b60ff16821015610c91575060006108c4565b82600083610ca08260026116c6565b60ff1692610cb0939291906116df565b610cb991611709565b60f01c9392505050565b60006108c482610cd1610ebe565b61137f565b805160209091012090565b6000817f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663134fbb4f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d73919061174f565b1492915050565b6001610d8860206002611888565b610d929190611894565b826020015410610dfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6d65726b6c6520747265652066756c6c000000000000000000000000000000006044820152606401610517565b6001826020016000828254610e1391906118a7565b9091555050602082015460005b6020811015610eb05781600116600103610e4f5782848260208110610e4757610e476118ba565b015550505050565b838160208110610e6157610e616118ba565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250600282610e9c91906118e9565b915080610ea881611924565b915050610e20565b50610eb961195c565b505050565b610ec6611471565b600081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb560208201527fb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d3060408201527f21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba8560608201527fe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a1934460808201527f0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d60a08201527f887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a196860c08201527fffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f8360e08201527f9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af6101008201527fcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e06101208201527ff9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a56101408201527ff8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf8926101608201527f3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c6101808201527fc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb6101a08201527f5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc6101c08201527fda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d26101e08201527f2733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981f6102008201527fe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a6102208201527f5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a06102408201527fb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa06102608201527fc65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e26102808201527ff4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd96102a08201527f5a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3776102c08201527f4df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee6526102e08201527fcdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef6103008201527f0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d6103208201527fb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d06103408201527f838c5655cb21c6cb83313b5a631175dff4963772cce9108188b34ac87c81c41e6103608201527f662ee4dd2dd7b2bc707961b1e646c4047669dcb6584f0d8d770daf5d7e7deb2e6103808201527f388ab20e2573d171a88108e79d820e98f26c0b84aa8b2f4aa4968dbb818ea3226103a08201527f93237c50ba75ee485f4c22adf2f741400bdf8d6a9cc7df7ecae576221665d7356103c08201527f8448818bb4ae4562849e949e17ac16e0be16688e156b5cf15e098c627c0056a96103e082015290565b6020820154600090815b602081101561144957600182821c1660008683602081106113ac576113ac6118ba565b01549050816001036113e9576040805160208101839052908101869052606001604051602081830303815290604052805190602001209450611434565b848684602081106113fc576113fc6118ba565b602002015160405160200161141b929190918252602082015260400190565b6040516020818303038152906040528051906020012094505b5050808061144190611924565b915050611389565b505092915050565b6040518060400160405280611464611471565b8152602001600081525090565b6040518061040001604052806020906020820280368337509192915050565b60008083601f8401126114a257600080fd5b50813567ffffffffffffffff8111156114ba57600080fd5b6020830191508360208285010111156114d257600080fd5b9250929050565b600080600080604085870312156114ef57600080fd5b843567ffffffffffffffff8082111561150757600080fd5b61151388838901611490565b9096509450602087013591508082111561152c57600080fd5b5061153987828801611490565b95989497509550505050565b60006020828403121561155757600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461157b57600080fd5b9392505050565b600060208083528351808285015260005b818110156115af57858101830151858201604001528201611593565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6000806020838503121561160157600080fd5b823567ffffffffffffffff81111561161857600080fd5b61162485828601611490565b90969095509350505050565b81516104208201908260005b602080821061164b575061165f565b83518352928301929091019060010161163c565b505050602083015161040083015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff8281168282160390808211156116bf576116bf611673565b5092915050565b60ff81811683821601908111156108c4576108c4611673565b600080858511156116ef57600080fd5b838611156116fc57600080fd5b5050820193919092039150565b7fffff00000000000000000000000000000000000000000000000000000000000081358181169160028510156114495760029490940360031b84901b1690921692915050565b60006020828403121561176157600080fd5b5051919050565b600181815b808511156117c157817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156117a7576117a7611673565b808516156117b457918102915b93841c939080029061176d565b509250929050565b6000826117d8575060016108c4565b816117e5575060006108c4565b81600181146117fb576002811461180557611821565b60019150506108c4565b60ff84111561181657611816611673565b50506001821b6108c4565b5060208310610133831016604e8410600b8410161715611844575081810a6108c4565b61184e8383611768565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561188057611880611673565b029392505050565b60006108c183836117c9565b818103818111156108c4576108c4611673565b808201808211156108c4576108c4611673565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008261191f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361195557611955611673565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea2646970667358221220df12990d8579f79afbcb459d3736d2d07f53d2104287442b7dbf9803c512e0c364736f6c6343000813003300000000000000000000000033db966328ea213b0f76ef96ca368ab37779f065
Deployed ByteCode
0x6080604052600436106101445760003560e01c8063907c0f92116100c0578063e445e7dd11610074578063ebf0c71711610059578063ebf0c7171461042e578063f2fde38b14610443578063fd54b2281461046357600080fd5b8063e445e7dd146103d7578063e5320bb9146103fe57600080fd5b8063aaccd230116100a5578063aaccd23014610356578063d5438eae14610376578063de523cf3146103aa57600080fd5b8063907c0f92146102d157806393c448471461030057600080fd5b8063715018a61161011757806382ea7bfe116100fc57806382ea7bfe146102305780638d3638f4146102725780638da5cb5b146102a657600080fd5b8063715018a6146101c95780637f5a7c7b146101de57600080fd5b806306661abd14610149578063086011b9146101745780630e72cc06146101895780633dfd3873146101a9575b600080fd5b34801561015557600080fd5b5060b7545b60405163ffffffff90911681526020015b60405180910390f35b6101876101823660046114d9565b610485565b005b34801561019557600080fd5b506101876101a4366004611545565b610532565b3480156101b557600080fd5b506101876101c4366004611545565b61067b565b3480156101d557600080fd5b506101876107bc565b3480156101ea57600080fd5b5060655461020b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161016b565b34801561023c57600080fd5b506102647f000000000000000000000000000000000000000000000000000000000003d7b881565b60405190815260200161016b565b34801561027e57600080fd5b5061015a7f0000000000000000000000000000000000000000000000000000000041786f6e81565b3480156102b257600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff1661020b565b3480156102dd57600080fd5b506102e66107d0565b6040805192835263ffffffff90911660208301520161016b565b34801561030c57600080fd5b506103496040518060400160405280600581526020017f352e372e3000000000000000000000000000000000000000000000000000000081525081565b60405161016b9190611582565b34801561036257600080fd5b506102646103713660046114d9565b6107f8565b34801561038257600080fd5b5061020b7f00000000000000000000000033db966328ea213b0f76ef96ca368ab37779f06581565b3480156103b657600080fd5b5060665461020b9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103e357600080fd5b506103ec61089b565b60405160ff909116815260200161016b565b34801561040a57600080fd5b5061041e6104193660046115ee565b6108a5565b604051901515815260200161016b565b34801561043a57600080fd5b506102646108ca565b34801561044f57600080fd5b5061018761045e366004611545565b6108d6565b34801561046f57600080fd5b5061047861098d565b60405161016b9190611630565b61048f84846108a5565b610520576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4162737472616374506f73744469737061746368486f6f6b3a20696e76616c6960448201527f64206d657461646174612076617269616e74000000000000000000000000000060648201526084015b60405180910390fd5b61052c848484846109dc565b50505050565b8073ffffffffffffffffffffffffffffffffffffffff81163b15158061056c575073ffffffffffffffffffffffffffffffffffffffff8116155b6105f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d61696c626f78436c69656e743a20696e76616c696420636f6e74726163742060448201527f73657474696e67000000000000000000000000000000000000000000000000006064820152608401610517565b610600610b7a565b606680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091556040519081527fc47cbcc588c67679e52261c45cc315e56562f8d0ccaba16facb9093ff9498799906020015b60405180910390a15050565b8073ffffffffffffffffffffffffffffffffffffffff81163b1515806106b5575073ffffffffffffffffffffffffffffffffffffffff8116155b610741576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d61696c626f78436c69656e743a20696e76616c696420636f6e74726163742060448201527f73657474696e67000000000000000000000000000000000000000000000000006064820152608401610517565b610749610b7a565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091556040519081527f4eab7b127c764308788622363ad3e9532de3dfba7845bd4f84c125a22544255a9060200161066f565b6107c4610b7a565b6107ce6000610bfb565b565b6000806107db6108ca565b60016107e660b75490565b6107f091906116a2565b915091509091565b600061080485856108a5565b610890576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4162737472616374506f73744469737061746368486f6f6b3a20696e76616c6960448201527f64206d657461646174612076617269616e7400000000000000000000000000006064820152608401610517565b600095945050505050565b600060035b905090565b60008115806108c1575060016108bb8484610c72565b61ffff16145b90505b92915050565b60006108a06097610cc3565b6108de610b7a565b73ffffffffffffffffffffffffffffffffffffffff8116610981576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610517565b61098a81610bfb565b50565b610995611451565b60408051610440810180835290916097918391820190839060209082845b8154815260200190600101908083116109b3575050509183525050602091820154910152919050565b3415610a6a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4d65726b6c6554726565486f6f6b3a206e6f2076616c7565206578706563746560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610517565b6000610aab83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610cd692505050565b9050610ab681610ce1565b610b1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f6d657373616765206e6f74206469737061746368696e670000000000000000006044820152606401610517565b6000610b2760b75490565b9050610b34609783610d7a565b6040805183815263ffffffff831660208201527f253a3a04cab70d47c1504809242d9350cd81627b4f1d50753e159cf8cd76ed33910160405180910390a1505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146107ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610517565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000610c7f8160026116c6565b60ff16821015610c91575060006108c4565b82600083610ca08260026116c6565b60ff1692610cb0939291906116df565b610cb991611709565b60f01c9392505050565b60006108c482610cd1610ebe565b61137f565b805160209091012090565b6000817f00000000000000000000000033db966328ea213b0f76ef96ca368ab37779f06573ffffffffffffffffffffffffffffffffffffffff1663134fbb4f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d73919061174f565b1492915050565b6001610d8860206002611888565b610d929190611894565b826020015410610dfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6d65726b6c6520747265652066756c6c000000000000000000000000000000006044820152606401610517565b6001826020016000828254610e1391906118a7565b9091555050602082015460005b6020811015610eb05781600116600103610e4f5782848260208110610e4757610e476118ba565b015550505050565b838160208110610e6157610e616118ba565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250600282610e9c91906118e9565b915080610ea881611924565b915050610e20565b50610eb961195c565b505050565b610ec6611471565b600081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb560208201527fb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d3060408201527f21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba8560608201527fe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a1934460808201527f0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d60a08201527f887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a196860c08201527fffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f8360e08201527f9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af6101008201527fcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e06101208201527ff9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a56101408201527ff8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf8926101608201527f3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c6101808201527fc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb6101a08201527f5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc6101c08201527fda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d26101e08201527f2733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981f6102008201527fe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a6102208201527f5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a06102408201527fb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa06102608201527fc65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e26102808201527ff4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd96102a08201527f5a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3776102c08201527f4df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee6526102e08201527fcdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef6103008201527f0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d6103208201527fb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d06103408201527f838c5655cb21c6cb83313b5a631175dff4963772cce9108188b34ac87c81c41e6103608201527f662ee4dd2dd7b2bc707961b1e646c4047669dcb6584f0d8d770daf5d7e7deb2e6103808201527f388ab20e2573d171a88108e79d820e98f26c0b84aa8b2f4aa4968dbb818ea3226103a08201527f93237c50ba75ee485f4c22adf2f741400bdf8d6a9cc7df7ecae576221665d7356103c08201527f8448818bb4ae4562849e949e17ac16e0be16688e156b5cf15e098c627c0056a96103e082015290565b6020820154600090815b602081101561144957600182821c1660008683602081106113ac576113ac6118ba565b01549050816001036113e9576040805160208101839052908101869052606001604051602081830303815290604052805190602001209450611434565b848684602081106113fc576113fc6118ba565b602002015160405160200161141b929190918252602082015260400190565b6040516020818303038152906040528051906020012094505b5050808061144190611924565b915050611389565b505092915050565b6040518060400160405280611464611471565b8152602001600081525090565b6040518061040001604052806020906020820280368337509192915050565b60008083601f8401126114a257600080fd5b50813567ffffffffffffffff8111156114ba57600080fd5b6020830191508360208285010111156114d257600080fd5b9250929050565b600080600080604085870312156114ef57600080fd5b843567ffffffffffffffff8082111561150757600080fd5b61151388838901611490565b9096509450602087013591508082111561152c57600080fd5b5061153987828801611490565b95989497509550505050565b60006020828403121561155757600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461157b57600080fd5b9392505050565b600060208083528351808285015260005b818110156115af57858101830151858201604001528201611593565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6000806020838503121561160157600080fd5b823567ffffffffffffffff81111561161857600080fd5b61162485828601611490565b90969095509350505050565b81516104208201908260005b602080821061164b575061165f565b83518352928301929091019060010161163c565b505050602083015161040083015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff8281168282160390808211156116bf576116bf611673565b5092915050565b60ff81811683821601908111156108c4576108c4611673565b600080858511156116ef57600080fd5b838611156116fc57600080fd5b5050820193919092039150565b7fffff00000000000000000000000000000000000000000000000000000000000081358181169160028510156114495760029490940360031b84901b1690921692915050565b60006020828403121561176157600080fd5b5051919050565b600181815b808511156117c157817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156117a7576117a7611673565b808516156117b457918102915b93841c939080029061176d565b509250929050565b6000826117d8575060016108c4565b816117e5575060006108c4565b81600181146117fb576002811461180557611821565b60019150506108c4565b60ff84111561181657611816611673565b50506001821b6108c4565b5060208310610133831016604e8410600b8410161715611844575081810a6108c4565b61184e8383611768565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561188057611880611673565b029392505050565b60006108c183836117c9565b818103818111156108c4576108c4611673565b808201808211156108c4576108c4611673565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008261191f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361195557611955611673565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea2646970667358221220df12990d8579f79afbcb459d3736d2d07f53d2104287442b7dbf9803c512e0c364736f6c63430008130033