ETH Price: $2,292.10 (-6.16%)

Contract

0x9707bfE566f883a1C1b6fBADC01E4eD7bC3DE7D4

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Submit Vote4272947482026-01-31 22:35:0127 hrs ago1769898901IN
0x9707bfE5...7bC3DE7D4
0.0002103 ETH0.000004150.021324
Submit Vote4223598472026-01-17 16:14:4615 days ago1768666486IN
0x9707bfE5...7bC3DE7D4
0.00019606 ETH0.000003930.020204
Withdraw4144376302025-12-25 18:16:2438 days ago1766686584IN
0x9707bfE5...7bC3DE7D4
0.00020927 ETH0.000001970.01
Withdraw4140234942025-12-24 13:34:3839 days ago1766583278IN
0x9707bfE5...7bC3DE7D4
0.00020927 ETH0.000014150.071719
Submit Vote4127073152025-12-20 18:19:4743 days ago1766254787IN
0x9707bfE5...7bC3DE7D4
0.00020927 ETH0.000001940.01
Submit Vote4030119772025-11-22 18:00:3771 days ago1763834437IN
0x9707bfE5...7bC3DE7D4
0.00020145 ETH0.000001970.01
Withdraw3981632132025-11-08 17:29:0285 days ago1762622942IN
0x9707bfE5...7bC3DE7D4
0.00018812 ETH0.0000020.01
Claim Rewards3962567952025-11-03 5:17:5090 days ago1762147070IN
0x9707bfE5...7bC3DE7D4
0.00016256 ETH0.000002450.01023
Submit Vote3887160082025-10-12 10:10:55112 days ago1760263855IN
0x9707bfE5...7bC3DE7D4
0.00016142 ETH0.00000510.025803
Claim Rewards3855943082025-10-03 9:46:12121 days ago1759484772IN
0x9707bfE5...7bC3DE7D4
0.00014005 ETH0.000002440.01
Exit Early3845905502025-09-30 12:09:28124 days ago1759234168IN
0x9707bfE5...7bC3DE7D4
0.00015303 ETH0.000002030.01
Claim Rewards3845903102025-09-30 12:08:28124 days ago1759234108IN
0x9707bfE5...7bC3DE7D4
0.00015303 ETH0.00000280.01
Withdraw3840298252025-09-28 21:16:00126 days ago1759094160IN
0x9707bfE5...7bC3DE7D4
0.00015303 ETH0.000002050.01
Submit Vote3835971962025-09-27 15:15:41127 days ago1758986141IN
0x9707bfE5...7bC3DE7D4
0.00015303 ETH0.000015560.079784
Claim Rewards3812546702025-09-20 20:54:39134 days ago1758401679IN
0x9707bfE5...7bC3DE7D4
0.00013878 ETH0.000002460.01
Withdraw3812537442025-09-20 20:50:48134 days ago1758401448IN
0x9707bfE5...7bC3DE7D4
0.00013878 ETH0.000001970.01
Claim Rewards3805187162025-09-18 17:49:20136 days ago1758217760IN
0x9707bfE5...7bC3DE7D4
0.00013878 ETH0.000003360.01
Withdraw3805177222025-09-18 17:45:13136 days ago1758217513IN
0x9707bfE5...7bC3DE7D4
0.00013878 ETH0.000002190.01
Claim Rewards3791912882025-09-14 21:39:07140 days ago1757885947IN
0x9707bfE5...7bC3DE7D4
0.00013878 ETH0.000002410.01
Withdraw3791909822025-09-14 21:37:51140 days ago1757885871IN
0x9707bfE5...7bC3DE7D4
0.00013878 ETH0.0000020.01
Submit Vote3787196422025-09-13 12:50:48141 days ago1757767848IN
0x9707bfE5...7bC3DE7D4
0.00013878 ETH0.000001960.01
Withdraw3776875362025-09-10 13:12:13144 days ago1757509933IN
0x9707bfE5...7bC3DE7D4
0.00014148 ETH0.000002960.014821
Claim Rewards3754859852025-09-04 4:26:19150 days ago1756959979IN
0x9707bfE5...7bC3DE7D4
0.00013992 ETH0.000002510.01
Claim Rewards3740397512025-08-31 0:06:38155 days ago1756598798IN
0x9707bfE5...7bC3DE7D4
0.0001584 ETH0.000002460.01
Submit Vote3739698802025-08-30 19:15:30155 days ago1756581330IN
0x9707bfE5...7bC3DE7D4
0.0001584 ETH0.000002030.01
View all transactions

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
4272947482026-01-31 22:35:0127 hrs ago1769898901
0x9707bfE5...7bC3DE7D4
0.0002103 ETH
4223598472026-01-17 16:14:4615 days ago1768666486
0x9707bfE5...7bC3DE7D4
0.00019606 ETH
4144376302025-12-25 18:16:2438 days ago1766686584
0x9707bfE5...7bC3DE7D4
0.00020927 ETH
4140234942025-12-24 13:34:3839 days ago1766583278
0x9707bfE5...7bC3DE7D4
0.00020927 ETH
4127073152025-12-20 18:19:4743 days ago1766254787
0x9707bfE5...7bC3DE7D4
0.00020927 ETH
4030119772025-11-22 18:00:3771 days ago1763834437
0x9707bfE5...7bC3DE7D4
0.00020145 ETH
3981632132025-11-08 17:29:0285 days ago1762622942
0x9707bfE5...7bC3DE7D4
0.00018812 ETH
3962567952025-11-03 5:17:5090 days ago1762147070
0x9707bfE5...7bC3DE7D4
0.00016256 ETH
3887160082025-10-12 10:10:55112 days ago1760263855
0x9707bfE5...7bC3DE7D4
0.00016142 ETH
3855943082025-10-03 9:46:12121 days ago1759484772
0x9707bfE5...7bC3DE7D4
0.00014005 ETH
3845905502025-09-30 12:09:28124 days ago1759234168
0x9707bfE5...7bC3DE7D4
0.00015303 ETH
3845903102025-09-30 12:08:28124 days ago1759234108
0x9707bfE5...7bC3DE7D4
0.00015303 ETH
3840298252025-09-28 21:16:00126 days ago1759094160
0x9707bfE5...7bC3DE7D4
0.00015303 ETH
3835971962025-09-27 15:15:41127 days ago1758986141
0x9707bfE5...7bC3DE7D4
0.00015303 ETH
3812546702025-09-20 20:54:39134 days ago1758401679
0x9707bfE5...7bC3DE7D4
0.00013878 ETH
3812537442025-09-20 20:50:48134 days ago1758401448
0x9707bfE5...7bC3DE7D4
0.00013878 ETH
3805187162025-09-18 17:49:20136 days ago1758217760
0x9707bfE5...7bC3DE7D4
0.00013878 ETH
3805177222025-09-18 17:45:13136 days ago1758217513
0x9707bfE5...7bC3DE7D4
0.00013878 ETH
3791912882025-09-14 21:39:07140 days ago1757885947
0x9707bfE5...7bC3DE7D4
0.00013878 ETH
3791909822025-09-14 21:37:51140 days ago1757885871
0x9707bfE5...7bC3DE7D4
0.00013878 ETH
3787196422025-09-13 12:50:48141 days ago1757767848
0x9707bfE5...7bC3DE7D4
0.00013878 ETH
3776875362025-09-10 13:12:13144 days ago1757509933
0x9707bfE5...7bC3DE7D4
0.00014148 ETH
3754859852025-09-04 4:26:19150 days ago1756959979
0x9707bfE5...7bC3DE7D4
0.00013992 ETH
3740397512025-08-31 0:06:38155 days ago1756598798
0x9707bfE5...7bC3DE7D4
0.0001584 ETH
3739698802025-08-30 19:15:30155 days ago1756581330
0x9707bfE5...7bC3DE7D4
0.0001584 ETH
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SpokeBridge

Compiler Version
v0.8.25+commit.b61c2a91

Optimization Enabled:
Yes with 200 runs

Other Settings:
cancun EvmVersion
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {IGateway} from "../interfaces/IGateway.sol";
import {TimeKeeper} from "../common/TimeKeeper.sol";
import {Bridge} from "../common/Bridge.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

