{"file_path":"contracts/HyperlaneTokenBridge.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.22;\n\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\n\ninterface IMailbox {\n    function dispatch(\n        uint32 _destinationDomain,\n        bytes32 _recipientAddress,\n        bytes calldata _messageBody\n    ) external payable returns (bytes32);\n\n    function quoteDispatch(\n        uint32 _destinationDomain,\n        bytes32 _recipientAddress,\n        bytes calldata _messageBody\n    ) external view returns (uint256);\n}\n\ninterface IMessageRecipient {\n    function handle(\n        uint32 _origin,\n        bytes32 _sender,\n        bytes calldata _message\n    ) external payable;\n}\n\ninterface IBridgeToken {\n    function mintPublic(address to, uint256 amount) external;\n    function burnFromPublic(address account, uint256 amount) external;\n    function mintPrivate(address to, uint256 amount) external;\n    function burnFromPrivate(address account, uint256 amount) external;\n}\n\ninterface IERC20MetadataLike {\n    function decimals() external view returns (uint8);\n}\n\n/**\n * @title HyperlaneTokenBridge\n * @notice Multi-token bridge with decimals normalization via sharedDecimals.\n */\ncontract HyperlaneTokenBridge is\n    Initializable,\n    IMessageRecipient,\n    OwnableUpgradeable,\n    UUPSUpgradeable,\n    PausableUpgradeable,\n    ReentrancyGuardUpgradeable\n{\n    using SafeERC20 for IERC20;\n    uint8 private constant NATIVE_DECIMALS = 18;\n    uint256 private constant MESSAGE_LENGTH = 128;\n    uint256 public constant USE_DEFAULT_DAILY_LIMIT = 0;\n\n    IMailbox public mailbox;\n    uint256 public defaultDailyLimit;\n\n    struct TokenConfig {\n        bool enabled;\n        bool isCollateral;\n        address token;\n        // The source-side bridge path treats `dailyLimit` as a per-transfer ceiling.\n        // Destination-side settlement and pending-claim release use `current24hAmount`\n        // as a cumulative 24-hour window guard on released value.\n        uint256 dailyLimit;\n        uint256 current24hAmount;\n        uint256 lastReset;\n    }\n\n    mapping(bytes32 => TokenConfig) private tokenConfigs;\n    mapping(bytes32 => mapping(uint32 => bytes32)) public remoteRouters;\n\n    struct TokenDecimalsConfig {\n        bool configured;\n        uint8 localDecimals;\n        uint8 sharedDecimals;\n    }\n\n    mapping(bytes32 => TokenDecimalsConfig) private tokenDecimalsConfigs;\n    mapping(bytes32 => mapping(address => uint256)) private pendingClaims;\n    mapping(address => bool) public whitelist;\n    bool public isPrivateBridge;\n    bool public whitelistEnabled;\n    uint8 public constant MESSAGE_VERSION = 1;\n\n    // --- Events ---\n    event TokenRegistered(bytes32 indexed tokenId, address indexed token, bool isCollateral, uint256 dailyLimit);\n    event TokenEnabled(bytes32 indexed tokenId, bool enabled);\n    event BridgeSent(bytes32 indexed tokenId, address indexed sender, uint32 indexed dstDomain, bytes32 recipient, uint256 amount);\n    event BridgeReceived(bytes32 indexed tokenId, address indexed recipient, uint32 indexed origin, uint256 amount);\n    event RemoteRouterSet(bytes32 indexed tokenId, uint32 indexed domain, bytes32 router);\n    event TokenDailyLimitChanged(bytes32 indexed tokenId, uint256 newLimit);\n    event TokenDecimalsConfigured(bytes32 indexed tokenId, uint8 localDecimals, uint8 sharedDecimals);\n    event AmountRounded(bytes32 indexed tokenId, uint256 amountLocal, uint256 amountShared, uint256 dustLocal);\n    event NativeLocked(\n        bytes32 indexed tokenId,\n        address indexed sender,\n        uint32 indexed dstDomain,\n        bytes32 recipient,\n        uint256 amount\n    );\n    event NativeReleased(bytes32 indexed tokenId, address indexed recipient, uint256 amount);\n    event PendingClaimRecorded(bytes32 indexed tokenId, address indexed account, uint32 indexed origin, uint256 amount);\n    event PendingClaimPaid(bytes32 indexed tokenId, address indexed account, address indexed recipient, uint256 amount);\n    event PendingClaimRecovered(\n        bytes32 indexed tokenId,\n        address indexed account,\n        address indexed recipient,\n        address operator,\n        uint256 amount\n    );\n    event BridgeModeConfigured(bool indexed isPrivateBridge);\n    event WhitelistStatusChanged(bool indexed enabled);\n    event WhitelistUpdated(address indexed account, bool indexed allowed);\n\n    /// @custom:oz-upgrades-unsafe-allow constructor\n    constructor() {\n        _disableInitializers();\n    }\n\n    modifier onlyMailbox() {\n        require(msg.sender == address(mailbox), \"Only mailbox\");\n        _;\n    }\n\n    modifier onlySelf() {\n        require(msg.sender == address(this), \"Only self\");\n        _;\n    }\n\n    function initialize(address _mailbox, uint256 _defaultDailyLimit, bool _isPrivateBridge) public initializer {\n        require(_mailbox != address(0), \"Invalid mailbox\");\n        __Ownable_init(msg.sender);\n        __UUPSUpgradeable_init();\n        __Pausable_init();\n        __ReentrancyGuard_init();\n\n        mailbox = IMailbox(_mailbox);\n        defaultDailyLimit = _defaultDailyLimit;\n        isPrivateBridge = _isPrivateBridge;\n        whitelistEnabled = _isPrivateBridge;\n\n        emit BridgeModeConfigured(_isPrivateBridge);\n        emit WhitelistStatusChanged(whitelistEnabled);\n    }\n\n    function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n\n    // --- Configuration ---\n\n    function registerToken(\n        bytes32 _tokenId,\n        address _token,\n        bool _isCollateral,\n        uint256 _dailyLimit\n    ) external onlyOwner {\n        require(_tokenId != bytes32(0), \"Invalid tokenId\");\n        require(!_isRegistered(_tokenId), \"Token already registered\");\n        if (!_isCollateral) {\n            require(_token != address(0), \"Invalid token\");\n        }\n        TokenConfig storage cfg = tokenConfigs[_tokenId];\n        cfg.enabled = true;\n        cfg.isCollateral = _isCollateral;\n        cfg.token = _token;\n        cfg.dailyLimit = _resolveDailyLimit(_dailyLimit);\n        cfg.current24hAmount = 0;\n        cfg.lastReset = 0;\n        emit TokenRegistered(_tokenId, _token, _isCollateral, cfg.dailyLimit);\n    }\n\n    function setTokenEnabled(bytes32 _tokenId, bool _enabled) external onlyOwner {\n        require(_isRegistered(_tokenId), \"Token not registered\");\n        tokenConfigs[_tokenId].enabled = _enabled;\n        emit TokenEnabled(_tokenId, _enabled);\n    }\n\n    function setWhitelistEnabled(bool _enabled) external onlyOwner {\n        whitelistEnabled = _enabled;\n        emit WhitelistStatusChanged(_enabled);\n    }\n\n    function setWhitelisted(address _account, bool _allowed) external onlyOwner {\n        require(_account != address(0), \"Invalid account\");\n        whitelist[_account] = _allowed;\n        emit WhitelistUpdated(_account, _allowed);\n    }\n\n    function setWhitelistedBatch(address[] calldata _accounts, bool _allowed) external onlyOwner {\n        uint256 length = _accounts.length;\n        for (uint256 i = 0; i < length; ++i) {\n            address account = _accounts[i];\n            require(account != address(0), \"Invalid account\");\n            whitelist[account] = _allowed;\n            emit WhitelistUpdated(account, _allowed);\n        }\n    }\n\n    function setTokenDailyLimit(bytes32 _tokenId, uint256 _limit) external onlyOwner {\n        require(_isRegistered(_tokenId), \"Token not registered\");\n        uint256 resolvedLimit = _resolveDailyLimit(_limit);\n        tokenConfigs[_tokenId].dailyLimit = resolvedLimit;\n        emit TokenDailyLimitChanged(_tokenId, resolvedLimit);\n    }\n\n    /// @dev Remote routers must be peer bridge contracts that encode messages with\n    ///      `abi.encode(uint8, bytes32, bytes32, uint256)` using `MESSAGE_VERSION`.\n    function setRemoteRouter(bytes32 _tokenId, uint32 _domain, bytes32 _router) external onlyOwner {\n        require(_isRegistered(_tokenId), \"Token not registered\");\n        remoteRouters[_tokenId][_domain] = _router;\n        emit RemoteRouterSet(_tokenId, _domain, _router);\n    }\n\n    function setPause(bool _status) external onlyOwner {\n        if (_status) {\n            _pause();\n        } else {\n            _unpause();\n        }\n    }\n\n    function setTokenDecimalsConfig(\n        bytes32 _tokenId,\n        uint8 _localDecimals,\n        uint8 _sharedDecimals\n    ) external onlyOwner {\n        require(_isRegistered(_tokenId), \"Token not registered\");\n        uint8 onchainLocal = _localDecimalsForToken(_tokenId);\n        require(_localDecimals == onchainLocal, \"localDecimals mismatch\");\n        _setTokenDecimalsConfig(_tokenId, _localDecimals, _sharedDecimals);\n    }\n\n    function autoSetTokenDecimalsConfig(\n        bytes32 _tokenId,\n        uint8 _sharedDecimals\n    ) external onlyOwner {\n        require(_isRegistered(_tokenId), \"Token not registered\");\n        uint8 local = _localDecimalsForToken(_tokenId);\n        _setTokenDecimalsConfig(_tokenId, local, _sharedDecimals);\n    }\n\n    function getTokenDecimalsConfig(bytes32 _tokenId)\n        external\n        view\n        returns (bool configured, uint8 localDecimals, uint8 sharedDecimals)\n    {\n        TokenDecimalsConfig storage d = tokenDecimalsConfigs[_tokenId];\n        return (d.configured, d.localDecimals, d.sharedDecimals);\n    }\n\n    // --- Bridge logic ---\n\n    /// @notice Backward-compatible bridge entrypoint.\n    /// @dev The fee portion of `msg.value` is treated as the caller's maximum mailbox fee budget.\n    ///      Production integrations should prefer `bridgeWithMaxFee(...)` for an explicit bound.\n    ///      This bridge assumes the configured mailbox returns a quote compatible with `dispatch(...)`\n    ///      for identical parameters.\n    function bridge(bytes32 _tokenId, uint32 _destDomain, bytes32 _recipient, uint256 _amount) external payable whenNotPaused nonReentrant {\n        _bridge(_tokenId, _destDomain, _recipient, _amount, _legacyBridgeMaxFee(_tokenId, _amount));\n    }\n\n    function bridgeWithMaxFee(\n        bytes32 _tokenId,\n        uint32 _destDomain,\n        bytes32 _recipient,\n        uint256 _amount,\n        uint256 _maxFee\n    ) external payable whenNotPaused nonReentrant {\n        _bridge(_tokenId, _destDomain, _recipient, _amount, _maxFee);\n    }\n\n    function handle(uint32 _origin, bytes32 _sender, bytes calldata _message) external payable override onlyMailbox whenNotPaused nonReentrant {\n        require(msg.value == 0, \"Unexpected ETH\");\n        (bytes32 tokenId, bytes32 recipientBytes, uint256 amountShared) = _decodeBridgeMessage(_message);\n        _requireCanonicalRecipient(recipientBytes);\n        _requireValidDecimalsConfig(tokenId);\n        uint256 amountLocal = _toLocalAmount(tokenId, amountShared);\n\n        TokenConfig storage cfg = tokenConfigs[tokenId];\n        require(cfg.enabled, \"Token disabled\");\n        require(_isRegistered(tokenId), \"Token not registered\");\n        require(_sender == remoteRouters[tokenId][_origin], \"Invalid remote router\");\n\n        address recipient = address(uint160(uint256(recipientBytes)));\n        _resetDailyUsageIfNeeded(cfg);\n\n        if (cfg.current24hAmount + amountLocal > cfg.dailyLimit) {\n            pendingClaims[tokenId][recipient] += amountLocal;\n            emit PendingClaimRecorded(tokenId, recipient, _origin, amountLocal);\n            return;\n        }\n\n        if (_deliver(tokenId, cfg, recipient, amountLocal)) {\n            cfg.current24hAmount += amountLocal;\n            emit BridgeReceived(tokenId, recipient, _origin, amountLocal);\n            return;\n        }\n\n        pendingClaims[tokenId][recipient] += amountLocal;\n        emit PendingClaimRecorded(tokenId, recipient, _origin, amountLocal);\n    }\n\n    function quoteBridge(bytes32 _tokenId, uint32 _destDomain, bytes32 _recipient, uint256 _amount) external view returns (uint256) {\n        TokenConfig storage cfg = tokenConfigs[_tokenId];\n        require(cfg.enabled, \"Token disabled\");\n        require(_isRegistered(_tokenId), \"Token not registered\");\n        require(remoteRouters[_tokenId][_destDomain] != bytes32(0), \"Remote router not set\");\n        require(_amount > 0, \"Amount must be > 0\");\n        _requireCanonicalRecipient(_recipient);\n        if (whitelistEnabled) {\n            _requireWhitelistedRecipient(_recipient);\n        }\n        _requireValidDecimalsConfig(_tokenId);\n        bytes memory message = _buildOutboundMessageView(_tokenId, _recipient, _amount);\n        return mailbox.quoteDispatch(_destDomain, remoteRouters[_tokenId][_destDomain], message);\n    }\n\n    function getToken(bytes32 _tokenId) external view returns (\n        bool enabled,\n        bool isCollateral,\n        address token,\n        uint256 dailyLimit,\n        uint256 current24hAmount,\n        uint256 lastReset\n    ) {\n        TokenConfig storage cfg = tokenConfigs[_tokenId];\n        return (\n            cfg.enabled,\n            cfg.isCollateral,\n            cfg.token,\n            cfg.dailyLimit,\n            cfg.current24hAmount,\n            cfg.lastReset\n        );\n    }\n\n    function isTokenRegistered(bytes32 _tokenId) external view returns (bool) {\n        return _isRegistered(_tokenId);\n    }\n\n    function getPendingClaim(bytes32 _tokenId, address _account) external view returns (uint256) {\n        return pendingClaims[_tokenId][_account];\n    }\n\n    function claimPending(bytes32 _tokenId, address _recipient) external whenNotPaused nonReentrant {\n        _settlePendingClaim(_tokenId, msg.sender, _recipient, pendingClaims[_tokenId][msg.sender]);\n    }\n\n    function claimPending(bytes32 _tokenId, address _recipient, uint256 _amount) external whenNotPaused nonReentrant {\n        _settlePendingClaim(_tokenId, msg.sender, _recipient, _amount);\n    }\n\n    function recoverPendingClaim(\n        bytes32 _tokenId,\n        address _account,\n        address _recipient,\n        uint256 _amount\n    ) external onlyOwner whenPaused nonReentrant {\n        _settlePendingClaim(_tokenId, _account, _recipient, _amount);\n        emit PendingClaimRecovered(_tokenId, _account, _recipient, msg.sender, _amount);\n    }\n\n    function getTokenDailyLimitState(bytes32 _tokenId)\n        external\n        view\n        returns (uint256 dailyLimit, uint256 currentWindowAmount, uint256 remainingDailyCapacity, uint256 lastReset)\n    {\n        TokenConfig storage cfg = tokenConfigs[_tokenId];\n        (currentWindowAmount, lastReset) = _currentDailyUsage(cfg);\n        dailyLimit = cfg.dailyLimit;\n        remainingDailyCapacity = dailyLimit > currentWindowAmount ? dailyLimit - currentWindowAmount : 0;\n    }\n\n    function getNativeCollateralHealth(bytes32 _tokenId)\n        external\n        view\n        returns (\n            bool enabled,\n            bool isNativeCollateral,\n            uint256 bridgeBalance,\n            uint256 dailyLimit,\n            uint256 current24hAmount,\n            uint256 remainingDailyCapacity\n        )\n    {\n        TokenConfig storage cfg = tokenConfigs[_tokenId];\n        enabled = cfg.enabled;\n        isNativeCollateral = _isNativeCollateral(cfg);\n        bridgeBalance = isNativeCollateral ? address(this).balance : 0;\n        dailyLimit = cfg.dailyLimit;\n        (current24hAmount, ) = _currentDailyUsage(cfg);\n        remainingDailyCapacity = dailyLimit > current24hAmount ? dailyLimit - current24hAmount : 0;\n    }\n\n    function canReleaseNative(bytes32 _tokenId, uint256 _amount)\n        external\n        view\n        returns (bool ok, uint256 bridgeBalance)\n    {\n        TokenConfig storage cfg = tokenConfigs[_tokenId];\n        require(_isNativeCollateral(cfg), \"Token is not native collateral\");\n        bridgeBalance = address(this).balance;\n        ok = bridgeBalance >= _amount;\n    }\n\n    // --- Internal helpers ---\n\n    function deliverNativeToRecipient(address _recipient, uint256 _amount) external onlySelf {\n        (bool ok, ) = payable(_recipient).call{value: _amount}(\"\");\n        require(ok, \"Native transfer failed\");\n    }\n\n    function deliverCollateralToRecipient(address _token, address _recipient, uint256 _amount) external onlySelf {\n        uint256 bridgeBefore = IERC20(_token).balanceOf(address(this));\n        uint256 recipientBefore = IERC20(_token).balanceOf(_recipient);\n        IERC20(_token).safeTransfer(_recipient, _amount);\n        uint256 bridgeAfter = IERC20(_token).balanceOf(address(this));\n        uint256 recipientAfter = IERC20(_token).balanceOf(_recipient);\n        require(bridgeAfter <= bridgeBefore, \"Bridge balance invariant\");\n        require(recipientAfter >= recipientBefore, \"Recipient balance invariant\");\n\n        uint256 debited = bridgeBefore - bridgeAfter;\n        uint256 received = recipientAfter - recipientBefore;\n        require(received == _amount, \"Recipient delta mismatch\");\n        require(debited == _amount, \"Bridge debit mismatch\");\n    }\n\n    function mintSyntheticToRecipient(address _token, address _recipient, uint256 _amount) external onlySelf {\n        if (isPrivateBridge) {\n            IBridgeToken(_token).mintPrivate(_recipient, _amount);\n        } else {\n            IBridgeToken(_token).mintPublic(_recipient, _amount);\n        }\n    }\n\n    function _bridge(\n        bytes32 _tokenId,\n        uint32 _destDomain,\n        bytes32 _recipient,\n        uint256 _amount,\n        uint256 _maxFee\n    ) internal {\n        _requireCanonicalRecipient(_recipient);\n        if (whitelistEnabled) {\n            require(whitelist[msg.sender], \"Sender not whitelisted\");\n            _requireWhitelistedRecipient(_recipient);\n        }\n        TokenConfig storage cfg = tokenConfigs[_tokenId];\n        require(cfg.enabled, \"Token disabled\");\n        require(_isRegistered(_tokenId), \"Token not registered\");\n        require(remoteRouters[_tokenId][_destDomain] != bytes32(0), \"Remote router not set\");\n        require(_amount > 0, \"Amount must be > 0\");\n        require(_amount <= cfg.dailyLimit, \"Amount exceeds outbound per-tx limit\");\n        _requireValidDecimalsConfig(_tokenId);\n\n        bool isNative = _isNativeCollateral(cfg);\n        bytes memory message = _buildOutboundMessage(_tokenId, _recipient, _amount);\n        uint256 totalFee = mailbox.quoteDispatch(_destDomain, remoteRouters[_tokenId][_destDomain], message);\n        require(totalFee <= _maxFee, \"Bridge fee exceeds max\");\n\n        if (isNative) {\n            require(msg.value >= totalFee + _amount, \"Insufficient native value\");\n            emit NativeLocked(_tokenId, msg.sender, _destDomain, _recipient, _amount);\n        } else if (cfg.isCollateral) {\n            uint256 beforeBalance = IERC20(cfg.token).balanceOf(address(this));\n            IERC20(cfg.token).safeTransferFrom(msg.sender, address(this), _amount);\n            uint256 received = IERC20(cfg.token).balanceOf(address(this)) - beforeBalance;\n            require(received == _amount, \"Fee-on-transfer unsupported\");\n        } else {\n            if (isPrivateBridge) {\n                IBridgeToken(cfg.token).burnFromPrivate(msg.sender, _amount);\n            } else {\n                IBridgeToken(cfg.token).burnFromPublic(msg.sender, _amount);\n            }\n        }\n\n        if (!isNative) {\n            require(msg.value >= totalFee, \"Insufficient fee\");\n        }\n\n        mailbox.dispatch{value: totalFee}(_destDomain, remoteRouters[_tokenId][_destDomain], message);\n\n        uint256 consumed = totalFee + (isNative ? _amount : 0);\n        if (msg.value > consumed) {\n            uint256 refund = msg.value - consumed;\n            (bool ok, ) = payable(msg.sender).call{value: refund}(\"\");\n            require(ok, \"Refund transfer failed\");\n        }\n\n        emit BridgeSent(_tokenId, msg.sender, _destDomain, _recipient, _amount);\n    }\n\n    /// @dev Remote peer bridges must emit messages using this exact ABI encoding.\n    function _encodeBridgeMessage(bytes32 _tokenId, bytes32 _recipient, uint256 _amountShared) internal pure returns (bytes memory) {\n        return abi.encode(MESSAGE_VERSION, _tokenId, _recipient, _amountShared);\n    }\n\n    function _decodeBridgeMessage(bytes calldata _message)\n        internal\n        pure\n        returns (bytes32 tokenId, bytes32 recipientBytes, uint256 amountShared)\n    {\n        require(_message.length == MESSAGE_LENGTH, \"Invalid message length\");\n        (uint8 version, bytes32 decodedTokenId, bytes32 decodedRecipientBytes, uint256 decodedAmountShared) =\n            abi.decode(_message, (uint8, bytes32, bytes32, uint256));\n        require(version == MESSAGE_VERSION, \"Unsupported message version\");\n        return (decodedTokenId, decodedRecipientBytes, decodedAmountShared);\n    }\n\n    function _settlePendingClaim(bytes32 _tokenId, address _account, address _recipient, uint256 _amount) internal {\n        require(_account != address(0), \"Invalid account\");\n        require(_recipient != address(0), \"Invalid recipient\");\n        require(_recipient != address(this), \"Bridge self recipient\");\n\n        uint256 claimable = pendingClaims[_tokenId][_account];\n        require(claimable > 0, \"No pending claim\");\n        require(_amount > 0 && _amount <= claimable, \"Invalid claim amount\");\n\n        TokenConfig storage cfg = tokenConfigs[_tokenId];\n        require(_isRegistered(_tokenId), \"Token not registered\");\n\n        _resetDailyUsageIfNeeded(cfg);\n        require(cfg.current24hAmount + _amount <= cfg.dailyLimit, \"Daily limit exceeded\");\n\n        pendingClaims[_tokenId][_account] = claimable - _amount;\n        bool delivered = _deliver(_tokenId, cfg, _recipient, _amount);\n        if (!delivered) {\n            pendingClaims[_tokenId][_account] = claimable;\n            revert(\"Pending claim delivery failed\");\n        }\n\n        cfg.current24hAmount += _amount;\n        emit PendingClaimPaid(_tokenId, _account, _recipient, _amount);\n    }\n\n    function _buildOutboundMessage(bytes32 _tokenId, bytes32 _recipient, uint256 _amountLocal) internal returns (bytes memory) {\n        TokenDecimalsConfig storage d = tokenDecimalsConfigs[_tokenId];\n        require(d.configured, \"Token decimals not configured\");\n        uint256 amountShared = _toSharedAmount(_tokenId, _amountLocal, d);\n        return _encodeBridgeMessage(_tokenId, _recipient, amountShared);\n    }\n\n    function _buildOutboundMessageView(bytes32 _tokenId, bytes32 _recipient, uint256 _amountLocal) internal view returns (bytes memory) {\n        TokenDecimalsConfig storage d = tokenDecimalsConfigs[_tokenId];\n        require(d.configured, \"Token decimals not configured\");\n        uint256 amountShared = _toSharedAmountView(_amountLocal, d);\n        return _encodeBridgeMessage(_tokenId, _recipient, amountShared);\n    }\n\n    function _toSharedAmount(bytes32 _tokenId, uint256 _amountLocal, TokenDecimalsConfig storage d) internal returns (uint256) {\n        if (d.localDecimals == d.sharedDecimals) return _amountLocal;\n        uint8 diff = d.localDecimals - d.sharedDecimals;\n        uint256 factor = 10 ** diff;\n        uint256 amountShared = _amountLocal / factor;\n        uint256 dust = _amountLocal % factor;\n        if (dust > 0) {\n            emit AmountRounded(_tokenId, _amountLocal, amountShared, dust);\n        }\n        return amountShared;\n    }\n\n    function _toSharedAmountView(uint256 _amountLocal, TokenDecimalsConfig storage d) internal view returns (uint256) {\n        if (d.localDecimals == d.sharedDecimals) return _amountLocal;\n        uint8 diff = d.localDecimals - d.sharedDecimals;\n        uint256 factor = 10 ** diff;\n        return _amountLocal / factor;\n    }\n\n    function _toLocalAmount(bytes32 _tokenId, uint256 _amountShared) internal view returns (uint256) {\n        TokenDecimalsConfig storage d = tokenDecimalsConfigs[_tokenId];\n        require(d.configured, \"Token decimals not configured\");\n        if (d.localDecimals == d.sharedDecimals) return _amountShared;\n        uint8 diff = d.localDecimals - d.sharedDecimals;\n        return _amountShared * (10 ** diff);\n    }\n\n    function _isNativeCollateral(TokenConfig storage cfg) internal view returns (bool) {\n        return cfg.isCollateral && cfg.token == address(0);\n    }\n\n    function _deliver(\n        bytes32 _tokenId,\n        TokenConfig storage cfg,\n        address _recipient,\n        uint256 _amount\n    ) internal returns (bool) {\n        if (_isNativeCollateral(cfg)) {\n            try this.deliverNativeToRecipient(_recipient, _amount) {\n                emit NativeReleased(_tokenId, _recipient, _amount);\n                return true;\n            } catch {\n                return false;\n            }\n        }\n\n        if (cfg.isCollateral) {\n            try this.deliverCollateralToRecipient(cfg.token, _recipient, _amount) {\n                return true;\n            } catch {\n                return false;\n            }\n        }\n\n        try this.mintSyntheticToRecipient(cfg.token, _recipient, _amount) {\n            return true;\n        } catch {\n            return false;\n        }\n    }\n\n    function _isRegistered(bytes32 _tokenId) internal view returns (bool) {\n        TokenConfig storage cfg = tokenConfigs[_tokenId];\n        return cfg.isCollateral || cfg.token != address(0);\n    }\n\n    function _localDecimalsForToken(bytes32 _tokenId) internal view returns (uint8) {\n        TokenConfig storage cfg = tokenConfigs[_tokenId];\n        if (_isNativeCollateral(cfg)) {\n            return NATIVE_DECIMALS;\n        }\n        return IERC20MetadataLike(cfg.token).decimals();\n    }\n\n    function _requireValidDecimalsConfig(bytes32 _tokenId) internal view {\n        TokenDecimalsConfig storage d = tokenDecimalsConfigs[_tokenId];\n        require(d.configured, \"Token decimals not configured\");\n        require(d.localDecimals == _localDecimalsForToken(_tokenId), \"Token decimals changed\");\n    }\n\n    function _setTokenDecimalsConfig(bytes32 _tokenId, uint8 _localDecimals, uint8 _sharedDecimals) internal {\n        require(_sharedDecimals <= _localDecimals, \"sharedDecimals > localDecimals not supported\");\n        tokenDecimalsConfigs[_tokenId] = TokenDecimalsConfig({\n            configured: true,\n            localDecimals: _localDecimals,\n            sharedDecimals: _sharedDecimals\n        });\n        emit TokenDecimalsConfigured(_tokenId, _localDecimals, _sharedDecimals);\n    }\n\n    function _resolveDailyLimit(uint256 _dailyLimit) internal view returns (uint256) {\n        return _dailyLimit == USE_DEFAULT_DAILY_LIMIT ? defaultDailyLimit : _dailyLimit;\n    }\n\n    function _requireCanonicalRecipient(bytes32 _recipient) internal view {\n        require(_recipient != bytes32(0) && (uint256(_recipient) >> 160) == 0, \"Invalid recipient\");\n        require(address(uint160(uint256(_recipient))) != address(this), \"Bridge self recipient\");\n    }\n\n    function _requireWhitelistedRecipient(bytes32 _recipient) internal view {\n        require(whitelist[address(uint160(uint256(_recipient)))], \"Recipient not whitelisted\");\n    }\n\n    function _legacyBridgeMaxFee(bytes32 _tokenId, uint256 _amount) internal returns (uint256) {\n        TokenConfig storage cfg = tokenConfigs[_tokenId];\n        if (_isNativeCollateral(cfg)) {\n            require(msg.value >= _amount, \"Insufficient native value\");\n            return msg.value - _amount;\n        }\n        return msg.value;\n    }\n\n    function _resetDailyUsageIfNeeded(TokenConfig storage cfg) internal {\n        if (block.timestamp > cfg.lastReset + 1 days) {\n            cfg.current24hAmount = 0;\n            cfg.lastReset = block.timestamp;\n        }\n    }\n\n    function _currentDailyUsage(TokenConfig storage cfg) internal view returns (uint256 current24hAmount, uint256 lastReset) {\n        if (block.timestamp > cfg.lastReset + 1 days) {\n            return (0, block.timestamp);\n        }\n        return (cfg.current24hAmount, cfg.lastReset);\n    }\n}\n","deployed_bytecode":"0x6080604052600436101561001257600080fd5b6000803560e01c8063052d9e7e14611b60578063155bf4e214611aee5780632036b42b14611ad2578063203fd1ec14611a4b5780632d4ba14914611a075780632f6707e91461191657806330da53c2146116b357806335075b521461164b5780633849c008146115cb57806339a8120b146114ca57806339ff7ca5146114a75780633c699382146114605780633f827a5a14611444578063445bbfd5146113fe5780634f1ef286146111d857806351fb012d146111b257806352d1902d1461114a57806356d5d47514611080578063578042f114610fe15780635c975abb14610fb15780635ffddf9e14610f885780636e7caec214610f05578063715018a614610e9b5780637c1b129a14610e5f5780637caccc9914610dce5780638d3ccf9f14610da05780638da5cb5b14610d6a57806391086dd614610bba5780639249fb7814610afb5780639281aa0b14610a7057806393fdfe8214610a1f5780639b19251a146109e0578063a6c74c721461095c578063ab456849146108f1578063ad3cb1cc146108a4578063bedb86fb146107c8578063c76b0888146107aa578063d39b42a814610454578063d5438eae1461042d578063e00a96fd146103de578063ef88b19414610399578063f2fde38b1461036c5763fc9f1092146101f657600080fd5b34610369576102fb9060206102b56102ae61021036611ce0565b8388969495929396526002875261022d60ff60408a205416611e58565b61023e610239866122c9565b611db4565b848852600387526040882063ffffffff8716600052875261026560406000205415156121e9565b61027081151561222d565b610279836125c1565b60ff60075460081c1661035b575b61029085612642565b8488526004875260408820906102a960ff8354166125f6565b6133b3565b90836133e1565b9160018060a01b03855416918552600384526040852063ffffffff82166000528452604060002054906040519687948593849363138857a360e31b85526004850161226e565b03915afa90811561034f5790610317575b602090604051908152f35b506020813d602011610347575b8161033160209383611c63565b81010312610342576020905161030c565b600080fd5b3d9150610324565b604051903d90823e3d90fd5b610364836132a3565b610287565b80fd5b503461036957602036600319011261036957610396610389611bed565b610391612293565b612173565b80f35b50346103695760403660031901126103695763ffffffff60406103ba611cb7565b92600435815260036020522091166000526020526020604060002054604051908152f35b5034610369576060366003190112610369576104186103fb611c03565b6104036124d7565b61040b612501565b6044359033600435613069565b60016000805160206135528339815191525580f35b5034610369578060031936011261036957546040516001600160a01b039091168152602090f35b50346103695761046336611c29565b9161046f303314611d4c565b6040516370a0823160e01b81523060048201526001600160a01b039190911691602082602481865afa91821561079f57859261076b575b506040516370a0823160e01b81526001600160a01b038216600482018190529190602081602481885afa90811561072a5786908892610735575b5060405163a9059cbb60e01b60208201526001600160a01b039390931660248401526044808401919091528252906105239061051d606482611c63565b85613338565b6040516370a0823160e01b815230600482015291602083602481885afa92831561072a5787936106f5575b506020906024604051809781936370a0823160e01b835260048301525afa9384156106ea5786946106b6575b508282116106715780841061062c5761059761059d928694611e35565b93611e35565b036105e757036105aa5780f35b60405162461bcd60e51b8152602060048201526015602482015274084e4d2c8ceca40c8cac4d2e840dad2e6dac2e8c6d605b1b6044820152606490fd5b60405162461bcd60e51b815260206004820152601860248201527f526563697069656e742064656c7461206d69736d6174636800000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601b60248201527f526563697069656e742062616c616e636520696e76617269616e7400000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601860248201527f4272696467652062616c616e636520696e76617269616e7400000000000000006044820152606490fd5b9093506020813d6020116106e2575b816106d260209383611c63565b810103126103425751923861057a565b3d91506106c5565b6040513d88823e3d90fd5b9092506020813d602011610722575b8161071160209383611c63565b81010312610342575191602061054e565b3d9150610704565b6040513d89823e3d90fd5b9150506020813d602011610763575b8161075160209383611c63565b8101031261034257518561051d6104e0565b3d9150610744565b9091506020813d602011610797575b8161078760209383611c63565b81010312610342575190386104a6565b3d915061077a565b6040513d87823e3d90fd5b50346103695780600319360112610369576020600154604051908152f35b5034610369576020366003190112610369576107e2611bc0565b6107ea612293565b1561084b576107f76124d7565b600160ff19600080516020613532833981519152541617600080516020613532833981519152557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b61085361303e565b60ff196000805160206135328339815191525416600080516020613532833981519152557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a180f35b5034610369578060031936011261036957506108ed6040516108c7604082611c63565b60058152640352e302e360dc1b6020820152604051918291602083526020830190611d0b565b0390f35b5034610369576109427f79c7172861b61247ba0b8e8aef82f44cd74d3c6558e350a74e9e1465e67487cb602061092636611cca565b610931949194612293565b61093d610239866122c9565b613032565b83855260028252806001604087200155604051908152a280f35b503461036957606036600319011261036957600435610979611cb7565b907fc23b28efe37127decf94c8f138ad29cae1db56add1cc807b2819ac0c45acbcbb602063ffffffff604435946109ae612293565b6109ba610239866122c9565b84875260038352604087208282166000528352856040600020556040519586521693a380f35b50346103695760203660031901126103695760209060ff906040906001600160a01b03610a0b611bed565b168152600684522054166040519015158152f35b503461036957604036600319011261036957610418600435610a3f611c03565b610a476124d7565b610a4f612501565b81845260056020908152604080862033600081815291909352205492613069565b503461036957604036600319011261036957610a8a611bed565b610a92611bcf565b90610a9b612293565b6001600160a01b031690610ab0821515611df7565b8183526006602052610ad181604085209060ff801983541691151516179055565b1515907ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d8380a380f35b503461036957608036600319011261036957600435610b18611c03565b6044356001600160a01b038116929091838303610bb657610b9e7f8cc049e63f4ea612c45ba2e74ba7ac0b1111724ace68014d6e3c520e3371d93191610b7b6064358096610b64612293565b610b6c61303e565b610b74612501565b8387613069565b6040805133815260208101969096526001600160a01b0390911694918291820190565b0390a460016000805160206135528339815191525580f35b8480fd5b503461036957608036600319011261036957600435610bd7611c03565b90610be0611bde565b91610be9612293565b8115610d3357610bf8826122c9565b610cee57821580610cab575b828552600260205260408520805462010000600160b01b031961ffff19909116921560081b61ff00169290921760011791909116601083901b62010000600160b01b03161781557faca7b9a76a4adaeda7a2bf81239cb2164e4517a7170e890ca18bf6d38db72f5a91856003610c7b606435613032565b600185018190556002850183905593015560408051951515865260208601929092526001600160a01b031693a380f35b6001600160a01b038216610c045760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b2103a37b5b2b760991b6044820152606490fd5b60405162461bcd60e51b815260206004820152601860248201527f546f6b656e20616c7265616479207265676973746572656400000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a59081d1bdad95b9259608a1b6044820152606490fd5b50346103695780600319360112610369576000805160206134f2833981519152546040516001600160a01b039091168152602090f35b50610418610dad36611ce0565b91610db66124d7565b610dbe612501565b610dc88385612ffe565b93612948565b50346103695760203660031901126103695760c090600435815260026020526040812060ff81541691610e00826128d8565b918215610e5957475b610e176001830154926124ac565b509283831115610e535750610e2c8383611e35565b935b60405195151586521515602086015260408501526060840152608083015260a0820152f35b93610e2e565b81610e09565b5060a036600319011261036957610418610e77611cb7565b610e7f6124d7565b610e87612501565b608435906064359060443590600435612948565b5034610369578060031936011261036957610eb4612293565b6000805160206134f283398151915280546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b503461036957610f286040610f1936611cca565b939081526002602052206128d8565b15610f43576040805147928310158152602081019290925290f35b60405162461bcd60e51b815260206004820152601e60248201527f546f6b656e206973206e6f74206e617469766520636f6c6c61746572616c00006044820152606490fd5b5034610369576020366003190112610369576020610fa76004356122c9565b6040519015158152f35b5034610369578060031936011261036957602060ff60008051602061353283398151915254166040519015158152f35b503461036957606036600319011261036957600435610ffe611c19565b6044359060ff8216820361107c57611014612293565b611020610239846122c9565b60ff61102b846122fc565b1660ff82160361103e576103969261239a565b60405162461bcd60e51b81526020600482015260166024820152750d8dec6c2d888cac6d2dac2d8e640dad2e6dac2e8c6d60531b6044820152606490fd5b8380fd5b5060603660031901126103695760043563ffffffff81168103611146576044359067ffffffffffffffff821161114257366023830112156111425781600401359067ffffffffffffffff821161107c57366024838501011161107c5783546001600160a01b0316330361110e576024610418936110fb6124d7565b611103612501565b019060243590611ea2565b60405162461bcd60e51b815260206004820152600c60248201526b09edcd8f240dac2d2d8c4def60a31b6044820152606490fd5b8280fd5b5080fd5b50346103695780600319360112610369577f000000000000000000000000c625deaabc944b503d81dd2f8b39f844c2b047916001600160a01b031630036111a35760206040516000805160206135128339815191528152f35b63703e46dd60e11b8152600490fd5b5034610369578060031936011261036957602060ff60075460081c166040519015158152f35b506040366003190112610369576111ed611bed565b6024359067ffffffffffffffff82116111425736602383011215611142578160040135908361121b83611c9b565b936112296040519586611c63565b8385526020850193366024828401011161114257806024602093018637850101526001600160a01b037f000000000000000000000000c625deaabc944b503d81dd2f8b39f844c2b04791163081149081156113db575b506113cc5761128c612293565b6040516352d1902d60e01b81526001600160a01b0382169390602081600481885afa869181611398575b506112cf57634c9c8ce360e01b86526004859052602486fd5b93846000805160206135128339815191528796036113865750823b156113745760008051602061351283398151915280546001600160a01b031916821790558491907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8380a2805115611359576113559382915190845af461134f611d84565b91613490565b5080f35b50505050346113655780f35b63b398979f60e01b8152600490fd5b634c9c8ce360e01b8552600452602484fd5b632a87526960e21b8652600452602485fd5b9091506020813d6020116113c4575b816113b460209383611c63565b81010312610342575190386112b6565b3d91506113a7565b63703e46dd60e11b8452600484fd5b600080516020613512833981519152546001600160a01b0316141590503861127f565b503461036957602036600319011261036957604060609160043581526004602052205460ff6040519181811615158352818160081c16602084015260101c166040820152f35b5034610369578060031936011261036957602060405160018152f35b503461036957604036600319011261036957604061147c611c03565b9160043581526005602052209060018060a01b03166000526020526020604060002054604051908152f35b5034610369578060031936011261036957602060ff600754166040519015158152f35b503461036957806114da36611c29565b916114e6303314611d4c565b60075460ff1615611563576001600160a01b031691823b1561155e57604051633627d3a160e01b81526001600160a01b0392909216600483015260248201529082908290604490829084905af180156115535761154257505080f35b8161154c91611c63565b6103695780f35b6040513d84823e3d90fd5b505050fd5b6001600160a01b03169291833b1561114257604051639f93f77960e01b81526001600160a01b0392909216600483015260248201529181908390604490829084905af180156115be576115b557505080f35b61039691611c63565b50604051903d90823e3d90fd5b5034610369576040366003190112610369576004357f765c0f39f280c04b857ee55d7ce19099562d4ef0a53f3ab80e09eea8fbe59eee602061160b611bcf565b611613612293565b61161f610239856122c9565b8385526002825261163f81604087209060ff801983541691151516179055565b6040519015158152a280f35b50346103695760203660031901126103695760809060043581526002602052600160408220611679816124ac565b9290910154928184116000146116ad57506116948184611e35565b905b604051938452602084015260408301526060820152f35b90611696565b5034610369576060366003190112610369576116cd611bed565b6116d5611bde565b600080516020613572833981519152549160ff8360401c16159267ffffffffffffffff81168015908161190e575b6001149081611904575b1590816118fb575b506118ec5767ffffffffffffffff19811660011760008051602061357283398151915255836118bf575b506001600160a01b031680156118885761175761330a565b61175f61330a565b61176833612173565b61177061330a565b61177861330a565b61178061330a565b61178861330a565b6001600080516020613552833981519152556bffffffffffffffffffffffff60a01b84541617835560243560015515159060ff60075461ff008460081b16908285169061ffff1916171780600755604051937fee7fbec60f2b1296e00bfa73f76113db4bcc15c79e436ade829a07ffb87d3ed78680a260081c1615157f1cf28b997975c7be355bcef74f2f5019aa48253bc1e54b3c8b002471865fdba88480a2611830575080f35b60207fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29168ff00000000000000001960008051602061357283398151915254166000805160206135728339815191525560018152a180f35b60405162461bcd60e51b815260206004820152600f60248201526e092dcecc2d8d2c840dac2d2d8c4def608b1b6044820152606490fd5b68ffffffffffffffffff19166801000000000000000117600080516020613572833981519152553861173f565b63f92ee8a960e01b8552600485fd5b90501538611715565b303b15915061170d565b859150611703565b50346103695760403660031901126103695760043567ffffffffffffffff8111611146573660238201121561114657806004013567ffffffffffffffff8111611142573660248260051b840101116111425790611971611bcf565b611979612293565b80151591845b84811015611a03576024600582901b830101356001600160a01b03811691908290036119ff5784826119b46001941515611df7565b80895260066020526119d58660408b209060ff801983541691151516179055565b7ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d8980a30161197f565b8680fd5b8580f35b503461036957604036600319011261036957610396600435611a27611c19565b90611a30612293565b611a3c610239826122c9565b611a45816122fc565b9061239a565b50346103695760403660031901126103695780808080611a69611bed565b611a74303314611d4c565b602435906001600160a01b03165af1611a8b611d84565b5015611a945780f35b60405162461bcd60e51b815260206004820152601660248201527513985d1a5d99481d1c985b9cd9995c8819985a5b195960521b6044820152606490fd5b5034610369578060031936011261036957602090604051908152f35b503461036957602036600319011261036957604060c091600435815260026020522080549060018101549060036002820154910154916040519360ff81161515855260ff8160081c161515602086015260018060a01b039060101c1660408501526060840152608083015260a0820152f35b503461036957602036600319011261036957611b7a611bc0565b611b82612293565b151560075461ff008260081b169061ff001916176007557f1cf28b997975c7be355bcef74f2f5019aa48253bc1e54b3c8b002471865fdba88280a280f35b60043590811515820361034257565b60243590811515820361034257565b60443590811515820361034257565b600435906001600160a01b038216820361034257565b602435906001600160a01b038216820361034257565b6024359060ff8216820361034257565b6060906003190112610342576004356001600160a01b038116810361034257906024356001600160a01b0381168103610342579060443590565b90601f8019910116810190811067ffffffffffffffff821117611c8557604052565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff8111611c8557601f01601f191660200190565b6024359063ffffffff8216820361034257565b6040906003190112610342576004359060243590565b6080906003190112610342576004359060243563ffffffff8116810361034257906044359060643590565b919082519283825260005b848110611d37575050826000602080949584010152601f8019910116010190565b80602080928401015182828601015201611d16565b15611d5357565b60405162461bcd60e51b815260206004820152600960248201526827b7363c9039b2b63360b91b6044820152606490fd5b3d15611daf573d90611d9582611c9b565b91611da36040519384611c63565b82523d6000602084013e565b606090565b15611dbb57565b60405162461bcd60e51b8152602060048201526014602482015273151bdad95b881b9bdd081c9959da5cdd195c995960621b6044820152606490fd5b15611dfe57565b60405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a59081858d8dbdd5b9d608a1b6044820152606490fd5b91908203918211611e4257565b634e487b7160e01b600052601160045260246000fd5b15611e5f57565b60405162461bcd60e51b815260206004820152600e60248201526d151bdad95b88191a5cd8589b195960921b6044820152606490fd5b91908201809211611e4257565b929190913461213d57608081036120ff5781608091810103126103425780359260ff8416809403610342576020820135916001604082013595036120ba576060611f0091611eef876125c1565b611ef885612642565b0135836126d8565b93826000526002602052604060002093611f1d60ff865416611e58565b611f29610239856122c9565b836000526003602052604060002063ffffffff84166000526020526040600020540361207d576001600160a01b031692611f6281612732565b84846002830192611f74838554611e95565b6001820154106120255790611f8a92918661275c565b611ff05750602063ffffffff7fb059c56ce928779a942b1e1d46b11907ed2974fa6551c6643e4a1664afdd3edb928460005260058352604060002060018060a01b03871660005283526040600020611fe3888254611e95565b90556040519687521694a4565b63ffffffff7fb6bfe3a2ebfacc79b2b41a5353910fda1b6564c15b7f133b99f52fe191ac6b899282611fe38860209554611e95565b50505050602063ffffffff7fb059c56ce928779a942b1e1d46b11907ed2974fa6551c6643e4a1664afdd3edb928460005260058352604060002060018060a01b03871660005283526040600020611fe3888254611e95565b60405162461bcd60e51b815260206004820152601560248201527424b73b30b634b2103932b6b7ba32903937baba32b960591b6044820152606490fd5b60405162461bcd60e51b815260206004820152601b60248201527f556e737570706f72746564206d6573736167652076657273696f6e00000000006044820152606490fd5b60405162461bcd60e51b8152602060048201526016602482015275092dcecc2d8d2c840dacae6e6c2ceca40d8cadccee8d60531b6044820152606490fd5b60405162461bcd60e51b815260206004820152600e60248201526d0aadccaf0e0cac6e8cac8408aa8960931b6044820152606490fd5b6001600160a01b031680156121d3576000805160206134f283398151915280546001600160a01b0319811683179091556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b156121f057565b60405162461bcd60e51b815260206004820152601560248201527414995b5bdd19481c9bdd5d195c881b9bdd081cd95d605a1b6044820152606490fd5b1561223457565b60405162461bcd60e51b81526020600482015260126024820152710416d6f756e74206d757374206265203e20360741b6044820152606490fd5b612290939263ffffffff60609316825260208201528160408201520190611d0b565b90565b6000805160206134f2833981519152546001600160a01b031633036122b457565b63118cdaa760e01b6000523360045260246000fd5b600052600260205260406000205460ff8160081c169081156122e9575090565b60101c6001600160a01b03161515919050565b60005260026020526040600020612312816128d8565b612394575460405163313ce56760e01b8152906020908290600490829060101c6001600160a01b03165afa9081156123885760009161234f575090565b6020813d602011612380575b8161236860209383611c63565b8101031261114657519060ff82168203610369575090565b3d915061235b565b6040513d6000823e3d90fd5b50601290565b9160ff91821691168181116124525760405191606083019183831067ffffffffffffffff841117611c85577f04d2dbb9ad83e59e1399967ff322f1d78473aada1431e5917c4368614338bfe59360409384526001815260208101838152848201908382528760005260046020526124248660002093511515849060ff801983541691151516179055565b519061ff0062ff00008454925160101b169260081b169062ffff0019161717905582519182526020820152a2565b60405162461bcd60e51b815260206004820152602c60248201527f736861726564446563696d616c73203e206c6f63616c446563696d616c73206e60448201526b1bdd081cdd5c1c1bdc9d195960a21b6064820152608490fd5b90600382015491620151808301808411611e425742116124ce57600201549190565b50600091504290565b60ff60008051602061353283398151915254166124f057565b63d93c066560e01b60005260046000fd5b6002600080516020613552833981519152541461252c57600260008051602061355283398151915255565b633ee5aeb560e01b60005260046000fd5b1561254457565b60405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b6044820152606490fd5b1561258457565b60405162461bcd60e51b8152602060048201526015602482015274109c9a5919d9481cd95b19881c9958da5c1a595b9d605a1b6044820152606490fd5b6125e890801515806125ea575b6125d79061253d565b6001600160a01b031630141561257d565b565b5060a081901c156125ce565b156125fd57565b60405162461bcd60e51b815260206004820152601d60248201527f546f6b656e20646563696d616c73206e6f7420636f6e666967757265640000006044820152606490fd5b80600052600460205260ff80612668604060002054936126638386166125f6565b6122fc565b169160081c160361267557565b60405162461bcd60e51b8152602060048201526016602482015275151bdad95b88191958da5b585b1cc818da185b99d95960521b6044820152606490fd5b9060ff8091169116039060ff8211611e4257565b60ff16604d8111611e4257600a0a90565b60005260046020526040600020546126f260ff82166125f6565b60ff808260081c169160101c169081811461272d5761271991612714916126b3565b6126c7565b90818102918183041490151715611e425790565b505090565b60038101908154620151808101809111611e42574211612750575050565b60026000910155429055565b92919060009361276b826128d8565b61283f5750805460ff8160081c166127f857505460101c6001600160a01b0316303b1561107c576040516339a8120b60e01b81526001600160a01b03918216600482015291166024820152604481019190915281808280606481015b038183305af191826127e3575b50506127dd5790565b50600190565b816127ed91611c63565b6111465781386127d4565b9050303b1561107c57604051631a73685560e31b81526001600160a01b0360109290921c8216600482015291166024820152604481019190915281808280606481016127c7565b919050303b1561107c5760405163080ff47b60e21b81526001600160a01b038216600482015260248101849052848160448183305af190816128c4575b506128875750505090565b6040519283526001600160a01b03169250907f8f9c086e9ec90b46781381ea2f47cbbbae7018ed8864f98379bb0265071eb84590602090a3600190565b856128d191969296611c63565b933861287c565b5460ff8160081c1690816128ea575090565b60101c6001600160a01b031615919050565b1561290357565b60405162461bcd60e51b815260206004820152601960248201527f496e73756666696369656e74206e61746976652076616c7565000000000000006044820152606490fd5b93929192612955846125c1565b6007549060009160ff8160081c16612f9d575b8683526002602052604083209081549161298460ff8416611e58565b6129906102398a6122c9565b88855260036020526040852063ffffffff871686526020526129b7604086205415156121e9565b6129c287151561222d565b60018101548711612f4c57612a5a926129da8a612642565b6129e3826128d8565b928a87526004602052612a12612a0b8c8b60408b2091612a0660ff8454166125f6565b61340c565b8b8d6133e1565b956020878d60018060a01b038b5416908b526003835260408b2063ffffffff8d168c52835260408b20548c6040519a8b948593849363138857a360e31b85526004850161226e565b03915afa958615612f41578896612f09575b508511612ecb578315612c6c57505050612a91612a898784611e95565b3410156128fc565b60405187815286602082015263ffffffff861690897f03f50561972cf218fe21736aa6bd39ad589960dcd13daf0439e16069c9e376ed60403393a45b8015612c2c575b6020612b1f9360018060a01b038654168a8752600383526040872063ffffffff891660005283526040600020548560405180988195829463fa31de0160e01b84528d6004850161226e565b03925af18015612c2157612bee575b612b3f925015612be7578490611e95565b803411612b84575b505063ffffffff91604051938452602084015216917f0830fdfcf51adca1fc3e5367d28c9e8d5a34fd9711af49f6bd678f03ed80d33b60403393a4565b8180612b91819334611e35565b335af1612b9c611d84565b5015612ba9573880612b47565b60405162461bcd60e51b81526020600482015260166024820152751499599d5b99081d1c985b9cd9995c8819985a5b195960521b6044820152606490fd5b8290611e95565b6020833d602011612c19575b81612c0760209383611c63565b8101031261034257612b3f9250612b2e565b3d9150612bfa565b6040513d86823e3d90fd5b81341015612ad45760405162461bcd60e51b815260206004820152601060248201526f496e73756666696369656e742066656560801b6044820152606490fd5b60ff8260081c16600014612dfa57505080546040516370a0823160e01b8152306004820152919060101c6001600160a01b0316602083602481845afa92831561072a578793612dc5575b506040516323b872dd60e01b6020808301919091523360248084019190915230604484015260648084018d905283529390929091612cfe91612cf9608483611c63565b613338565b546040516370a0823160e01b8152306004820152928391829060101c6001600160a01b03165afa9081156106ea57908892918791612d8c575b5090612d4291611e35565b14612acd5760405162461bcd60e51b815260206004820152601b60248201527f4665652d6f6e2d7472616e7366657220756e737570706f7274656400000000006044820152606490fd5b919250506020813d602011612dbd575b81612da960209383611c63565b810103126103425751879190612d42612d37565b3d9150612d9c565b9092506020813d602011612df2575b81612de160209383611c63565b810103126103425751916024612cb6565b3d9150612dd4565b60ff1615612e6957505460101c6001600160a01b0316803b15610bb657604051630265959960e21b8152336004820152602481018890529085908290604490829084905af1801561079f57908591612e54575b5050612acd565b81612e5e91611c63565b61107c578338612e4d565b60101c6001600160a01b03169050803b15610bb657604051635699f18160e01b8152336004820152602481018890529085908290604490829084905af1801561079f57612eb7575b50612acd565b84612ec491959295611c63565b9238612eb1565b60405162461bcd60e51b8152602060048201526016602482015275084e4d2c8ceca40cccaca40caf0c6cacac8e640dac2f60531b6044820152606490fd5b9095506020813d602011612f39575b81612f2560209383611c63565b81010312612f3557519438612a6c565b8780fd5b3d9150612f18565b6040513d8a823e3d90fd5b60405162461bcd60e51b8152602060048201526024808201527f416d6f756e742065786365656473206f7574626f756e64207065722d7478206c6044820152631a5b5a5d60e21b6064820152608490fd5b338352600660205260ff60408420541615612fc057612fbb866132a3565b612968565b60405162461bcd60e51b815260206004820152601660248201527514d95b99195c881b9bdd081dda1a5d195b1a5cdd195960521b6044820152606490fd5b600052600260205261301360406000206128d8565b61301c57503490565b8061302c612290923410156128fc565b34611e35565b80612290575060015490565b60ff60008051602061353283398151915254161561305857565b638dfc202b60e01b60005260046000fd5b90926001600160a01b03841692613081841515611df7565b6001600160a01b0381169461309786151561253d565b6130a33087141561257d565b836000526005602052604060002085600052602052604060002054801561326b5783151580613261575b15613225578460005260026020526040600020906130ed610239876122c9565b6130f682612732565b6002820193613106868654611e95565b6001840154106131e9576131409261311f878094611e35565b88600052600560205260406000208a6000526020526040600020558761275c565b15613181575081816131767f4d56815d17c3d4548a8ecda3498620849040e851ae43ff46a0972e2920920ac79460209454611e95565b9055604051908152a4565b60008481526005602090815260408083206001600160a01b039094168352929052205060405162461bcd60e51b815260206004820152601d60248201527f50656e64696e6720636c61696d2064656c6976657279206661696c65640000006044820152606490fd5b60405162461bcd60e51b815260206004820152601460248201527311185a5b1e481b1a5b5a5d08195e18d95959195960621b6044820152606490fd5b60405162461bcd60e51b8152602060048201526014602482015273125b9d985b1a590818db185a5b48185b5bdd5b9d60621b6044820152606490fd5b50808411156130cd565b60405162461bcd60e51b815260206004820152601060248201526f4e6f2070656e64696e6720636c61696d60801b6044820152606490fd5b6001600160a01b031660009081526006602052604090205460ff16156132c557565b60405162461bcd60e51b815260206004820152601960248201527f526563697069656e74206e6f742077686974656c6973746564000000000000006044820152606490fd5b60ff6000805160206135728339815191525460401c161561332757565b631afcd79f60e31b60005260046000fd5b906000602091828151910182855af115612388576000513d61338a57506001600160a01b0381163b155b6133695750565b635274afe760e01b60009081526001600160a01b0391909116600452602490fd5b60011415613362565b811561339d570490565b634e487b7160e01b600052601260045260246000fd5b905460ff808260081c169160101c169081811461272d5761271461229093926133db926126b3565b90613393565b919060405192600160208501526040840152606083015260808201526080815261229060a082611c63565b90915460ff808260081c169160101c169081811461344b5761343191612714916126b3565b9161343c8382613393565b92801561339d57810680613451575b50505090565b7fbc264b43f8e7d6cfe143996f01b0d3ef76b7721d69ba96e92a7c8c72131e555d916060916040519182528560208301526040820152a238808061344b565b906134b657508051156134a557602081519101fd5b63d6bda27560e01b60005260046000fd5b815115806134e8575b6134c7575090565b639996b31560e01b60009081526001600160a01b0391909116600452602490fd5b50803b156134bf56fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbccd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033009b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a2646970667358221220b5ef7f310a111030d14e59cc22d878a8b3fcea76f1106188143dbad3628c755364736f6c634300081c0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"paris","libraries":{},"optimizer":{"enabled":true,"runs":200},"outputSelection":{"*":{"":["*"],"*":["*"]}},"viaIR":true},"optimization_runs":200,"sourcify_repo_url":null,"decoded_constructor_args":null,"compiler_version":"v0.8.28+commit.7893614a","is_verified_via_verifier_alliance":false,"verified_at":"2026-04-27T10:51:28.621890Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x60a080604052346100ea57306080527ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c166100d9576002600160401b03196001600160401b03821601610073575b6040516135c790816100f0823960805181818161115d01526112540152f35b6001600160401b0319166001600160401b039081177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005581527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a13880610054565b63f92ee8a960e01b60005260046000fd5b600080fdfe6080604052600436101561001257600080fd5b6000803560e01c8063052d9e7e14611b60578063155bf4e214611aee5780632036b42b14611ad2578063203fd1ec14611a4b5780632d4ba14914611a075780632f6707e91461191657806330da53c2146116b357806335075b521461164b5780633849c008146115cb57806339a8120b146114ca57806339ff7ca5146114a75780633c699382146114605780633f827a5a14611444578063445bbfd5146113fe5780634f1ef286146111d857806351fb012d146111b257806352d1902d1461114a57806356d5d47514611080578063578042f114610fe15780635c975abb14610fb15780635ffddf9e14610f885780636e7caec214610f05578063715018a614610e9b5780637c1b129a14610e5f5780637caccc9914610dce5780638d3ccf9f14610da05780638da5cb5b14610d6a57806391086dd614610bba5780639249fb7814610afb5780639281aa0b14610a7057806393fdfe8214610a1f5780639b19251a146109e0578063a6c74c721461095c578063ab456849146108f1578063ad3cb1cc146108a4578063bedb86fb146107c8578063c76b0888146107aa578063d39b42a814610454578063d5438eae1461042d578063e00a96fd146103de578063ef88b19414610399578063f2fde38b1461036c5763fc9f1092146101f657600080fd5b34610369576102fb9060206102b56102ae61021036611ce0565b8388969495929396526002875261022d60ff60408a205416611e58565b61023e610239866122c9565b611db4565b848852600387526040882063ffffffff8716600052875261026560406000205415156121e9565b61027081151561222d565b610279836125c1565b60ff60075460081c1661035b575b61029085612642565b8488526004875260408820906102a960ff8354166125f6565b6133b3565b90836133e1565b9160018060a01b03855416918552600384526040852063ffffffff82166000528452604060002054906040519687948593849363138857a360e31b85526004850161226e565b03915afa90811561034f5790610317575b602090604051908152f35b506020813d602011610347575b8161033160209383611c63565b81010312610342576020905161030c565b600080fd5b3d9150610324565b604051903d90823e3d90fd5b610364836132a3565b610287565b80fd5b503461036957602036600319011261036957610396610389611bed565b610391612293565b612173565b80f35b50346103695760403660031901126103695763ffffffff60406103ba611cb7565b92600435815260036020522091166000526020526020604060002054604051908152f35b5034610369576060366003190112610369576104186103fb611c03565b6104036124d7565b61040b612501565b6044359033600435613069565b60016000805160206135528339815191525580f35b5034610369578060031936011261036957546040516001600160a01b039091168152602090f35b50346103695761046336611c29565b9161046f303314611d4c565b6040516370a0823160e01b81523060048201526001600160a01b039190911691602082602481865afa91821561079f57859261076b575b506040516370a0823160e01b81526001600160a01b038216600482018190529190602081602481885afa90811561072a5786908892610735575b5060405163a9059cbb60e01b60208201526001600160a01b039390931660248401526044808401919091528252906105239061051d606482611c63565b85613338565b6040516370a0823160e01b815230600482015291602083602481885afa92831561072a5787936106f5575b506020906024604051809781936370a0823160e01b835260048301525afa9384156106ea5786946106b6575b508282116106715780841061062c5761059761059d928694611e35565b93611e35565b036105e757036105aa5780f35b60405162461bcd60e51b8152602060048201526015602482015274084e4d2c8ceca40c8cac4d2e840dad2e6dac2e8c6d605b1b6044820152606490fd5b60405162461bcd60e51b815260206004820152601860248201527f526563697069656e742064656c7461206d69736d6174636800000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601b60248201527f526563697069656e742062616c616e636520696e76617269616e7400000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601860248201527f4272696467652062616c616e636520696e76617269616e7400000000000000006044820152606490fd5b9093506020813d6020116106e2575b816106d260209383611c63565b810103126103425751923861057a565b3d91506106c5565b6040513d88823e3d90fd5b9092506020813d602011610722575b8161071160209383611c63565b81010312610342575191602061054e565b3d9150610704565b6040513d89823e3d90fd5b9150506020813d602011610763575b8161075160209383611c63565b8101031261034257518561051d6104e0565b3d9150610744565b9091506020813d602011610797575b8161078760209383611c63565b81010312610342575190386104a6565b3d915061077a565b6040513d87823e3d90fd5b50346103695780600319360112610369576020600154604051908152f35b5034610369576020366003190112610369576107e2611bc0565b6107ea612293565b1561084b576107f76124d7565b600160ff19600080516020613532833981519152541617600080516020613532833981519152557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b61085361303e565b60ff196000805160206135328339815191525416600080516020613532833981519152557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a180f35b5034610369578060031936011261036957506108ed6040516108c7604082611c63565b60058152640352e302e360dc1b6020820152604051918291602083526020830190611d0b565b0390f35b5034610369576109427f79c7172861b61247ba0b8e8aef82f44cd74d3c6558e350a74e9e1465e67487cb602061092636611cca565b610931949194612293565b61093d610239866122c9565b613032565b83855260028252806001604087200155604051908152a280f35b503461036957606036600319011261036957600435610979611cb7565b907fc23b28efe37127decf94c8f138ad29cae1db56add1cc807b2819ac0c45acbcbb602063ffffffff604435946109ae612293565b6109ba610239866122c9565b84875260038352604087208282166000528352856040600020556040519586521693a380f35b50346103695760203660031901126103695760209060ff906040906001600160a01b03610a0b611bed565b168152600684522054166040519015158152f35b503461036957604036600319011261036957610418600435610a3f611c03565b610a476124d7565b610a4f612501565b81845260056020908152604080862033600081815291909352205492613069565b503461036957604036600319011261036957610a8a611bed565b610a92611bcf565b90610a9b612293565b6001600160a01b031690610ab0821515611df7565b8183526006602052610ad181604085209060ff801983541691151516179055565b1515907ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d8380a380f35b503461036957608036600319011261036957600435610b18611c03565b6044356001600160a01b038116929091838303610bb657610b9e7f8cc049e63f4ea612c45ba2e74ba7ac0b1111724ace68014d6e3c520e3371d93191610b7b6064358096610b64612293565b610b6c61303e565b610b74612501565b8387613069565b6040805133815260208101969096526001600160a01b0390911694918291820190565b0390a460016000805160206135528339815191525580f35b8480fd5b503461036957608036600319011261036957600435610bd7611c03565b90610be0611bde565b91610be9612293565b8115610d3357610bf8826122c9565b610cee57821580610cab575b828552600260205260408520805462010000600160b01b031961ffff19909116921560081b61ff00169290921760011791909116601083901b62010000600160b01b03161781557faca7b9a76a4adaeda7a2bf81239cb2164e4517a7170e890ca18bf6d38db72f5a91856003610c7b606435613032565b600185018190556002850183905593015560408051951515865260208601929092526001600160a01b031693a380f35b6001600160a01b038216610c045760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b2103a37b5b2b760991b6044820152606490fd5b60405162461bcd60e51b815260206004820152601860248201527f546f6b656e20616c7265616479207265676973746572656400000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a59081d1bdad95b9259608a1b6044820152606490fd5b50346103695780600319360112610369576000805160206134f2833981519152546040516001600160a01b039091168152602090f35b50610418610dad36611ce0565b91610db66124d7565b610dbe612501565b610dc88385612ffe565b93612948565b50346103695760203660031901126103695760c090600435815260026020526040812060ff81541691610e00826128d8565b918215610e5957475b610e176001830154926124ac565b509283831115610e535750610e2c8383611e35565b935b60405195151586521515602086015260408501526060840152608083015260a0820152f35b93610e2e565b81610e09565b5060a036600319011261036957610418610e77611cb7565b610e7f6124d7565b610e87612501565b608435906064359060443590600435612948565b5034610369578060031936011261036957610eb4612293565b6000805160206134f283398151915280546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b503461036957610f286040610f1936611cca565b939081526002602052206128d8565b15610f43576040805147928310158152602081019290925290f35b60405162461bcd60e51b815260206004820152601e60248201527f546f6b656e206973206e6f74206e617469766520636f6c6c61746572616c00006044820152606490fd5b5034610369576020366003190112610369576020610fa76004356122c9565b6040519015158152f35b5034610369578060031936011261036957602060ff60008051602061353283398151915254166040519015158152f35b503461036957606036600319011261036957600435610ffe611c19565b6044359060ff8216820361107c57611014612293565b611020610239846122c9565b60ff61102b846122fc565b1660ff82160361103e576103969261239a565b60405162461bcd60e51b81526020600482015260166024820152750d8dec6c2d888cac6d2dac2d8e640dad2e6dac2e8c6d60531b6044820152606490fd5b8380fd5b5060603660031901126103695760043563ffffffff81168103611146576044359067ffffffffffffffff821161114257366023830112156111425781600401359067ffffffffffffffff821161107c57366024838501011161107c5783546001600160a01b0316330361110e576024610418936110fb6124d7565b611103612501565b019060243590611ea2565b60405162461bcd60e51b815260206004820152600c60248201526b09edcd8f240dac2d2d8c4def60a31b6044820152606490fd5b8280fd5b5080fd5b50346103695780600319360112610369577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031630036111a35760206040516000805160206135128339815191528152f35b63703e46dd60e11b8152600490fd5b5034610369578060031936011261036957602060ff60075460081c166040519015158152f35b506040366003190112610369576111ed611bed565b6024359067ffffffffffffffff82116111425736602383011215611142578160040135908361121b83611c9b565b936112296040519586611c63565b8385526020850193366024828401011161114257806024602093018637850101526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163081149081156113db575b506113cc5761128c612293565b6040516352d1902d60e01b81526001600160a01b0382169390602081600481885afa869181611398575b506112cf57634c9c8ce360e01b86526004859052602486fd5b93846000805160206135128339815191528796036113865750823b156113745760008051602061351283398151915280546001600160a01b031916821790558491907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8380a2805115611359576113559382915190845af461134f611d84565b91613490565b5080f35b50505050346113655780f35b63b398979f60e01b8152600490fd5b634c9c8ce360e01b8552600452602484fd5b632a87526960e21b8652600452602485fd5b9091506020813d6020116113c4575b816113b460209383611c63565b81010312610342575190386112b6565b3d91506113a7565b63703e46dd60e11b8452600484fd5b600080516020613512833981519152546001600160a01b0316141590503861127f565b503461036957602036600319011261036957604060609160043581526004602052205460ff6040519181811615158352818160081c16602084015260101c166040820152f35b5034610369578060031936011261036957602060405160018152f35b503461036957604036600319011261036957604061147c611c03565b9160043581526005602052209060018060a01b03166000526020526020604060002054604051908152f35b5034610369578060031936011261036957602060ff600754166040519015158152f35b503461036957806114da36611c29565b916114e6303314611d4c565b60075460ff1615611563576001600160a01b031691823b1561155e57604051633627d3a160e01b81526001600160a01b0392909216600483015260248201529082908290604490829084905af180156115535761154257505080f35b8161154c91611c63565b6103695780f35b6040513d84823e3d90fd5b505050fd5b6001600160a01b03169291833b1561114257604051639f93f77960e01b81526001600160a01b0392909216600483015260248201529181908390604490829084905af180156115be576115b557505080f35b61039691611c63565b50604051903d90823e3d90fd5b5034610369576040366003190112610369576004357f765c0f39f280c04b857ee55d7ce19099562d4ef0a53f3ab80e09eea8fbe59eee602061160b611bcf565b611613612293565b61161f610239856122c9565b8385526002825261163f81604087209060ff801983541691151516179055565b6040519015158152a280f35b50346103695760203660031901126103695760809060043581526002602052600160408220611679816124ac565b9290910154928184116000146116ad57506116948184611e35565b905b604051938452602084015260408301526060820152f35b90611696565b5034610369576060366003190112610369576116cd611bed565b6116d5611bde565b600080516020613572833981519152549160ff8360401c16159267ffffffffffffffff81168015908161190e575b6001149081611904575b1590816118fb575b506118ec5767ffffffffffffffff19811660011760008051602061357283398151915255836118bf575b506001600160a01b031680156118885761175761330a565b61175f61330a565b61176833612173565b61177061330a565b61177861330a565b61178061330a565b61178861330a565b6001600080516020613552833981519152556bffffffffffffffffffffffff60a01b84541617835560243560015515159060ff60075461ff008460081b16908285169061ffff1916171780600755604051937fee7fbec60f2b1296e00bfa73f76113db4bcc15c79e436ade829a07ffb87d3ed78680a260081c1615157f1cf28b997975c7be355bcef74f2f5019aa48253bc1e54b3c8b002471865fdba88480a2611830575080f35b60207fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29168ff00000000000000001960008051602061357283398151915254166000805160206135728339815191525560018152a180f35b60405162461bcd60e51b815260206004820152600f60248201526e092dcecc2d8d2c840dac2d2d8c4def608b1b6044820152606490fd5b68ffffffffffffffffff19166801000000000000000117600080516020613572833981519152553861173f565b63f92ee8a960e01b8552600485fd5b90501538611715565b303b15915061170d565b859150611703565b50346103695760403660031901126103695760043567ffffffffffffffff8111611146573660238201121561114657806004013567ffffffffffffffff8111611142573660248260051b840101116111425790611971611bcf565b611979612293565b80151591845b84811015611a03576024600582901b830101356001600160a01b03811691908290036119ff5784826119b46001941515611df7565b80895260066020526119d58660408b209060ff801983541691151516179055565b7ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d8980a30161197f565b8680fd5b8580f35b503461036957604036600319011261036957610396600435611a27611c19565b90611a30612293565b611a3c610239826122c9565b611a45816122fc565b9061239a565b50346103695760403660031901126103695780808080611a69611bed565b611a74303314611d4c565b602435906001600160a01b03165af1611a8b611d84565b5015611a945780f35b60405162461bcd60e51b815260206004820152601660248201527513985d1a5d99481d1c985b9cd9995c8819985a5b195960521b6044820152606490fd5b5034610369578060031936011261036957602090604051908152f35b503461036957602036600319011261036957604060c091600435815260026020522080549060018101549060036002820154910154916040519360ff81161515855260ff8160081c161515602086015260018060a01b039060101c1660408501526060840152608083015260a0820152f35b503461036957602036600319011261036957611b7a611bc0565b611b82612293565b151560075461ff008260081b169061ff001916176007557f1cf28b997975c7be355bcef74f2f5019aa48253bc1e54b3c8b002471865fdba88280a280f35b60043590811515820361034257565b60243590811515820361034257565b60443590811515820361034257565b600435906001600160a01b038216820361034257565b602435906001600160a01b038216820361034257565b6024359060ff8216820361034257565b6060906003190112610342576004356001600160a01b038116810361034257906024356001600160a01b0381168103610342579060443590565b90601f8019910116810190811067ffffffffffffffff821117611c8557604052565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff8111611c8557601f01601f191660200190565b6024359063ffffffff8216820361034257565b6040906003190112610342576004359060243590565b6080906003190112610342576004359060243563ffffffff8116810361034257906044359060643590565b919082519283825260005b848110611d37575050826000602080949584010152601f8019910116010190565b80602080928401015182828601015201611d16565b15611d5357565b60405162461bcd60e51b815260206004820152600960248201526827b7363c9039b2b63360b91b6044820152606490fd5b3d15611daf573d90611d9582611c9b565b91611da36040519384611c63565b82523d6000602084013e565b606090565b15611dbb57565b60405162461bcd60e51b8152602060048201526014602482015273151bdad95b881b9bdd081c9959da5cdd195c995960621b6044820152606490fd5b15611dfe57565b60405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a59081858d8dbdd5b9d608a1b6044820152606490fd5b91908203918211611e4257565b634e487b7160e01b600052601160045260246000fd5b15611e5f57565b60405162461bcd60e51b815260206004820152600e60248201526d151bdad95b88191a5cd8589b195960921b6044820152606490fd5b91908201809211611e4257565b929190913461213d57608081036120ff5781608091810103126103425780359260ff8416809403610342576020820135916001604082013595036120ba576060611f0091611eef876125c1565b611ef885612642565b0135836126d8565b93826000526002602052604060002093611f1d60ff865416611e58565b611f29610239856122c9565b836000526003602052604060002063ffffffff84166000526020526040600020540361207d576001600160a01b031692611f6281612732565b84846002830192611f74838554611e95565b6001820154106120255790611f8a92918661275c565b611ff05750602063ffffffff7fb059c56ce928779a942b1e1d46b11907ed2974fa6551c6643e4a1664afdd3edb928460005260058352604060002060018060a01b03871660005283526040600020611fe3888254611e95565b90556040519687521694a4565b63ffffffff7fb6bfe3a2ebfacc79b2b41a5353910fda1b6564c15b7f133b99f52fe191ac6b899282611fe38860209554611e95565b50505050602063ffffffff7fb059c56ce928779a942b1e1d46b11907ed2974fa6551c6643e4a1664afdd3edb928460005260058352604060002060018060a01b03871660005283526040600020611fe3888254611e95565b60405162461bcd60e51b815260206004820152601560248201527424b73b30b634b2103932b6b7ba32903937baba32b960591b6044820152606490fd5b60405162461bcd60e51b815260206004820152601b60248201527f556e737570706f72746564206d6573736167652076657273696f6e00000000006044820152606490fd5b60405162461bcd60e51b8152602060048201526016602482015275092dcecc2d8d2c840dacae6e6c2ceca40d8cadccee8d60531b6044820152606490fd5b60405162461bcd60e51b815260206004820152600e60248201526d0aadccaf0e0cac6e8cac8408aa8960931b6044820152606490fd5b6001600160a01b031680156121d3576000805160206134f283398151915280546001600160a01b0319811683179091556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b156121f057565b60405162461bcd60e51b815260206004820152601560248201527414995b5bdd19481c9bdd5d195c881b9bdd081cd95d605a1b6044820152606490fd5b1561223457565b60405162461bcd60e51b81526020600482015260126024820152710416d6f756e74206d757374206265203e20360741b6044820152606490fd5b612290939263ffffffff60609316825260208201528160408201520190611d0b565b90565b6000805160206134f2833981519152546001600160a01b031633036122b457565b63118cdaa760e01b6000523360045260246000fd5b600052600260205260406000205460ff8160081c169081156122e9575090565b60101c6001600160a01b03161515919050565b60005260026020526040600020612312816128d8565b612394575460405163313ce56760e01b8152906020908290600490829060101c6001600160a01b03165afa9081156123885760009161234f575090565b6020813d602011612380575b8161236860209383611c63565b8101031261114657519060ff82168203610369575090565b3d915061235b565b6040513d6000823e3d90fd5b50601290565b9160ff91821691168181116124525760405191606083019183831067ffffffffffffffff841117611c85577f04d2dbb9ad83e59e1399967ff322f1d78473aada1431e5917c4368614338bfe59360409384526001815260208101838152848201908382528760005260046020526124248660002093511515849060ff801983541691151516179055565b519061ff0062ff00008454925160101b169260081b169062ffff0019161717905582519182526020820152a2565b60405162461bcd60e51b815260206004820152602c60248201527f736861726564446563696d616c73203e206c6f63616c446563696d616c73206e60448201526b1bdd081cdd5c1c1bdc9d195960a21b6064820152608490fd5b90600382015491620151808301808411611e425742116124ce57600201549190565b50600091504290565b60ff60008051602061353283398151915254166124f057565b63d93c066560e01b60005260046000fd5b6002600080516020613552833981519152541461252c57600260008051602061355283398151915255565b633ee5aeb560e01b60005260046000fd5b1561254457565b60405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b6044820152606490fd5b1561258457565b60405162461bcd60e51b8152602060048201526015602482015274109c9a5919d9481cd95b19881c9958da5c1a595b9d605a1b6044820152606490fd5b6125e890801515806125ea575b6125d79061253d565b6001600160a01b031630141561257d565b565b5060a081901c156125ce565b156125fd57565b60405162461bcd60e51b815260206004820152601d60248201527f546f6b656e20646563696d616c73206e6f7420636f6e666967757265640000006044820152606490fd5b80600052600460205260ff80612668604060002054936126638386166125f6565b6122fc565b169160081c160361267557565b60405162461bcd60e51b8152602060048201526016602482015275151bdad95b88191958da5b585b1cc818da185b99d95960521b6044820152606490fd5b9060ff8091169116039060ff8211611e4257565b60ff16604d8111611e4257600a0a90565b60005260046020526040600020546126f260ff82166125f6565b60ff808260081c169160101c169081811461272d5761271991612714916126b3565b6126c7565b90818102918183041490151715611e425790565b505090565b60038101908154620151808101809111611e42574211612750575050565b60026000910155429055565b92919060009361276b826128d8565b61283f5750805460ff8160081c166127f857505460101c6001600160a01b0316303b1561107c576040516339a8120b60e01b81526001600160a01b03918216600482015291166024820152604481019190915281808280606481015b038183305af191826127e3575b50506127dd5790565b50600190565b816127ed91611c63565b6111465781386127d4565b9050303b1561107c57604051631a73685560e31b81526001600160a01b0360109290921c8216600482015291166024820152604481019190915281808280606481016127c7565b919050303b1561107c5760405163080ff47b60e21b81526001600160a01b038216600482015260248101849052848160448183305af190816128c4575b506128875750505090565b6040519283526001600160a01b03169250907f8f9c086e9ec90b46781381ea2f47cbbbae7018ed8864f98379bb0265071eb84590602090a3600190565b856128d191969296611c63565b933861287c565b5460ff8160081c1690816128ea575090565b60101c6001600160a01b031615919050565b1561290357565b60405162461bcd60e51b815260206004820152601960248201527f496e73756666696369656e74206e61746976652076616c7565000000000000006044820152606490fd5b93929192612955846125c1565b6007549060009160ff8160081c16612f9d575b8683526002602052604083209081549161298460ff8416611e58565b6129906102398a6122c9565b88855260036020526040852063ffffffff871686526020526129b7604086205415156121e9565b6129c287151561222d565b60018101548711612f4c57612a5a926129da8a612642565b6129e3826128d8565b928a87526004602052612a12612a0b8c8b60408b2091612a0660ff8454166125f6565b61340c565b8b8d6133e1565b956020878d60018060a01b038b5416908b526003835260408b2063ffffffff8d168c52835260408b20548c6040519a8b948593849363138857a360e31b85526004850161226e565b03915afa958615612f41578896612f09575b508511612ecb578315612c6c57505050612a91612a898784611e95565b3410156128fc565b60405187815286602082015263ffffffff861690897f03f50561972cf218fe21736aa6bd39ad589960dcd13daf0439e16069c9e376ed60403393a45b8015612c2c575b6020612b1f9360018060a01b038654168a8752600383526040872063ffffffff891660005283526040600020548560405180988195829463fa31de0160e01b84528d6004850161226e565b03925af18015612c2157612bee575b612b3f925015612be7578490611e95565b803411612b84575b505063ffffffff91604051938452602084015216917f0830fdfcf51adca1fc3e5367d28c9e8d5a34fd9711af49f6bd678f03ed80d33b60403393a4565b8180612b91819334611e35565b335af1612b9c611d84565b5015612ba9573880612b47565b60405162461bcd60e51b81526020600482015260166024820152751499599d5b99081d1c985b9cd9995c8819985a5b195960521b6044820152606490fd5b8290611e95565b6020833d602011612c19575b81612c0760209383611c63565b8101031261034257612b3f9250612b2e565b3d9150612bfa565b6040513d86823e3d90fd5b81341015612ad45760405162461bcd60e51b815260206004820152601060248201526f496e73756666696369656e742066656560801b6044820152606490fd5b60ff8260081c16600014612dfa57505080546040516370a0823160e01b8152306004820152919060101c6001600160a01b0316602083602481845afa92831561072a578793612dc5575b506040516323b872dd60e01b6020808301919091523360248084019190915230604484015260648084018d905283529390929091612cfe91612cf9608483611c63565b613338565b546040516370a0823160e01b8152306004820152928391829060101c6001600160a01b03165afa9081156106ea57908892918791612d8c575b5090612d4291611e35565b14612acd5760405162461bcd60e51b815260206004820152601b60248201527f4665652d6f6e2d7472616e7366657220756e737570706f7274656400000000006044820152606490fd5b919250506020813d602011612dbd575b81612da960209383611c63565b810103126103425751879190612d42612d37565b3d9150612d9c565b9092506020813d602011612df2575b81612de160209383611c63565b810103126103425751916024612cb6565b3d9150612dd4565b60ff1615612e6957505460101c6001600160a01b0316803b15610bb657604051630265959960e21b8152336004820152602481018890529085908290604490829084905af1801561079f57908591612e54575b5050612acd565b81612e5e91611c63565b61107c578338612e4d565b60101c6001600160a01b03169050803b15610bb657604051635699f18160e01b8152336004820152602481018890529085908290604490829084905af1801561079f57612eb7575b50612acd565b84612ec491959295611c63565b9238612eb1565b60405162461bcd60e51b8152602060048201526016602482015275084e4d2c8ceca40cccaca40caf0c6cacac8e640dac2f60531b6044820152606490fd5b9095506020813d602011612f39575b81612f2560209383611c63565b81010312612f3557519438612a6c565b8780fd5b3d9150612f18565b6040513d8a823e3d90fd5b60405162461bcd60e51b8152602060048201526024808201527f416d6f756e742065786365656473206f7574626f756e64207065722d7478206c6044820152631a5b5a5d60e21b6064820152608490fd5b338352600660205260ff60408420541615612fc057612fbb866132a3565b612968565b60405162461bcd60e51b815260206004820152601660248201527514d95b99195c881b9bdd081dda1a5d195b1a5cdd195960521b6044820152606490fd5b600052600260205261301360406000206128d8565b61301c57503490565b8061302c612290923410156128fc565b34611e35565b80612290575060015490565b60ff60008051602061353283398151915254161561305857565b638dfc202b60e01b60005260046000fd5b90926001600160a01b03841692613081841515611df7565b6001600160a01b0381169461309786151561253d565b6130a33087141561257d565b836000526005602052604060002085600052602052604060002054801561326b5783151580613261575b15613225578460005260026020526040600020906130ed610239876122c9565b6130f682612732565b6002820193613106868654611e95565b6001840154106131e9576131409261311f878094611e35565b88600052600560205260406000208a6000526020526040600020558761275c565b15613181575081816131767f4d56815d17c3d4548a8ecda3498620849040e851ae43ff46a0972e2920920ac79460209454611e95565b9055604051908152a4565b60008481526005602090815260408083206001600160a01b039094168352929052205060405162461bcd60e51b815260206004820152601d60248201527f50656e64696e6720636c61696d2064656c6976657279206661696c65640000006044820152606490fd5b60405162461bcd60e51b815260206004820152601460248201527311185a5b1e481b1a5b5a5d08195e18d95959195960621b6044820152606490fd5b60405162461bcd60e51b8152602060048201526014602482015273125b9d985b1a590818db185a5b48185b5bdd5b9d60621b6044820152606490fd5b50808411156130cd565b60405162461bcd60e51b815260206004820152601060248201526f4e6f2070656e64696e6720636c61696d60801b6044820152606490fd5b6001600160a01b031660009081526006602052604090205460ff16156132c557565b60405162461bcd60e51b815260206004820152601960248201527f526563697069656e74206e6f742077686974656c6973746564000000000000006044820152606490fd5b60ff6000805160206135728339815191525460401c161561332757565b631afcd79f60e31b60005260046000fd5b906000602091828151910182855af115612388576000513d61338a57506001600160a01b0381163b155b6133695750565b635274afe760e01b60009081526001600160a01b0391909116600452602490fd5b60011415613362565b811561339d570490565b634e487b7160e01b600052601260045260246000fd5b905460ff808260081c169160101c169081811461272d5761271461229093926133db926126b3565b90613393565b919060405192600160208501526040840152606083015260808201526080815261229060a082611c63565b90915460ff808260081c169160101c169081811461344b5761343191612714916126b3565b9161343c8382613393565b92801561339d57810680613451575b50505090565b7fbc264b43f8e7d6cfe143996f01b0d3ef76b7721d69ba96e92a7c8c72131e555d916060916040519182528560208301526040820152a238808061344b565b906134b657508051156134a557602081519101fd5b63d6bda27560e01b60005260046000fd5b815115806134e8575b6134c7575090565b639996b31560e01b60009081526001600160a01b0391909116600452602490fd5b50803b156134bf56fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbccd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033009b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a2646970667358221220b5ef7f310a111030d14e59cc22d878a8b3fcea76f1106188143dbad3628c755364736f6c634300081c0033","name":"HyperlaneTokenBridge","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":false,"language":"solidity","evm_version":"paris","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"@openzeppelin/contracts/proxy/beacon/IBeacon.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (proxy/beacon/IBeacon.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n    /**\n     * @dev Must return an address that can be used as a delegate call target.\n     *\n     * {UpgradeableBeacon} will check that this address is a contract.\n     */\n    function implementation() external view returns (address);\n}\n"},{"file_path":"@openzeppelin/contracts/interfaces/draft-IERC1822.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n    /**\n     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n     * address.\n     *\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n     * function revert if invoked through a proxy.\n     */\n    function proxiableUUID() external view returns (bytes32);\n}\n"},{"file_path":"@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (proxy/ERC1967/ERC1967Utils.sol)\n\npragma solidity ^0.8.21;\n\nimport {IBeacon} from \"../beacon/IBeacon.sol\";\nimport {IERC1967} from \"../../interfaces/IERC1967.sol\";\nimport {Address} from \"../../utils/Address.sol\";\nimport {StorageSlot} from \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This library provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.\n */\nlibrary ERC1967Utils {\n    /**\n     * @dev Storage slot with the address of the current implementation.\n     * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1.\n     */\n    // solhint-disable-next-line private-vars-leading-underscore\n    bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n    /**\n     * @dev The `implementation` of the proxy is invalid.\n     */\n    error ERC1967InvalidImplementation(address implementation);\n\n    /**\n     * @dev The `admin` of the proxy is invalid.\n     */\n    error ERC1967InvalidAdmin(address admin);\n\n    /**\n     * @dev The `beacon` of the proxy is invalid.\n     */\n    error ERC1967InvalidBeacon(address beacon);\n\n    /**\n     * @dev An upgrade function sees `msg.value > 0` that may be lost.\n     */\n    error ERC1967NonPayable();\n\n    /**\n     * @dev Returns the current implementation address.\n     */\n    function getImplementation() internal view returns (address) {\n        return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the ERC-1967 implementation slot.\n     */\n    function _setImplementation(address newImplementation) private {\n        if (newImplementation.code.length == 0) {\n            revert ERC1967InvalidImplementation(newImplementation);\n        }\n        StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\n    }\n\n    /**\n     * @dev Performs implementation upgrade with additional setup call if data is nonempty.\n     * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\n     * to avoid stuck value in the contract.\n     *\n     * Emits an {IERC1967-Upgraded} event.\n     */\n    function upgradeToAndCall(address newImplementation, bytes memory data) internal {\n        _setImplementation(newImplementation);\n        emit IERC1967.Upgraded(newImplementation);\n\n        if (data.length > 0) {\n            Address.functionDelegateCall(newImplementation, data);\n        } else {\n            _checkNonPayable();\n        }\n    }\n\n    /**\n     * @dev Storage slot with the admin of the contract.\n     * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1.\n     */\n    // solhint-disable-next-line private-vars-leading-underscore\n    bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n    /**\n     * @dev Returns the current admin.\n     *\n     * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\n     * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n     * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n     */\n    function getAdmin() internal view returns (address) {\n        return StorageSlot.getAddressSlot(ADMIN_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the ERC-1967 admin slot.\n     */\n    function _setAdmin(address newAdmin) private {\n        if (newAdmin == address(0)) {\n            revert ERC1967InvalidAdmin(address(0));\n        }\n        StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;\n    }\n\n    /**\n     * @dev Changes the admin of the proxy.\n     *\n     * Emits an {IERC1967-AdminChanged} event.\n     */\n    function changeAdmin(address newAdmin) internal {\n        emit IERC1967.AdminChanged(getAdmin(), newAdmin);\n        _setAdmin(newAdmin);\n    }\n\n    /**\n     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n     * This is the keccak-256 hash of \"eip1967.proxy.beacon\" subtracted by 1.\n     */\n    // solhint-disable-next-line private-vars-leading-underscore\n    bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n    /**\n     * @dev Returns the current beacon.\n     */\n    function getBeacon() internal view returns (address) {\n        return StorageSlot.getAddressSlot(BEACON_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new beacon in the ERC-1967 beacon slot.\n     */\n    function _setBeacon(address newBeacon) private {\n        if (newBeacon.code.length == 0) {\n            revert ERC1967InvalidBeacon(newBeacon);\n        }\n\n        StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;\n\n        address beaconImplementation = IBeacon(newBeacon).implementation();\n        if (beaconImplementation.code.length == 0) {\n            revert ERC1967InvalidImplementation(beaconImplementation);\n        }\n    }\n\n    /**\n     * @dev Change the beacon and trigger a setup call if data is nonempty.\n     * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\n     * to avoid stuck value in the contract.\n     *\n     * Emits an {IERC1967-BeaconUpgraded} event.\n     *\n     * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since\n     * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for\n     * efficiency.\n     */\n    function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {\n        _setBeacon(newBeacon);\n        emit IERC1967.BeaconUpgraded(newBeacon);\n\n        if (data.length > 0) {\n            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n        } else {\n            _checkNonPayable();\n        }\n    }\n\n    /**\n     * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract\n     * if an upgrade doesn't perform an initialization call.\n     */\n    function _checkNonPayable() private {\n        if (msg.value > 0) {\n            revert ERC1967NonPayable();\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\n    struct OwnableStorage {\n        address _owner;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Ownable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\n\n    function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\n        assembly {\n            $.slot := OwnableStorageLocation\n        }\n    }\n\n    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    function __Ownable_init(address initialOwner) internal onlyInitializing {\n        __Ownable_init_unchained(initialOwner);\n    }\n\n    function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        OwnableStorage storage $ = _getOwnableStorage();\n        return $._owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        OwnableStorage storage $ = _getOwnableStorage();\n        address oldOwner = $._owner;\n        $._owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Storage of the initializable contract.\n     *\n     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n     * when using with upgradeable contracts.\n     *\n     * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n     */\n    struct InitializableStorage {\n        /**\n         * @dev Indicates that the contract has been initialized.\n         */\n        uint64 _initialized;\n        /**\n         * @dev Indicates that the contract is in the process of being initialized.\n         */\n        bool _initializing;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n    /**\n     * @dev The contract is already initialized.\n     */\n    error InvalidInitialization();\n\n    /**\n     * @dev The contract is not initializing.\n     */\n    error NotInitializing();\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint64 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n     * production.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        // Cache values to avoid duplicated sloads\n        bool isTopLevelCall = !$._initializing;\n        uint64 initialized = $._initialized;\n\n        // Allowed calls:\n        // - initialSetup: the contract is not in the initializing state and no previous version was\n        //                 initialized\n        // - construction: the contract is initialized at version 1 (no reinitialization) and the\n        //                 current contract is just being deployed\n        bool initialSetup = initialized == 0 && isTopLevelCall;\n        bool construction = initialized == 1 && address(this).code.length == 0;\n\n        if (!initialSetup && !construction) {\n            revert InvalidInitialization();\n        }\n        $._initialized = 1;\n        if (isTopLevelCall) {\n            $._initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            $._initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint64 version) {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing || $._initialized >= version) {\n            revert InvalidInitialization();\n        }\n        $._initialized = version;\n        $._initializing = true;\n        _;\n        $._initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        _checkInitializing();\n        _;\n    }\n\n    /**\n     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n     */\n    function _checkInitializing() internal view virtual {\n        if (!_isInitializing()) {\n            revert NotInitializing();\n        }\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing) {\n            revert InvalidInitialization();\n        }\n        if ($._initialized != type(uint64).max) {\n            $._initialized = type(uint64).max;\n            emit Initialized(type(uint64).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint64) {\n        return _getInitializableStorage()._initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _getInitializableStorage()._initializing;\n    }\n\n    /**\n     * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.\n     *\n     * NOTE: Consider following the ERC-7201 formula to derive storage locations.\n     */\n    function _initializableStorageSlot() internal pure virtual returns (bytes32) {\n        return INITIALIZABLE_STORAGE;\n    }\n\n    /**\n     * @dev Returns a pointer to the storage namespace.\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n        bytes32 slot = _initializableStorageSlot();\n        assembly {\n            $.slot := slot\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.22;\n\nimport {IERC1822Proxiable} from \"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\";\nimport {ERC1967Utils} from \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol\";\nimport {Initializable} from \"./Initializable.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n */\nabstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {\n    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n    address private immutable __self = address(this);\n\n    /**\n     * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`\n     * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,\n     * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.\n     * If the getter returns `\"5.0.0\"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must\n     * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function\n     * during an upgrade.\n     */\n    string public constant UPGRADE_INTERFACE_VERSION = \"5.0.0\";\n\n    /**\n     * @dev The call is from an unauthorized context.\n     */\n    error UUPSUnauthorizedCallContext();\n\n    /**\n     * @dev The storage `slot` is unsupported as a UUID.\n     */\n    error UUPSUnsupportedProxiableUUID(bytes32 slot);\n\n    /**\n     * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n     * a proxy contract with an implementation (as defined in ERC-1967) pointing to self. This should only be the case\n     * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n     * function through ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n     * fail.\n     */\n    modifier onlyProxy() {\n        _checkProxy();\n        _;\n    }\n\n    /**\n     * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n     * callable on the implementing contract but not through proxies.\n     */\n    modifier notDelegated() {\n        _checkNotDelegated();\n        _;\n    }\n\n    function __UUPSUpgradeable_init() internal onlyInitializing {\n    }\n\n    function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the\n     * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n     *\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n     * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n     */\n    function proxiableUUID() external view virtual notDelegated returns (bytes32) {\n        return ERC1967Utils.IMPLEMENTATION_SLOT;\n    }\n\n    /**\n     * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n     * encoded in `data`.\n     *\n     * Calls {_authorizeUpgrade}.\n     *\n     * Emits an {Upgraded} event.\n     *\n     * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n     */\n    function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\n        _authorizeUpgrade(newImplementation);\n        _upgradeToAndCallUUPS(newImplementation, data);\n    }\n\n    /**\n     * @dev Reverts if the execution is not performed via delegatecall or the execution\n     * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.\n     */\n    function _checkProxy() internal view virtual {\n        if (\n            address(this) == __self || // Must be called through delegatecall\n            ERC1967Utils.getImplementation() != __self // Must be called through an active proxy\n        ) {\n            revert UUPSUnauthorizedCallContext();\n        }\n    }\n\n    /**\n     * @dev Reverts if the execution is performed via delegatecall.\n     * See {notDelegated}.\n     */\n    function _checkNotDelegated() internal view virtual {\n        if (address(this) != __self) {\n            // Must not be called through delegatecall\n            revert UUPSUnauthorizedCallContext();\n        }\n    }\n\n    /**\n     * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n     * {upgradeToAndCall}.\n     *\n     * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n     *\n     * ```solidity\n     * function _authorizeUpgrade(address) internal onlyOwner {}\n     * ```\n     */\n    function _authorizeUpgrade(address newImplementation) internal virtual;\n\n    /**\n     * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.\n     *\n     * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value\n     * is expected to be the implementation slot in ERC-1967.\n     *\n     * Emits an {IERC1967-Upgraded} event.\n     */\n    function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {\n        try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n            if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {\n                revert UUPSUnsupportedProxiableUUID(slot);\n            }\n            ERC1967Utils.upgradeToAndCall(newImplementation, data);\n        } catch {\n            // The implementation is not UUPS\n            revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n    /// @custom:storage-location erc7201:openzeppelin.storage.Pausable\n    struct PausableStorage {\n        bool _paused;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Pausable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300;\n\n    function _getPausableStorage() private pure returns (PausableStorage storage $) {\n        assembly {\n            $.slot := PausableStorageLocation\n        }\n    }\n\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    /**\n     * @dev The operation failed because the contract is paused.\n     */\n    error EnforcedPause();\n\n    /**\n     * @dev The operation failed because the contract is not paused.\n     */\n    error ExpectedPause();\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    function __Pausable_init() internal onlyInitializing {\n    }\n\n    function __Pausable_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        PausableStorage storage $ = _getPausableStorage();\n        return $._paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        if (paused()) {\n            revert EnforcedPause();\n        }\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        if (!paused()) {\n            revert ExpectedPause();\n        }\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        PausableStorage storage $ = _getPausableStorage();\n        $._paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        PausableStorage storage $ = _getPausableStorage();\n        $._paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,\n * consider using {ReentrancyGuardTransient} instead.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard\n    struct ReentrancyGuardStorage {\n        uint256 _status;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n    function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) {\n        assembly {\n            $.slot := ReentrancyGuardStorageLocation\n        }\n    }\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        $._status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        if ($._status == ENTERED) {\n            revert ReentrancyGuardReentrantCall();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        $._status = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        $._status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        return $._status == ENTERED;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/interfaces/IERC1363.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @title IERC1363\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\n *\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\n */\ninterface IERC1363 is IERC20, IERC165 {\n    /*\n     * Note: the ERC-165 identifier for this interface is 0xb0202a11.\n     * 0xb0202a11 ===\n     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\n     */\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @param data Additional data with no specified format, sent in call to `spender`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\n}\n"},{"file_path":"@openzeppelin/contracts/interfaces/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC165} from \"../utils/introspection/IERC165.sol\";\n"},{"file_path":"@openzeppelin/contracts/interfaces/IERC1967.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1967.sol)\n\npragma solidity >=0.4.11;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n */\ninterface IERC1967 {\n    /**\n     * @dev Emitted when the implementation is upgraded.\n     */\n    event Upgraded(address indexed implementation);\n\n    /**\n     * @dev Emitted when the admin account has changed.\n     */\n    event AdminChanged(address previousAdmin, address newAdmin);\n\n    /**\n     * @dev Emitted when the beacon is changed.\n     */\n    event BeaconUpgraded(address indexed beacon);\n}\n"},{"file_path":"@openzeppelin/contracts/interfaces/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC1363} from \"../../../interfaces/IERC1363.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    /**\n     * @dev An operation with an ERC-20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n    }\n\n    /**\n     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\n     */\n    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\n        return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\n     */\n    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\n        return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     *\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     *\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     *\n     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\n     * only sets the \"standard\" allowance. Any temporary allowance will remain active, in addition to the value being\n     * set here.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            safeTransfer(token, to, value);\n        } else if (!token.transferAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\n     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferFromAndCallRelaxed(\n        IERC1363 token,\n        address from,\n        address to,\n        uint256 value,\n        bytes memory data\n    ) internal {\n        if (to.code.length == 0) {\n            safeTransferFrom(token, from, to, value);\n        } else if (!token.transferFromAndCall(from, to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\n     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\n     * once without retrying, and relies on the returned value to be true.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            forceApprove(token, to, value);\n        } else if (!token.approveAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        uint256 returnSize;\n        uint256 returnValue;\n        assembly (\"memory-safe\") {\n            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\n            // bubble errors\n            if iszero(success) {\n                let ptr := mload(0x40)\n                returndatacopy(ptr, 0, returndatasize())\n                revert(ptr, returndatasize())\n            }\n            returnSize := returndatasize()\n            returnValue := mload(0)\n        }\n\n        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        bool success;\n        uint256 returnSize;\n        uint256 returnValue;\n        assembly (\"memory-safe\") {\n            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\n            returnSize := returndatasize()\n            returnValue := mload(0)\n        }\n        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Address.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\nimport {Errors} from \"./Errors.sol\";\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert Errors.InsufficientBalance(address(this).balance, amount);\n        }\n\n        (bool success, bytes memory returndata) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            _revert(returndata);\n        }\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {Errors.FailedCall} error.\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert Errors.InsufficientBalance(address(this).balance, value);\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case\n     * of an unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {Errors.FailedCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.\n     */\n    function _revert(bytes memory returndata) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            assembly (\"memory-safe\") {\n                revert(add(returndata, 0x20), mload(returndata))\n            }\n        } else {\n            revert Errors.FailedCall();\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Errors.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of common custom errors used in multiple contracts\n *\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\n * It is recommended to avoid relying on the error API for critical functionality.\n *\n * _Available since v5.1._\n */\nlibrary Errors {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error InsufficientBalance(uint256 balance, uint256 needed);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedCall();\n\n    /**\n     * @dev The deployment failed.\n     */\n    error FailedDeployment();\n\n    /**\n     * @dev A necessary precompile is missing.\n     */\n    error MissingPrecompile(address);\n}\n"},{"file_path":"@openzeppelin/contracts/utils/StorageSlot.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC-1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(newImplementation.code.length > 0);\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    struct Int256Slot {\n        int256 value;\n    }\n\n    struct StringSlot {\n        string value;\n    }\n\n    struct BytesSlot {\n        bytes value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Int256Slot` with member `value` located at `slot`.\n     */\n    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `StringSlot` with member `value` located at `slot`.\n     */\n    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n     */\n    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BytesSlot` with member `value` located at `slot`.\n     */\n    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n     */\n    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/introspection/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","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":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"tokenId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amountLocal","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountShared","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dustLocal","type":"uint256"}],"name":"AmountRounded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"isPrivateBridge","type":"bool"}],"name":"BridgeModeConfigured","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"tokenId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"uint32","name":"origin","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"tokenId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint32","name":"dstDomain","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"recipient","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"tokenId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint32","name":"dstDomain","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"recipient","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"NativeLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"tokenId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"NativeReleased","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":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"tokenId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PendingClaimPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"tokenId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint32","name":"origin","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PendingClaimRecorded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"tokenId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PendingClaimRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"tokenId","type":"bytes32"},{"indexed":true,"internalType":"uint32","name":"domain","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"router","type":"bytes32"}],"name":"RemoteRouterSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"tokenId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"newLimit","type":"uint256"}],"name":"TokenDailyLimitChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"tokenId","type":"bytes32"},{"indexed":false,"internalType":"uint8","name":"localDecimals","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"sharedDecimals","type":"uint8"}],"name":"TokenDecimalsConfigured","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"tokenId","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"TokenEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"tokenId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bool","name":"isCollateral","type":"bool"},{"indexed":false,"internalType":"uint256","name":"dailyLimit","type":"uint256"}],"name":"TokenRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"enabled","type":"bool"}],"name":"WhitelistStatusChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"bool","name":"allowed","type":"bool"}],"name":"WhitelistUpdated","type":"event"},{"inputs":[],"name":"MESSAGE_VERSION","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USE_DEFAULT_DAILY_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"},{"internalType":"uint8","name":"_sharedDecimals","type":"uint8"}],"name":"autoSetTokenDecimalsConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"},{"internalType":"uint32","name":"_destDomain","type":"uint32"},{"internalType":"bytes32","name":"_recipient","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"bridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"},{"internalType":"uint32","name":"_destDomain","type":"uint32"},{"internalType":"bytes32","name":"_recipient","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_maxFee","type":"uint256"}],"name":"bridgeWithMaxFee","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"canReleaseNative","outputs":[{"internalType":"bool","name":"ok","type":"bool"},{"internalType":"uint256","name":"bridgeBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimPending","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"claimPending","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultDailyLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deliverCollateralToRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deliverNativeToRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"}],"name":"getNativeCollateralHealth","outputs":[{"internalType":"bool","name":"enabled","type":"bool"},{"internalType":"bool","name":"isNativeCollateral","type":"bool"},{"internalType":"uint256","name":"bridgeBalance","type":"uint256"},{"internalType":"uint256","name":"dailyLimit","type":"uint256"},{"internalType":"uint256","name":"current24hAmount","type":"uint256"},{"internalType":"uint256","name":"remainingDailyCapacity","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"},{"internalType":"address","name":"_account","type":"address"}],"name":"getPendingClaim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"}],"name":"getToken","outputs":[{"internalType":"bool","name":"enabled","type":"bool"},{"internalType":"bool","name":"isCollateral","type":"bool"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"dailyLimit","type":"uint256"},{"internalType":"uint256","name":"current24hAmount","type":"uint256"},{"internalType":"uint256","name":"lastReset","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"}],"name":"getTokenDailyLimitState","outputs":[{"internalType":"uint256","name":"dailyLimit","type":"uint256"},{"internalType":"uint256","name":"currentWindowAmount","type":"uint256"},{"internalType":"uint256","name":"remainingDailyCapacity","type":"uint256"},{"internalType":"uint256","name":"lastReset","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"}],"name":"getTokenDecimalsConfig","outputs":[{"internalType":"bool","name":"configured","type":"bool"},{"internalType":"uint8","name":"localDecimals","type":"uint8"},{"internalType":"uint8","name":"sharedDecimals","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_origin","type":"uint32"},{"internalType":"bytes32","name":"_sender","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"}],"name":"handle","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_mailbox","type":"address"},{"internalType":"uint256","name":"_defaultDailyLimit","type":"uint256"},{"internalType":"bool","name":"_isPrivateBridge","type":"bool"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isPrivateBridge","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"}],"name":"isTokenRegistered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mailbox","outputs":[{"internalType":"contract IMailbox","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mintSyntheticToRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"},{"internalType":"uint32","name":"_destDomain","type":"uint32"},{"internalType":"bytes32","name":"_recipient","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"quoteBridge","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"},{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recoverPendingClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"bool","name":"_isCollateral","type":"bool"},{"internalType":"uint256","name":"_dailyLimit","type":"uint256"}],"name":"registerToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"remoteRouters","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_status","type":"bool"}],"name":"setPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"},{"internalType":"uint32","name":"_domain","type":"uint32"},{"internalType":"bytes32","name":"_router","type":"bytes32"}],"name":"setRemoteRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"},{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"setTokenDailyLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"},{"internalType":"uint8","name":"_localDecimals","type":"uint8"},{"internalType":"uint8","name":"_sharedDecimals","type":"uint8"}],"name":"setTokenDecimalsConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"},{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setTokenEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setWhitelistEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setWhitelisted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_accounts","type":"address[]"},{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setWhitelistedBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whitelistEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":null}