contract SpokeBridge is TimeKeeper, Bridge {
    using SafeERC20 for IERC20;

    /// @notice xCLEAR address on the Hub
    address public immutable hubCLEAR;

    /// @notice WETH address on the Hub
    address public immutable hubWETH;

    constructor(
        uint32 _everclearId,
        address _clear,
        address _xClear,
        address _lockbox,
        address _gateway,
        address _owner,
        address _hubCLEAR,
        address _hubWETH
    ) Bridge(_everclearId, _gateway, _xClear, _clear, _lockbox, _owner) {
        if (_hubCLEAR == address(0)) revert ZeroAddress();
        if (_hubWETH == address(0)) revert ZeroAddress();

        hubCLEAR = _hubCLEAR;
        hubWETH = _hubWETH;
    }

    /////////////////////////////// Admin Functions ////////////////////////////////
    /**
     * @notice Admin function to bridge xCLEAR to Hub and send to a recipient
     * @param _amount The amount of xCLEAR to bridge
     * @param _receiver address to receive xCLEAR
     * @param _gasLimit gas limit to use for Hyperlane
     * @return _messageId from Hyperlane
     * @return _feeSpent gas fee spent
     */
    function adminBridge(uint128 _amount, address _receiver, uint256 _gasLimit)
        external
        payable
        onlyOwner
        returns (bytes32 _messageId, uint256 _feeSpent)
    {
        _bridgeOut(msg.sender, _amount);
        bytes32 _sender = _toBytes32(msg.sender);
        bytes memory _message = abi.encode(1, _sender, _amount, _receiver);
        (_messageId, _feeSpent) = gateway.sendMessage{value: msg.value}(EVERCLEAR_ID, _message, _gasLimit);
    }

    /**
     * @notice Update the local mailbox address
     * @param _newMailbox The new mailbox address
     */
    function updateMailbox(address _newMailbox) external onlyOwner {
        if (_newMailbox == address(0)) revert ZeroAddress();
        gateway.updateMailbox(_newMailbox);
    }

    /**
     * @notice Update the interchain security module address
     * @param _newSecurityModule The new security module address
     */
    function updateSecurityModule(address _newSecurityModule) external onlyOwner {
        if (_newSecurityModule == address(0)) revert ZeroAddress();
        gateway.updateSecurityModule(_newSecurityModule);
    }

    /////////////////////////////// Public Functions ////////////////////////////////
    /**
     * @notice Execute increase lock position on vbCLEAR from Spoke
     * @dev User will need to call with msg.value for fee which should = _fee + ((_fee * _bufferBPS)
     * @param _additionalAmountToLock The additional amount to lock
     * @param _expiry expiry time for the lock
     * @param _gasLimit gas limit to use for Hyperlane
     * @return _messageId from Hyperlane
     * @return _feeSpent gas fee spent
     */
    function increaseLockPosition(uint128 _additionalAmountToLock, uint128 _expiry, uint256 _gasLimit)
        external
        payable
        returns (bytes32 _messageId, uint256 _feeSpent)
    {
        if (!_isValidWeekTime(_expiry)) revert InvalidWeekTime(_expiry);
        if (_isTimeInThePast(_expiry)) revert ExpiryInThePast(_expiry);
        if (_expiry > block.timestamp + MAX_LOCK_TIME) revert ExceededMaxLockTime();
        if (_expiry < block.timestamp + MIN_LOCK_TIME) revert InsufficientLockTime();

        _bridgeOut(msg.sender, _additionalAmountToLock);
        bytes32 _sender = _toBytes32(msg.sender);
        bytes memory _message = abi.encode(2, _sender, _additionalAmountToLock, _expiry);
        (_messageId, _feeSpent) = gateway.sendMessage{value: msg.value}(EVERCLEAR_ID, _message, _gasLimit);
    }

    /**
     * @notice Execute withdraw on vbCLEAR from Spoke
     * @param _domain The domain to withdraw from
     * @param _gasLimit gas limit to use for Hyperlane
     * @return _messageId from Hyperlane
     * @return _feeSpent gas fee spent
     */
    function withdraw(uint32 _domain, uint256 _gasLimit)
        external
        payable
        returns (bytes32 _messageId, uint256 _feeSpent)
    {
        bytes32 _sender = _toBytes32(msg.sender);
        bytes memory _message = abi.encode(3, _sender, _domain);
        (_messageId, _feeSpent) = gateway.sendMessage{value: msg.value}(EVERCLEAR_ID, _message, _gasLimit);
    }

    /**
     * @notice Execute delegate on vbCLEAR from Spoke
     * @param _delegate The address to delegate to
     * @param _gasLimit gas limit to use for Hyperlane
     * @return _messageId from Hyperlane
     * @return _feeSpent gas fee spent
     */
    function delegate(bytes32 _delegate, uint256 _gasLimit)
        external
        payable
        returns (bytes32 _messageId, uint256 _feeSpent)
    {
        bytes32 _sender = _toBytes32(msg.sender);
        bytes memory _message = abi.encode(4, _sender, _delegate);
        (_messageId, _feeSpent) = gateway.sendMessage{value: msg.value}(EVERCLEAR_ID, _message, _gasLimit);
    }

    /**
     * @notice Execute exit early on vbCLEAR from Spoke
     * @param _amountToUnlock The amount to unlock
     * @param _domain The domain to unlock from
     * @param _gasLimit gas limit to use for Hyperlane
     * @return _messageId from Hyperlane
     * @return _feeSpent gas fee spent
     */
    function exitEarly(uint128 _amountToUnlock, uint32 _domain, uint256 _gasLimit)
        external
        payable
        returns (bytes32 _messageId, uint256 _feeSpent)
    {
        bytes32 _sender = _toBytes32(msg.sender);
        bytes memory _message = abi.encode(5, _sender, _amountToUnlock, _domain);
        (_messageId, _feeSpent) = gateway.sendMessage{value: msg.value}(EVERCLEAR_ID, _message, _gasLimit);
    }

    /**
     * @notice Execute vote on HubGauge from Spoke
     * @param _domain The domain to vote on
     * @param _gasLimit gas limit to use for Hyperlane
     * @return _messageId from Hyperlane
     * @return _feeSpent gas fee spent
     */
    function submitVote(uint32 _domain, uint256 _gasLimit)
        external
        payable
        returns (bytes32 _messageId, uint256 _feeSpent)
    {
        bytes32 _sender = _toBytes32(msg.sender);
        bytes memory _message = abi.encode(6, _sender, _domain);
        (_messageId, _feeSpent) = gateway.sendMessage{value: msg.value}(EVERCLEAR_ID, _message, _gasLimit);
    }

    /**
     * @notice Execute delegated vote on HubGauge from Spoke
     * @param _grantors The grantors to vote on behalf of
     * @param _domain The domain to vote on
     * @param _gasLimit gas limit to use for Hyperlane
     * @return _messageId from Hyperlane
     * @return _feeSpent gas fee spent
     */
    function submitDelegatedVote(bytes32[] calldata _grantors, uint32 _domain, uint256 _gasLimit)
        external
        payable
        returns (bytes32 _messageId, uint256 _feeSpent)
    {
        bytes32 _sender = _toBytes32(msg.sender);
        bytes memory _message = abi.encode(7, _sender, _grantors, _domain);
        (_messageId, _feeSpent) = gateway.sendMessage{value: msg.value}(EVERCLEAR_ID, _message, _gasLimit);
    }

    /**
     * @notice Execute claim rewards on RewardDistributor from Spoke
     * @param _claim The claim to execute
     * @param _domain The domain to claim xCLEAR to
     * @param _gasLimit gas limit to use for Hyperlane
     * @return _messageId from Hyperlane
     * @return _feeSpent gas fee spent
     */
    function claimRewards(Claim[] memory _claim, uint32 _domain, address _receiver, uint256 _gasLimit)
        external
        payable
        returns (bytes32 _messageId, uint256 _feeSpent)
    {
        if (_claim.length == 0) revert InvalidInput();
        if (_receiver == address(0)) revert ZeroAddress();
        bytes32 _sender = _toBytes32(msg.sender);
        _claim = _rewriteClaim(_sender, _claim);
        bytes memory _message = abi.encode(8, _sender, _claim, _domain, _receiver);
        (_messageId, _feeSpent) = gateway.sendMessage{value: msg.value}(EVERCLEAR_ID, _message, _gasLimit);
    }

    /**
     * @notice Receive message from HubBridge via Hyperlane
     * @dev All messages will be bridgeIn xCLEAR to receiver from withdraw, exitEarly, or claimRewards tx's
     * that were originally executed from SpokeBridge
     * @param _message The message to receive
     */
    function receiveMessage(bytes memory _message) external onlyGateway {
        (bytes32 _receiverBytes, uint128 _amount) = abi.decode(_message, (bytes32, uint128));
        address _receiverAddress = _toAddress(_receiverBytes);
        _bridgeIn(_receiverAddress, _amount);
    }

    /////////////////////////////// Internal Functions ////////////////////////////////
    /**
     * @notice Rewrites the account for the claim to the msg.sender and ensures tokens valid
     * @param _sender msg.sender to use for rewrite
     * @param _claim The claim to rewrite
     */
    function _rewriteClaim(bytes32 _sender, Claim[] memory _claim) internal view returns (Claim[] memory) {
        for (uint256 i = 0; i < _claim.length; i++) {
            address _currentToken = _claim[i].token;
            if (_currentToken != hubWETH && _currentToken != hubCLEAR) revert InvalidToken();
            _claim[i].account = _sender;
        }

        return _claim;
    }

    /**
     * @notice Using Yul to pack command and address into single slot
     * @dev Command is from the function calling this and used on HubBridge to route the action
     * @param _command The command to pack
     */
    function _buildCommand(uint8 _command) private view returns (bytes32 _senderWithCommand) {
        assembly {
            _senderWithCommand := add(shl(mul(31, 8), _command), caller())
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {IMessageReceiver} from "./IMessageReceiver.sol";
import {IMailbox} from "@hyperlane/interfaces/IMailbox.sol";

interface IGateway {
    /*///////////////////////////////////////////////////////////////
                              EVENTS
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Emitted when the mailbox is updated
     * @param _oldMailbox The old mailbox address
     * @param _newMailbox The new mailbox address
     */
    event MailboxUpdated(address _oldMailbox, address _newMailbox);

    /**
     * @notice Emitted when the security module is updated
     * @param _oldSecurityModule The old security module address
     * @param _newSecurityModule The new security module address
     */
    event SecurityModuleUpdated(address _oldSecurityModule, address _newSecurityModule);

    /*///////////////////////////////////////////////////////////////
                              ERRORS
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Thrown when the message origin is invalid
     */
    error Gateway_Handle_InvalidOriginDomain();

    /**
     * @notice Thrown when the sender is not the appropriate remote Gateway
     */
    error Gateway_Handle_InvalidSender();

    /**
     * @notice Thrown when the caller is not the local mailbox
     */
    error Gateway_Handle_NotCalledByMailbox();

    /**
     * @notice Thrown when the GasTank does not have enough native asset to cover the fee
     */
    error Gateway_SendMessage_InsufficientBalance();

    /**
     * @notice Thrown when the message dispatcher is not the local receiver
     */
    error Gateway_SendMessage_UnauthorizedCaller();

    /**
     * @notice Thrown when the call returning the unused fee fails
     */
    error Gateway_SendMessage_UnsuccessfulRebate();

    /**
     * @notice Thrown when an address equals the address zero
     */
    error Gateway_ZeroAddress();

    /*///////////////////////////////////////////////////////////////
                              LOGIC
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Send a message to the transport layer using the gas tank
     * @param _chainId The id of the destination chain
     * @param _message The message to send
     * @param _fee The fee to send the message
     * @param _gasLimit The gas limit to use on destination
     * @return _messageId The id message of the transport layer
     * @return _feeSpent The fee spent to send the message
     * @dev only called by the spoke contract
     */
    function sendMessage(uint32 _chainId, bytes memory _message, uint256 _fee, uint256 _gasLimit)
        external
        returns (bytes32 _messageId, uint256 _feeSpent);

    /**
     * @notice Send a message to the transport layer
     * @param _chainId The id of the destination chain
     * @param _message The message to send
     * @param _gasLimit The gas limit to use on destination
     * @return _messageId The id message of the transport layer
     * @return _feeSpent The fee spent to send the message
     * @dev only called by the spoke contract
     */
    function sendMessage(uint32 _chainId, bytes memory _message, uint256 _gasLimit)
        external
        payable
        returns (bytes32 _messageId, uint256 _feeSpent);

    /**
     * @notice Updates the mailbox
     * @param _mailbox The new mailbox address
     * @dev only called by the `receiver`
     */
    function updateMailbox(address _mailbox) external;

    /**
     * @notice Updates the gateway security module
     * @param _securityModule The address of the new security module
     * @dev only called by the `receiver`
     */
    function updateSecurityModule(address _securityModule) external;

    /*///////////////////////////////////////////////////////////////
                              VIEWS
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Returns the transport layer message routing smart contract
     * @dev this is independent of the transport layer used, adopting mailbox name because its descriptive enough
     *      using address instead of specific interface to be independent from HL or any other TL
     * @return _mailbox The address of the mailbox
     */
    function mailbox() external view returns (IMailbox _mailbox);

    /**
     * @notice Returns the message receiver for this Gateway (EverclearHub / EverclearSpoke)
     * @return _receiver The message receiver
     */
    function receiver() external view returns (IMessageReceiver _receiver);

    /**
     * @notice Quotes cost of sending a message to the transport layer
     * @param _chainId The id of the destination chain
     * @param _message The message to send
     * @param _gasLimit The gas limit for delivering the message
     * @return _fee The fee to send the message
     */
    function quoteMessage(uint32 _chainId, bytes memory _message, uint256 _gasLimit)
        external
        view
        returns (uint256 _fee);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {ITimeKeeper} from "../interfaces/ITimeKeeper.sol";

abstract contract TimeKeeper is ITimeKeeper {
    uint128 public constant WEEK = 7 days;
    uint128 public constant MAX_LOCK_TIME = 730 days;
    uint128 public constant MIN_LOCK_TIME = 90 days;

    /**
     * @notice Checks if a timestamp is currently expired (less than or equal to the current block timestamp)
     * @param expiry The timestamp to check
     */
    function _isCurrentlyExpired(uint256 expiry) internal view returns (bool) {
        return (expiry <= block.timestamp);
    }

    /**
     * @notice Checks if a provided time equals 0 when modulo used with WEEK i.e. timestamp aligns with start of week
     * @param time The timestamp to check
     */
    function _isValidWeekTime(uint256 time) internal pure returns (bool) {
        return time % WEEK == 0;
    }

    /**
     * @notice Checks if a provided timestamp is in the past
     * @param timestamp The timestamp to check
     */
    function _isTimeInThePast(uint256 timestamp) internal view returns (bool) {
        return (timestamp <= block.timestamp); // same definition as isCurrentlyExpired
    }

    /**
     * @notice Returns the current week start timestamp
     */
    function _getCurrentWeekStart() internal view returns (uint128) {
        return _getWeekStartTimestamp(uint128(block.timestamp));
    }

    /**
     * @notice Returns the week start timestamp for a given timestamp
     * @param timestamp The timestamp to check
     */
    function _getWeekStartTimestamp(uint128 timestamp) internal pure returns (uint128) {
        return (timestamp / WEEK) * WEEK;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IXERC20} from "../interfaces/IXERC20.sol";
import {IXERC20Lockbox} from "../interfaces/IXERC20Lockbox.sol";
import {IBridge} from "../interfaces/IBridge.sol";
import {IGateway} from "../interfaces/IGateway.sol";
import "@openzeppelin/contracts/access/Ownable2Step.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {AddressConversion} from "./AddressConversion.sol";

abstract contract Bridge is Ownable2Step, AddressConversion, IBridge {
    using SafeERC20 for IERC20;

    /// @notice Chain id for Everclear roll-up
    uint32 public immutable EVERCLEAR_ID;

    /// @notice The origin ERC20 token on current chain if applicable (can be null)
    IERC20 public immutable CLEAR;

    /// @notice xCLEAR address on the current chain
    IXERC20 public immutable xCLEAR;

    /// @notice Lockbox address on the current chain (can be null)
    IXERC20Lockbox public immutable LOCKBOX;

    /// @notice Gateway address on the current chain
    IGateway public gateway;

    /// @notice Nonce used for errors
    uint128 internal nonce;

    /// @notice Error struct used for Bridge retries in abstract contract
    mapping(uint256 => Error) public errors;

    /// @notice Message gas limit stored by domain
    mapping(uint256 => uint256) public messageGasLimit;

    /// @notice Limits the caller to the gateway contract
    modifier onlyGateway() {
        if (msg.sender != address(gateway)) revert NotCalledByGateway();
        _;
    }

    constructor(
        uint32 _everclearId,
        address _gateway,
        address _xCLEAR,
        address _CLEAR,
        address _LOCKBOX,
        address _owner
    ) Ownable(_owner) {
        if (_xCLEAR == address(0)) revert ZeroAddress();

        EVERCLEAR_ID = _everclearId;
        gateway = IGateway(_gateway);
        xCLEAR = IXERC20(_xCLEAR);
        CLEAR = IERC20(_CLEAR);
        LOCKBOX = IXERC20Lockbox(_LOCKBOX);
    }
    /////////////////////////////// Admin Functions ////////////////////////////////
    /**
     * @notice Update the gateway address
     * @param _newGateway The new gateway address
     */

    function updateGateway(address _newGateway) external onlyOwner {
        address _oldGateway = address(gateway);
        gateway = IGateway(_newGateway);

        emit GatewayUpdated(_oldGateway, _newGateway);
    }

    /**
     * @notice Update the message gas limit for array of domains
     * @param _domain array of domains
     * @param _newGasLimit array of gas limits for each domain
     */
    function updateMessageGasLimit(uint256[] calldata _domain, uint256[] calldata _newGasLimit) external onlyOwner {
        if (_domain.length != _newGasLimit.length) revert InvalidInput();
        uint256[] memory _oldGasLimit = new uint256[](_domain.length);

        for (uint256 i; i < _domain.length; i++) {
            _oldGasLimit[i] = messageGasLimit[_domain[i]];
            messageGasLimit[_domain[i]] = _newGasLimit[i];
        }

        emit MessageGasLimitUpdated(_domain, _oldGasLimit, _newGasLimit);
    }

    /**
     * @notice Withdraw ETH from the contract to recipient
     * @dev Expect ETH to be in contract from users overpaying for the message and Gateway refund
     * @param _receiver The receiver address
     */
    function withdrawETH(address _receiver) external onlyOwner {
        (bool success,) = payable(_receiver).call{value: address(this).balance}("");
        if (!success) revert TransferFailed();
        emit WithdrawETH(_receiver, address(this).balance);
    }

    /////////////////////////////// Public Functions ////////////////////////////////
    /**
     * @notice Retry minting the xCLEAR token
     * @param _errorId The error id to retry
     */
    function retryMint(uint256 _errorId) external virtual {
        Error memory _error = errors[_errorId];
        delete errors[_errorId];

        if (_error.user == address(0)) revert NoErrorFound();

        emit RetryMint(_errorId, block.chainid, _error.user, _error.amount);
        _bridgeIn(_error.user, _error.amount);
    }

    /////////////////////////////// Internal Functions ////////////////////////////////
    /**
     * @notice Burn xCLEAR tokens
     * @param _user The user to burn tokens from
     * @param _amount The amount of tokens to burn
     */
    function _bridgeOut(address _user, uint256 _amount) internal virtual {
        // Lock CLEAR in lockbox and burn minted tokens.
        if (address(LOCKBOX) != address(0)) {
            CLEAR.safeTransferFrom(_user, address(this), _amount);
            CLEAR.approve(address(LOCKBOX), _amount);
            LOCKBOX.deposit(_amount);
            xCLEAR.burn(address(this), _amount);
        } else {
            xCLEAR.burn(_user, _amount);
        }
    }

    /**
     * @notice Mint xCLEAR tokens
     * @param _user The user to mint tokens to
     * @param _amount The amount of tokens to mint
     */
    function _bridgeIn(address _user, uint256 _amount) internal virtual {
        try xCLEAR.mint(address(this), _amount) {
            if (address(LOCKBOX) != address(0)) {
                LOCKBOX.withdraw(_amount);
                CLEAR.safeTransfer(_user, _amount);
            } else {
                IERC20(address(xCLEAR)).safeTransfer(_user, _amount);
            }
            emit BridgedIn(EVERCLEAR_ID, _user, _amount);
        } catch {
            uint256 _nonce = nonce;
            errors[_nonce] = Error(EVERCLEAR_ID, _user, _amount);
            nonce++;
            emit BridgeInError(_nonce, _user, _amount, block.timestamp);
        }
    }

    /**
     * @notice Received used when gateway sends refund back to this contract
     */
    receive() external payable {}
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    /**
     * @dev An operation with an ERC20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data);
        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

/**
 * @title IMessageReceiver
 * @notice Interface for the transport layer communication with the message receiver
 */
interface IMessageReceiver {
    /*///////////////////////////////////////////////////////////////
                              LOGIC
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Receive a message from the transport layer
     * @param _message The message to receive encoded as bytes
     * @dev This function should be called by the the gateway contract
     */
    function receiveMessage(bytes calldata _message) external;
}

// 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);
}

File 9 of 20 : ITimeKeeper.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

interface ITimeKeeper {
    error TimeInFuture();
    error ExceededMaxLockTime();
    error InsufficientLockTime();
    error InvalidWeekTime(uint256 _expiry);
    error ExpiryInThePast(uint256 _expiry);
    error InsufficientAmount(uint256 _amount);
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.4 <0.9.0;

interface IXERC20 {
    /**
     * @notice Emits when a lockbox is set
     *
     * @param _lockbox The address of the lockbox
     */
    event LockboxSet(address _lockbox);

    /**
     * @notice Emits when a limit is set
     *
     * @param _mintingLimit The updated minting limit we are setting to the bridge
     * @param _burningLimit The updated burning limit we are setting to the bridge
     * @param _bridge The address of the bridge we are setting the limit too
     */
    event BridgeLimitsSet(uint256 _mintingLimit, uint256 _burningLimit, address indexed _bridge);

    /**
     * @notice Reverts when a user with too low of a limit tries to call mint/burn
     */
    error IXERC20_NotHighEnoughLimits();

    /**
     * @notice Reverts when caller is not the factory
     */
    error IXERC20_NotFactory();

    /**
     * @notice Reverts when limits are too high
     */
    error IXERC20_LimitsTooHigh();

    /**
     * @notice Contains the full minting and burning data for a particular bridge
     *
     * @param minterParams The minting parameters for the bridge
     * @param burnerParams The burning parameters for the bridge
     */
    struct Bridge {
        BridgeParameters minterParams;
        BridgeParameters burnerParams;
    }

    /**
     * @notice Contains the mint or burn parameters for a bridge
     *
     * @param timestamp The timestamp of the last mint/burn
     * @param ratePerSecond The rate per second of the bridge
     * @param maxLimit The max limit of the bridge
     * @param currentLimit The current limit of the bridge
     */
    struct BridgeParameters {
        uint256 timestamp;
        uint256 ratePerSecond;
        uint256 maxLimit;
        uint256 currentLimit;
    }

    /**
     * @notice Sets the lockbox address
     *
     * @param _lockbox The address of the lockbox
     */
    function setLockbox(address _lockbox) external;

    /**
     * @notice Updates the limits of any bridge
     * @dev Can only be called by the owner
     * @param _mintingLimit The updated minting limit we are setting to the bridge
     * @param _burningLimit The updated burning limit we are setting to the bridge
     * @param _bridge The address of the bridge we are setting the limits too
     */
    function setLimits(address _bridge, uint256 _mintingLimit, uint256 _burningLimit) external;

    /**
     * @notice Returns the max limit of a minter
     *
     * @param _minter The minter we are viewing the limits of
     *  @return _limit The limit the minter has
     */
    function mintingMaxLimitOf(address _minter) external view returns (uint256 _limit);

    /**
     * @notice Returns the max limit of a bridge
     *
     * @param _bridge the bridge we are viewing the limits of
     * @return _limit The limit the bridge has
     */
    function burningMaxLimitOf(address _bridge) external view returns (uint256 _limit);

    /**
     * @notice Returns the current limit of a minter
     *
     * @param _minter The minter we are viewing the limits of
     * @return _limit The limit the minter has
     */
    function mintingCurrentLimitOf(address _minter) external view returns (uint256 _limit);

    /**
     * @notice Returns the current limit of a bridge
     *
     * @param _bridge the bridge we are viewing the limits of
     * @return _limit The limit the bridge has
     */
    function burningCurrentLimitOf(address _bridge) external view returns (uint256 _limit);

    /**
     * @notice Mints tokens for a user
     * @dev Can only be called by a minter
     * @param _user The address of the user who needs tokens minted
     * @param _amount The amount of tokens being minted
     */
    function mint(address _user, uint256 _amount) external;

    /**
     * @notice Burns tokens for a user
     * @dev Can only be called by a minter
     * @param _user The address of the user who needs tokens burned
     * @param _amount The amount of tokens being burned
     */
    function burn(address _user, uint256 _amount) external;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IXERC20Lockbox {
    /**
     * @notice Emitted when tokens are deposited into the lockbox
     */
    event Deposit(address _sender, uint256 _amount);

    /**
     * @notice Emitted when tokens are withdrawn from the lockbox
     */
    event Withdraw(address _sender, uint256 _amount);

    /**
     * @notice Reverts when a user tries to deposit native tokens on a non-native lockbox
     */
    error IXERC20Lockbox_NotNative();

    /**
     * @notice Reverts when a user tries to deposit non-native tokens on a native lockbox
     */
    error IXERC20Lockbox_Native();

    /**
     * @notice Reverts when a user tries to withdraw and the call fails
     */
    error IXERC20Lockbox_WithdrawFailed();

    /**
     * @notice Deposit ERC20 tokens into the lockbox
     *
     * @param _amount The amount of tokens to deposit
     */
    function deposit(uint256 _amount) external;

    /**
     * @notice Deposit ERC20 tokens into the lockbox, and send the XERC20 to a user
     *
     * @param _user The user to send the XERC20 to
     * @param _amount The amount of tokens to deposit
     */
    function depositTo(address _user, uint256 _amount) external;

    /**
     * @notice Deposit the native asset into the lockbox, and send the XERC20 to a user
     *
     * @param _user The user to send the XERC20 to
     */
    function depositNativeTo(address _user) external payable;

    /**
     * @notice Withdraw ERC20 tokens from the lockbox
     *
     * @param _amount The amount of tokens to withdraw
     */
    function withdraw(uint256 _amount) external;

    /**
     * @notice Withdraw ERC20 tokens from the lockbox
     *
     * @param _user The user to withdraw to
     * @param _amount The amount of tokens to withdraw
     */
    function withdrawTo(address _user, uint256 _amount) external;
}

File 12 of 20 : IBridge.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

interface IBridge {
    struct Error {
        uint256 chainId;
        address user;
        uint256 amount;
    }

    struct Claim {
        address token;
        bytes32 account;
        uint256 amount;
        bytes32[] merkleProof;
    }

    // Events
    event BridgedOut(uint256 dstChainId, address bridgeUser, address tokenReceiver, uint256 amount);
    event BridgedIn(uint256 srcChainId, bytes32 tokenReceiver, uint256 amount);
    event BridgedIn(uint256 srcChainId, address tokenReceiver, uint256 amount);
    event BridgeInError(uint256 errorId, address user, uint256 amount, uint256 timestamp);
    event BridgedLock(uint256 chainId, bytes32 receiver, uint128 amount, uint128 expiry);
    event BridgedLockError(uint256 errorId, address receiver, uint256 amount, uint256 expiry);
    event MessageGasLimitUpdated(uint256[] _domain, uint256[] oldGasLimit, uint256[] newGasLimit);
    event GatewayUpdated(address oldGateway, address newGateway);
    event RetryTransfer(uint256 errorId, uint256 chainId, bytes32 user, uint256 amount);
    event RetryMint(uint256 errorId, uint256 chainId, bytes32 user, uint256 amount);
    event RetryMint(uint256 errorId, uint256 chainId, address user, uint256 amount);
    event RetryLock(uint256 errorId, bytes32 receiver, uint256 amount, uint256 expiry);
    event RetryBridgeOut(uint256 errorId, bytes32 user, uint128 amount, uint32 domain);
    event RetryMessage(uint256 errorId, bytes32 user, uint128 amount, uint32 domain);
    event MintMessageSent(bytes32 sender, uint256 amount, uint32 domain, bytes32 messageId, uint256 feeSpent);
    event WithdrawETH(address receiver, uint256 amount);
    event ReturnFeeUpdated(uint256[] domain, uint256[] oldFee, uint256[] newFee);
    event ProcessError(uint256 nonce, uint8 id, bytes32 sender, uint256 amount, uint256 additionalData);
    event EthWithdrawn(address sender, uint256 amount, uint256 withdrawId);

    // Errors
    error ZeroAddress();
    error InvalidSender();
    error InvalidOriginDomain();
    error InvalidInput();
    error InvalidToken();
    error NoErrorFound();
    error NotCalledByMailbox();
    error NotCalledByGateway();
    error UnsupportedOperation();
    error NothingClaimed();
    error InvalidErrorId();
    error InvalidClaimLength();
    error TransferFailed();
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol)

pragma solidity ^0.8.20;

import {Ownable} from "./Ownable.sol";

/**
 * @dev Contract module which provides access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is specified at deployment time in the constructor for `Ownable`. This
 * can later be changed with {transferOwnership} and {acceptOwnership}.
 *
 * This module is used through inheritance. It will make available all functions
 * from parent (Ownable).
 */
abstract contract Ownable2Step is Ownable {
    address private _pendingOwner;

    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Returns the address of the pending owner.
     */
    function pendingOwner() public view virtual returns (address) {
        return _pendingOwner;
    }

    /**
     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual override onlyOwner {
        _pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner(), newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual override {
        delete _pendingOwner;
        super._transferOwnership(newOwner);
    }

    /**
     * @dev The new owner accepts the ownership transfer.
     */
    function acceptOwnership() public virtual {
        address sender = _msgSender();
        if (pendingOwner() != sender) {
            revert OwnableUnauthorizedAccount(sender);
        }
        _transferOwnership(sender);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

contract AddressConversion {
    /**
     * @notice Cast an address to a bytes32
     * @param _addr The address to cast
     * @dev Alignment presevering cast
     */
    function _toBytes32(address _addr) internal pure returns (bytes32) {
        return bytes32(uint256(uint160(_addr)));
    }

    /**
     * @notice Cast a bytes32 to an address
     * @param _buf The bytes32 to cast
     * @dev Alignment presevering cast
     */
    function _toAddress(bytes32 _buf) internal pure returns (address) {
        return address(uint160(uint256(_buf)));
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * ==== Security Considerations
 *
 * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
 * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
 * considered as an intention to spend the allowance in any specific way. The second is that because permits have
 * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
 * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
 * generally recommended is:
 *
 * ```solidity
 * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
 *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
 *     doThing(..., value);
 * }
 *
 * function doThing(..., uint256 value) public {
 *     token.safeTransferFrom(msg.sender, address(this), value);
 *     ...
 * }
 * ```
 *
 * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
 * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
 * {SafeERC20-safeTransferFrom}).
 *
 * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
 * contracts should have entry points that don't rely on permit.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     *
     * CAUTION: See Security Considerations above.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error AddressInsufficientBalance(address account);

    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedInnerCall();

    /**
     * @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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert AddressInsufficientBalance(address(this));
        }

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert FailedInnerCall();
        }
    }

    /**
     * @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 or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {FailedInnerCall} error.
     *
     * 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.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @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`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert AddressInsufficientBalance(address(this));
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
     * unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {FailedInnerCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
     */
    function _revert(bytes memory returndata) 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 FailedInnerCall();
        }
    }
}

// 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,
        WEIGHT_MERKLE_ROOT_MULTISIG,
        WEIGHT_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);
}

// 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);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.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.
 *
 * The initial owner is set to the address provided by the deployer. 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 Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @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 {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @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 {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _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);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @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 Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

Settings
{
  "remappings": [
    "@hyperlane/=node_modules/@hyperlane-xyz/core/contracts/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "ds-test/=lib/isolmate/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "isolmate/=lib/isolmate/src/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"uint32","name":"_everclearId","type":"uint32"},{"internalType":"address","name":"_clear","type":"address"},{"internalType":"address","name":"_xClear","type":"address"},{"internalType":"address","name":"_lockbox","type":"address"},{"internalType":"address","name":"_gateway","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_hubCLEAR","type":"address"},{"internalType":"address","name":"_hubWETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"ExceededMaxLockTime","type":"error"},{"inputs":[{"internalType":"uint256","name":"_expiry","type":"uint256"}],"name":"ExpiryInThePast","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"InsufficientAmount","type":"error"},{"inputs":[],"name":"InsufficientLockTime","type":"error"},{"inputs":[],"name":"InvalidClaimLength","type":"error"},{"inputs":[],"name":"InvalidErrorId","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[],"name":"InvalidOriginDomain","type":"error"},{"inputs":[],"name":"InvalidSender","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[{"internalType":"uint256","name":"_expiry","type":"uint256"}],"name":"InvalidWeekTime","type":"error"},{"inputs":[],"name":"NoErrorFound","type":"error"},{"inputs":[],"name":"NotCalledByGateway","type":"error"},{"inputs":[],"name":"NotCalledByMailbox","type":"error"},{"inputs":[],"name":"NothingClaimed","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"TimeInFuture","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UnsupportedOperation","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"errorId","type":"uint256"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"BridgeInError","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"srcChainId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"tokenReceiver","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgedIn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"srcChainId","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenReceiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgedIn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"receiver","type":"bytes32"},{"indexed":false,"internalType":"uint128","name":"amount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"expiry","type":"uint128"}],"name":"BridgedLock","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"errorId","type":"uint256"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expiry","type":"uint256"}],"name":"BridgedLockError","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"dstChainId","type":"uint256"},{"indexed":false,"internalType":"address","name":"bridgeUser","type":"address"},{"indexed":false,"internalType":"address","name":"tokenReceiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgedOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"withdrawId","type":"uint256"}],"name":"EthWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldGateway","type":"address"},{"indexed":false,"internalType":"address","name":"newGateway","type":"address"}],"name":"GatewayUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"_domain","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"oldGasLimit","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"newGasLimit","type":"uint256[]"}],"name":"MessageGasLimitUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"sender","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"domain","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"messageId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"feeSpent","type":"uint256"}],"name":"MintMessageSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"id","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"sender","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"additionalData","type":"uint256"}],"name":"ProcessError","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"errorId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"user","type":"bytes32"},{"indexed":false,"internalType":"uint128","name":"amount","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"domain","type":"uint32"}],"name":"RetryBridgeOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"errorId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"receiver","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expiry","type":"uint256"}],"name":"RetryLock","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"errorId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"user","type":"bytes32"},{"indexed":false,"internalType":"uint128","name":"amount","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"domain","type":"uint32"}],"name":"RetryMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"errorId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"user","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RetryMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"errorId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RetryMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"errorId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"user","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RetryTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"domain","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"oldFee","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"newFee","type":"uint256[]"}],"name":"ReturnFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawETH","type":"event"},{"inputs":[],"name":"CLEAR","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EVERCLEAR_ID","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCKBOX","outputs":[{"internalType":"contract IXERC20Lockbox","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_LOCK_TIME","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_LOCK_TIME","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WEEK","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_amount","type":"uint128"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_gasLimit","type":"uint256"}],"name":"adminBridge","outputs":[{"internalType":"bytes32","name":"_messageId","type":"bytes32"},{"internalType":"uint256","name":"_feeSpent","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"account","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"internalType":"struct IBridge.Claim[]","name":"_claim","type":"tuple[]"},{"internalType":"uint32","name":"_domain","type":"uint32"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_gasLimit","type":"uint256"}],"name":"claimRewards","outputs":[{"internalType":"bytes32","name":"_messageId","type":"bytes32"},{"internalType":"uint256","name":"_feeSpent","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_delegate","type":"bytes32"},{"internalType":"uint256","name":"_gasLimit","type":"uint256"}],"name":"delegate","outputs":[{"internalType":"bytes32","name":"_messageId","type":"bytes32"},{"internalType":"uint256","name":"_feeSpent","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"errors","outputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"_amountToUnlock","type":"uint128"},{"internalType":"uint32","name":"_domain","type":"uint32"},{"internalType":"uint256","name":"_gasLimit","type":"uint256"}],"name":"exitEarly","outputs":[{"internalType":"bytes32","name":"_messageId","type":"bytes32"},{"internalType":"uint256","name":"_feeSpent","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"gateway","outputs":[{"internalType":"contract IGateway","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hubCLEAR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hubWETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"_additionalAmountToLock","type":"uint128"},{"internalType":"uint128","name":"_expiry","type":"uint128"},{"internalType":"uint256","name":"_gasLimit","type":"uint256"}],"name":"increaseLockPosition","outputs":[{"internalType":"bytes32","name":"_messageId","type":"bytes32"},{"internalType":"uint256","name":"_feeSpent","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"messageGasLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_message","type":"bytes"}],"name":"receiveMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_errorId","type":"uint256"}],"name":"retryMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_grantors","type":"bytes32[]"},{"internalType":"uint32","name":"_domain","type":"uint32"},{"internalType":"uint256","name":"_gasLimit","type":"uint256"}],"name":"submitDelegatedVote","outputs":[{"internalType":"bytes32","name":"_messageId","type":"bytes32"},{"internalType":"uint256","name":"_feeSpent","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"},{"internalType":"uint256","name":"_gasLimit","type":"uint256"}],"name":"submitVote","outputs":[{"internalType":"bytes32","name":"_messageId","type":"bytes32"},{"internalType":"uint256","name":"_feeSpent","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newGateway","type":"address"}],"name":"updateGateway","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newMailbox","type":"address"}],"name":"updateMailbox","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_domain","type":"uint256[]"},{"internalType":"uint256[]","name":"_newGasLimit","type":"uint256[]"}],"name":"updateMessageGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newSecurityModule","type":"address"}],"name":"updateSecurityModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"},{"internalType":"uint256","name":"_gasLimit","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"bytes32","name":"_messageId","type":"bytes32"},{"internalType":"uint256","name":"_feeSpent","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"xCLEAR","outputs":[{"internalType":"contract IXERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

610140604052348015610010575f80fd5b5060405161259238038061259283398101604081905261002f916101ba565b878487898887806001600160a01b03811661006357604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61006c81610134565b506001600160a01b0384166100945760405163d92e233d60e01b815260040160405180910390fd5b5063ffffffff94909416608052600280546001600160a01b0319166001600160a01b0394851617905590821660c052811660a05290811660e05282166100ed5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0381166101145760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0391821661010052166101205250610256945050505050565b600180546001600160a01b031916905561014d81610150565b50565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146101b5575f80fd5b919050565b5f805f805f805f80610100898b0312156101d2575f80fd5b885163ffffffff811681146101e5575f80fd5b97506101f360208a0161019f565b965061020160408a0161019f565b955061020f60608a0161019f565b945061021d60808a0161019f565b935061022b60a08a0161019f565b925061023960c08a0161019f565b915061024760e08a0161019f565b90509295985092959890939650565b60805160a05160c05160e05161010051610120516122706103225f395f818161037a01526116c301525f818161044d015261170001525f818161025e015281816110f8015281816111710152818161122101528181611502015261154501525f81816102e00152818161129a015281816113260152818161138a01526115ec01525f81816103ad01528181611132015281816111a001526115b101525f8181610313015281816106cf015281816109e801528181610b18015281816113f8015261161e01526122705ff3fe6080604052600436106101de575f3560e01c80638da5cb5b116100fd578063cd6c9d5611610092578063f4359ce511610062578063f4359ce5146105bc578063f953cec7146105d2578063fa78668f146105f1578063fed1a60614610608575f80fd5b8063cd6c9d561461055a578063dfd402781461056d578063e30c397814610580578063f2fde38b1461059d575f80fd5b8063a90b421e116100cd578063a90b421e146104d0578063b48dc48314610509578063c0346b2014610528578063c79ceab214610547575f80fd5b80638da5cb5b1461046f5780638eb7cb381461048b57806391a3ef8e1461049e578063a16d8dfb146104bd575f80fd5b806369ed2c691161017357806379ba50971161014357806379ba5097146103f65780637f973b921461040a5780638a901b9f1461041d5780638c110bfc1461043c575f80fd5b806369ed2c69146103695780636cb7f8241461039c5780636f3014d4146103cf578063715018a6146103e2575f80fd5b806357140716116101ae57806357140716146102ae5780635aafc404146102cf5780635ff9a87414610302578063690d83201461034a575f80fd5b80630e19dc3a146101e9578063116191b61461021657806322ad76c61461024d5780633ff0320714610280575f80fd5b366101e557005b5f80fd5b6101fc6101f7366004611a1f565b61066e565b604080519283526020830191909152015b60405180910390f35b348015610221575f80fd5b50600254610235906001600160a01b031681565b6040516001600160a01b03909116815260200161020d565b348015610258575f80fd5b506102357f000000000000000000000000000000000000000000000000000000000000000081565b34801561028b575f80fd5b506102966276a70081565b6040516001600160801b03909116815260200161020d565b3480156102b9575f80fd5b506102cd6102c8366004611a8f565b610748565b005b3480156102da575f80fd5b506102357f000000000000000000000000000000000000000000000000000000000000000081565b34801561030d575f80fd5b506103357f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff909116815260200161020d565b348015610355575f80fd5b506102cd610364366004611b0c565b61089e565b348015610374575f80fd5b506102357f000000000000000000000000000000000000000000000000000000000000000081565b3480156103a7575f80fd5b506102357f000000000000000000000000000000000000000000000000000000000000000081565b6101fc6103dd366004611b39565b61095c565b3480156103ed575f80fd5b506102cd610a62565b348015610401575f80fd5b506102cd610a75565b6101fc610418366004611b74565b610abe565b348015610428575f80fd5b506102cd610437366004611b0c565b610b93565b348015610447575f80fd5b506102357f000000000000000000000000000000000000000000000000000000000000000081565b34801561047a575f80fd5b505f546001600160a01b0316610235565b6101fc610499366004611bcc565b610c20565b3480156104a9575f80fd5b506102cd6104b8366004611b0c565b610c47565b6101fc6104cb366004611a1f565b610ca8565b3480156104db575f80fd5b506104fb6104ea366004611bec565b60056020525f908152604090205481565b60405190815260200161020d565b348015610514575f80fd5b506102cd610523366004611bec565b610cd4565b348015610533575f80fd5b506102cd610542366004611b0c565b610dc0565b6101fc610555366004611c03565b610e22565b6101fc610568366004611c2e565b610e5d565b6101fc61057b366004611cfd565b610f80565b34801561058b575f80fd5b506001546001600160a01b0316610235565b3480156105a8575f80fd5b506102cd6105b7366004611b0c565b610ff2565b3480156105c7575f80fd5b5061029662093a8081565b3480156105dd575f80fd5b506102cd6105ec366004611e95565b611062565b3480156105fc575f80fd5b506102966303c2670081565b348015610613575f80fd5b5061064b610622366004611bec565b60046020525f908152604090208054600182015460029092015490916001600160a01b03169083565b604080519384526001600160a01b0390921660208401529082015260600161020d565b60408051600360208201523391810182905263ffffffff841660608201525f91829182906080015b60408051601f1981840301815290829052600254630fa310a560e21b83529092506001600160a01b031690633e8c42949034906106fb907f00000000000000000000000000000000000000000000000000000000000000009086908b90600401611f24565b604080518083038185885af1158015610716573d5f803e3d5ffd5b50505050506040513d601f19601f8201168201806040525081019061073b9190611f6d565b9097909650945050505050565b6107506110ca565b8281146107705760405163b4fa3fb360e01b815260040160405180910390fd5b5f8367ffffffffffffffff81111561078a5761078a611c6c565b6040519080825280602002602001820160405280156107b3578160200160208202803683370190505b5090505f5b848110156108575760055f8787848181106107d5576107d5611f8f565b9050602002013581526020019081526020015f20548282815181106107fc576107fc611f8f565b60200260200101818152505083838281811061081a5761081a611f8f565b9050602002013560055f88888581811061083657610836611f8f565b602090810292909201358352508101919091526040015f20556001016107b8565b507f6613c18159729ca09ace69207d47ea3b0bc287f6e94c15b74df839a62fa84af6858583868660405161088f959493929190611fd3565b60405180910390a15050505050565b6108a66110ca565b5f816001600160a01b0316476040515f6040518083038185875af1925050503d805f81146108ef576040519150601f19603f3d011682016040523d82523d5f602084013e6108f4565b606091505b5050905080610916576040516312171d8360e31b815260040160405180910390fd5b604080516001600160a01b03841681524760208201527f566e45b1c8057e725bf62796a7f1d37ae294393cab069725a09daddd1af98b7991015b60405180910390a15050565b5f806109666110ca565b61097933866001600160801b03166110f6565b6040805160016020820152339181018290526001600160801b03871660608201526001600160a01b03861660808201525f9060a0015b60408051601f1981840301815290829052600254630fa310a560e21b83529092506001600160a01b031690633e8c4294903490610a14907f00000000000000000000000000000000000000000000000000000000000000009086908b90600401611f24565b604080518083038185885af1158015610a2f573d5f803e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190610a549190611f6d565b909890975095505050505050565b610a6a6110ca565b610a735f611355565b565b60015433906001600160a01b03168114610ab25760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b610abb81611355565b50565b5f80803390505f600782898989604051602001610adf95949392919061203f565b60408051601f1981840301815290829052600254630fa310a560e21b83529092506001600160a01b031690633e8c4294903490610b44907f00000000000000000000000000000000000000000000000000000000000000009086908b90600401611f24565b604080518083038185885af1158015610b5f573d5f803e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190610b849190611f6d565b90999098509650505050505050565b610b9b6110ca565b6001600160a01b038116610bc25760405163d92e233d60e01b815260040160405180910390fd5b600254604051638a901b9f60e01b81526001600160a01b03838116600483015290911690638a901b9f906024015b5f604051808303815f87803b158015610c07575f80fd5b505af1158015610c19573d5f803e3d5ffd5b5050505050565b604080516004602082015233918101829052606081018490525f9182918290608001610696565b610c4f6110ca565b6001600160a01b038116610c765760405163d92e233d60e01b815260040160405180910390fd5b6002546040516348d1f7c760e11b81526001600160a01b038381166004830152909116906391a3ef8e90602401610bf0565b60408051600660208201523391810182905263ffffffff841660608201525f9182918290608001610696565b5f8181526004602081815260408084208151606081018352815481526001820180546001600160a01b03808216848801908152600286018054978601979097528a8a5297909652928790556001600160a01b0319909216909155939055905116610d5157604051634b87c11b60e01b815260040160405180910390fd5b602080820151604080840151815186815246948101949094526001600160a01b039092169083015260608201527ed95ebd7a46bc45511f5bfbd0d7082034ad2134bfa27b37424ec8b1e4e705fa9060800160405180910390a1610dbc8160200151826040015161136e565b5050565b610dc86110ca565b600280546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f68e84423772dadc3e4047f8b5bd221ddb02dc67796e7852533fd976947d86c519101610950565b6040805160056020820152339181018290526001600160801b038516606082015263ffffffff841660808201525f918291829060a0016109af565b5f80610e71846001600160801b031661167f565b610e995760405163579ccf8160e01b81526001600160801b0385166004820152602401610aa9565b6001600160801b0384164210610ecd5760405163d928003560e01b81526001600160801b0385166004820152602401610aa9565b610edb6303c267004261208d565b846001600160801b03161115610f045760405163524f072160e01b815260040160405180910390fd5b610f116276a7004261208d565b846001600160801b03161015610f3a5760405163538ed2bd60e11b815260040160405180910390fd5b610f4d33866001600160801b03166110f6565b6040805160026020820152339181018290526001600160801b038781166060830152861660808201525f9060a0016109af565b5f8085515f03610fa35760405163b4fa3fb360e01b815260040160405180910390fd5b6001600160a01b038416610fca5760405163d92e233d60e01b815260040160405180910390fd5b33610fd58188611694565b96505f600882898989604051602001610adf9594939291906120a0565b610ffa6110ca565b600180546001600160a01b0383166001600160a01b0319909116811790915561102a5f546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6002546001600160a01b0316331461108d576040516302af9f8d60e11b815260040160405180910390fd5b5f80828060200190518101906110a39190612193565b915091505f6110af8390565b90506110c481836001600160801b031661136e565b50505050565b5f546001600160a01b03163314610a735760405163118cdaa760e01b8152336004820152602401610aa9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316156113005761115a6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016833084611788565b60405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303815f875af11580156111e6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061120a91906121c1565b5060405163b6b55f2560e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b6b55f25906024015f604051808303815f87803b15801561126a575f80fd5b505af115801561127c573d5f803e3d5ffd5b5050604051632770a7eb60e21b8152306004820152602481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169250639dc29fac91506044015b5f604051808303815f87803b1580156112e6575f80fd5b505af11580156112f8573d5f803e3d5ffd5b505050505050565b604051632770a7eb60e21b81526001600160a01b038381166004830152602482018390527f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906044016112cf565b600180546001600160a01b0319169055610abb816117ef565b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f19906044015f604051808303815f87803b1580156113d3575f80fd5b505af19250505080156113e4575060015b6115005760038054604080516060810182527f000000000000000000000000000000000000000000000000000000000000000063ffffffff1681526001600160a01b0386811660208084019182528385018881526001600160801b039687165f81815260049093529582209451855591516001850180546001600160a01b031916919094161790925551600290920191909155835491939190921691611489836121e0565b82546001600160801b039182166101009390930a928302919092021990911617905550604080518281526001600160a01b03851660208201529081018390524260608201527fccf5db7950e0fc0591d37908fe217166c1296c548cd7db2ba22bfda3f55c44779060800160405180910390a1505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316156115df57604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d906024015f604051808303815f87803b15801561158e575f80fd5b505af11580156115a0573d5f803e3d5ffd5b506115da9250506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169050838361183e565b611613565b6116136001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016838361183e565b6040805163ffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526001600160a01b03841660208201529081018290527fee8d2d3b6400c99942181eba0fe478db850dbcd0fe427164578909a39bc9a11390606001610950565b5f61168d62093a8083612205565b1592915050565b60605f5b825181101561177d575f8382815181106116b4576116b4611f8f565b60200260200101515f015190507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b03161415801561173557507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b031614155b156117535760405163c1ab6dc160e01b815260040160405180910390fd5b8484838151811061176657611766611f8f565b602090810291909101810151015250600101611698565b508190505b92915050565b6040516001600160a01b0384811660248301528381166044830152606482018390526110c49186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611874565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516001600160a01b0383811660248301526044820183905261186f91859182169063a9059cbb906064016117bd565b505050565b5f6118886001600160a01b038416836118d5565b905080515f141580156118ac5750808060200190518101906118aa91906121c1565b155b1561186f57604051635274afe760e01b81526001600160a01b0384166004820152602401610aa9565b60606118e283835f6118e9565b9392505050565b60608147101561190e5760405163cd78605960e01b8152306004820152602401610aa9565b5f80856001600160a01b031684866040516119299190612224565b5f6040518083038185875af1925050503d805f8114611963576040519150601f19603f3d011682016040523d82523d5f602084013e611968565b606091505b5091509150611978868383611982565b9695505050505050565b60608261199757611992826119de565b6118e2565b81511580156119ae57506001600160a01b0384163b155b156119d757604051639996b31560e01b81526001600160a01b0385166004820152602401610aa9565b50806118e2565b8051156119ee5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b803563ffffffff81168114611a1a575f80fd5b919050565b5f8060408385031215611a30575f80fd5b611a3983611a07565b946020939093013593505050565b5f8083601f840112611a57575f80fd5b50813567ffffffffffffffff811115611a6e575f80fd5b6020830191508360208260051b8501011115611a88575f80fd5b9250929050565b5f805f8060408587031215611aa2575f80fd5b843567ffffffffffffffff80821115611ab9575f80fd5b611ac588838901611a47565b90965094506020870135915080821115611add575f80fd5b50611aea87828801611a47565b95989497509550505050565b80356001600160a01b0381168114611a1a575f80fd5b5f60208284031215611b1c575f80fd5b6118e282611af6565b6001600160801b0381168114610abb575f80fd5b5f805f60608486031215611b4b575f80fd5b8335611b5681611b25565b9250611b6460208501611af6565b9150604084013590509250925092565b5f805f8060608587031215611b87575f80fd5b843567ffffffffffffffff811115611b9d575f80fd5b611ba987828801611a47565b9095509350611bbc905060208601611a07565b9396929550929360400135925050565b5f8060408385031215611bdd575f80fd5b50508035926020909101359150565b5f60208284031215611bfc575f80fd5b5035919050565b5f805f60608486031215611c15575f80fd5b8335611c2081611b25565b9250611b6460208501611a07565b5f805f60608486031215611c40575f80fd5b8335611c4b81611b25565b92506020840135611c5b81611b25565b929592945050506040919091013590565b634e487b7160e01b5f52604160045260245ffd5b6040516080810167ffffffffffffffff81118282101715611ca357611ca3611c6c565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611cd257611cd2611c6c565b604052919050565b5f67ffffffffffffffff821115611cf357611cf3611c6c565b5060051b60200190565b5f805f8060808587031215611d10575f80fd5b67ffffffffffffffff85351115611d25575f80fd5b8435850186601f820112611d37575f80fd5b611d49611d448235611cda565b611ca9565b81358082526020808301929160051b84010189811115611d67575f80fd5b602084015b81811015611e635767ffffffffffffffff81351115611d89575f80fd5b803585016080818d03601f19011215611da0575f80fd5b611da8611c80565b611db460208301611af6565b8152604082013560208201526060820135604082015267ffffffffffffffff60808301351115611de2575f80fd5b6080820135820191508c603f830112611df9575f80fd5b611e09611d446020840135611cda565b602083810135808352908201919060051b84016040018f811115611e2b575f80fd5b6040850194505b80851015611e4d578435835260209485019490920191611e32565b5060608301525085525060209384019301611d6c565b5050809650505050611e7760208601611a07565b9250611e8560408601611af6565b9396929550929360600135925050565b5f6020808385031215611ea6575f80fd5b823567ffffffffffffffff80821115611ebd575f80fd5b818501915085601f830112611ed0575f80fd5b813581811115611ee257611ee2611c6c565b611ef4601f8201601f19168501611ca9565b91508082528684828501011115611f09575f80fd5b80848401858401375f90820190930192909252509392505050565b63ffffffff84168152606060208201525f83518060608401528060208601608085015e5f608082850101526080601f19601f830116840101915050826040830152949350505050565b5f8060408385031215611f7e575f80fd5b505080516020909101519092909150565b634e487b7160e01b5f52603260045260245ffd5b8183525f6001600160fb1b03831115611fba575f80fd5b8260051b80836020870137939093016020019392505050565b606081525f611fe6606083018789611fa3565b8281036020848101919091528651808352878201928201905f5b8181101561201c57845183529383019391830191600101612000565b50508481036040860152612031818789611fa3565b9a9950505050505050505050565b60ff86168152846020820152608060408201525f612061608083018587611fa3565b905063ffffffff831660608301529695505050505050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561178257611782612079565b5f60a080830160ff8916845260208881860152604060a0604087015282895180855260c08801915060c08160051b8901019450838b015f5b8281101561215e5789870360bf19018452815180516001600160a01b031688528681015187890152858101518689015260609081015160809189018290528051918901829052870190898901905f905b808210156121485783518352928901929189019160019190910190612128565b50909850505092850192908501906001016120d8565b50505063ffffffff891660608801525091935061217a92505050565b6001600160a01b03831660808301529695505050505050565b5f80604083850312156121a4575f80fd5b8251915060208301516121b681611b25565b809150509250929050565b5f602082840312156121d1575f80fd5b815180151581146118e2575f80fd5b5f6001600160801b038083168181036121fb576121fb612079565b6001019392505050565b5f8261221f57634e487b7160e01b5f52601260045260245ffd5b500690565b5f82518060208501845e5f92019182525091905056fea2646970667358221220ef50e0daf2d7c5009c6b3a2749ab16c1e28ace0b0e1dad480f0fae5bf9fc0f1964736f6c6343000819003300000000000000000000000000000000000000000000000000000000000062ef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000058b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000223b2bbe9a77db651ce241f33fd7d7a67887a1e000000000000000000000000058b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e80000000000000000000000002e31ebd2eb114943630db6ba8c7f7687bda5835f

Deployed Bytecode

0x6080604052600436106101de575f3560e01c80638da5cb5b116100fd578063cd6c9d5611610092578063f4359ce511610062578063f4359ce5146105bc578063f953cec7146105d2578063fa78668f146105f1578063fed1a60614610608575f80fd5b8063cd6c9d561461055a578063dfd402781461056d578063e30c397814610580578063f2fde38b1461059d575f80fd5b8063a90b421e116100cd578063a90b421e146104d0578063b48dc48314610509578063c0346b2014610528578063c79ceab214610547575f80fd5b80638da5cb5b1461046f5780638eb7cb381461048b57806391a3ef8e1461049e578063a16d8dfb146104bd575f80fd5b806369ed2c691161017357806379ba50971161014357806379ba5097146103f65780637f973b921461040a5780638a901b9f1461041d5780638c110bfc1461043c575f80fd5b806369ed2c69146103695780636cb7f8241461039c5780636f3014d4146103cf578063715018a6146103e2575f80fd5b806357140716116101ae57806357140716146102ae5780635aafc404146102cf5780635ff9a87414610302578063690d83201461034a575f80fd5b80630e19dc3a146101e9578063116191b61461021657806322ad76c61461024d5780633ff0320714610280575f80fd5b366101e557005b5f80fd5b6101fc6101f7366004611a1f565b61066e565b604080519283526020830191909152015b60405180910390f35b348015610221575f80fd5b50600254610235906001600160a01b031681565b6040516001600160a01b03909116815260200161020d565b348015610258575f80fd5b506102357f000000000000000000000000000000000000000000000000000000000000000081565b34801561028b575f80fd5b506102966276a70081565b6040516001600160801b03909116815260200161020d565b3480156102b9575f80fd5b506102cd6102c8366004611a8f565b610748565b005b3480156102da575f80fd5b506102357f00000000000000000000000058b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e881565b34801561030d575f80fd5b506103357f00000000000000000000000000000000000000000000000000000000000062ef81565b60405163ffffffff909116815260200161020d565b348015610355575f80fd5b506102cd610364366004611b0c565b61089e565b348015610374575f80fd5b506102357f0000000000000000000000002e31ebd2eb114943630db6ba8c7f7687bda5835f81565b3480156103a7575f80fd5b506102357f000000000000000000000000000000000000000000000000000000000000000081565b6101fc6103dd366004611b39565b61095c565b3480156103ed575f80fd5b506102cd610a62565b348015610401575f80fd5b506102cd610a75565b6101fc610418366004611b74565b610abe565b348015610428575f80fd5b506102cd610437366004611b0c565b610b93565b348015610447575f80fd5b506102357f00000000000000000000000058b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e881565b34801561047a575f80fd5b505f546001600160a01b0316610235565b6101fc610499366004611bcc565b610c20565b3480156104a9575f80fd5b506102cd6104b8366004611b0c565b610c47565b6101fc6104cb366004611a1f565b610ca8565b3480156104db575f80fd5b506104fb6104ea366004611bec565b60056020525f908152604090205481565b60405190815260200161020d565b348015610514575f80fd5b506102cd610523366004611bec565b610cd4565b348015610533575f80fd5b506102cd610542366004611b0c565b610dc0565b6101fc610555366004611c03565b610e22565b6101fc610568366004611c2e565b610e5d565b6101fc61057b366004611cfd565b610f80565b34801561058b575f80fd5b506001546001600160a01b0316610235565b3480156105a8575f80fd5b506102cd6105b7366004611b0c565b610ff2565b3480156105c7575f80fd5b5061029662093a8081565b3480156105dd575f80fd5b506102cd6105ec366004611e95565b611062565b3480156105fc575f80fd5b506102966303c2670081565b348015610613575f80fd5b5061064b610622366004611bec565b60046020525f908152604090208054600182015460029092015490916001600160a01b03169083565b604080519384526001600160a01b0390921660208401529082015260600161020d565b60408051600360208201523391810182905263ffffffff841660608201525f91829182906080015b60408051601f1981840301815290829052600254630fa310a560e21b83529092506001600160a01b031690633e8c42949034906106fb907f00000000000000000000000000000000000000000000000000000000000062ef9086908b90600401611f24565b604080518083038185885af1158015610716573d5f803e3d5ffd5b50505050506040513d601f19601f8201168201806040525081019061073b9190611f6d565b9097909650945050505050565b6107506110ca565b8281146107705760405163b4fa3fb360e01b815260040160405180910390fd5b5f8367ffffffffffffffff81111561078a5761078a611c6c565b6040519080825280602002602001820160405280156107b3578160200160208202803683370190505b5090505f5b848110156108575760055f8787848181106107d5576107d5611f8f565b9050602002013581526020019081526020015f20548282815181106107fc576107fc611f8f565b60200260200101818152505083838281811061081a5761081a611f8f565b9050602002013560055f88888581811061083657610836611f8f565b602090810292909201358352508101919091526040015f20556001016107b8565b507f6613c18159729ca09ace69207d47ea3b0bc287f6e94c15b74df839a62fa84af6858583868660405161088f959493929190611fd3565b60405180910390a15050505050565b6108a66110ca565b5f816001600160a01b0316476040515f6040518083038185875af1925050503d805f81146108ef576040519150601f19603f3d011682016040523d82523d5f602084013e6108f4565b606091505b5050905080610916576040516312171d8360e31b815260040160405180910390fd5b604080516001600160a01b03841681524760208201527f566e45b1c8057e725bf62796a7f1d37ae294393cab069725a09daddd1af98b7991015b60405180910390a15050565b5f806109666110ca565b61097933866001600160801b03166110f6565b6040805160016020820152339181018290526001600160801b03871660608201526001600160a01b03861660808201525f9060a0015b60408051601f1981840301815290829052600254630fa310a560e21b83529092506001600160a01b031690633e8c4294903490610a14907f00000000000000000000000000000000000000000000000000000000000062ef9086908b90600401611f24565b604080518083038185885af1158015610a2f573d5f803e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190610a549190611f6d565b909890975095505050505050565b610a6a6110ca565b610a735f611355565b565b60015433906001600160a01b03168114610ab25760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b610abb81611355565b50565b5f80803390505f600782898989604051602001610adf95949392919061203f565b60408051601f1981840301815290829052600254630fa310a560e21b83529092506001600160a01b031690633e8c4294903490610b44907f00000000000000000000000000000000000000000000000000000000000062ef9086908b90600401611f24565b604080518083038185885af1158015610b5f573d5f803e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190610b849190611f6d565b90999098509650505050505050565b610b9b6110ca565b6001600160a01b038116610bc25760405163d92e233d60e01b815260040160405180910390fd5b600254604051638a901b9f60e01b81526001600160a01b03838116600483015290911690638a901b9f906024015b5f604051808303815f87803b158015610c07575f80fd5b505af1158015610c19573d5f803e3d5ffd5b5050505050565b604080516004602082015233918101829052606081018490525f9182918290608001610696565b610c4f6110ca565b6001600160a01b038116610c765760405163d92e233d60e01b815260040160405180910390fd5b6002546040516348d1f7c760e11b81526001600160a01b038381166004830152909116906391a3ef8e90602401610bf0565b60408051600660208201523391810182905263ffffffff841660608201525f9182918290608001610696565b5f8181526004602081815260408084208151606081018352815481526001820180546001600160a01b03808216848801908152600286018054978601979097528a8a5297909652928790556001600160a01b0319909216909155939055905116610d5157604051634b87c11b60e01b815260040160405180910390fd5b602080820151604080840151815186815246948101949094526001600160a01b039092169083015260608201527ed95ebd7a46bc45511f5bfbd0d7082034ad2134bfa27b37424ec8b1e4e705fa9060800160405180910390a1610dbc8160200151826040015161136e565b5050565b610dc86110ca565b600280546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f68e84423772dadc3e4047f8b5bd221ddb02dc67796e7852533fd976947d86c519101610950565b6040805160056020820152339181018290526001600160801b038516606082015263ffffffff841660808201525f918291829060a0016109af565b5f80610e71846001600160801b031661167f565b610e995760405163579ccf8160e01b81526001600160801b0385166004820152602401610aa9565b6001600160801b0384164210610ecd5760405163d928003560e01b81526001600160801b0385166004820152602401610aa9565b610edb6303c267004261208d565b846001600160801b03161115610f045760405163524f072160e01b815260040160405180910390fd5b610f116276a7004261208d565b846001600160801b03161015610f3a5760405163538ed2bd60e11b815260040160405180910390fd5b610f4d33866001600160801b03166110f6565b6040805160026020820152339181018290526001600160801b038781166060830152861660808201525f9060a0016109af565b5f8085515f03610fa35760405163b4fa3fb360e01b815260040160405180910390fd5b6001600160a01b038416610fca5760405163d92e233d60e01b815260040160405180910390fd5b33610fd58188611694565b96505f600882898989604051602001610adf9594939291906120a0565b610ffa6110ca565b600180546001600160a01b0383166001600160a01b0319909116811790915561102a5f546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6002546001600160a01b0316331461108d576040516302af9f8d60e11b815260040160405180910390fd5b5f80828060200190518101906110a39190612193565b915091505f6110af8390565b90506110c481836001600160801b031661136e565b50505050565b5f546001600160a01b03163314610a735760405163118cdaa760e01b8152336004820152602401610aa9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316156113005761115a6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016833084611788565b60405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303815f875af11580156111e6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061120a91906121c1565b5060405163b6b55f2560e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b6b55f25906024015f604051808303815f87803b15801561126a575f80fd5b505af115801561127c573d5f803e3d5ffd5b5050604051632770a7eb60e21b8152306004820152602481018490527f00000000000000000000000058b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e86001600160a01b03169250639dc29fac91506044015b5f604051808303815f87803b1580156112e6575f80fd5b505af11580156112f8573d5f803e3d5ffd5b505050505050565b604051632770a7eb60e21b81526001600160a01b038381166004830152602482018390527f00000000000000000000000058b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e81690639dc29fac906044016112cf565b600180546001600160a01b0319169055610abb816117ef565b6040516340c10f1960e01b8152306004820152602481018290527f00000000000000000000000058b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e86001600160a01b0316906340c10f19906044015f604051808303815f87803b1580156113d3575f80fd5b505af19250505080156113e4575060015b6115005760038054604080516060810182527f00000000000000000000000000000000000000000000000000000000000062ef63ffffffff1681526001600160a01b0386811660208084019182528385018881526001600160801b039687165f81815260049093529582209451855591516001850180546001600160a01b031916919094161790925551600290920191909155835491939190921691611489836121e0565b82546001600160801b039182166101009390930a928302919092021990911617905550604080518281526001600160a01b03851660208201529081018390524260608201527fccf5db7950e0fc0591d37908fe217166c1296c548cd7db2ba22bfda3f55c44779060800160405180910390a1505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316156115df57604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d906024015f604051808303815f87803b15801561158e575f80fd5b505af11580156115a0573d5f803e3d5ffd5b506115da9250506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169050838361183e565b611613565b6116136001600160a01b037f00000000000000000000000058b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e816838361183e565b6040805163ffffffff7f00000000000000000000000000000000000000000000000000000000000062ef1681526001600160a01b03841660208201529081018290527fee8d2d3b6400c99942181eba0fe478db850dbcd0fe427164578909a39bc9a11390606001610950565b5f61168d62093a8083612205565b1592915050565b60605f5b825181101561177d575f8382815181106116b4576116b4611f8f565b60200260200101515f015190507f0000000000000000000000002e31ebd2eb114943630db6ba8c7f7687bda5835f6001600160a01b0316816001600160a01b03161415801561173557507f00000000000000000000000058b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e86001600160a01b0316816001600160a01b031614155b156117535760405163c1ab6dc160e01b815260040160405180910390fd5b8484838151811061176657611766611f8f565b602090810291909101810151015250600101611698565b508190505b92915050565b6040516001600160a01b0384811660248301528381166044830152606482018390526110c49186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611874565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516001600160a01b0383811660248301526044820183905261186f91859182169063a9059cbb906064016117bd565b505050565b5f6118886001600160a01b038416836118d5565b905080515f141580156118ac5750808060200190518101906118aa91906121c1565b155b1561186f57604051635274afe760e01b81526001600160a01b0384166004820152602401610aa9565b60606118e283835f6118e9565b9392505050565b60608147101561190e5760405163cd78605960e01b8152306004820152602401610aa9565b5f80856001600160a01b031684866040516119299190612224565b5f6040518083038185875af1925050503d805f8114611963576040519150601f19603f3d011682016040523d82523d5f602084013e611968565b606091505b5091509150611978868383611982565b9695505050505050565b60608261199757611992826119de565b6118e2565b81511580156119ae57506001600160a01b0384163b155b156119d757604051639996b31560e01b81526001600160a01b0385166004820152602401610aa9565b50806118e2565b8051156119ee5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b803563ffffffff81168114611a1a575f80fd5b919050565b5f8060408385031215611a30575f80fd5b611a3983611a07565b946020939093013593505050565b5f8083601f840112611a57575f80fd5b50813567ffffffffffffffff811115611a6e575f80fd5b6020830191508360208260051b8501011115611a88575f80fd5b9250929050565b5f805f8060408587031215611aa2575f80fd5b843567ffffffffffffffff80821115611ab9575f80fd5b611ac588838901611a47565b90965094506020870135915080821115611add575f80fd5b50611aea87828801611a47565b95989497509550505050565b80356001600160a01b0381168114611a1a575f80fd5b5f60208284031215611b1c575f80fd5b6118e282611af6565b6001600160801b0381168114610abb575f80fd5b5f805f60608486031215611b4b575f80fd5b8335611b5681611b25565b9250611b6460208501611af6565b9150604084013590509250925092565b5f805f8060608587031215611b87575f80fd5b843567ffffffffffffffff811115611b9d575f80fd5b611ba987828801611a47565b9095509350611bbc905060208601611a07565b9396929550929360400135925050565b5f8060408385031215611bdd575f80fd5b50508035926020909101359150565b5f60208284031215611bfc575f80fd5b5035919050565b5f805f60608486031215611c15575f80fd5b8335611c2081611b25565b9250611b6460208501611a07565b5f805f60608486031215611c40575f80fd5b8335611c4b81611b25565b92506020840135611c5b81611b25565b929592945050506040919091013590565b634e487b7160e01b5f52604160045260245ffd5b6040516080810167ffffffffffffffff81118282101715611ca357611ca3611c6c565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611cd257611cd2611c6c565b604052919050565b5f67ffffffffffffffff821115611cf357611cf3611c6c565b5060051b60200190565b5f805f8060808587031215611d10575f80fd5b67ffffffffffffffff85351115611d25575f80fd5b8435850186601f820112611d37575f80fd5b611d49611d448235611cda565b611ca9565b81358082526020808301929160051b84010189811115611d67575f80fd5b602084015b81811015611e635767ffffffffffffffff81351115611d89575f80fd5b803585016080818d03601f19011215611da0575f80fd5b611da8611c80565b611db460208301611af6565b8152604082013560208201526060820135604082015267ffffffffffffffff60808301351115611de2575f80fd5b6080820135820191508c603f830112611df9575f80fd5b611e09611d446020840135611cda565b602083810135808352908201919060051b84016040018f811115611e2b575f80fd5b6040850194505b80851015611e4d578435835260209485019490920191611e32565b5060608301525085525060209384019301611d6c565b5050809650505050611e7760208601611a07565b9250611e8560408601611af6565b9396929550929360600135925050565b5f6020808385031215611ea6575f80fd5b823567ffffffffffffffff80821115611ebd575f80fd5b818501915085601f830112611ed0575f80fd5b813581811115611ee257611ee2611c6c565b611ef4601f8201601f19168501611ca9565b91508082528684828501011115611f09575f80fd5b80848401858401375f90820190930192909252509392505050565b63ffffffff84168152606060208201525f83518060608401528060208601608085015e5f608082850101526080601f19601f830116840101915050826040830152949350505050565b5f8060408385031215611f7e575f80fd5b505080516020909101519092909150565b634e487b7160e01b5f52603260045260245ffd5b8183525f6001600160fb1b03831115611fba575f80fd5b8260051b80836020870137939093016020019392505050565b606081525f611fe6606083018789611fa3565b8281036020848101919091528651808352878201928201905f5b8181101561201c57845183529383019391830191600101612000565b50508481036040860152612031818789611fa3565b9a9950505050505050505050565b60ff86168152846020820152608060408201525f612061608083018587611fa3565b905063ffffffff831660608301529695505050505050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561178257611782612079565b5f60a080830160ff8916845260208881860152604060a0604087015282895180855260c08801915060c08160051b8901019450838b015f5b8281101561215e5789870360bf19018452815180516001600160a01b031688528681015187890152858101518689015260609081015160809189018290528051918901829052870190898901905f905b808210156121485783518352928901929189019160019190910190612128565b50909850505092850192908501906001016120d8565b50505063ffffffff891660608801525091935061217a92505050565b6001600160a01b03831660808301529695505050505050565b5f80604083850312156121a4575f80fd5b8251915060208301516121b681611b25565b809150509250929050565b5f602082840312156121d1575f80fd5b815180151581146118e2575f80fd5b5f6001600160801b038083168181036121fb576121fb612079565b6001019392505050565b5f8261221f57634e487b7160e01b5f52601260045260245ffd5b500690565b5f82518060208501845e5f92019182525091905056fea2646970667358221220ef50e0daf2d7c5009c6b3a2749ab16c1e28ace0b0e1dad480f0fae5bf9fc0f1964736f6c63430008190033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000000000000000000000000000000000000000062ef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000058b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000223b2bbe9a77db651ce241f33fd7d7a67887a1e000000000000000000000000058b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e80000000000000000000000002e31ebd2eb114943630db6ba8c7f7687bda5835f

-----Decoded View---------------
Arg [0] : _everclearId (uint32): 25327
Arg [1] : _clear (address): 0x0000000000000000000000000000000000000000
Arg [2] : _xClear (address): 0x58b9cB810A68a7f3e1E4f8Cb45D1B9B3c79705E8
Arg [3] : _lockbox (address): 0x0000000000000000000000000000000000000000
Arg [4] : _gateway (address): 0x0000000000000000000000000000000000000000
Arg [5] : _owner (address): 0x223B2BBe9a77db651CE241f33Fd7d7A67887A1e0
Arg [6] : _hubCLEAR (address): 0x58b9cB810A68a7f3e1E4f8Cb45D1B9B3c79705E8
Arg [7] : _hubWETH (address): 0x2e31ebD2eB114943630Db6ba8c7f7687bdA5835F

-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000062ef
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [2] : 00000000000000000000000058b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e8
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 000000000000000000000000223b2bbe9a77db651ce241f33fd7d7a67887a1e0
Arg [6] : 00000000000000000000000058b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e8
Arg [7] : 0000000000000000000000002e31ebd2eb114943630db6ba8c7f7687bda5835f


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.