{"file_path":"contracts/bridgehub/Bridgehub.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.28;\n\nimport {EnumerableMap} from \"@openzeppelin/contracts-v4/utils/structs/EnumerableMap.sol\";\n\nimport {Ownable2StepUpgradeable} from \"@openzeppelin/contracts-upgradeable-v4/access/Ownable2StepUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable-v4/security/PausableUpgradeable.sol\";\n\nimport {IBridgehub, L2TransactionRequestDirect, L2TransactionRequestTwoBridgesInner, L2TransactionRequestTwoBridgesOuter} from \"./IBridgehub.sol\";\nimport {IAssetRouterBase} from \"../bridge/asset-router/IAssetRouterBase.sol\";\nimport {IL1AssetRouter} from \"../bridge/asset-router/IL1AssetRouter.sol\";\nimport {IL1BaseTokenAssetHandler} from \"../bridge/interfaces/IL1BaseTokenAssetHandler.sol\";\nimport {IChainTypeManager} from \"../state-transition/IChainTypeManager.sol\";\nimport {ReentrancyGuard} from \"../common/ReentrancyGuard.sol\";\nimport {DataEncoding} from \"../common/libraries/DataEncoding.sol\";\nimport {IZKChain} from \"../state-transition/chain-interfaces/IZKChain.sol\";\n\nimport {BRIDGEHUB_MIN_SECOND_BRIDGE_ADDRESS, ETH_TOKEN_ADDRESS, SETTLEMENT_LAYER_RELAY_SENDER, TWO_BRIDGES_MAGIC_VALUE} from \"../common/Config.sol\";\nimport {BridgehubL2TransactionRequest, L2Log, L2Message, TxStatus} from \"../common/Messaging.sol\";\nimport {AddressAliasHelper} from \"../vendor/AddressAliasHelper.sol\";\nimport {IMessageRoot} from \"./IMessageRoot.sol\";\nimport {ICTMDeploymentTracker} from \"./ICTMDeploymentTracker.sol\";\nimport {AlreadyCurrentSL, ChainIdAlreadyPresent, ChainNotLegacy, ChainNotPresentInCTM, NotChainAssetHandler, NotCurrentSL, NotInGatewayMode, NotL1, NotRelayedSender, SLNotWhitelisted, SecondBridgeAddressTooLow} from \"./L1BridgehubErrors.sol\";\nimport {AssetHandlerNotRegistered, AssetIdAlreadyRegistered, AssetIdNotSupported, BridgeHubAlreadyRegistered, CTMAlreadyRegistered, CTMNotRegistered, ChainIdAlreadyExists, ChainIdCantBeCurrentChain, ChainIdMismatch, ChainIdNotRegistered, ChainIdTooBig, EmptyAssetId, IncorrectBridgeHubAddress, MigrationPaused, MsgValueMismatch, NoCTMForAssetId, SettlementLayersMustSettleOnL1, SharedBridgeNotSet, Unauthorized, WrongMagicValue, ZKChainLimitReached, ZeroAddress, ZeroChainId} from \"../common/L1ContractErrors.sol\";\n\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\n/// @dev The Bridgehub contract serves as the primary entry point for L1->L2 communication,\n/// facilitating interactions between end user and bridges.\n/// It also manages state transition managers, base tokens, and chain registrations.\ncontract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, PausableUpgradeable {\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\n\n    /// @notice the asset id of Eth. This is only used on L1.\n    bytes32 internal immutable ETH_TOKEN_ASSET_ID;\n\n    /// @notice The chain id of L1. This contract can be deployed on multiple layers, but this value is still equal to the\n    /// L1 that is at the most base layer.\n    uint256 public immutable L1_CHAIN_ID;\n\n    /// @notice The total number of ZK chains can be created/connected to this CTM.\n    /// This is the temporary security measure.\n    uint256 public immutable MAX_NUMBER_OF_ZK_CHAINS;\n\n    /// @notice all the ether and ERC20 tokens are held by NativeVaultToken managed by the asset router.\n    address public assetRouter;\n\n    /// @notice ChainTypeManagers that are registered, and ZKchains that use these CTMs can use this bridgehub as settlement layer.\n    mapping(address chainTypeManager => bool) public chainTypeManagerIsRegistered;\n\n    /// @notice we store registered tokens (for arbitrary base token)\n    mapping(address baseToken => bool) internal __DEPRECATED_tokenIsRegistered;\n\n    /// @notice chainID => ChainTypeManager contract address, CTM that is managing rules for a given ZKchain.\n    mapping(uint256 chainId => address) public chainTypeManager;\n\n    /// @notice chainID => baseToken contract address, token that is used as 'base token' by a given child chain.\n    // slither-disable-next-line uninitialized-state\n    mapping(uint256 chainId => address) internal __DEPRECATED_baseToken;\n\n    /// @dev used to manage non critical updates\n    address public admin;\n\n    /// @dev used to accept the admin role\n    address private pendingAdmin;\n\n    /// @notice The map from chainId => zkChain contract\n    EnumerableMap.UintToAddressMap internal zkChainMap;\n\n    /// @notice The contract that stores the cross-chain message root for each chain and the aggregated root.\n    /// @dev Note that the message root does not contain messages from the chain it is deployed on. It may\n    /// be added later on if needed.\n    IMessageRoot public override messageRoot;\n\n    /// @notice Mapping from chain id to encoding of the base token used for deposits / withdrawals\n    mapping(uint256 chainId => bytes32) public baseTokenAssetId;\n\n    /// @notice The deployment tracker for the state transition managers.\n    /// @dev The L1 address of the ctm deployer is provided.\n    ICTMDeploymentTracker public l1CtmDeployer;\n\n    /// @dev asset info used to identify chains in the Shared Bridge\n    mapping(bytes32 ctmAssetId => address ctmAddress) public ctmAssetIdToAddress;\n\n    /// @dev ctmAddress to ctmAssetId\n    mapping(address ctmAddress => bytes32 ctmAssetId) public ctmAssetIdFromAddress;\n\n    /// @dev used to indicate the currently active settlement layer for a given chainId\n    mapping(uint256 chainId => uint256 activeSettlementLayerChainId) public settlementLayer;\n\n    /// @notice shows whether the given chain can be used as a settlement layer.\n    /// @dev the Gateway will be one of the possible settlement layers. The L1 is also a settlement layer.\n    /// @dev Sync layer chain is expected to have .. as the base token.\n    mapping(uint256 chainId => bool isWhitelistedSettlementLayer) public whitelistedSettlementLayers;\n\n    /// @notice we store registered assetIds (for arbitrary base token)\n    mapping(bytes32 baseTokenAssetId => bool) public assetIdIsRegistered;\n\n    /// @notice used to pause the migrations of chains. Used for stopping migrations during upgrades.\n    bool public migrationPaused;\n\n    /// @notice the chain asset handler used for chain migration.\n    address public chainAssetHandler;\n\n    modifier onlyOwnerOrAdmin() {\n        if (msg.sender != admin && msg.sender != owner()) {\n            revert Unauthorized(msg.sender);\n        }\n        _;\n    }\n\n    modifier onlyL1() {\n        if (L1_CHAIN_ID != block.chainid) {\n            revert NotL1(L1_CHAIN_ID, block.chainid);\n        }\n        _;\n    }\n\n    modifier onlySettlementLayerRelayedSender() {\n        /// There is no sender for the wrapping, we use a virtual address.\n        if (msg.sender != SETTLEMENT_LAYER_RELAY_SENDER) {\n            revert NotRelayedSender(msg.sender, SETTLEMENT_LAYER_RELAY_SENDER);\n        }\n        _;\n    }\n\n    modifier whenMigrationsNotPaused() {\n        if (migrationPaused) {\n            revert MigrationPaused();\n        }\n        _;\n    }\n\n    modifier onlyChainAssetHandler() {\n        if (msg.sender != chainAssetHandler) {\n            revert NotChainAssetHandler(msg.sender, chainAssetHandler);\n        }\n        _;\n    }\n\n    /// @notice to avoid parity hack\n    constructor(uint256 _l1ChainId, address _owner, uint256 _maxNumberOfZKChains) reentrancyGuardInitializer {\n        _disableInitializers();\n        L1_CHAIN_ID = _l1ChainId;\n        MAX_NUMBER_OF_ZK_CHAINS = _maxNumberOfZKChains;\n\n        // Note that this assumes that the bridgehub only accepts transactions on chains with ETH base token only.\n        // This is indeed true, since the only methods where this immutable is used are the ones with `onlyL1` modifier.\n        // We will change this with interop.\n        ETH_TOKEN_ASSET_ID = DataEncoding.encodeNTVAssetId(L1_CHAIN_ID, ETH_TOKEN_ADDRESS);\n        _transferOwnership(_owner);\n        _initializeInner();\n    }\n\n    /// @notice used to initialize the contract\n    /// @notice this contract is also deployed on L2 as a system contract there the owner and the related functions will not be used\n    /// @param _owner the owner of the contract\n    function initialize(address _owner) external reentrancyGuardInitializer onlyL1 {\n        _transferOwnership(_owner);\n        _initializeInner();\n    }\n\n    /// @notice Used to initialize the contract on L1\n    function initializeV2() external initializer onlyL1 {\n        _initializeInner();\n    }\n\n    /// @notice Initializes the contract\n    function _initializeInner() internal {\n        assetIdIsRegistered[ETH_TOKEN_ASSET_ID] = true;\n        whitelistedSettlementLayers[L1_CHAIN_ID] = true;\n    }\n\n    //// Initialization and registration\n\n    /// @inheritdoc IBridgehub\n    /// @dev Please note, if the owner wants to enforce the admin change it must execute both `setPendingAdmin` and\n    /// `acceptAdmin` atomically. Otherwise `admin` can set different pending admin and so fail to accept the admin rights.\n    function setPendingAdmin(address _newPendingAdmin) external onlyOwnerOrAdmin {\n        if (_newPendingAdmin == address(0)) {\n            revert ZeroAddress();\n        }\n        // Save previous value into the stack to put it into the event later\n        address oldPendingAdmin = pendingAdmin;\n        // Change pending admin\n        pendingAdmin = _newPendingAdmin;\n        emit NewPendingAdmin(oldPendingAdmin, _newPendingAdmin);\n    }\n\n    /// @inheritdoc IBridgehub\n    function acceptAdmin() external {\n        address currentPendingAdmin = pendingAdmin;\n        // Only proposed by current admin address can claim the admin rights\n        if (msg.sender != currentPendingAdmin) {\n            revert Unauthorized(msg.sender);\n        }\n\n        address previousAdmin = admin;\n        admin = currentPendingAdmin;\n        delete pendingAdmin;\n\n        emit NewPendingAdmin(currentPendingAdmin, address(0));\n        emit NewAdmin(previousAdmin, currentPendingAdmin);\n    }\n\n    /// @notice To set the addresses of some of the ecosystem contracts, only Owner. Not done in initialize, as\n    /// the order of deployment is Bridgehub, other contracts, and then we call this.\n    /// @param _assetRouter the shared bridge address\n    /// @param _l1CtmDeployer the ctm deployment tracker address. Note, that the address of the L1 CTM deployer is provided.\n    /// @param _messageRoot the message root address\n    function setAddresses(\n        address _assetRouter,\n        ICTMDeploymentTracker _l1CtmDeployer,\n        IMessageRoot _messageRoot,\n        address _chainAssetHandler\n    ) external onlyOwner {\n        assetRouter = _assetRouter;\n        l1CtmDeployer = _l1CtmDeployer;\n        messageRoot = _messageRoot;\n        chainAssetHandler = _chainAssetHandler;\n    }\n\n    /// @notice Used to set the chain asset handler address.\n    /// @dev Called during v29 upgrade.\n    /// @param _chainAssetHandler the chain asset handler address\n    function setChainAssetHandler(address _chainAssetHandler) external onlyOwner {\n        chainAssetHandler = _chainAssetHandler;\n    }\n\n    /// @notice Used to set the legacy chain data for the upgrade.\n    /// @param _chainId The chainId of the legacy chain we are migrating.\n    function registerLegacyChain(uint256 _chainId) external override onlyL1 {\n        address ctm = chainTypeManager[_chainId];\n        if (ctm == address(0)) {\n            revert ChainNotLegacy();\n        }\n        if (zkChainMap.contains(_chainId)) {\n            revert ChainIdAlreadyPresent();\n        }\n\n        // From now on, since `zkChainMap` did not contain the chain, we assume\n        // that the chain is a legacy chain in the process of migration, i.e.\n        // its stored `baseTokenAssetId`, etc.\n\n        address token = __DEPRECATED_baseToken[_chainId];\n        if (token == address(0)) {\n            revert ChainNotLegacy();\n        }\n\n        bytes32 assetId = DataEncoding.encodeNTVAssetId(block.chainid, token);\n\n        baseTokenAssetId[_chainId] = assetId;\n        assetIdIsRegistered[assetId] = true;\n\n        address chainAddress = IChainTypeManager(ctm).getZKChainLegacy(_chainId);\n        if (chainAddress == address(0)) {\n            revert ChainNotPresentInCTM();\n        }\n        _registerNewZKChain(_chainId, chainAddress, false);\n        messageRoot.addNewChain(_chainId);\n        settlementLayer[_chainId] = block.chainid;\n    }\n\n    //// Registry\n\n    /// @notice Chain Type Manager can be any contract with the appropriate interface/functionality\n    /// @param _chainTypeManager the state transition manager address to be added\n    function addChainTypeManager(address _chainTypeManager) external onlyOwner {\n        if (_chainTypeManager == address(0)) {\n            revert ZeroAddress();\n        }\n        if (chainTypeManagerIsRegistered[_chainTypeManager]) {\n            revert CTMAlreadyRegistered();\n        }\n        chainTypeManagerIsRegistered[_chainTypeManager] = true;\n\n        emit ChainTypeManagerAdded(_chainTypeManager);\n    }\n\n    /// @notice Chain Type Manager can be any contract with the appropriate interface/functionality\n    /// @notice this stops new Chains from using the CTM, old chains are not affected\n    /// @param _chainTypeManager the state transition manager address to be removed\n    function removeChainTypeManager(address _chainTypeManager) external onlyOwner {\n        if (_chainTypeManager == address(0)) {\n            revert ZeroAddress();\n        }\n        if (!chainTypeManagerIsRegistered[_chainTypeManager]) {\n            revert CTMNotRegistered();\n        }\n        chainTypeManagerIsRegistered[_chainTypeManager] = false;\n\n        emit ChainTypeManagerRemoved(_chainTypeManager);\n    }\n\n    /// @notice asset id can represent any token contract with the appropriate interface/functionality\n    /// @param _baseTokenAssetId asset id of base token to be registered\n    function addTokenAssetId(bytes32 _baseTokenAssetId) external onlyOwnerOrAdmin {\n        if (assetIdIsRegistered[_baseTokenAssetId]) {\n            revert AssetIdAlreadyRegistered();\n        }\n        assetIdIsRegistered[_baseTokenAssetId] = true;\n\n        emit BaseTokenAssetIdRegistered(_baseTokenAssetId);\n    }\n\n    /// @notice Used to register a chain as a settlement layer.\n    /// @param _newSettlementLayerChainId the chainId of the chain\n    /// @param _isWhitelisted whether the chain is a whitelisted settlement layer\n    function registerSettlementLayer(\n        uint256 _newSettlementLayerChainId,\n        bool _isWhitelisted\n    ) external onlyOwner onlyL1 {\n        if (settlementLayer[_newSettlementLayerChainId] != block.chainid) {\n            revert SettlementLayersMustSettleOnL1();\n        }\n        whitelistedSettlementLayers[_newSettlementLayerChainId] = _isWhitelisted;\n        emit SettlementLayerRegistered(_newSettlementLayerChainId, _isWhitelisted);\n    }\n\n    /// @dev Used to set the assetAddress for a given assetInfo.\n    /// @param _additionalData the additional data to identify the asset\n    /// @param _assetAddress the asset handler address\n    function setCTMAssetAddress(bytes32 _additionalData, address _assetAddress) external {\n        // It is a simplified version of the logic used by the AssetRouter to manage asset handlers.\n        // CTM's assetId is `keccak256(abi.encode(L1_CHAIN_ID, l1CtmDeployer, ctmAddress))`.\n        // And the l1CtmDeployer is considered the deployment tracker for the CTM asset.\n        //\n        // The l1CtmDeployer will call this method to set the asset handler address for the assetId.\n        // If the chain is not the same as L1, we assume that it is done via L1->L2 communication and so we unalias the sender.\n        //\n        // For simpler handling we allow anyone to call this method. It is okay, since during bridging operations\n        // it is double checked that `assetId` is indeed derived from the `l1CtmDeployer`.\n        // TODO(EVM-703): This logic should be revised once interchain communication is implemented.\n\n        address sender = L1_CHAIN_ID == block.chainid ? msg.sender : AddressAliasHelper.undoL1ToL2Alias(msg.sender);\n        // This method can be accessed by l1CtmDeployer only\n        if (sender != address(l1CtmDeployer)) {\n            revert Unauthorized(sender);\n        }\n        if (!chainTypeManagerIsRegistered[_assetAddress]) {\n            revert CTMNotRegistered();\n        }\n\n        bytes32 ctmAssetId = DataEncoding.encodeAssetId(L1_CHAIN_ID, _additionalData, sender);\n        ctmAssetIdToAddress[ctmAssetId] = _assetAddress;\n        ctmAssetIdFromAddress[_assetAddress] = ctmAssetId;\n        emit AssetRegistered(ctmAssetId, _assetAddress, _additionalData, msg.sender);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                          Chain Registration\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice register new chain. New chains can be only registered on Bridgehub deployed on L1. Later they can be moved to any other layer.\n    /// @notice for Eth the baseToken address is 1\n    /// @param _chainId the chainId of the chain\n    /// @param _chainTypeManager the state transition manager address\n    /// @param _baseTokenAssetId the base token asset id of the chain\n    /// @param _salt the salt for the chainId, currently not used\n    /// @param _admin the admin of the chain\n    /// @param _initData the fixed initialization data for the chain\n    /// @param _factoryDeps the factory dependencies for the chain's deployment\n    function createNewChain(\n        uint256 _chainId,\n        address _chainTypeManager,\n        bytes32 _baseTokenAssetId,\n        // solhint-disable-next-line no-unused-vars\n        uint256 _salt,\n        address _admin,\n        bytes calldata _initData,\n        bytes[] calldata _factoryDeps\n    ) external onlyOwnerOrAdmin nonReentrant whenNotPaused onlyL1 returns (uint256) {\n        _validateChainParams({_chainId: _chainId, _assetId: _baseTokenAssetId, _chainTypeManager: _chainTypeManager});\n\n        chainTypeManager[_chainId] = _chainTypeManager;\n\n        baseTokenAssetId[_chainId] = _baseTokenAssetId;\n        settlementLayer[_chainId] = block.chainid;\n\n        address chainAddress = IChainTypeManager(_chainTypeManager).createNewChain({\n            _chainId: _chainId,\n            _baseTokenAssetId: _baseTokenAssetId,\n            _admin: _admin,\n            _initData: _initData,\n            _factoryDeps: _factoryDeps\n        });\n        _registerNewZKChain(_chainId, chainAddress, true);\n        messageRoot.addNewChain(_chainId);\n\n        emit NewChain(_chainId, _chainTypeManager, _admin);\n        return _chainId;\n    }\n\n    /// @notice This function is used to register a new zkChain in the system.\n    /// @notice see external counterpart for full natspec.\n    function _registerNewZKChain(uint256 _chainId, address _zkChain, bool _checkMaxNumberOfZKChains) internal {\n        // slither-disable-next-line unused-return\n        zkChainMap.set(_chainId, _zkChain);\n        if (_checkMaxNumberOfZKChains && zkChainMap.length() > MAX_NUMBER_OF_ZK_CHAINS) {\n            revert ZKChainLimitReached();\n        }\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                             Getters\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice baseToken function, which takes chainId as input, reads assetHandler from AR, and tokenAddress from AH\n    function baseToken(uint256 _chainId) public view returns (address) {\n        bytes32 baseTokenAssetId = baseTokenAssetId[_chainId];\n        address assetHandlerAddress = IAssetRouterBase(assetRouter).assetHandlerAddress(baseTokenAssetId);\n\n        // It is possible that the asset handler is not deployed for a chain on the current layer.\n        // In this case we throw an error.\n        if (assetHandlerAddress == address(0)) {\n            revert AssetHandlerNotRegistered(baseTokenAssetId);\n        }\n        return IL1BaseTokenAssetHandler(assetHandlerAddress).tokenAddress(baseTokenAssetId);\n    }\n\n    /// @notice Returns all the registered zkChain addresses\n    function getAllZKChains() public view override returns (address[] memory chainAddresses) {\n        uint256[] memory keys = zkChainMap.keys();\n        chainAddresses = new address[](keys.length);\n        uint256 keysLength = keys.length;\n        for (uint256 i = 0; i < keysLength; ++i) {\n            chainAddresses[i] = zkChainMap.get(keys[i]);\n        }\n    }\n\n    /// @notice Returns all the registered zkChain chainIDs\n    function getAllZKChainChainIDs() public view override returns (uint256[] memory) {\n        return zkChainMap.keys();\n    }\n\n    /// @notice Returns the address of the ZK chain with the corresponding chainID\n    /// @param _chainId the chainId of the chain\n    /// @return chainAddress the address of the ZK chain\n    function getZKChain(uint256 _chainId) public view override returns (address chainAddress) {\n        // slither-disable-next-line unused-return\n        (, chainAddress) = zkChainMap.tryGet(_chainId);\n    }\n\n    function ctmAssetIdFromChainId(uint256 _chainId) public view override returns (bytes32) {\n        address ctmAddress = chainTypeManager[_chainId];\n        if (ctmAddress == address(0)) {\n            revert ChainIdNotRegistered(_chainId);\n        }\n        return ctmAssetIdFromAddress[ctmAddress];\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        Mailbox forwarder\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice the mailbox is called directly after the assetRouter received the deposit\n    /// this assumes that either ether is the base token or\n    /// the msg.sender has approved mintValue allowance for the nativeTokenVault.\n    /// This means this is not ideal for contract calls, as the contract would have to handle token allowance of the base Token.\n    /// In case allowance is provided to the Asset Router, then it will be transferred to NTV.\n    function requestL2TransactionDirect(\n        L2TransactionRequestDirect calldata _request\n    ) external payable override nonReentrant whenNotPaused onlyL1 returns (bytes32 canonicalTxHash) {\n        // Note: If the ZK chain with corresponding `chainId` is not yet created,\n        // the transaction will revert on `bridgehubRequestL2Transaction` as call to zero address.\n        {\n            bytes32 tokenAssetId = baseTokenAssetId[_request.chainId];\n            if (tokenAssetId == ETH_TOKEN_ASSET_ID) {\n                if (msg.value != _request.mintValue) {\n                    revert MsgValueMismatch(_request.mintValue, msg.value);\n                }\n            } else {\n                if (msg.value != 0) {\n                    revert MsgValueMismatch(0, msg.value);\n                }\n            }\n\n            // slither-disable-next-line arbitrary-send-eth\n            IL1AssetRouter(assetRouter).bridgehubDepositBaseToken{value: msg.value}(\n                _request.chainId,\n                tokenAssetId,\n                msg.sender,\n                _request.mintValue\n            );\n        }\n\n        canonicalTxHash = _sendRequest(\n            _request.chainId,\n            _request.refundRecipient,\n            BridgehubL2TransactionRequest({\n                sender: msg.sender,\n                contractL2: _request.l2Contract,\n                mintValue: _request.mintValue,\n                l2Value: _request.l2Value,\n                l2Calldata: _request.l2Calldata,\n                l2GasLimit: _request.l2GasLimit,\n                l2GasPerPubdataByteLimit: _request.l2GasPerPubdataByteLimit,\n                factoryDeps: _request.factoryDeps,\n                refundRecipient: address(0)\n            })\n        );\n    }\n\n    /// @notice After depositing funds to the assetRouter, the secondBridge is called\n    ///  to return the actual L2 message which is sent to the Mailbox.\n    ///  This assumes that either ether is the base token or\n    ///  the msg.sender has approved the nativeTokenVault with the mintValue,\n    ///  and also the necessary approvals are given for the second bridge.\n    ///  In case allowance is provided to the Shared Bridge, then it will be transferred to NTV.\n    /// @notice The logic of this bridge is to allow easy depositing for bridges.\n    /// Each contract that handles the users ERC20 tokens needs approvals from the user, this contract allows\n    /// the user to approve for each token only its respective bridge\n    /// @notice This function is great for contract calls to L2, the secondBridge can be any contract.\n    /// @param _request the request for the L2 transaction\n    function requestL2TransactionTwoBridges(\n        L2TransactionRequestTwoBridgesOuter calldata _request\n    ) external payable override nonReentrant whenNotPaused onlyL1 returns (bytes32 canonicalTxHash) {\n        if (_request.secondBridgeAddress <= BRIDGEHUB_MIN_SECOND_BRIDGE_ADDRESS) {\n            revert SecondBridgeAddressTooLow(_request.secondBridgeAddress, BRIDGEHUB_MIN_SECOND_BRIDGE_ADDRESS);\n        }\n\n        {\n            bytes32 tokenAssetId = baseTokenAssetId[_request.chainId];\n            uint256 baseTokenMsgValue;\n            if (tokenAssetId == ETH_TOKEN_ASSET_ID) {\n                if (msg.value != _request.mintValue + _request.secondBridgeValue) {\n                    revert MsgValueMismatch(_request.mintValue + _request.secondBridgeValue, msg.value);\n                }\n                baseTokenMsgValue = _request.mintValue;\n            } else {\n                if (msg.value != _request.secondBridgeValue) {\n                    revert MsgValueMismatch(_request.secondBridgeValue, msg.value);\n                }\n                baseTokenMsgValue = 0;\n            }\n\n            // slither-disable-next-line arbitrary-send-eth\n            IL1AssetRouter(assetRouter).bridgehubDepositBaseToken{value: baseTokenMsgValue}(\n                _request.chainId,\n                tokenAssetId,\n                msg.sender,\n                _request.mintValue\n            );\n        }\n\n        // slither-disable-next-line arbitrary-send-eth\n        L2TransactionRequestTwoBridgesInner memory outputRequest = IL1AssetRouter(_request.secondBridgeAddress)\n            .bridgehubDeposit{value: _request.secondBridgeValue}(\n            _request.chainId,\n            msg.sender,\n            _request.l2Value,\n            _request.secondBridgeCalldata\n        );\n\n        if (outputRequest.magicValue != TWO_BRIDGES_MAGIC_VALUE) {\n            revert WrongMagicValue(uint256(TWO_BRIDGES_MAGIC_VALUE), uint256(outputRequest.magicValue));\n        }\n\n        canonicalTxHash = _sendRequest(\n            _request.chainId,\n            _request.refundRecipient,\n            BridgehubL2TransactionRequest({\n                sender: _request.secondBridgeAddress,\n                contractL2: outputRequest.l2Contract,\n                mintValue: _request.mintValue,\n                l2Value: _request.l2Value,\n                l2Calldata: outputRequest.l2Calldata,\n                l2GasLimit: _request.l2GasLimit,\n                l2GasPerPubdataByteLimit: _request.l2GasPerPubdataByteLimit,\n                factoryDeps: outputRequest.factoryDeps,\n                refundRecipient: address(0)\n            })\n        );\n\n        IL1AssetRouter(_request.secondBridgeAddress).bridgehubConfirmL2Transaction(\n            _request.chainId,\n            outputRequest.txDataHash,\n            canonicalTxHash\n        );\n    }\n\n    /// @notice This function is used to send a request to the ZK chain.\n    /// @param _chainId the chainId of the chain\n    /// @param _refundRecipient the refund recipient\n    /// @param _request the request\n    /// @return canonicalTxHash the canonical transaction hash\n    function _sendRequest(\n        uint256 _chainId,\n        address _refundRecipient,\n        BridgehubL2TransactionRequest memory _request\n    ) internal returns (bytes32 canonicalTxHash) {\n        address refundRecipient = AddressAliasHelper.actualRefundRecipient(_refundRecipient, msg.sender);\n        _request.refundRecipient = refundRecipient;\n        address zkChain = zkChainMap.get(_chainId);\n\n        canonicalTxHash = IZKChain(zkChain).bridgehubRequestL2Transaction(_request);\n    }\n\n    /// @notice Used to forward a transaction on the gateway to the chains mailbox (from L1).\n    /// @param _chainId the chainId of the chain\n    /// @param _canonicalTxHash the canonical transaction hash\n    /// @param _expirationTimestamp the expiration timestamp for the transaction\n    function forwardTransactionOnGateway(\n        uint256 _chainId,\n        bytes32 _canonicalTxHash,\n        uint64 _expirationTimestamp\n    ) external override onlySettlementLayerRelayedSender {\n        if (L1_CHAIN_ID == block.chainid) {\n            revert NotInGatewayMode();\n        }\n        address zkChain = zkChainMap.get(_chainId);\n        IZKChain(zkChain).bridgehubRequestL2TransactionOnGateway(_canonicalTxHash, _expirationTimestamp);\n    }\n\n    /// @notice forwards function call to Mailbox based on ChainId\n    /// @param _chainId The chain ID of the ZK chain where to prove L2 message inclusion.\n    /// @param _batchNumber The executed L2 batch number in which the message appeared\n    /// @param _index The position in the L2 logs Merkle tree of the l2Log that was sent with the message\n    /// @param _message Information about the sent message: sender address, the message itself, tx index in the L2 batch where the message was sent\n    /// @param _proof Merkle proof for inclusion of L2 log that was sent with the message\n    /// @return Whether the proof is valid\n    function proveL2MessageInclusion(\n        uint256 _chainId,\n        uint256 _batchNumber,\n        uint256 _index,\n        L2Message calldata _message,\n        bytes32[] calldata _proof\n    ) external view override returns (bool) {\n        address zkChain = zkChainMap.get(_chainId);\n        return IZKChain(zkChain).proveL2MessageInclusion(_batchNumber, _index, _message, _proof);\n    }\n\n    /// @notice forwards function call to Mailbox based on ChainId\n    /// @param _chainId The chain ID of the ZK chain where to prove L2 log inclusion.\n    /// @param _batchNumber The executed L2 batch number in which the log appeared\n    /// @param _index The position of the l2log in the L2 logs Merkle tree\n    /// @param _log Information about the sent log\n    /// @param _proof Merkle proof for inclusion of the L2 log\n    /// @return Whether the proof is correct and L2 log is included in batch\n    function proveL2LogInclusion(\n        uint256 _chainId,\n        uint256 _batchNumber,\n        uint256 _index,\n        L2Log calldata _log,\n        bytes32[] calldata _proof\n    ) external view override returns (bool) {\n        address zkChain = zkChainMap.get(_chainId);\n        return IZKChain(zkChain).proveL2LogInclusion(_batchNumber, _index, _log, _proof);\n    }\n\n    /// @notice forwards function call to Mailbox based on ChainId\n    /// @param _chainId The chain ID of the ZK chain where to prove L1->L2 tx status.\n    /// @param _l2TxHash The L2 canonical transaction hash\n    /// @param _l2BatchNumber The L2 batch number where the transaction was processed\n    /// @param _l2MessageIndex The position in the L2 logs Merkle tree of the l2Log that was sent with the message\n    /// @param _l2TxNumberInBatch The L2 transaction number in the batch, in which the log was sent\n    /// @param _merkleProof The Merkle proof of the processing L1 -> L2 transaction\n    /// @param _status The execution status of the L1 -> L2 transaction (true - success & 0 - fail)\n    /// @return Whether the proof is correct and the transaction was actually executed with provided status\n    /// NOTE: It may return `false` for incorrect proof, but it doesn't mean that the L1 -> L2 transaction has an opposite status!\n    function proveL1ToL2TransactionStatus(\n        uint256 _chainId,\n        bytes32 _l2TxHash,\n        uint256 _l2BatchNumber,\n        uint256 _l2MessageIndex,\n        uint16 _l2TxNumberInBatch,\n        bytes32[] calldata _merkleProof,\n        TxStatus _status\n    ) external view override returns (bool) {\n        address zkChain = zkChainMap.get(_chainId);\n        return\n            IZKChain(zkChain).proveL1ToL2TransactionStatus({\n                _l2TxHash: _l2TxHash,\n                _l2BatchNumber: _l2BatchNumber,\n                _l2MessageIndex: _l2MessageIndex,\n                _l2TxNumberInBatch: _l2TxNumberInBatch,\n                _merkleProof: _merkleProof,\n                _status: _status\n            });\n    }\n\n    /// @notice forwards function call to Mailbox based on ChainId\n    function l2TransactionBaseCost(\n        uint256 _chainId,\n        uint256 _gasPrice,\n        uint256 _l2GasLimit,\n        uint256 _l2GasPerPubdataByteLimit\n    ) external view returns (uint256) {\n        address zkChain = zkChainMap.get(_chainId);\n        return IZKChain(zkChain).l2TransactionBaseCost(_gasPrice, _l2GasLimit, _l2GasPerPubdataByteLimit);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        Chain migration\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice IL1AssetHandler interface, used to migrate (transfer) a chain to the settlement layer.\n    /// @param _chainId The chain ID of the migrating chain.\n    /// @param _newSettlementLayerChainId The chain ID of the new settlement layer.\n    /// @return zkChain The address of the ZK chain.\n    /// @return ctm The address of the CTM of the chain.\n    function forwardedBridgeBurnSetSettlementLayer(\n        uint256 _chainId,\n        uint256 _newSettlementLayerChainId\n    ) external onlyChainAssetHandler returns (address zkChain, address ctm) {\n        if (!whitelistedSettlementLayers[_newSettlementLayerChainId]) {\n            revert SLNotWhitelisted();\n        }\n\n        if (settlementLayer[_chainId] != block.chainid) {\n            revert NotCurrentSL(settlementLayer[_chainId], block.chainid);\n        }\n        settlementLayer[_chainId] = _newSettlementLayerChainId;\n\n        if (whitelistedSettlementLayers[_chainId]) {\n            revert SettlementLayersMustSettleOnL1();\n        }\n        zkChain = zkChainMap.get(_chainId);\n        ctm = chainTypeManager[_chainId];\n    }\n\n    /// @notice IL1AssetHandler interface, used to migrate (transfer) a chain to the settlement layer.\n    /// @param _assetId The asset ID of the chain.\n    /// @param _chainId The chain ID of the ZK chain.\n    /// @param _baseTokenAssetId The asset ID of the base token.\n    /// @return zkChain The address of the ZK chain.\n    /// @return ctm The address of the CTM of the chain.\n    function forwardedBridgeMint(\n        bytes32 _assetId,\n        uint256 _chainId,\n        bytes32 _baseTokenAssetId\n    ) external onlyChainAssetHandler returns (address zkChain, address ctm) {\n        ctm = ctmAssetIdToAddress[_assetId];\n        if (ctm == address(0)) {\n            revert NoCTMForAssetId(_assetId);\n        }\n        if (settlementLayer[_chainId] == block.chainid) {\n            revert AlreadyCurrentSL(block.chainid);\n        }\n\n        settlementLayer[_chainId] = block.chainid;\n        chainTypeManager[_chainId] = ctm;\n        baseTokenAssetId[_chainId] = _baseTokenAssetId;\n        // To keep `assetIdIsRegistered` consistent, we'll also automatically register the base token.\n        // It is assumed that if the bridging happened, the token was approved on L1 already.\n        assetIdIsRegistered[_baseTokenAssetId] = true;\n\n        zkChain = getZKChain(_chainId);\n    }\n\n    /// @notice Used to recover a failed migration.\n    /// @param _chainId The chain ID of the chain.\n    /// @return zkChain The address of the ZK chain.\n    /// @return ctm The address of the CTM of the chain.\n    function forwardedBridgeRecoverFailedTransfer(\n        uint256 _chainId\n    ) external onlyChainAssetHandler returns (address zkChain, address ctm) {\n        settlementLayer[_chainId] = block.chainid;\n        zkChain = getZKChain(_chainId);\n        ctm = chainTypeManager[_chainId];\n    }\n\n    /*////////////////////////////////////////////////////////////\n                            Chain registration\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice This function is used to register a new zkChain in the system.\n    /// @param _chainId The chain ID of the ZK chain\n    /// @param _zkChain The address of the ZK chain's DiamondProxy contract.\n    /// @param _checkMaxNumberOfZKChains Whether to check that the limit for the number\n    /// of chains has not been crossed.\n    /// @dev Providing `_checkMaxNumberOfZKChains = false` may be preferable in cases\n    /// where we want to guarantee that a chain can be added. These include:\n    /// - Migration of a chain from the mapping in the old CTM\n    /// - Migration of a chain to a new settlement layer\n    function registerNewZKChain(\n        uint256 _chainId,\n        address _zkChain,\n        bool _checkMaxNumberOfZKChains\n    ) public onlyChainAssetHandler {\n        _registerNewZKChain(_chainId, _zkChain, _checkMaxNumberOfZKChains);\n    }\n\n    /// @dev Registers an already deployed chain with the bridgehub\n    /// @param _chainId The chain Id of the chain\n    /// @param _zkChain Address of the zkChain\n    function registerAlreadyDeployedZKChain(uint256 _chainId, address _zkChain) external onlyOwner onlyL1 {\n        if (_zkChain == address(0)) {\n            revert ZeroAddress();\n        }\n        if (zkChainMap.contains(_chainId)) {\n            revert ChainIdAlreadyExists();\n        }\n        if (IZKChain(_zkChain).getChainId() != _chainId) {\n            revert ChainIdMismatch();\n        }\n\n        address ctm = IZKChain(_zkChain).getChainTypeManager();\n        address chainAdmin = IZKChain(_zkChain).getAdmin();\n        bytes32 chainBaseTokenAssetId = IZKChain(_zkChain).getBaseTokenAssetId();\n        address bridgeHub = IZKChain(_zkChain).getBridgehub();\n\n        if (bridgeHub != address(this)) {\n            revert IncorrectBridgeHubAddress(bridgeHub);\n        }\n\n        _validateChainParams({_chainId: _chainId, _assetId: chainBaseTokenAssetId, _chainTypeManager: ctm});\n\n        chainTypeManager[_chainId] = ctm;\n\n        baseTokenAssetId[_chainId] = chainBaseTokenAssetId;\n        settlementLayer[_chainId] = block.chainid;\n\n        _registerNewZKChain(_chainId, _zkChain, true);\n        messageRoot.addNewChain(_chainId);\n\n        emit NewChain(_chainId, ctm, chainAdmin);\n    }\n\n    function _validateChainParams(uint256 _chainId, bytes32 _assetId, address _chainTypeManager) internal view {\n        if (_chainId == 0) {\n            revert ZeroChainId();\n        }\n\n        if (_chainId > type(uint48).max) {\n            revert ChainIdTooBig();\n        }\n\n        if (_chainId == block.chainid) {\n            revert ChainIdCantBeCurrentChain();\n        }\n\n        if (_chainTypeManager == address(0)) {\n            revert ZeroAddress();\n        }\n        if (_assetId == bytes32(0)) {\n            revert EmptyAssetId();\n        }\n\n        if (!chainTypeManagerIsRegistered[_chainTypeManager]) {\n            revert CTMNotRegistered();\n        }\n\n        if (!assetIdIsRegistered[_assetId]) {\n            revert AssetIdNotSupported(_assetId);\n        }\n\n        if (assetRouter == address(0)) {\n            revert SharedBridgeNotSet();\n        }\n        if (chainTypeManager[_chainId] != address(0)) {\n            revert BridgeHubAlreadyRegistered();\n        }\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                            PAUSE\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Pauses all functions marked with the `whenNotPaused` modifier.\n    function pause() external onlyOwner {\n        _pause();\n    }\n\n    /// @notice Unpauses the contract, allowing all functions marked with the `whenNotPaused` modifier to be called again.\n    function unpause() external onlyOwner {\n        _unpause();\n    }\n\n    /// @notice Pauses migration functions.\n    /// @dev Remove this with V30, the functionality was moved to the ChainAssetHandler in V29.\n    function pauseMigration() external onlyOwner {\n        migrationPaused = true;\n    }\n\n    /// @notice Unpauses migration functions.\n    function unpauseMigration() external onlyOwner {\n        migrationPaused = false;\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                            Legacy functions\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice return the ZK chain contract for a chainId\n    function getHyperchain(uint256 _chainId) public view returns (address) {\n        return getZKChain(_chainId);\n    }\n\n    /// @notice return the asset router\n    function sharedBridge() public view returns (address) {\n        return assetRouter;\n    }\n}\n","deployed_bytecode":"0x608060405260043610610371575f3560e01c806379ba5097116101c8578063d4b9f4fa116100fd578063e680c4c11161009d578063f2fde38b1161006d578063f2fde38b14610b1e578063f7c7eb9214610b3d578063f851a44014610b51578063ff5a62a114610b7d575f5ffd5b8063e680c4c114610a93578063e6d9923b14610ab2578063e9420f8c14610ad1578063f113c88b14610aff575f5ffd5b8063dead6f7f116100d8578063dead6f7f146109f1578063e0ab636814610a10578063e30c397814610a3e578063e52db4ca14610a68575f5ffd5b8063d4b9f4fa14610993578063d52471c1146109bf578063dc8e4b26146109d2575f5ffd5b8063ac700e6311610168578063b93c936611610143578063b93c9366146108ee578063bc0aac101461091c578063c4d66de814610948578063cbe8361214610967575f5ffd5b8063ac700e631461089c578063b292f5f1146108b0578063b5662c5d146108cf575f5ffd5b80638f8d37a8116101a35780638f8d37a8146107ea57806399c16d1a1461081d5780639d5bd3da1461083c5780639f115e381461087d575f5ffd5b806379ba5097146107985780638456cb59146107ac5780638da5cb5b146107c0575f5ffd5b80633f4ba83a116102a95780635cd8a76b1161024957806370d8af871161021957806370d8af871461070957806370fccb521461073a578063715018a6146107655780637162327414610779575f5ffd5b80635cd8a76b1461068a578063671a71311461069e57806368b8d331146106c95780637011be85146106ea575f5ffd5b80634dd18bf5116102845780634dd18bf514610616578063524c0cfa1461063557806359ec65a2146106545780635c975abb14610673575f5ffd5b80633f4ba83a146105c257806349707f31146105d65780634a945f8d146105f7575f5ffd5b806324fd57fb116103145780632f90b184116102ef5780632f90b18414610527578063332b96dc1461055a57806338720778146105795780633885a750146105a3575f5ffd5b806324fd57fb146104cc5780632a641114146104df5780632dbcf55f14610508575f5ffd5b806317fa37511161034f57806317fa3751146104425780631c50cfea1461046157806322f3a9ba1461048057806324358c611461049f575f5ffd5b80630641e4f71461037557806307621f84146103c65780630e18b6811461042c575b5f5ffd5b348015610380575f5ffd5b5061039461038f3660046147ed565b610b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152015b60405180910390f35b3480156103d1575f5ffd5b506104076103e036600461480d565b60d66020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103bd565b348015610437575f5ffd5b50610440610d57565b005b34801561044d575f5ffd5b5061039461045c366004614824565b610e85565b34801561046c575f5ffd5b5061044061047b36600461480d565b611055565b34801561048b575f5ffd5b5061044061049a36600461487e565b611176565b3480156104aa575f5ffd5b506104be6104b936600461480d565b6111ca565b6040519081526020016103bd565b6104be6104da3660046148b0565b611252565b3480156104ea575f5ffd5b5060db546104f89060ff1681565b60405190151581526020016103bd565b348015610513575f5ffd5b506104406105223660046148e2565b6118b4565b348015610532575f5ffd5b506104be7f000000000000000000000000000000000000000000000000000000000000000181565b348015610565575f5ffd5b5061044061057436600461487e565b611ad8565b348015610584575f5ffd5b5060c95473ffffffffffffffffffffffffffffffffffffffff16610407565b3480156105ae575f5ffd5b506104406105bd36600461480d565b611bfe565b3480156105cd575f5ffd5b50610440611f48565b3480156105e1575f5ffd5b506105ea611f5a565b6040516103bd9190614910565b348015610602575f5ffd5b50610440610611366004614968565b61202e565b348015610621575f5ffd5b5061044061063036600461487e565b6120d2565b348015610640575f5ffd5b5061044061064f3660046149c1565b61220e565b34801561065f575f5ffd5b5061040761066e36600461480d565b612370565b34801561067e575f5ffd5b5060975460ff166104f8565b348015610695575f5ffd5b506104406124fa565b3480156106a9575f5ffd5b506104be6106b836600461480d565b60d86020525f908152604090205481565b3480156106d4575f5ffd5b506106dd612791565b6040516103bd9190614a03565b3480156106f5575f5ffd5b50610440610704366004614a47565b6127a2565b348015610714575f5ffd5b5060db5461040790610100900473ffffffffffffffffffffffffffffffffffffffff1681565b348015610745575f5ffd5b506104be61075436600461487e565b60d76020525f908152604090205481565b348015610770575f5ffd5b5061044061282e565b348015610784575f5ffd5b506104be610793366004614a7b565b61283f565b3480156107a3575f5ffd5b506104406128f4565b3480156107b7575f5ffd5b506104406129a6565b3480156107cb575f5ffd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610407565b3480156107f5575f5ffd5b506104be7f000000000000000000000000000000000000000000000000000000000000006481565b348015610828575f5ffd5b506104f8610837366004614aeb565b6129b6565b348015610847575f5ffd5b5061040761085636600461480d565b60cc6020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b348015610888575f5ffd5b5061039461089736600461480d565b612a6b565b3480156108a7575f5ffd5b50610440612b33565b3480156108bb575f5ffd5b506104f86108ca366004614b86565b612b68565b3480156108da575f5ffd5b506104406108e93660046148e2565b612c23565b3480156108f9575f5ffd5b506104f861090836600461487e565b60ca6020525f908152604090205460ff1681565b348015610927575f5ffd5b5060c9546104079073ffffffffffffffffffffffffffffffffffffffff1681565b348015610953575f5ffd5b5061044061096236600461487e565b613156565b348015610972575f5ffd5b5060d5546104079073ffffffffffffffffffffffffffffffffffffffff1681565b34801561099e575f5ffd5b5060d3546104079073ffffffffffffffffffffffffffffffffffffffff1681565b6104be6109cd3660046148b0565b61327d565b3480156109dd575f5ffd5b506104406109ec366004614c11565b613635565b3480156109fc575f5ffd5b50610407610a0b36600461480d565b61376d565b348015610a1b575f5ffd5b506104f8610a2a36600461480d565b60da6020525f908152604090205460ff1681565b348015610a49575f5ffd5b5060655473ffffffffffffffffffffffffffffffffffffffff16610407565b348015610a73575f5ffd5b506104be610a8236600461480d565b60d46020525f908152604090205481565b348015610a9e575f5ffd5b50610407610aad36600461480d565b61377d565b348015610abd575f5ffd5b506104f8610acc366004614c34565b613790565b348015610adc575f5ffd5b506104f8610aeb36600461480d565b60d96020525f908152604090205460ff1681565b348015610b0a575f5ffd5b506104be610b19366004614cad565b6137fa565b348015610b29575f5ffd5b50610440610b3836600461487e565b613bbd565b348015610b48575f5ffd5b50610440613c6d565b348015610b5c575f5ffd5b5060ce546104079073ffffffffffffffffffffffffffffffffffffffff1681565b348015610b88575f5ffd5b50610440610b9736600461487e565b613c9f565b60db545f908190610100900473ffffffffffffffffffffffffffffffffffffffff163314610c215760db546040517f8beee3a300000000000000000000000000000000000000000000000000000000815233600482015261010090910473ffffffffffffffffffffffffffffffffffffffff1660248201526044015b60405180910390fd5b5f83815260d9602052604090205460ff16610c68576040517f90c7cbf100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f84815260d860205260409020544614610cc7575f84815260d86020526040908190205490517fc0ca91820000000000000000000000000000000000000000000000000000000081526004810191909152466024820152604401610c18565b5f84815260d86020908152604080832086905560d990915290205460ff1615610d1c576040517f02181a1300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2760d085613dc9565b5f94855260cc602052604090942054939473ffffffffffffffffffffffffffffffffffffffff9094169392505050565b60cf5473ffffffffffffffffffffffffffffffffffffffff16338114610dab576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610c18565b60ce805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000808416821790945560cf80549094169093556040519116915f917fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9908390a38173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc60405160405180910390a35050565b60db545f908190610100900473ffffffffffffffffffffffffffffffffffffffff163314610f055760db546040517f8beee3a300000000000000000000000000000000000000000000000000000000815233600482015261010090910473ffffffffffffffffffffffffffffffffffffffff166024820152604401610c18565b505f84815260d6602052604090205473ffffffffffffffffffffffffffffffffffffffff1680610f64576040517fce63ce1700000000000000000000000000000000000000000000000000000000815260048101869052602401610c18565b5f84815260d86020526040902054469003610fad576040517f587df426000000000000000000000000000000000000000000000000000000008152466004820152602401610c18565b5f84815260d86020908152604080832046905560cc825280832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff861617905560d4825280832086905585835260da909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561104b8461377d565b9150935093915050565b60ce5473ffffffffffffffffffffffffffffffffffffffff163314801590611095575060335473ffffffffffffffffffffffffffffffffffffffff163314155b156110ce576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610c18565b5f81815260da602052604090205460ff1615611116576040517ffe919e2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81815260da602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f3df150949161462acf3be30521d7da9e533b247327a254e55dd01875897a6df391a250565b61117e613dd4565b60db805473ffffffffffffffffffffffffffffffffffffffff909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b5f81815260cc602052604081205473ffffffffffffffffffffffffffffffffffffffff1680611228576040517f23f3c35700000000000000000000000000000000000000000000000000000000815260048101849052602401610c18565b73ffffffffffffffffffffffffffffffffffffffff165f90815260d7602052604090205492915050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f908082036112af576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600181146112e9576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455611315613e55565b467f000000000000000000000000000000000000000000000000000000000000000114611396576040517fecb344490000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000016004820152466024820152604401610c18565b61ffff6113a960e0850160c0860161487e565b73ffffffffffffffffffffffffffffffffffffffff1611611427576113d460e0840160c0850161487e565b6040517fb78dbaa700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015261ffff6024820152604401610c18565b82355f90815260d46020526040812054907f05e1c3ae4b9732444ae25217ac7666e46fa365fee1768de00c9fcb65532b760982036114d05761147160e08601356020870135614dba565b34146114c55761148960e08601356020870135614dba565b6040517f4a0944310000000000000000000000000000000000000000000000000000000081526004810191909152346024820152604401610c18565b50602084013561151c565b8460e001353414611519576040517f4a09443100000000000000000000000000000000000000000000000000000000815260e08601356004820152346024820152604401610c18565b505f5b60c9546040517fc487944000000000000000000000000000000000000000000000000000000000815286356004820152602481018490523360448201526020870135606482015273ffffffffffffffffffffffffffffffffffffffff9091169063c48794409083906084015f604051808303818588803b15801561159e575f5ffd5b505af11580156115b0573d5f5f3e3d5ffd5b505050505050505f8360c00160208101906115cb919061487e565b73ffffffffffffffffffffffffffffffffffffffff1663ca408c2360e086013586353360408901356116016101008b018b614dcd565b6040518763ffffffff1660e01b8152600401611621959493929190614e75565b5f6040518083038185885af115801561163c573d5f5f3e3d5ffd5b50505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611682919081019061501a565b90506116af60017fa175e001c0e5684bc26302c2f9a55aec9f3936fe2aef558034003ef4da7fc77e615151565b81511461171e576116e160017fa175e001c0e5684bc26302c2f9a55aec9f3936fe2aef558034003ef4da7fc77e615151565b81516040517f15e8e42900000000000000000000000000000000000000000000000000000000815260048101929092526024820152604401610c18565b6117e6843561173360c0870160a0880161487e565b6040805161012081019091528061175060e08a0160c08b0161487e565b73ffffffffffffffffffffffffffffffffffffffff168152602001856020015173ffffffffffffffffffffffffffffffffffffffff1681526020018860200135815260200188604001358152602001856040015181526020018860600135815260200188608001358152602001856060015181526020015f73ffffffffffffffffffffffffffffffffffffffff16815250613ec2565b92506117f860e0850160c0860161487e565b60808201516040517f8eb7db570000000000000000000000000000000000000000000000000000000081528635600482015260248101919091526044810185905273ffffffffffffffffffffffffffffffffffffffff9190911690638eb7db57906064015f604051808303815f87803b158015611873575f5ffd5b505af1158015611885573d5f5f3e3d5ffd5b505050505060017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45550919050565b5f467f000000000000000000000000000000000000000000000000000000000000000114611904577fffffffffffffffffffffffffeeeeffffffffffffffffffffffffffffffffeeef3301611906565b335b60d55490915073ffffffffffffffffffffffffffffffffffffffff808316911614611975576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610c18565b73ffffffffffffffffffffffffffffffffffffffff82165f90815260ca602052604090205460ff166119d3576040517fc630ef3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517f000000000000000000000000000000000000000000000000000000000000000160208083019190915273ffffffffffffffffffffffffffffffffffffffff841682840152606080830187905283518084039091018152608090920190925280519101205f905f81815260d66020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff891690811790915580845260d783529281902084905551338152929350869284917f8f09d7694a9ae17acec5cf132d594d7eee23572f7fe132396ce72b1afbf7ef20910160405180910390a450505050565b611ae0613dd4565b73ffffffffffffffffffffffffffffffffffffffff8116611b2d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f90815260ca602052604090205460ff16611b8b576040517fc630ef3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f81815260ca602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f4e04a497739580efe78a7ee09cdabe6f6fe90965c683292a519102ce5193b68a9190a250565b467f000000000000000000000000000000000000000000000000000000000000000114611c7f576040517fecb344490000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000016004820152466024820152604401610c18565b5f81815260cc602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611cda576040517f5de7210700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ce560d083613f6a565b15611d1c576040517fff514c1000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f82815260cd602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611d77576040517f5de7210700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611d824683613f75565b5f85815260d46020908152604080832084905583835260da90915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f4caa740f000000000000000000000000000000000000000000000000000000008152600481018790529192509073ffffffffffffffffffffffffffffffffffffffff851690634caa740f90602401602060405180830381865afa158015611e34573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e589190615164565b905073ffffffffffffffffffffffffffffffffffffffff8116611ea7576040517f4bd4ae0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611eb285825f613fd5565b60d3546040517fd4ce08c20000000000000000000000000000000000000000000000000000000081526004810187905273ffffffffffffffffffffffffffffffffffffffff9091169063d4ce08c2906024015f604051808303815f87803b158015611f1b575f5ffd5b505af1158015611f2d573d5f5f3e3d5ffd5b5050505f958652505060d86020525050604090912046905550565b611f50613dd4565b611f5861404e565b565b60605f611f6760d06140cb565b9050805167ffffffffffffffff811115611f8357611f83614ebb565b604051908082528060200260200182016040528015611fac578160200160208202803683370190505b5081519092505f5b8181101561202857611fe9838281518110611fd157611fd161517f565b602002602001015160d0613dc990919063ffffffff16565b848281518110611ffb57611ffb61517f565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101611fb4565b50505090565b612036613dd4565b60c9805473ffffffffffffffffffffffffffffffffffffffff9586167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560d580549486169482169490941790935560d38054928516929093169190911790915560db805491909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909116179055565b60ce5473ffffffffffffffffffffffffffffffffffffffff163314801590612112575060335473ffffffffffffffffffffffffffffffffffffffff163314155b1561214b576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610c18565b73ffffffffffffffffffffffffffffffffffffffff8116612198576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60cf805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9905f90a35050565b3373111111111111111111111111111111111111111114612277576040517fa2ac02a00000000000000000000000000000000000000000000000000000000081523360048201527311111111111111111111111111111111111111116024820152604401610c18565b467f0000000000000000000000000000000000000000000000000000000000000001036122d0576040517f472477e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6122dc60d085613dc9565b6040517fddcc9eec0000000000000000000000000000000000000000000000000000000081526004810185905267ffffffffffffffff8416602482015290915073ffffffffffffffffffffffffffffffffffffffff82169063ddcc9eec906044015f604051808303815f87803b158015612354575f5ffd5b505af1158015612366573d5f5f3e3d5ffd5b5050505050505050565b5f81815260d460205260408082205460c95491517f53b9e632000000000000000000000000000000000000000000000000000000008152600481018290529091839173ffffffffffffffffffffffffffffffffffffffff909116906353b9e63290602401602060405180830381865afa1580156123ef573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124139190615164565b905073ffffffffffffffffffffffffffffffffffffffff8116612465576040517f6410796800000000000000000000000000000000000000000000000000000000815260048101839052602401610c18565b6040517f97bb3ce90000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff8216906397bb3ce990602401602060405180830381865afa1580156124ce573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124f29190615164565b949350505050565b5f54610100900460ff161580801561251857505f54600160ff909116105b806125315750303b15801561253157505f5460ff166001145b6125bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610c18565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015612619575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b467f00000000000000000000000000000000000000000000000000000000000000011461269a576040517fecb344490000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000016004820152466024820152604401610c18565b7f05e1c3ae4b9732444ae25217ac7666e46fa365fee1768de00c9fcb65532b76095f90815260da60209081526040808320805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091821681179092557f0000000000000000000000000000000000000000000000000000000000000001855260d9909352922080549091169091179055801561278e575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b606061279d60d06140cb565b905090565b60db54610100900473ffffffffffffffffffffffffffffffffffffffff16331461281e5760db546040517f8beee3a300000000000000000000000000000000000000000000000000000000815233600482015261010090910473ffffffffffffffffffffffffffffffffffffffff166024820152604401610c18565b612829838383613fd5565b505050565b612836613dd4565b611f585f6140d7565b5f8061284c60d087613dc9565b6040517fb473318e00000000000000000000000000000000000000000000000000000000815260048101879052602481018690526044810185905290915073ffffffffffffffffffffffffffffffffffffffff82169063b473318e90606401602060405180830381865afa1580156128c6573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128ea91906151ac565b9695505050505050565b606554339073ffffffffffffffffffffffffffffffffffffffff16811461299d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610c18565b61278e816140d7565b6129ae613dd4565b611f58614108565b5f806129c360d089613dc9565b6040517fe4948f4300000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063e4948f4390612a20908a908a908a908a908a9060040161526c565b602060405180830381865afa158015612a3b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a5f91906152f0565b98975050505050505050565b60db545f908190610100900473ffffffffffffffffffffffffffffffffffffffff163314612aeb5760db546040517f8beee3a300000000000000000000000000000000000000000000000000000000815233600482015261010090910473ffffffffffffffffffffffffffffffffffffffff166024820152604401610c18565b5f83815260d860205260409020469055612b048361377d565b5f93845260cc602052604090932054929373ffffffffffffffffffffffffffffffffffffffff90931692915050565b612b3b613dd4565b60db80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b5f80612b7560d08b613dc9565b6040517f042901c700000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063042901c790612bd6908c908c908c908c908c908c908c9060040161530b565b602060405180830381865afa158015612bf1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c1591906152f0565b9a9950505050505050505050565b612c2b613dd4565b467f000000000000000000000000000000000000000000000000000000000000000114612cac576040517fecb344490000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000016004820152466024820152604401610c18565b73ffffffffffffffffffffffffffffffffffffffff8116612cf9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612d0460d083613f6a565b15612d3b576040517f24591d8900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818173ffffffffffffffffffffffffffffffffffffffff16633408e4706040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d85573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612da991906151ac565b14612de0576040517fa179f8c900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8173ffffffffffffffffffffffffffffffffffffffff1663946ebad16040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e2a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e4e9190615164565b90505f8273ffffffffffffffffffffffffffffffffffffffff16636e9960c36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e9a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ebe9190615164565b90505f8373ffffffffffffffffffffffffffffffffffffffff1663960dcf246040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f0a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f2e91906151ac565b90505f8473ffffffffffffffffffffffffffffffffffffffff16633591c1a06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f7a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f9e9190615164565b905073ffffffffffffffffffffffffffffffffffffffff81163014613007576040517fdd381a4c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610c18565b613012868386614163565b5f86815260cc6020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff891617905560d4825280832085905560d8909152902046905561308086866001613fd5565b60d3546040517fd4ce08c20000000000000000000000000000000000000000000000000000000081526004810188905273ffffffffffffffffffffffffffffffffffffffff9091169063d4ce08c2906024015f604051808303815f87803b1580156130e9575f5ffd5b505af11580156130fb573d5f5f3e3d5ffd5b505060405173ffffffffffffffffffffffffffffffffffffffff8781168252861692508891507f1e9125bc72db22c58abff6821d7333551967e26454b419ffa958e4cb8ef476009060200160405180910390a3505050505050565b61315e6143eb565b467f0000000000000000000000000000000000000000000000000000000000000001146131df576040517fecb344490000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000016004820152466024820152604401610c18565b6131e8816140d7565b7f05e1c3ae4b9732444ae25217ac7666e46fa365fee1768de00c9fcb65532b76095f90815260da60209081526040808320805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091821681179092557f0000000000000000000000000000000000000000000000000000000000000001855260d990935292208054909116909117905550565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f908082036132da576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114613314576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455613340613e55565b467f0000000000000000000000000000000000000000000000000000000000000001146133c1576040517fecb344490000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000016004820152466024820152604401610c18565b82355f90815260d460205260409020547f05e1c3ae4b9732444ae25217ac7666e46fa365fee1768de00c9fcb65532b760981036134465783602001353414613441576040517f4a09443100000000000000000000000000000000000000000000000000000000815260208501356004820152346024820152604401610c18565b613486565b3415613486576040517f4a0944310000000000000000000000000000000000000000000000000000000081525f6004820152346024820152604401610c18565b60c9546040517fc487944000000000000000000000000000000000000000000000000000000000815285356004820152602481018390523360448201526020860135606482015273ffffffffffffffffffffffffffffffffffffffff9091169063c48794409034906084015f604051808303818588803b158015613508575f5ffd5b505af115801561351a573d5f5f3e3d5ffd5b5061360a9450508635925061353a9150506101208601610100870161487e565b604080516101208101825233815290602082019061355e9060608a01908a0161487e565b73ffffffffffffffffffffffffffffffffffffffff168152602088810135908201526060808901356040830152016135996080890189614dcd565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050509082525060a0880135602082015260c088013560408201526060016135f360e0890189615383565b6135fc916153e7565b81525f602090910152613ec2565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4559392505050565b61363d613dd4565b467f0000000000000000000000000000000000000000000000000000000000000001146136be576040517fecb344490000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000016004820152466024820152604401610c18565b5f82815260d860205260409020544614613704576040517f02181a1300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f82815260d9602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168415159081179091559051909184917f02629feb109d94b16a367231d248ba81c462f51ce5b984835f150f1c9f49ed259190a35050565b5f6137778261377d565b92915050565b5f61378960d08361444b565b9392505050565b5f8061379d60d089613dc9565b6040517f263b7f8e00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063263b7f8e90612a20908a908a908a908a908a9060040161548a565b60ce545f9073ffffffffffffffffffffffffffffffffffffffff16331480159061383c575060335473ffffffffffffffffffffffffffffffffffffffff163314155b15613875576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610c18565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f8190036138d1576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001811461390b576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455613937613e55565b467f0000000000000000000000000000000000000000000000000000000000000001146139b8576040517fecb344490000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000016004820152466024820152604401610c18565b6139c38b8a8c614163565b5f8b815260cc6020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8f1690811790915560d483528184208d905560d8909252808320469055517f88c7c5d20000000000000000000000000000000000000000000000000000000081526388c7c5d290613a6d908f908e908d908d908d908d908d9060040161552a565b6020604051808303815f875af1158015613a89573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613aad9190615164565b9050613abb8c826001613fd5565b60d3546040517fd4ce08c2000000000000000000000000000000000000000000000000000000008152600481018e905273ffffffffffffffffffffffffffffffffffffffff9091169063d4ce08c2906024015f604051808303815f87803b158015613b24575f5ffd5b505af1158015613b36573d5f5f3e3d5ffd5b505060405173ffffffffffffffffffffffffffffffffffffffff8e811682528b1692508e91507f1e9125bc72db22c58abff6821d7333551967e26454b419ffa958e4cb8ef476009060200160405180910390a3505060017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455509798975050505050505050565b613bc5613dd4565b6065805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155613c2860335473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b613c75613dd4565b60db80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b613ca7613dd4565b73ffffffffffffffffffffffffffffffffffffffff8116613cf4576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f90815260ca602052604090205460ff1615613d53576040517fec27343900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f81815260ca602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f2eae91be1021e05cc8076387b0182458ae474ae44ee44cc59aefda6ca53c1f429190a250565b5f6137898383614468565b60335473ffffffffffffffffffffffffffffffffffffffff163314611f58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c18565b60975460ff1615611f58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610c18565b5f5f613ece84336144f1565b73ffffffffffffffffffffffffffffffffffffffff811661010085015290505f613ef960d087613dc9565b6040517f12f43dab00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8216906312f43dab90613f4e9087906004016156b3565b6020604051808303815f875af11580156128c6573d5f5f3e3d5ffd5b5f613789838361458f565b5f82613f856201000060046157b6565b60408051602081019390935273ffffffffffffffffffffffffffffffffffffffff918216908301528316606082015260800160405160208183030381529060405280519060200120905092915050565b613fe160d0848461459a565b5080801561401757507f000000000000000000000000000000000000000000000000000000000000006461401560d06145bc565b115b15612829576040517f601b688200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6140566145c6565b609780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b60605f61378983614632565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561278e8161463d565b614110613e55565b609780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586140a13390565b825f0361419c576040517fc84885d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b65ffffffffffff8311156141dc576040517f8f620a0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b468303614215576040517f717a165600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116614262576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81614299576040517f2d4d012f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f90815260ca602052604090205460ff166142f7576040517fc630ef3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f82815260da602052604090205460ff16614341576040517f04a0b7e900000000000000000000000000000000000000000000000000000000815260048101839052602401610c18565b60c95473ffffffffffffffffffffffffffffffffffffffff16614390576040517f856d5b7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f83815260cc602052604090205473ffffffffffffffffffffffffffffffffffffffff1615612829576040517f6cf1231200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf480546001909155801561278e576040517fdf3a8fdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80808061445986866146b3565b909450925050505b9250929050565b5f8181526002830160205260408120548015158061448b575061448b848461458f565b613789576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f456e756d657261626c654d61703a206e6f6e6578697374656e74206b657900006044820152606401610c18565b5f73ffffffffffffffffffffffffffffffffffffffff831661454f5773ffffffffffffffffffffffffffffffffffffffff82163214614546577311110000000000000000000000000000000011118201614548565b815b9050613777565b73ffffffffffffffffffffffffffffffffffffffff83163b15614588577311110000000000000000000000000000000011118301614548565b5090919050565b5f61378983836146eb565b5f6124f2848473ffffffffffffffffffffffffffffffffffffffff8516614702565b5f6137778261471e565b60975460ff16611f58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610c18565b606061377782614728565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f8181526002830160205260408120548190806146e0576146d4858561458f565b92505f91506144619050565b600192509050614461565b5f8181526001830160205260408120541515613789565b5f82815260028401602052604081208290556124f28484614734565b5f6137778261473f565b60605f61378983614748565b5f61378983836147a1565b5f613777825490565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561479557602002820191905f5260205f20905b815481526020019060010190808311614781575b50505050509050919050565b5f8181526001830160205260408120546147e657508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155613777565b505f613777565b5f5f604083850312156147fe575f5ffd5b50508035926020909101359150565b5f6020828403121561481d575f5ffd5b5035919050565b5f5f5f60608486031215614836575f5ffd5b505081359360208301359350604090920135919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461278e575f5ffd5b80356148798161484d565b919050565b5f6020828403121561488e575f5ffd5b81356137898161484d565b5f61012082840312156148aa575f5ffd5b50919050565b5f602082840312156148c0575f5ffd5b813567ffffffffffffffff8111156148d6575f5ffd5b6124f284828501614899565b5f5f604083850312156148f3575f5ffd5b8235915060208301356149058161484d565b809150509250929050565b602080825282518282018190525f918401906040840190835b8181101561495d57835173ffffffffffffffffffffffffffffffffffffffff16835260209384019390920191600101614929565b509095945050505050565b5f5f5f5f6080858703121561497b575f5ffd5b84356149868161484d565b935060208501356149968161484d565b925060408501356149a68161484d565b915060608501356149b68161484d565b939692955090935050565b5f5f5f606084860312156149d3575f5ffd5b8335925060208401359150604084013567ffffffffffffffff811681146149f8575f5ffd5b809150509250925092565b602080825282518282018190525f918401906040840190835b8181101561495d578351835260209384019390920191600101614a1c565b801515811461278e575f5ffd5b5f5f5f60608486031215614a59575f5ffd5b833592506020840135614a6b8161484d565b915060408401356149f881614a3a565b5f5f5f5f60808587031215614a8e575f5ffd5b5050823594602084013594506040840135936060013592509050565b5f5f83601f840112614aba575f5ffd5b50813567ffffffffffffffff811115614ad1575f5ffd5b6020830191508360208260051b8501011115614461575f5ffd5b5f5f5f5f5f5f60a08789031215614b00575f5ffd5b863595506020870135945060408701359350606087013567ffffffffffffffff811115614b2b575f5ffd5b87016060818a031215614b3c575f5ffd5b9250608087013567ffffffffffffffff811115614b57575f5ffd5b614b6389828a01614aaa565b979a9699509497509295939492505050565b803561ffff81168114614879575f5ffd5b5f5f5f5f5f5f5f5f60e0898b031215614b9d575f5ffd5b88359750602089013596506040890135955060608901359450614bc260808a01614b75565b935060a089013567ffffffffffffffff811115614bdd575f5ffd5b614be98b828c01614aaa565b90945092505060c089013560028110614c00575f5ffd5b809150509295985092959890939650565b5f5f60408385031215614c22575f5ffd5b82359150602083013561490581614a3a565b5f5f5f5f5f5f868803610140811215614c4b575f5ffd5b87359650602088013595506040880135945060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa082011215614c8c575f5ffd5b5060608701925061012087013567ffffffffffffffff811115614b57575f5ffd5b5f5f5f5f5f5f5f5f5f60e08a8c031215614cc5575f5ffd5b8935985060208a0135614cd78161484d565b975060408a0135965060608a0135955060808a0135614cf58161484d565b945060a08a013567ffffffffffffffff811115614d10575f5ffd5b8a01601f81018c13614d20575f5ffd5b803567ffffffffffffffff811115614d36575f5ffd5b8c6020828401011115614d47575f5ffd5b6020919091019450925060c08a013567ffffffffffffffff811115614d6a575f5ffd5b614d768c828d01614aaa565b915080935050809150509295985092959850929598565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082018082111561377757613777614d8d565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614e00575f5ffd5b83018035915067ffffffffffffffff821115614e1a575f5ffd5b602001915036819003821315614461575f5ffd5b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b85815273ffffffffffffffffffffffffffffffffffffffff85166020820152836040820152608060608201525f614eb0608083018486614e2e565b979650505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60405160a0810167ffffffffffffffff81118282101715614f0b57614f0b614ebb565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5857614f58614ebb565b604052919050565b5f67ffffffffffffffff821115614f7957614f79614ebb565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112614fb4575f5ffd5b8151614fc7614fc282614f60565b614f11565b818152846020838601011115614fdb575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f67ffffffffffffffff82111561501057615010614ebb565b5060051b60200190565b5f6020828403121561502a575f5ffd5b815167ffffffffffffffff811115615040575f5ffd5b820160a08185031215615051575f5ffd5b615059614ee8565b81518152602082015161506b8161484d565b6020820152604082015167ffffffffffffffff811115615089575f5ffd5b61509586828501614fa5565b604083015250606082015167ffffffffffffffff8111156150b4575f5ffd5b8201601f810186136150c4575f5ffd5b80516150d2614fc282614ff7565b8082825260208201915060208360051b8501019250888311156150f3575f5ffd5b602084015b8381101561513457805167ffffffffffffffff811115615116575f5ffd5b6151258b602083890101614fa5565b845250602092830192016150f8565b506060850152505050608091820151918101919091529392505050565b8181038181111561377757613777614d8d565b5f60208284031215615174575f5ffd5b81516137898161484d565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f602082840312156151bc575f5ffd5b5051919050565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126151f6575f5ffd5b830160208101925035905067ffffffffffffffff811115615215575f5ffd5b803603821315614461575f5ffd5b8183525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115615253575f5ffd5b8260051b80836020870137939093016020019392505050565b8581528460208201526080604082015261ffff61528885614b75565b1660808201525f602085013561529d8161484d565b73ffffffffffffffffffffffffffffffffffffffff1660a08301526152c560408601866151c3565b606060c08501526152da60e085018284614e2e565b9150508281036060840152612a5f818587615223565b5f60208284031215615300575f5ffd5b815161378981614a3a565b87815286602082015285604082015261ffff8516606082015260c060808201525f61533a60c083018587615223565b905060028310615371577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b8260a083015298975050505050505050565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126153b6575f5ffd5b83018035915067ffffffffffffffff8211156153d0575f5ffd5b6020019150600581901b3603821315614461575f5ffd5b5f6153f4614fc284614ff7565b8381526020810190600585901b84013681111561540f575f5ffd5b845b8181101561495d57803567ffffffffffffffff81111561542f575f5ffd5b860136601f82011261543f575f5ffd5b803561544d614fc282614f60565b818152366020838501011115615461575f5ffd5b816020840160208301375f60208383010152808752505050602084019350602081019050615411565b8581528460208201525f843560ff81168082146154a5575f5ffd5b60408401525060208501356154b981614a3a565b1515606083015261ffff6154cf60408701614b75565b1660808301526154e16060860161486e565b73ffffffffffffffffffffffffffffffffffffffff811660a084015250608085013560c083015260a085013560e08301526101206101008301819052614eb09083018486615223565b87815286602082015273ffffffffffffffffffffffffffffffffffffffff8616604082015260a060608201525f61556560a083018688614e2e565b8281036080840152838152602080820190600586901b830101865f5b878110156155dd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08584030184526155ba828a6151c3565b6155c5858284614e2e565b60209687019690955093909301925050600101615581565b50909c9b505050505050505050505050565b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b5f82825180855260208501945060208160051b830101602085015f5b838110156156a7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08584030188526156918383516155ef565b6020988901989093509190910190600101615657565b50909695505050505050565b602081526156da60208201835173ffffffffffffffffffffffffffffffffffffffff169052565b5f6020830151615702604084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040830151606083015260608301516080830152608083015161012060a08401526157326101408401826155ef565b905060a084015160c084015260c084015160e084015260e08401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084830301610100850152615782828261563b565b9150506101008401516157ae61012085018273ffffffffffffffffffffffffffffffffffffffff169052565b509392505050565b73ffffffffffffffffffffffffffffffffffffffff818116838216019081111561377757613777614d8d56fea264697066735822122006a6e419ee8d59e80df5bb72e1898f00bf6749cdef0e9be132c95a1e89a0236564736f6c634300081c0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":9999999},"remappings":[":@ensdomains/=node_modules/@ensdomains/",":@openzeppelin/contracts-upgradeable-v4/=lib/openzeppelin-contracts-upgradeable-v4/contracts/",":@openzeppelin/contracts-v4/=lib/openzeppelin-contracts-v4/contracts/",":ds-test/=lib/forge-std/lib/ds-test/src/",":erc4626-tests/=lib/openzeppelin-contracts-upgradeable-v4/lib/erc4626-tests/",":eth-gas-reporter/=node_modules/eth-gas-reporter/",":forge-std/=lib/forge-std/src/",":foundry-test/=test/foundry/",":hardhat/=node_modules/hardhat/",":l2-contracts/=../l2-contracts/contracts/",":murky/=lib/murky/src/",":openzeppelin-contracts-upgradeable-v4/=lib/openzeppelin-contracts-upgradeable-v4/",":openzeppelin-contracts-v4/=lib/openzeppelin-contracts-v4/",":openzeppelin-contracts/=lib/murky/lib/openzeppelin-contracts/"]},"optimization_runs":9999999,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/full_match/1/0xc89423b4909080fB8F8A43dF5E1C27001e55C24B/","decoded_constructor_args":[["1",{"internalType":"uint256","name":"_l1ChainId","type":"uint256"}],["0xE30Dca3047B37dc7d88849dE4A4Dc07937ad5Ab3",{"internalType":"address","name":"_owner","type":"address"}],["100",{"internalType":"uint256","name":"_maxNumberOfZKChains","type":"uint256"}]],"compiler_version":"0.8.28+commit.7893614a","is_verified_via_verifier_alliance":false,"verified_at":"2025-11-27T05:51:31.658968Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x60e060405234801561000f575f5ffd5b50604051615bc2380380615bc283398101604081905261002e91610263565b6100366100a4565b61003e6100ee565b60a083905260c08190526100538360016101aa565b60805261005f826101fe565b61009c6080515f90815260da602090815260408083208054600160ff19918216811790925560a051855260d9909352922080549091169091179055565b5050506102d1565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf48054600190915580156100eb5760405163df3a8fdd60e01b815260040160405180910390fd5b50565b5f54610100900460ff16156101595760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116146101a8575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b5f826101ba6201000060046102a6565b6040805160208101939093526001600160a01b0391821690830152831660608201526080016040516020818303038152906040528051906020012090505b92915050565b606580546001600160a01b03191690556100eb81603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f5f5f60608486031215610275575f5ffd5b835160208501519093506001600160a01b0381168114610293575f5ffd5b6040949094015192959394509192915050565b6001600160a01b0381811683821601908111156101f857634e487b7160e01b5f52601160045260245ffd5b60805160a05160c0516158186103aa5f395f81816107fb0152613fec01525f81816105380152818161131801528181611364015281816118b8015281816119d901528181611c0101528181611c4d0152818161227a0152818161261c01528181612668015281816126fa01528181612c2e01528181612c7a01528181613161015281816131ad01528181613248015281816133430152818161338f015281816136400152818161368c0152818161393a015261398601525f818161143a0152818161269c015281816131ea01526133d301526158185ff3fe608060405260043610610371575f3560e01c806379ba5097116101c8578063d4b9f4fa116100fd578063e680c4c11161009d578063f2fde38b1161006d578063f2fde38b14610b1e578063f7c7eb9214610b3d578063f851a44014610b51578063ff5a62a114610b7d575f5ffd5b8063e680c4c114610a93578063e6d9923b14610ab2578063e9420f8c14610ad1578063f113c88b14610aff575f5ffd5b8063dead6f7f116100d8578063dead6f7f146109f1578063e0ab636814610a10578063e30c397814610a3e578063e52db4ca14610a68575f5ffd5b8063d4b9f4fa14610993578063d52471c1146109bf578063dc8e4b26146109d2575f5ffd5b8063ac700e6311610168578063b93c936611610143578063b93c9366146108ee578063bc0aac101461091c578063c4d66de814610948578063cbe8361214610967575f5ffd5b8063ac700e631461089c578063b292f5f1146108b0578063b5662c5d146108cf575f5ffd5b80638f8d37a8116101a35780638f8d37a8146107ea57806399c16d1a1461081d5780639d5bd3da1461083c5780639f115e381461087d575f5ffd5b806379ba5097146107985780638456cb59146107ac5780638da5cb5b146107c0575f5ffd5b80633f4ba83a116102a95780635cd8a76b1161024957806370d8af871161021957806370d8af871461070957806370fccb521461073a578063715018a6146107655780637162327414610779575f5ffd5b80635cd8a76b1461068a578063671a71311461069e57806368b8d331146106c95780637011be85146106ea575f5ffd5b80634dd18bf5116102845780634dd18bf514610616578063524c0cfa1461063557806359ec65a2146106545780635c975abb14610673575f5ffd5b80633f4ba83a146105c257806349707f31146105d65780634a945f8d146105f7575f5ffd5b806324fd57fb116103145780632f90b184116102ef5780632f90b18414610527578063332b96dc1461055a57806338720778146105795780633885a750146105a3575f5ffd5b806324fd57fb146104cc5780632a641114146104df5780632dbcf55f14610508575f5ffd5b806317fa37511161034f57806317fa3751146104425780631c50cfea1461046157806322f3a9ba1461048057806324358c611461049f575f5ffd5b80630641e4f71461037557806307621f84146103c65780630e18b6811461042c575b5f5ffd5b348015610380575f5ffd5b5061039461038f3660046147ed565b610b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152015b60405180910390f35b3480156103d1575f5ffd5b506104076103e036600461480d565b60d66020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103bd565b348015610437575f5ffd5b50610440610d57565b005b34801561044d575f5ffd5b5061039461045c366004614824565b610e85565b34801561046c575f5ffd5b5061044061047b36600461480d565b611055565b34801561048b575f5ffd5b5061044061049a36600461487e565b611176565b3480156104aa575f5ffd5b506104be6104b936600461480d565b6111ca565b6040519081526020016103bd565b6104be6104da3660046148b0565b611252565b3480156104ea575f5ffd5b5060db546104f89060ff1681565b60405190151581526020016103bd565b348015610513575f5ffd5b506104406105223660046148e2565b6118b4565b348015610532575f5ffd5b506104be7f000000000000000000000000000000000000000000000000000000000000000081565b348015610565575f5ffd5b5061044061057436600461487e565b611ad8565b348015610584575f5ffd5b5060c95473ffffffffffffffffffffffffffffffffffffffff16610407565b3480156105ae575f5ffd5b506104406105bd36600461480d565b611bfe565b3480156105cd575f5ffd5b50610440611f48565b3480156105e1575f5ffd5b506105ea611f5a565b6040516103bd9190614910565b348015610602575f5ffd5b50610440610611366004614968565b61202e565b348015610621575f5ffd5b5061044061063036600461487e565b6120d2565b348015610640575f5ffd5b5061044061064f3660046149c1565b61220e565b34801561065f575f5ffd5b5061040761066e36600461480d565b612370565b34801561067e575f5ffd5b5060975460ff166104f8565b348015610695575f5ffd5b506104406124fa565b3480156106a9575f5ffd5b506104be6106b836600461480d565b60d86020525f908152604090205481565b3480156106d4575f5ffd5b506106dd612791565b6040516103bd9190614a03565b3480156106f5575f5ffd5b50610440610704366004614a47565b6127a2565b348015610714575f5ffd5b5060db5461040790610100900473ffffffffffffffffffffffffffffffffffffffff1681565b348015610745575f5ffd5b506104be61075436600461487e565b60d76020525f908152604090205481565b348015610770575f5ffd5b5061044061282e565b348015610784575f5ffd5b506104be610793366004614a7b565b61283f565b3480156107a3575f5ffd5b506104406128f4565b3480156107b7575f5ffd5b506104406129a6565b3480156107cb575f5ffd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610407565b3480156107f5575f5ffd5b506104be7f000000000000000000000000000000000000000000000000000000000000000081565b348015610828575f5ffd5b506104f8610837366004614aeb565b6129b6565b348015610847575f5ffd5b5061040761085636600461480d565b60cc6020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b348015610888575f5ffd5b5061039461089736600461480d565b612a6b565b3480156108a7575f5ffd5b50610440612b33565b3480156108bb575f5ffd5b506104f86108ca366004614b86565b612b68565b3480156108da575f5ffd5b506104406108e93660046148e2565b612c23565b3480156108f9575f5ffd5b506104f861090836600461487e565b60ca6020525f908152604090205460ff1681565b348015610927575f5ffd5b5060c9546104079073ffffffffffffffffffffffffffffffffffffffff1681565b348015610953575f5ffd5b5061044061096236600461487e565b613156565b348015610972575f5ffd5b5060d5546104079073ffffffffffffffffffffffffffffffffffffffff1681565b34801561099e575f5ffd5b5060d3546104079073ffffffffffffffffffffffffffffffffffffffff1681565b6104be6109cd3660046148b0565b61327d565b3480156109dd575f5ffd5b506104406109ec366004614c11565b613635565b3480156109fc575f5ffd5b50610407610a0b36600461480d565b61376d565b348015610a1b575f5ffd5b506104f8610a2a36600461480d565b60da6020525f908152604090205460ff1681565b348015610a49575f5ffd5b5060655473ffffffffffffffffffffffffffffffffffffffff16610407565b348015610a73575f5ffd5b506104be610a8236600461480d565b60d46020525f908152604090205481565b348015610a9e575f5ffd5b50610407610aad36600461480d565b61377d565b348015610abd575f5ffd5b506104f8610acc366004614c34565b613790565b348015610adc575f5ffd5b506104f8610aeb36600461480d565b60d96020525f908152604090205460ff1681565b348015610b0a575f5ffd5b506104be610b19366004614cad565b6137fa565b348015610b29575f5ffd5b50610440610b3836600461487e565b613bbd565b348015610b48575f5ffd5b50610440613c6d565b348015610b5c575f5ffd5b5060ce546104079073ffffffffffffffffffffffffffffffffffffffff1681565b348015610b88575f5ffd5b50610440610b9736600461487e565b613c9f565b60db545f908190610100900473ffffffffffffffffffffffffffffffffffffffff163314610c215760db546040517f8beee3a300000000000000000000000000000000000000000000000000000000815233600482015261010090910473ffffffffffffffffffffffffffffffffffffffff1660248201526044015b60405180910390fd5b5f83815260d9602052604090205460ff16610c68576040517f90c7cbf100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f84815260d860205260409020544614610cc7575f84815260d86020526040908190205490517fc0ca91820000000000000000000000000000000000000000000000000000000081526004810191909152466024820152604401610c18565b5f84815260d86020908152604080832086905560d990915290205460ff1615610d1c576040517f02181a1300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2760d085613dc9565b5f94855260cc602052604090942054939473ffffffffffffffffffffffffffffffffffffffff9094169392505050565b60cf5473ffffffffffffffffffffffffffffffffffffffff16338114610dab576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610c18565b60ce805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000808416821790945560cf80549094169093556040519116915f917fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9908390a38173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc60405160405180910390a35050565b60db545f908190610100900473ffffffffffffffffffffffffffffffffffffffff163314610f055760db546040517f8beee3a300000000000000000000000000000000000000000000000000000000815233600482015261010090910473ffffffffffffffffffffffffffffffffffffffff166024820152604401610c18565b505f84815260d6602052604090205473ffffffffffffffffffffffffffffffffffffffff1680610f64576040517fce63ce1700000000000000000000000000000000000000000000000000000000815260048101869052602401610c18565b5f84815260d86020526040902054469003610fad576040517f587df426000000000000000000000000000000000000000000000000000000008152466004820152602401610c18565b5f84815260d86020908152604080832046905560cc825280832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff861617905560d4825280832086905585835260da909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561104b8461377d565b9150935093915050565b60ce5473ffffffffffffffffffffffffffffffffffffffff163314801590611095575060335473ffffffffffffffffffffffffffffffffffffffff163314155b156110ce576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610c18565b5f81815260da602052604090205460ff1615611116576040517ffe919e2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81815260da602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f3df150949161462acf3be30521d7da9e533b247327a254e55dd01875897a6df391a250565b61117e613dd4565b60db805473ffffffffffffffffffffffffffffffffffffffff909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b5f81815260cc602052604081205473ffffffffffffffffffffffffffffffffffffffff1680611228576040517f23f3c35700000000000000000000000000000000000000000000000000000000815260048101849052602401610c18565b73ffffffffffffffffffffffffffffffffffffffff165f90815260d7602052604090205492915050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f908082036112af576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600181146112e9576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455611315613e55565b467f000000000000000000000000000000000000000000000000000000000000000014611396576040517fecb344490000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610c18565b61ffff6113a960e0850160c0860161487e565b73ffffffffffffffffffffffffffffffffffffffff1611611427576113d460e0840160c0850161487e565b6040517fb78dbaa700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015261ffff6024820152604401610c18565b82355f90815260d46020526040812054907f000000000000000000000000000000000000000000000000000000000000000082036114d05761147160e08601356020870135614dba565b34146114c55761148960e08601356020870135614dba565b6040517f4a0944310000000000000000000000000000000000000000000000000000000081526004810191909152346024820152604401610c18565b50602084013561151c565b8460e001353414611519576040517f4a09443100000000000000000000000000000000000000000000000000000000815260e08601356004820152346024820152604401610c18565b505f5b60c9546040517fc487944000000000000000000000000000000000000000000000000000000000815286356004820152602481018490523360448201526020870135606482015273ffffffffffffffffffffffffffffffffffffffff9091169063c48794409083906084015f604051808303818588803b15801561159e575f5ffd5b505af11580156115b0573d5f5f3e3d5ffd5b505050505050505f8360c00160208101906115cb919061487e565b73ffffffffffffffffffffffffffffffffffffffff1663ca408c2360e086013586353360408901356116016101008b018b614dcd565b6040518763ffffffff1660e01b8152600401611621959493929190614e75565b5f6040518083038185885af115801561163c573d5f5f3e3d5ffd5b50505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611682919081019061501a565b90506116af60017fa175e001c0e5684bc26302c2f9a55aec9f3936fe2aef558034003ef4da7fc77e615151565b81511461171e576116e160017fa175e001c0e5684bc26302c2f9a55aec9f3936fe2aef558034003ef4da7fc77e615151565b81516040517f15e8e42900000000000000000000000000000000000000000000000000000000815260048101929092526024820152604401610c18565b6117e6843561173360c0870160a0880161487e565b6040805161012081019091528061175060e08a0160c08b0161487e565b73ffffffffffffffffffffffffffffffffffffffff168152602001856020015173ffffffffffffffffffffffffffffffffffffffff1681526020018860200135815260200188604001358152602001856040015181526020018860600135815260200188608001358152602001856060015181526020015f73ffffffffffffffffffffffffffffffffffffffff16815250613ec2565b92506117f860e0850160c0860161487e565b60808201516040517f8eb7db570000000000000000000000000000000000000000000000000000000081528635600482015260248101919091526044810185905273ffffffffffffffffffffffffffffffffffffffff9190911690638eb7db57906064015f604051808303815f87803b158015611873575f5ffd5b505af1158015611885573d5f5f3e3d5ffd5b505050505060017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45550919050565b5f467f000000000000000000000000000000000000000000000000000000000000000014611904577fffffffffffffffffffffffffeeeeffffffffffffffffffffffffffffffffeeef3301611906565b335b60d55490915073ffffffffffffffffffffffffffffffffffffffff808316911614611975576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610c18565b73ffffffffffffffffffffffffffffffffffffffff82165f90815260ca602052604090205460ff166119d3576040517fc630ef3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517f000000000000000000000000000000000000000000000000000000000000000060208083019190915273ffffffffffffffffffffffffffffffffffffffff841682840152606080830187905283518084039091018152608090920190925280519101205f905f81815260d66020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff891690811790915580845260d783529281902084905551338152929350869284917f8f09d7694a9ae17acec5cf132d594d7eee23572f7fe132396ce72b1afbf7ef20910160405180910390a450505050565b611ae0613dd4565b73ffffffffffffffffffffffffffffffffffffffff8116611b2d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f90815260ca602052604090205460ff16611b8b576040517fc630ef3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f81815260ca602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f4e04a497739580efe78a7ee09cdabe6f6fe90965c683292a519102ce5193b68a9190a250565b467f000000000000000000000000000000000000000000000000000000000000000014611c7f576040517fecb344490000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610c18565b5f81815260cc602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611cda576040517f5de7210700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ce560d083613f6a565b15611d1c576040517fff514c1000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f82815260cd602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611d77576040517f5de7210700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611d824683613f75565b5f85815260d46020908152604080832084905583835260da90915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f4caa740f000000000000000000000000000000000000000000000000000000008152600481018790529192509073ffffffffffffffffffffffffffffffffffffffff851690634caa740f90602401602060405180830381865afa158015611e34573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e589190615164565b905073ffffffffffffffffffffffffffffffffffffffff8116611ea7576040517f4bd4ae0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611eb285825f613fd5565b60d3546040517fd4ce08c20000000000000000000000000000000000000000000000000000000081526004810187905273ffffffffffffffffffffffffffffffffffffffff9091169063d4ce08c2906024015f604051808303815f87803b158015611f1b575f5ffd5b505af1158015611f2d573d5f5f3e3d5ffd5b5050505f958652505060d86020525050604090912046905550565b611f50613dd4565b611f5861404e565b565b60605f611f6760d06140cb565b9050805167ffffffffffffffff811115611f8357611f83614ebb565b604051908082528060200260200182016040528015611fac578160200160208202803683370190505b5081519092505f5b8181101561202857611fe9838281518110611fd157611fd161517f565b602002602001015160d0613dc990919063ffffffff16565b848281518110611ffb57611ffb61517f565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101611fb4565b50505090565b612036613dd4565b60c9805473ffffffffffffffffffffffffffffffffffffffff9586167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560d580549486169482169490941790935560d38054928516929093169190911790915560db805491909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909116179055565b60ce5473ffffffffffffffffffffffffffffffffffffffff163314801590612112575060335473ffffffffffffffffffffffffffffffffffffffff163314155b1561214b576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610c18565b73ffffffffffffffffffffffffffffffffffffffff8116612198576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60cf805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9905f90a35050565b3373111111111111111111111111111111111111111114612277576040517fa2ac02a00000000000000000000000000000000000000000000000000000000081523360048201527311111111111111111111111111111111111111116024820152604401610c18565b467f0000000000000000000000000000000000000000000000000000000000000000036122d0576040517f472477e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6122dc60d085613dc9565b6040517fddcc9eec0000000000000000000000000000000000000000000000000000000081526004810185905267ffffffffffffffff8416602482015290915073ffffffffffffffffffffffffffffffffffffffff82169063ddcc9eec906044015f604051808303815f87803b158015612354575f5ffd5b505af1158015612366573d5f5f3e3d5ffd5b5050505050505050565b5f81815260d460205260408082205460c95491517f53b9e632000000000000000000000000000000000000000000000000000000008152600481018290529091839173ffffffffffffffffffffffffffffffffffffffff909116906353b9e63290602401602060405180830381865afa1580156123ef573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124139190615164565b905073ffffffffffffffffffffffffffffffffffffffff8116612465576040517f6410796800000000000000000000000000000000000000000000000000000000815260048101839052602401610c18565b6040517f97bb3ce90000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff8216906397bb3ce990602401602060405180830381865afa1580156124ce573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124f29190615164565b949350505050565b5f54610100900460ff161580801561251857505f54600160ff909116105b806125315750303b15801561253157505f5460ff166001145b6125bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610c18565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015612619575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b467f00000000000000000000000000000000000000000000000000000000000000001461269a576040517fecb344490000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610c18565b7f00000000000000000000000000000000000000000000000000000000000000005f90815260da60209081526040808320805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091821681179092557f0000000000000000000000000000000000000000000000000000000000000000855260d9909352922080549091169091179055801561278e575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b606061279d60d06140cb565b905090565b60db54610100900473ffffffffffffffffffffffffffffffffffffffff16331461281e5760db546040517f8beee3a300000000000000000000000000000000000000000000000000000000815233600482015261010090910473ffffffffffffffffffffffffffffffffffffffff166024820152604401610c18565b612829838383613fd5565b505050565b612836613dd4565b611f585f6140d7565b5f8061284c60d087613dc9565b6040517fb473318e00000000000000000000000000000000000000000000000000000000815260048101879052602481018690526044810185905290915073ffffffffffffffffffffffffffffffffffffffff82169063b473318e90606401602060405180830381865afa1580156128c6573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128ea91906151ac565b9695505050505050565b606554339073ffffffffffffffffffffffffffffffffffffffff16811461299d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610c18565b61278e816140d7565b6129ae613dd4565b611f58614108565b5f806129c360d089613dc9565b6040517fe4948f4300000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063e4948f4390612a20908a908a908a908a908a9060040161526c565b602060405180830381865afa158015612a3b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a5f91906152f0565b98975050505050505050565b60db545f908190610100900473ffffffffffffffffffffffffffffffffffffffff163314612aeb5760db546040517f8beee3a300000000000000000000000000000000000000000000000000000000815233600482015261010090910473ffffffffffffffffffffffffffffffffffffffff166024820152604401610c18565b5f83815260d860205260409020469055612b048361377d565b5f93845260cc602052604090932054929373ffffffffffffffffffffffffffffffffffffffff90931692915050565b612b3b613dd4565b60db80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b5f80612b7560d08b613dc9565b6040517f042901c700000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063042901c790612bd6908c908c908c908c908c908c908c9060040161530b565b602060405180830381865afa158015612bf1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c1591906152f0565b9a9950505050505050505050565b612c2b613dd4565b467f000000000000000000000000000000000000000000000000000000000000000014612cac576040517fecb344490000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610c18565b73ffffffffffffffffffffffffffffffffffffffff8116612cf9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612d0460d083613f6a565b15612d3b576040517f24591d8900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818173ffffffffffffffffffffffffffffffffffffffff16633408e4706040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d85573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612da991906151ac565b14612de0576040517fa179f8c900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8173ffffffffffffffffffffffffffffffffffffffff1663946ebad16040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e2a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e4e9190615164565b90505f8273ffffffffffffffffffffffffffffffffffffffff16636e9960c36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e9a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ebe9190615164565b90505f8373ffffffffffffffffffffffffffffffffffffffff1663960dcf246040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f0a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f2e91906151ac565b90505f8473ffffffffffffffffffffffffffffffffffffffff16633591c1a06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f7a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f9e9190615164565b905073ffffffffffffffffffffffffffffffffffffffff81163014613007576040517fdd381a4c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610c18565b613012868386614163565b5f86815260cc6020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff891617905560d4825280832085905560d8909152902046905561308086866001613fd5565b60d3546040517fd4ce08c20000000000000000000000000000000000000000000000000000000081526004810188905273ffffffffffffffffffffffffffffffffffffffff9091169063d4ce08c2906024015f604051808303815f87803b1580156130e9575f5ffd5b505af11580156130fb573d5f5f3e3d5ffd5b505060405173ffffffffffffffffffffffffffffffffffffffff8781168252861692508891507f1e9125bc72db22c58abff6821d7333551967e26454b419ffa958e4cb8ef476009060200160405180910390a3505050505050565b61315e6143eb565b467f0000000000000000000000000000000000000000000000000000000000000000146131df576040517fecb344490000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610c18565b6131e8816140d7565b7f00000000000000000000000000000000000000000000000000000000000000005f90815260da60209081526040808320805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091821681179092557f0000000000000000000000000000000000000000000000000000000000000000855260d990935292208054909116909117905550565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f908082036132da576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114613314576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455613340613e55565b467f0000000000000000000000000000000000000000000000000000000000000000146133c1576040517fecb344490000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610c18565b82355f90815260d460205260409020547f000000000000000000000000000000000000000000000000000000000000000081036134465783602001353414613441576040517f4a09443100000000000000000000000000000000000000000000000000000000815260208501356004820152346024820152604401610c18565b613486565b3415613486576040517f4a0944310000000000000000000000000000000000000000000000000000000081525f6004820152346024820152604401610c18565b60c9546040517fc487944000000000000000000000000000000000000000000000000000000000815285356004820152602481018390523360448201526020860135606482015273ffffffffffffffffffffffffffffffffffffffff9091169063c48794409034906084015f604051808303818588803b158015613508575f5ffd5b505af115801561351a573d5f5f3e3d5ffd5b5061360a9450508635925061353a9150506101208601610100870161487e565b604080516101208101825233815290602082019061355e9060608a01908a0161487e565b73ffffffffffffffffffffffffffffffffffffffff168152602088810135908201526060808901356040830152016135996080890189614dcd565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050509082525060a0880135602082015260c088013560408201526060016135f360e0890189615383565b6135fc916153e7565b81525f602090910152613ec2565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4559392505050565b61363d613dd4565b467f0000000000000000000000000000000000000000000000000000000000000000146136be576040517fecb344490000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610c18565b5f82815260d860205260409020544614613704576040517f02181a1300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f82815260d9602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168415159081179091559051909184917f02629feb109d94b16a367231d248ba81c462f51ce5b984835f150f1c9f49ed259190a35050565b5f6137778261377d565b92915050565b5f61378960d08361444b565b9392505050565b5f8061379d60d089613dc9565b6040517f263b7f8e00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063263b7f8e90612a20908a908a908a908a908a9060040161548a565b60ce545f9073ffffffffffffffffffffffffffffffffffffffff16331480159061383c575060335473ffffffffffffffffffffffffffffffffffffffff163314155b15613875576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610c18565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f8190036138d1576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001811461390b576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455613937613e55565b467f0000000000000000000000000000000000000000000000000000000000000000146139b8576040517fecb344490000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610c18565b6139c38b8a8c614163565b5f8b815260cc6020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8f1690811790915560d483528184208d905560d8909252808320469055517f88c7c5d20000000000000000000000000000000000000000000000000000000081526388c7c5d290613a6d908f908e908d908d908d908d908d9060040161552a565b6020604051808303815f875af1158015613a89573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613aad9190615164565b9050613abb8c826001613fd5565b60d3546040517fd4ce08c2000000000000000000000000000000000000000000000000000000008152600481018e905273ffffffffffffffffffffffffffffffffffffffff9091169063d4ce08c2906024015f604051808303815f87803b158015613b24575f5ffd5b505af1158015613b36573d5f5f3e3d5ffd5b505060405173ffffffffffffffffffffffffffffffffffffffff8e811682528b1692508e91507f1e9125bc72db22c58abff6821d7333551967e26454b419ffa958e4cb8ef476009060200160405180910390a3505060017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455509798975050505050505050565b613bc5613dd4565b6065805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155613c2860335473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b613c75613dd4565b60db80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b613ca7613dd4565b73ffffffffffffffffffffffffffffffffffffffff8116613cf4576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f90815260ca602052604090205460ff1615613d53576040517fec27343900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f81815260ca602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f2eae91be1021e05cc8076387b0182458ae474ae44ee44cc59aefda6ca53c1f429190a250565b5f6137898383614468565b60335473ffffffffffffffffffffffffffffffffffffffff163314611f58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c18565b60975460ff1615611f58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610c18565b5f5f613ece84336144f1565b73ffffffffffffffffffffffffffffffffffffffff811661010085015290505f613ef960d087613dc9565b6040517f12f43dab00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8216906312f43dab90613f4e9087906004016156b3565b6020604051808303815f875af11580156128c6573d5f5f3e3d5ffd5b5f613789838361458f565b5f82613f856201000060046157b6565b60408051602081019390935273ffffffffffffffffffffffffffffffffffffffff918216908301528316606082015260800160405160208183030381529060405280519060200120905092915050565b613fe160d0848461459a565b5080801561401757507f000000000000000000000000000000000000000000000000000000000000000061401560d06145bc565b115b15612829576040517f601b688200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6140566145c6565b609780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b60605f61378983614632565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561278e8161463d565b614110613e55565b609780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586140a13390565b825f0361419c576040517fc84885d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b65ffffffffffff8311156141dc576040517f8f620a0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b468303614215576040517f717a165600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116614262576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81614299576040517f2d4d012f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f90815260ca602052604090205460ff166142f7576040517fc630ef3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f82815260da602052604090205460ff16614341576040517f04a0b7e900000000000000000000000000000000000000000000000000000000815260048101839052602401610c18565b60c95473ffffffffffffffffffffffffffffffffffffffff16614390576040517f856d5b7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f83815260cc602052604090205473ffffffffffffffffffffffffffffffffffffffff1615612829576040517f6cf1231200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf480546001909155801561278e576040517fdf3a8fdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80808061445986866146b3565b909450925050505b9250929050565b5f8181526002830160205260408120548015158061448b575061448b848461458f565b613789576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f456e756d657261626c654d61703a206e6f6e6578697374656e74206b657900006044820152606401610c18565b5f73ffffffffffffffffffffffffffffffffffffffff831661454f5773ffffffffffffffffffffffffffffffffffffffff82163214614546577311110000000000000000000000000000000011118201614548565b815b9050613777565b73ffffffffffffffffffffffffffffffffffffffff83163b15614588577311110000000000000000000000000000000011118301614548565b5090919050565b5f61378983836146eb565b5f6124f2848473ffffffffffffffffffffffffffffffffffffffff8516614702565b5f6137778261471e565b60975460ff16611f58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610c18565b606061377782614728565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f8181526002830160205260408120548190806146e0576146d4858561458f565b92505f91506144619050565b600192509050614461565b5f8181526001830160205260408120541515613789565b5f82815260028401602052604081208290556124f28484614734565b5f6137778261473f565b60605f61378983614748565b5f61378983836147a1565b5f613777825490565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561479557602002820191905f5260205f20905b815481526020019060010190808311614781575b50505050509050919050565b5f8181526001830160205260408120546147e657508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155613777565b505f613777565b5f5f604083850312156147fe575f5ffd5b50508035926020909101359150565b5f6020828403121561481d575f5ffd5b5035919050565b5f5f5f60608486031215614836575f5ffd5b505081359360208301359350604090920135919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461278e575f5ffd5b80356148798161484d565b919050565b5f6020828403121561488e575f5ffd5b81356137898161484d565b5f61012082840312156148aa575f5ffd5b50919050565b5f602082840312156148c0575f5ffd5b813567ffffffffffffffff8111156148d6575f5ffd5b6124f284828501614899565b5f5f604083850312156148f3575f5ffd5b8235915060208301356149058161484d565b809150509250929050565b602080825282518282018190525f918401906040840190835b8181101561495d57835173ffffffffffffffffffffffffffffffffffffffff16835260209384019390920191600101614929565b509095945050505050565b5f5f5f5f6080858703121561497b575f5ffd5b84356149868161484d565b935060208501356149968161484d565b925060408501356149a68161484d565b915060608501356149b68161484d565b939692955090935050565b5f5f5f606084860312156149d3575f5ffd5b8335925060208401359150604084013567ffffffffffffffff811681146149f8575f5ffd5b809150509250925092565b602080825282518282018190525f918401906040840190835b8181101561495d578351835260209384019390920191600101614a1c565b801515811461278e575f5ffd5b5f5f5f60608486031215614a59575f5ffd5b833592506020840135614a6b8161484d565b915060408401356149f881614a3a565b5f5f5f5f60808587031215614a8e575f5ffd5b5050823594602084013594506040840135936060013592509050565b5f5f83601f840112614aba575f5ffd5b50813567ffffffffffffffff811115614ad1575f5ffd5b6020830191508360208260051b8501011115614461575f5ffd5b5f5f5f5f5f5f60a08789031215614b00575f5ffd5b863595506020870135945060408701359350606087013567ffffffffffffffff811115614b2b575f5ffd5b87016060818a031215614b3c575f5ffd5b9250608087013567ffffffffffffffff811115614b57575f5ffd5b614b6389828a01614aaa565b979a9699509497509295939492505050565b803561ffff81168114614879575f5ffd5b5f5f5f5f5f5f5f5f60e0898b031215614b9d575f5ffd5b88359750602089013596506040890135955060608901359450614bc260808a01614b75565b935060a089013567ffffffffffffffff811115614bdd575f5ffd5b614be98b828c01614aaa565b90945092505060c089013560028110614c00575f5ffd5b809150509295985092959890939650565b5f5f60408385031215614c22575f5ffd5b82359150602083013561490581614a3a565b5f5f5f5f5f5f868803610140811215614c4b575f5ffd5b87359650602088013595506040880135945060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa082011215614c8c575f5ffd5b5060608701925061012087013567ffffffffffffffff811115614b57575f5ffd5b5f5f5f5f5f5f5f5f5f60e08a8c031215614cc5575f5ffd5b8935985060208a0135614cd78161484d565b975060408a0135965060608a0135955060808a0135614cf58161484d565b945060a08a013567ffffffffffffffff811115614d10575f5ffd5b8a01601f81018c13614d20575f5ffd5b803567ffffffffffffffff811115614d36575f5ffd5b8c6020828401011115614d47575f5ffd5b6020919091019450925060c08a013567ffffffffffffffff811115614d6a575f5ffd5b614d768c828d01614aaa565b915080935050809150509295985092959850929598565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082018082111561377757613777614d8d565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614e00575f5ffd5b83018035915067ffffffffffffffff821115614e1a575f5ffd5b602001915036819003821315614461575f5ffd5b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b85815273ffffffffffffffffffffffffffffffffffffffff85166020820152836040820152608060608201525f614eb0608083018486614e2e565b979650505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60405160a0810167ffffffffffffffff81118282101715614f0b57614f0b614ebb565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5857614f58614ebb565b604052919050565b5f67ffffffffffffffff821115614f7957614f79614ebb565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112614fb4575f5ffd5b8151614fc7614fc282614f60565b614f11565b818152846020838601011115614fdb575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f67ffffffffffffffff82111561501057615010614ebb565b5060051b60200190565b5f6020828403121561502a575f5ffd5b815167ffffffffffffffff811115615040575f5ffd5b820160a08185031215615051575f5ffd5b615059614ee8565b81518152602082015161506b8161484d565b6020820152604082015167ffffffffffffffff811115615089575f5ffd5b61509586828501614fa5565b604083015250606082015167ffffffffffffffff8111156150b4575f5ffd5b8201601f810186136150c4575f5ffd5b80516150d2614fc282614ff7565b8082825260208201915060208360051b8501019250888311156150f3575f5ffd5b602084015b8381101561513457805167ffffffffffffffff811115615116575f5ffd5b6151258b602083890101614fa5565b845250602092830192016150f8565b506060850152505050608091820151918101919091529392505050565b8181038181111561377757613777614d8d565b5f60208284031215615174575f5ffd5b81516137898161484d565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f602082840312156151bc575f5ffd5b5051919050565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126151f6575f5ffd5b830160208101925035905067ffffffffffffffff811115615215575f5ffd5b803603821315614461575f5ffd5b8183525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115615253575f5ffd5b8260051b80836020870137939093016020019392505050565b8581528460208201526080604082015261ffff61528885614b75565b1660808201525f602085013561529d8161484d565b73ffffffffffffffffffffffffffffffffffffffff1660a08301526152c560408601866151c3565b606060c08501526152da60e085018284614e2e565b9150508281036060840152612a5f818587615223565b5f60208284031215615300575f5ffd5b815161378981614a3a565b87815286602082015285604082015261ffff8516606082015260c060808201525f61533a60c083018587615223565b905060028310615371577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b8260a083015298975050505050505050565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126153b6575f5ffd5b83018035915067ffffffffffffffff8211156153d0575f5ffd5b6020019150600581901b3603821315614461575f5ffd5b5f6153f4614fc284614ff7565b8381526020810190600585901b84013681111561540f575f5ffd5b845b8181101561495d57803567ffffffffffffffff81111561542f575f5ffd5b860136601f82011261543f575f5ffd5b803561544d614fc282614f60565b818152366020838501011115615461575f5ffd5b816020840160208301375f60208383010152808752505050602084019350602081019050615411565b8581528460208201525f843560ff81168082146154a5575f5ffd5b60408401525060208501356154b981614a3a565b1515606083015261ffff6154cf60408701614b75565b1660808301526154e16060860161486e565b73ffffffffffffffffffffffffffffffffffffffff811660a084015250608085013560c083015260a085013560e08301526101206101008301819052614eb09083018486615223565b87815286602082015273ffffffffffffffffffffffffffffffffffffffff8616604082015260a060608201525f61556560a083018688614e2e565b8281036080840152838152602080820190600586901b830101865f5b878110156155dd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08584030184526155ba828a6151c3565b6155c5858284614e2e565b60209687019690955093909301925050600101615581565b50909c9b505050505050505050505050565b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b5f82825180855260208501945060208160051b830101602085015f5b838110156156a7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08584030188526156918383516155ef565b6020988901989093509190910190600101615657565b50909695505050505050565b602081526156da60208201835173ffffffffffffffffffffffffffffffffffffffff169052565b5f6020830151615702604084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040830151606083015260608301516080830152608083015161012060a08401526157326101408401826155ef565b905060a084015160c084015260c084015160e084015260e08401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084830301610100850152615782828261563b565b9150506101008401516157ae61012085018273ffffffffffffffffffffffffffffffffffffffff169052565b509392505050565b73ffffffffffffffffffffffffffffffffffffffff818116838216019081111561377757613777614d8d56fea264697066735822122006a6e419ee8d59e80df5bb72e1898f00bf6749cdef0e9be132c95a1e89a0236564736f6c634300081c00330000000000000000000000000000000000000000000000000000000000000001000000000000000000000000e30dca3047b37dc7d88849de4a4dc07937ad5ab30000000000000000000000000000000000000000000000000000000000000064","name":"Bridgehub","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"cancun","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[{"file_path":"contracts/common/libraries/UncheckedMath.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\n/**\n * @author Matter Labs\n * @custom:security-contact security@matterlabs.dev\n * @notice The library for unchecked math.\n */\nlibrary UncheckedMath {\n    function uncheckedInc(uint256 _number) internal pure returns (uint256) {\n        unchecked {\n            return _number + 1;\n        }\n    }\n\n    function uncheckedAdd(uint256 _lhs, uint256 _rhs) internal pure returns (uint256) {\n        unchecked {\n            return _lhs + _rhs;\n        }\n    }\n}\n"},{"file_path":"contracts/state-transition/chain-interfaces/IMailbox.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {IMessageVerification} from \"./IMessageVerification.sol\";\nimport {IMailboxImpl} from \"./IMailboxImpl.sol\";\n\n/// @title The interface of the ZKsync Mailbox contract that provides interfaces for L1 <-> L2 interaction.\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\ninterface IMailbox is IMessageVerification, IMailboxImpl {}\n"},{"file_path":"lib/openzeppelin-contracts-upgradeable-v4/contracts/access/Ownable2StepUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"},{"file_path":"contracts/state-transition/chain-deps/ZKChainStorage.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.28;\n\nimport {IVerifier, VerifierParams} from \"../chain-interfaces/IVerifier.sol\";\nimport {PriorityQueue} from \"../../state-transition/libraries/PriorityQueue.sol\";\nimport {PriorityTree} from \"../../state-transition/libraries/PriorityTree.sol\";\n\n/// @notice Indicates whether an upgrade is initiated and if yes what type\n/// @param None Upgrade is NOT initiated\n/// @param Transparent Fully transparent upgrade is initiated, upgrade data is publicly known\n/// @param Shadow Shadow upgrade is initiated, upgrade data is hidden\nenum UpgradeState {\n    None,\n    Transparent,\n    Shadow\n}\n\n/// @dev Logically separated part of the storage structure, which is responsible for everything related to proxy\n/// upgrades and diamond cuts\n/// @param proposedUpgradeHash The hash of the current upgrade proposal, zero if there is no active proposal\n/// @param state Indicates whether an upgrade is initiated and if yes what type\n/// @param securityCouncil Address which has the permission to approve instant upgrades (expected to be a Gnosis\n/// multisig)\n/// @param approvedBySecurityCouncil Indicates whether the security council has approved the upgrade\n/// @param proposedUpgradeTimestamp The timestamp when the upgrade was proposed, zero if there are no active proposals\n/// @param currentProposalId The serial number of proposed upgrades, increments when proposing a new one\nstruct UpgradeStorage {\n    bytes32 proposedUpgradeHash;\n    UpgradeState state;\n    address securityCouncil;\n    bool approvedBySecurityCouncil;\n    uint40 proposedUpgradeTimestamp;\n    uint40 currentProposalId;\n}\n\n/// @notice The struct that describes whether users will be charged for pubdata for L1->L2 transactions.\n/// @param Rollup The users are charged for pubdata & it is priced based on the gas price on Ethereum.\n/// @param Validium The pubdata is considered free with regard to the L1 gas price.\nenum PubdataPricingMode {\n    Rollup,\n    Validium\n}\n\n/// @notice The fee params for L1->L2 transactions for the network.\n/// @param pubdataPricingMode How the users will charged for pubdata in L1->L2 transactions.\n/// @param batchOverheadL1Gas The amount of L1 gas required to process the batch (except for the calldata).\n/// @param maxPubdataPerBatch The maximal number of pubdata that can be emitted per batch.\n/// @param priorityTxMaxPubdata The maximal amount of pubdata a priority transaction is allowed to publish.\n/// It can be slightly less than maxPubdataPerBatch in order to have some margin for the bootloader execution.\n/// @param minimalL2GasPrice The minimal L2 gas price to be used by L1->L2 transactions. It should represent\n/// the price that a single unit of compute costs.\nstruct FeeParams {\n    PubdataPricingMode pubdataPricingMode;\n    uint32 batchOverheadL1Gas;\n    uint32 maxPubdataPerBatch;\n    uint32 maxL2GasPerBatch;\n    uint32 priorityTxMaxPubdata;\n    uint64 minimalL2GasPrice;\n}\n\n/// @dev storing all storage variables for ZK chain diamond facets\n/// NOTE: It is used in a proxy, so it is possible to add new variables to the end\n/// but NOT to modify already existing variables or change their order.\n/// NOTE: variables prefixed with '__DEPRECATED_' are deprecated and shouldn't be used.\n/// Their presence is maintained for compatibility and to prevent storage collision.\n// solhint-disable-next-line gas-struct-packing\nstruct ZKChainStorage {\n    /// @dev Storage of variables needed for deprecated diamond cut facet\n    uint256[7] __DEPRECATED_diamondCutStorage;\n    /// @notice Address which will exercise critical changes to the Diamond Proxy (upgrades, freezing & unfreezing). Replaced by CTM\n    address __DEPRECATED_governor;\n    /// @notice Address that the governor proposed as one that will replace it\n    address __DEPRECATED_pendingGovernor;\n    /// @notice List of permitted validators\n    mapping(address validatorAddress => bool isValidator) validators;\n    /// @dev Verifier contract. Used to verify aggregated proof for batches\n    IVerifier verifier;\n    /// @notice Total number of executed batches i.e. batches[totalBatchesExecuted] points at the latest executed batch\n    /// (batch 0 is genesis)\n    uint256 totalBatchesExecuted;\n    /// @notice Total number of proved batches i.e. batches[totalBatchesProved] points at the latest proved batch\n    uint256 totalBatchesVerified;\n    /// @notice Total number of committed batches i.e. batches[totalBatchesCommitted] points at the latest committed\n    /// batch\n    uint256 totalBatchesCommitted;\n    /// @dev Stored hashed StoredBatch for batch number\n    mapping(uint256 batchNumber => bytes32 batchHash) storedBatchHashes;\n    /// @dev Stored root hashes of L2 -> L1 logs\n    mapping(uint256 batchNumber => bytes32 l2LogsRootHash) l2LogsRootHashes;\n    /// @dev Container that stores transactions requested from L1\n    PriorityQueue.Queue __DEPRECATED_priorityQueue;\n    /// @dev The smart contract that manages the list with permission to call contract functions\n    address __DEPRECATED_allowList;\n    VerifierParams __DEPRECATED_verifierParams;\n    /// @notice Bytecode hash of bootloader program.\n    /// @dev Used as an input to zkp-circuit.\n    bytes32 l2BootloaderBytecodeHash;\n    /// @notice Bytecode hash of default account (bytecode for EOA).\n    /// @dev Used as an input to zkp-circuit.\n    bytes32 l2DefaultAccountBytecodeHash;\n    /// @dev Indicates that the porter may be touched on L2 transactions.\n    /// @dev Used as an input to zkp-circuit.\n    bool zkPorterIsAvailable;\n    /// @dev The maximum number of the L2 gas that a user can request for L1 -> L2 transactions\n    /// @dev This is the maximum number of L2 gas that is available for the \"body\" of the transaction, i.e.\n    /// without overhead for proving the batch.\n    uint256 priorityTxMaxGasLimit;\n    /// @dev Storage of variables needed for upgrade facet\n    UpgradeStorage __DEPRECATED_upgrades;\n    /// @dev A mapping L2 batch number => message number => flag.\n    /// @dev The L2 -> L1 log is sent for every withdrawal, so this mapping is serving as\n    /// a flag to indicate that the message was already processed.\n    /// @dev Used to indicate that eth withdrawal was already processed\n    mapping(uint256 l2BatchNumber => mapping(uint256 l2ToL1MessageNumber => bool isFinalized)) isEthWithdrawalFinalized;\n    /// @dev The most recent withdrawal time and amount reset\n    uint256 __DEPRECATED_lastWithdrawalLimitReset;\n    /// @dev The accumulated withdrawn amount during the withdrawal limit window\n    uint256 __DEPRECATED_withdrawnAmountInWindow;\n    /// @dev A mapping user address => the total deposited amount by the user\n    mapping(address => uint256) __DEPRECATED_totalDepositedAmountPerUser;\n    /// @dev Stores the protocol version. Note, that the protocol version may not only encompass changes to the\n    /// smart contracts, but also to the node behavior.\n    uint256 protocolVersion;\n    /// @dev Hash of the system contract upgrade transaction. If 0, then no upgrade transaction needs to be done.\n    bytes32 l2SystemContractsUpgradeTxHash;\n    /// @dev Batch number where the upgrade transaction has happened. If 0, then no upgrade transaction has happened\n    /// yet.\n    uint256 l2SystemContractsUpgradeBatchNumber;\n    /// @dev Address which will exercise non-critical changes to the Diamond Proxy (changing validator set & unfreezing)\n    address admin;\n    /// @notice Address that the admin proposed as one that will replace admin role\n    address pendingAdmin;\n    /// @dev Fee params used to derive gasPrice for the L1->L2 transactions. For L2 transactions,\n    /// the bootloader gives enough freedom to the operator.\n    /// @dev The value is only for the L1 deployment of the ZK Chain, since payment for all the priority transactions is\n    /// charged at that level.\n    FeeParams feeParams;\n    /// @dev Address of the blob versioned hash getter smart contract used for EIP-4844 versioned hashes.\n    address __DEPRECATED_blobVersionedHashRetriever;\n    /// @dev The chainId of the chain\n    uint256 chainId;\n    /// @dev The address of the bridgehub\n    address bridgehub;\n    /// @dev The address of the ChainTypeManager\n    address chainTypeManager;\n    /// @dev The address of the baseToken contract. Eth is address(1)\n    address __DEPRECATED_baseToken;\n    /// @dev The address of the baseTokenbridge. Eth also uses the shared bridge\n    address __DEPRECATED_baseTokenBridge;\n    /// @notice gasPriceMultiplier for each baseToken, so that each L1->L2 transaction pays for its transaction on the destination\n    /// we multiply by the nominator, and divide by the denominator\n    uint128 baseTokenGasPriceMultiplierNominator;\n    uint128 baseTokenGasPriceMultiplierDenominator;\n    /// @dev The optional address of the contract that has to be used for transaction filtering/whitelisting\n    address transactionFilterer;\n    /// @dev The address of the l1DAValidator contract.\n    /// This contract is responsible for the verification of the correctness of the DA on L1.\n    address l1DAValidator;\n    /// @dev The address of the contract on L2 that is responsible for the data availability verification.\n    /// This contract sends `l2DAValidatorOutputHash` to L1 via L2->L1 system log and it will routed to the `l1DAValidator` contract.\n    address l2DAValidator;\n    /// @dev the Asset Id of the baseToken\n    bytes32 baseTokenAssetId;\n    /// @dev If this ZKchain settles on this chain, then this is zero. Otherwise it is the address of the ZKchain that is a\n    /// settlement layer for this ZKchain. (think about it as a 'forwarding' address for the chain that migrated away).\n    address settlementLayer;\n    /// @dev Priority tree, the new data structure for priority queue\n    PriorityTree.Tree priorityTree;\n    /// @dev Whether the chain is a permanent rollup. Note, that it only enforces the DA validator pair, but\n    /// it does not enforce any other parameters, e.g. `pubdataPricingMode`\n    bool isPermanentRollup;\n    /// @notice Bytecode hash of evm emulator.\n    /// @dev Used as an input to zkp-circuit.\n    bytes32 l2EvmEmulatorBytecodeHash;\n    /// @notice The precommitment for the latest uncommitted batch (i.e. totalBatchesCommitted + 1).\n    /// @dev Whenever the `totalBatchesCommitted` changes, this variable is reset to `DEFAULT_PRECOMMITMENT_FOR_THE_LAST_BATCH`\n    /// (the value of the constant can be found in Config.sol).\n    bytes32 precommitmentForTheLatestBatch;\n}\n"},{"file_path":"contracts/state-transition/chain-interfaces/IMailboxImpl.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {IZKChainBase} from \"./IZKChainBase.sol\";\nimport {BridgehubL2TransactionRequest, L2CanonicalTransaction, L2Log, L2Message, TxStatus} from \"../../common/Messaging.sol\";\n\n/// @title The interface of the ZKsync Mailbox contract that provides functions for L1 <-> L2 interaction.\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\ninterface IMailboxImpl is IZKChainBase {\n    /// @notice Prove that a specific arbitrary-length message was sent in a specific L2 batch number.\n    /// @param _batchNumber The executed L2 batch number in which the message appeared.\n    /// @param _index The position in the L2 logs Merkle tree of the l2Log that was sent with the message.\n    /// @param _message Information about the sent message: sender address, the message itself, tx index in the L2 batch where the message was sent.\n    /// @param _proof Merkle proof for inclusion of L2 log that was sent with the message.\n    /// @return Boolean specifying whether the proof is valid.\n    function proveL2MessageInclusion(\n        uint256 _batchNumber,\n        uint256 _index,\n        L2Message calldata _message,\n        bytes32[] calldata _proof\n    ) external view returns (bool);\n\n    /// @notice Prove that a specific L2 log was sent in a specific L2 batch.\n    /// @param _batchNumber The executed L2 batch number in which the log appeared.\n    /// @param _index The position of the l2log in the L2 logs Merkle tree.\n    /// @param _log Information about the sent log.\n    /// @param _proof Merkle proof for inclusion of the L2 log.\n    /// @return Whether the proof is correct and L2 log is included in batch.\n    function proveL2LogInclusion(\n        uint256 _batchNumber,\n        uint256 _index,\n        L2Log calldata _log,\n        bytes32[] calldata _proof\n    ) external view returns (bool);\n\n    /// @notice Prove that the L1 -> L2 transaction was processed with the specified status.\n    /// @param _l2TxHash The L2 canonical transaction hash.\n    /// @param _l2BatchNumber The L2 batch number where the transaction was processed.\n    /// @param _l2MessageIndex The position in the L2 logs Merkle tree of the l2Log that was sent with the message.\n    /// @param _l2TxNumberInBatch The L2 transaction number in the batch, in which the log was sent.\n    /// @param _merkleProof The Merkle proof of the processing L1 -> L2 transaction.\n    /// @param _status The execution status of the L1 -> L2 transaction (true - success & 0 - fail).\n    /// @return Whether the proof is correct and the transaction was actually executed with provided status.\n    /// NOTE: It may return `false` for incorrect proof, but it doesn't mean that the L1 -> L2 transaction has an opposite status!\n    function proveL1ToL2TransactionStatus(\n        bytes32 _l2TxHash,\n        uint256 _l2BatchNumber,\n        uint256 _l2MessageIndex,\n        uint16 _l2TxNumberInBatch,\n        bytes32[] calldata _merkleProof,\n        TxStatus _status\n    ) external view returns (bool);\n\n    /// @notice Finalize the withdrawal and release funds.\n    /// @param _l2BatchNumber The L2 batch number where the withdrawal was processed.\n    /// @param _l2MessageIndex The position in the L2 logs Merkle tree of the l2Log that was sent with the message.\n    /// @param _l2TxNumberInBatch The L2 transaction number in a batch, in which the log was sent.\n    /// @param _message The L2 withdraw data, stored in an L2 -> L1 message.\n    /// @param _merkleProof The Merkle proof of the inclusion L2 -> L1 message about withdrawal initialization.\n    function finalizeEthWithdrawal(\n        uint256 _l2BatchNumber,\n        uint256 _l2MessageIndex,\n        uint16 _l2TxNumberInBatch,\n        bytes calldata _message,\n        bytes32[] calldata _merkleProof\n    ) external;\n\n    /// @notice Request execution of L2 transaction from L1.\n    /// @param _contractL2 The L2 receiver address.\n    /// @param _l2Value `msg.value` of L2 transaction.\n    /// @param _calldata The input of the L2 transaction.\n    /// @param _l2GasLimit Maximum amount of L2 gas that transaction can consume during execution on L2.\n    /// @param _l2GasPerPubdataByteLimit The maximum amount L2 gas that the operator may charge the user for single byte of pubdata.\n    /// @param _factoryDeps An array of L2 bytecodes that will be marked as known on L2.\n    /// @param _refundRecipient The address on L2 that will receive the refund for the transaction.\n    /// @dev If the L2 deposit finalization transaction fails, the `_refundRecipient` will receive the `_l2Value`.\n    /// Please note, the contract may change the refund recipient's address to eliminate sending funds to addresses out of control.\n    /// - If `_refundRecipient` is a contract on L1, the refund will be sent to the aliased `_refundRecipient`.\n    /// - If `_refundRecipient` is set to `address(0)` and the sender has NO deployed bytecode on L1, the refund will be sent to the `msg.sender` address.\n    /// - If `_refundRecipient` is set to `address(0)` and the sender has deployed bytecode on L1, the refund will be sent to the aliased `msg.sender` address.\n    /// @dev The address aliasing of L1 contracts as refund recipient on L2 is necessary to guarantee that the funds are controllable,\n    /// since address aliasing to the from address for the L2 tx will be applied if the L1 `msg.sender` is a contract.\n    /// Without address aliasing for L1 contracts as refund recipients they would not be able to make proper L2 tx requests\n    /// through the Mailbox to use or withdraw the funds from L2, and the funds would be lost.\n    /// @return canonicalTxHash The hash of the requested L2 transaction. This hash can be used to follow the transaction status.\n    function requestL2Transaction(\n        address _contractL2,\n        uint256 _l2Value,\n        bytes calldata _calldata,\n        uint256 _l2GasLimit,\n        uint256 _l2GasPerPubdataByteLimit,\n        bytes[] calldata _factoryDeps,\n        address _refundRecipient\n    ) external payable returns (bytes32 canonicalTxHash);\n\n    /// @notice Request execution of L2 transaction through the Bridgehub.\n    /// @dev Only accessible from L1, this is getting checked in the Bridgehub.\n    /// @param _request the request for the L2 transaction.\n    function bridgehubRequestL2Transaction(\n        BridgehubL2TransactionRequest calldata _request\n    ) external returns (bytes32 canonicalTxHash);\n\n    /// @notice The chain's mailbox receives the tx from the Bridgehub on Gateway.\n    /// @param _canonicalTxHash the canonical transaction hash.\n    /// @param _expirationTimestamp the expiration timestamp for the transaction.\n    function bridgehubRequestL2TransactionOnGateway(bytes32 _canonicalTxHash, uint64 _expirationTimestamp) external;\n\n    /// @notice Request execution of service L2 transaction from L1.\n    /// @dev Used for chain configuration. Can be called only by DiamondProxy itself.\n    /// @param _contractL2 The L2 receiver address.\n    /// @param _l2Calldata The input of the L2 transaction.\n    function requestL2ServiceTransaction(\n        address _contractL2,\n        bytes calldata _l2Calldata\n    ) external returns (bytes32 canonicalTxHash);\n\n    /// @dev On L1 we have to forward to the Gateway's mailbox which sends to the Bridgehub on the Gateway.\n    /// @param _chainId the chainId of the chain.\n    /// @param _canonicalTxHash the canonical transaction hash.\n    /// @param _expirationTimestamp the expiration timestamp.\n    function requestL2TransactionToGatewayMailbox(\n        uint256 _chainId,\n        bytes32 _canonicalTxHash,\n        uint64 _expirationTimestamp\n    ) external returns (bytes32 canonicalTxHash);\n\n    /// @notice Estimates the cost in Ether of requesting execution of an L2 transaction from L1.\n    /// @param _gasPrice expected L1 gas price at which the user requests the transaction execution.\n    /// @param _l2GasLimit Maximum amount of L2 gas that transaction can consume during execution on L2.\n    /// @param _l2GasPerPubdataByteLimit The maximum amount of L2 gas that the operator may charge the user for a single byte of pubdata.\n    /// @return The estimated ETH spent on L2 gas for the transaction.\n    function l2TransactionBaseCost(\n        uint256 _gasPrice,\n        uint256 _l2GasLimit,\n        uint256 _l2GasPerPubdataByteLimit\n    ) external view returns (uint256);\n\n    /// @dev Proves that a certain leaf was included as part of the log merkle tree.\n    /// @dev Warning: this function does not enforce any additional checks on the structure\n    /// of the leaf. This means that it can accept intermediate nodes of the Merkle tree as a `_leaf` as\n    /// well as the default \"empty\" leaves. It is the responsibility of the caller to ensure that the\n    /// `_leaf` is a hash of a valid leaf.\n    /// @param _batchNumber The batch number of the leaf to be proven.\n    /// @param _leafProofMask The leaf proof mask.\n    /// @param _leaf The leaf to be proven.\n    /// @param _proof The proof.\n    function proveL2LeafInclusion(\n        uint256 _batchNumber,\n        uint256 _leafProofMask,\n        bytes32 _leaf,\n        bytes32[] calldata _proof\n    ) external view returns (bool);\n\n    /// @notice New priority request event. Emitted when a request is placed into the priority queue.\n    /// @param txId Serial number of the priority operation.\n    /// @param txHash keccak256 hash of encoded transaction representation.\n    /// @param expirationTimestamp Timestamp up to which priority request should be processed.\n    /// @param transaction The whole transaction structure that is requested to be executed on L2.\n    /// @param factoryDeps An array of bytecodes that were shown in the L1 public data.\n    /// Will be marked as known bytecodes in L2.\n    event NewPriorityRequest(\n        uint256 txId,\n        bytes32 txHash,\n        uint64 expirationTimestamp,\n        L2CanonicalTransaction transaction,\n        bytes[] factoryDeps\n    );\n\n    /// @notice Indexed new priority request event. Emitted when a request is placed into the priority queue.\n    /// @dev We define a new event similar to NewPriorityRequest, as modifying it could break existing indexers.\n    /// The indexed txId and txHash helps to simplify external node implementation for fast finality.\n    /// @param txId Serial number of the priority operation.\n    /// @param txHash keccak256 hash of encoded transaction representation.\n    event NewPriorityRequestId(uint256 indexed txId, bytes32 indexed txHash);\n\n    /// @notice New relayed priority request event. It is emitted on a chain that is deployed\n    /// on top of the gateway when it receives a request relayed via the Bridgehub.\n    /// @dev IMPORTANT: this event most likely will be removed in the future, so\n    /// no one should rely on it for indexing purposes.\n    /// @param txId Serial number of the priority operation.\n    /// @param txHash keccak256 hash of encoded transaction representation.\n    /// @param expirationTimestamp Timestamp up to which priority request should be processed.\n    event NewRelayedPriorityTransaction(uint256 txId, bytes32 txHash, uint64 expirationTimestamp);\n}\n"},{"file_path":"lib/openzeppelin-contracts-v4/contracts/utils/structs/EnumerableSet.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n *     // Add the library methods\n *     using EnumerableSet for EnumerableSet.AddressSet;\n *\n *     // Declare a set state variable\n *     EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n    // To implement this library for multiple types with as little code\n    // repetition as possible, we write it in terms of a generic Set type with\n    // bytes32 values.\n    // The Set implementation uses private functions, and user-facing\n    // implementations (such as AddressSet) are just wrappers around the\n    // underlying Set.\n    // This means that we can only create new EnumerableSets for types that fit\n    // in bytes32.\n\n    struct Set {\n        // Storage of set values\n        bytes32[] _values;\n        // Position of the value in the `values` array, plus 1 because index 0\n        // means a value is not in the set.\n        mapping(bytes32 => uint256) _indexes;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function _add(Set storage set, bytes32 value) private returns (bool) {\n        if (!_contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._indexes[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function _remove(Set storage set, bytes32 value) private returns (bool) {\n        // We read and store the value's index to prevent multiple reads from the same storage slot\n        uint256 valueIndex = set._indexes[value];\n\n        if (valueIndex != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 toDeleteIndex = valueIndex - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (lastIndex != toDeleteIndex) {\n                bytes32 lastValue = set._values[lastIndex];\n\n                // Move the last value to the index where the value to delete is\n                set._values[toDeleteIndex] = lastValue;\n                // Update the index for the moved value\n                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the index for the deleted slot\n            delete set._indexes[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function _contains(Set storage set, bytes32 value) private view returns (bool) {\n        return set._indexes[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function _length(Set storage set) private view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function _at(Set storage set, uint256 index) private view returns (bytes32) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function _values(Set storage set) private view returns (bytes32[] memory) {\n        return set._values;\n    }\n\n    // Bytes32Set\n\n    struct Bytes32Set {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _add(set._inner, value);\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _remove(set._inner, value);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n        return _contains(set._inner, value);\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(Bytes32Set storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n        return _at(set._inner, index);\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        bytes32[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // AddressSet\n\n    struct AddressSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(AddressSet storage set, address value) internal returns (bool) {\n        return _add(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(AddressSet storage set, address value) internal returns (bool) {\n        return _remove(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(AddressSet storage set, address value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(AddressSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(AddressSet storage set, uint256 index) internal view returns (address) {\n        return address(uint160(uint256(_at(set._inner, index))));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(AddressSet storage set) internal view returns (address[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        address[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // UintSet\n\n    struct UintSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(UintSet storage set, uint256 value) internal returns (bool) {\n        return _add(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(UintSet storage set, uint256 value) internal returns (bool) {\n        return _remove(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(UintSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n        return uint256(_at(set._inner, index));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(UintSet storage set) internal view returns (uint256[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        uint256[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n}\n"},{"file_path":"contracts/state-transition/chain-interfaces/IMessageVerification.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {L2Log, L2Message} from \"../../common/Messaging.sol\";\n\n/// @title The interface of the ZKsync MessageVerification contract that can be used to prove L2 message inclusion.\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\ninterface IMessageVerification {\n    /// @notice Prove that a specific arbitrary-length message was sent in a specific L2 batch/block number.\n    /// @param _chainId The chain id of the L2 where the message comes from.\n    /// @param _blockOrBatchNumber The executed L2 batch/block number in which the message appeared.\n    /// @param _index The position in the L2 logs Merkle tree of the l2Log that was sent with the message.\n    /// @param _message Information about the sent message: sender address, the message itself, tx index in the L2 batch where the message was sent.\n    /// @param _proof Merkle proof for inclusion of L2 log that was sent with the message.\n    /// @return Boolean specifying whether the proof is valid.\n    function proveL2MessageInclusionShared(\n        uint256 _chainId,\n        uint256 _blockOrBatchNumber,\n        uint256 _index,\n        L2Message calldata _message,\n        bytes32[] calldata _proof\n    ) external view returns (bool);\n\n    /// @notice Prove that a specific L2 log was sent in a specific L2 batch.\n    /// @param _chainId The chain id of the L2 where the log comes from.\n    /// @param _blockOrBatchNumber The executed L2 batch/block number in which the log appeared.\n    /// @param _index The position of the l2log in the L2 logs Merkle tree.\n    /// @param _log Information about the sent log.\n    /// @param _proof Merkle proof for inclusion of the L2 log.\n    /// @return Whether the proof is correct and L2 log is included in batch.\n    function proveL2LogInclusionShared(\n        uint256 _chainId,\n        uint256 _blockOrBatchNumber,\n        uint256 _index,\n        L2Log calldata _log,\n        bytes32[] calldata _proof\n    ) external view returns (bool);\n\n    /// @dev Proves that a certain leaf was included as part of the log merkle tree.\n    /// @dev Warning: this function does not enforce any additional checks on the structure\n    /// of the leaf. This means that it can accept intermediate nodes of the Merkle tree as a `_leaf` as\n    /// well as the default \"empty\" leaves. It is the responsibility of the caller to ensure that the\n    /// `_leaf` is a hash of a valid leaf.\n    /// @param _chainId The chain id of the L2 where the leaf comes from.\n    /// @param _blockOrBatchNumber The batch/block number of the leaf to be proven.\n    /// @param _leafProofMask The leaf proof mask.\n    /// @param _leaf The leaf to be proven.\n    /// @param _proof The proof.\n    function proveL2LeafInclusionShared(\n        uint256 _chainId,\n        uint256 _blockOrBatchNumber,\n        uint256 _leafProofMask,\n        bytes32 _leaf,\n        bytes32[] calldata _proof\n    ) external view returns (bool);\n}\n"},{"file_path":"contracts/state-transition/libraries/Diamond.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {SafeCast} from \"@openzeppelin/contracts-v4/utils/math/SafeCast.sol\";\nimport {UncheckedMath} from \"../../common/libraries/UncheckedMath.sol\";\nimport {AddressHasNoCode, DelegateCallFailed, FacetExists, NoFunctionsForDiamondCut, NonEmptyCalldata, RemoveFunctionFacetAddressNotZero, RemoveFunctionFacetAddressZero, ReplaceFunctionFacetAddressZero, SelectorsMustAllHaveSameFreezability, UndefinedDiamondCutAction} from \"../../common/L1ContractErrors.sol\";\n\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\n/// @notice The helper library for managing the EIP-2535 diamond proxy.\nlibrary Diamond {\n    using UncheckedMath for uint256;\n    using SafeCast for uint256;\n\n    /// @dev Magic value that should be returned by diamond cut initialize contracts.\n    /// @dev Used to distinguish calls to contracts that were supposed to be used as diamond initializer from other contracts.\n    bytes32 internal constant DIAMOND_INIT_SUCCESS_RETURN_VALUE =\n        0x33774e659306e47509050e97cb651e731180a42d458212294d30751925c551a2; // keccak256(\"diamond.zksync.init\") - 1\n\n    /// @dev Storage position of `DiamondStorage` structure.\n    bytes32 private constant DIAMOND_STORAGE_POSITION =\n        0xc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131b; // keccak256(\"diamond.standard.diamond.storage\") - 1;\n\n    event DiamondCut(FacetCut[] facetCuts, address initAddress, bytes initCalldata);\n\n    /// @dev Utility struct that contains associated facet & meta information of selector\n    /// @param facetAddress address of the facet which is connected with selector\n    /// @param selectorPosition index in `FacetToSelectors.selectors` array, where is selector stored\n    /// @param isFreezable denotes whether the selector can be frozen.\n    struct SelectorToFacet {\n        address facetAddress;\n        uint16 selectorPosition;\n        bool isFreezable;\n    }\n\n    /// @dev Utility struct that contains associated selectors & meta information of facet\n    /// @param selectors list of all selectors that belong to the facet\n    /// @param facetPosition index in `DiamondStorage.facets` array, where is facet stored\n    struct FacetToSelectors {\n        bytes4[] selectors;\n        uint16 facetPosition;\n    }\n\n    /// @notice The structure that holds all diamond proxy associated parameters\n    /// @dev According to the EIP-2535 should be stored on a special storage key - `DIAMOND_STORAGE_POSITION`\n    /// @param selectorToFacet A mapping from the selector to the facet address and its meta information\n    /// @param facetToSelectors A mapping from facet address to its selectors with meta information\n    /// @param facets The array of all unique facet addresses that belong to the diamond proxy\n    /// @param isFrozen Denotes whether the diamond proxy is frozen and all freezable facets are not accessible\n    struct DiamondStorage {\n        mapping(bytes4 selector => SelectorToFacet selectorInfo) selectorToFacet;\n        mapping(address facetAddress => FacetToSelectors facetInfo) facetToSelectors;\n        address[] facets;\n        bool isFrozen;\n    }\n\n    /// @dev Parameters for diamond changes that touch one of the facets\n    /// @param facet The address of facet that's affected by the cut\n    /// @param action The action that is made on the facet\n    /// @param isFreezable Denotes whether the facet & all their selectors can be frozen\n    /// @param selectors An array of unique selectors that belongs to the facet address\n    // solhint-disable-next-line gas-struct-packing\n    struct FacetCut {\n        address facet;\n        Action action;\n        bool isFreezable;\n        bytes4[] selectors;\n    }\n\n    /// @dev Structure of the diamond proxy changes\n    /// @param facetCuts The set of changes (adding/removing/replacement) of implementation contracts\n    /// @param initAddress The address that's delegate called after setting up new facet changes\n    /// @param initCalldata Calldata for the delegate call to `initAddress`\n    struct DiamondCutData {\n        FacetCut[] facetCuts;\n        address initAddress;\n        bytes initCalldata;\n    }\n\n    /// @dev Type of change over diamond: add/replace/remove facets\n    enum Action {\n        Add,\n        Replace,\n        Remove\n    }\n\n    /// @return diamondStorage The pointer to the storage where all specific diamond proxy parameters stored\n    function getDiamondStorage() internal pure returns (DiamondStorage storage diamondStorage) {\n        bytes32 position = DIAMOND_STORAGE_POSITION;\n        assembly {\n            diamondStorage.slot := position\n        }\n    }\n\n    /// @dev Add/replace/remove any number of selectors and optionally execute a function with delegatecall\n    /// @param _diamondCut Diamond's facet changes and the parameters to optional initialization delegatecall\n    function diamondCut(DiamondCutData memory _diamondCut) internal {\n        FacetCut[] memory facetCuts = _diamondCut.facetCuts;\n        address initAddress = _diamondCut.initAddress;\n        bytes memory initCalldata = _diamondCut.initCalldata;\n        uint256 facetCutsLength = facetCuts.length;\n        for (uint256 i = 0; i < facetCutsLength; i = i.uncheckedInc()) {\n            Action action = facetCuts[i].action;\n            address facet = facetCuts[i].facet;\n            bool isFacetFreezable = facetCuts[i].isFreezable;\n            bytes4[] memory selectors = facetCuts[i].selectors;\n\n            if (selectors.length == 0) {\n                revert NoFunctionsForDiamondCut();\n            }\n\n            if (action == Action.Add) {\n                _addFunctions(facet, selectors, isFacetFreezable);\n            } else if (action == Action.Replace) {\n                _replaceFunctions(facet, selectors, isFacetFreezable);\n            } else if (action == Action.Remove) {\n                _removeFunctions(facet, selectors);\n            } else {\n                revert UndefinedDiamondCutAction();\n            }\n        }\n\n        _initializeDiamondCut(initAddress, initCalldata);\n        emit DiamondCut(facetCuts, initAddress, initCalldata);\n    }\n\n    /// @dev Add new functions to the diamond proxy\n    /// NOTE: expect but NOT enforce that `_selectors` is NON-EMPTY array\n    function _addFunctions(address _facet, bytes4[] memory _selectors, bool _isFacetFreezable) private {\n        DiamondStorage storage ds = getDiamondStorage();\n\n        // Facet with no code cannot be added.\n        // This check also verifies that the facet does not have zero address, since it is the\n        // address with which 0x00000000 selector is associated.\n        if (_facet.code.length == 0) {\n            revert AddressHasNoCode(_facet);\n        }\n\n        // Add facet to the list of facets if the facet address is new one\n        _saveFacetIfNew(_facet);\n\n        uint256 selectorsLength = _selectors.length;\n        for (uint256 i = 0; i < selectorsLength; i = i.uncheckedInc()) {\n            bytes4 selector = _selectors[i];\n            SelectorToFacet memory oldFacet = ds.selectorToFacet[selector];\n            if (oldFacet.facetAddress != address(0)) {\n                revert FacetExists(selector, oldFacet.facetAddress);\n            }\n\n            _addOneFunction(_facet, selector, _isFacetFreezable);\n        }\n    }\n\n    /// @dev Change associated facets to already known function selectors\n    /// NOTE: expect but NOT enforce that `_selectors` is NON-EMPTY array\n    function _replaceFunctions(address _facet, bytes4[] memory _selectors, bool _isFacetFreezable) private {\n        DiamondStorage storage ds = getDiamondStorage();\n\n        // Facet with no code cannot be added.\n        // This check also verifies that the facet does not have zero address, since it is the\n        // address with which 0x00000000 selector is associated.\n        if (_facet.code.length == 0) {\n            revert AddressHasNoCode(_facet);\n        }\n\n        uint256 selectorsLength = _selectors.length;\n        for (uint256 i = 0; i < selectorsLength; i = i.uncheckedInc()) {\n            bytes4 selector = _selectors[i];\n            SelectorToFacet memory oldFacet = ds.selectorToFacet[selector];\n            // it is impossible to replace the facet with zero address\n            if (oldFacet.facetAddress == address(0)) {\n                revert ReplaceFunctionFacetAddressZero();\n            }\n\n            _removeOneFunction(oldFacet.facetAddress, selector);\n            // Add facet to the list of facets if the facet address is a new one\n            _saveFacetIfNew(_facet);\n            _addOneFunction(_facet, selector, _isFacetFreezable);\n        }\n    }\n\n    /// @dev Remove association with function and facet\n    /// NOTE: expect but NOT enforce that `_selectors` is NON-EMPTY array\n    function _removeFunctions(address _facet, bytes4[] memory _selectors) private {\n        DiamondStorage storage ds = getDiamondStorage();\n\n        // facet address must be zero\n        if (_facet != address(0)) {\n            revert RemoveFunctionFacetAddressNotZero(_facet);\n        }\n\n        uint256 selectorsLength = _selectors.length;\n        for (uint256 i = 0; i < selectorsLength; i = i.uncheckedInc()) {\n            bytes4 selector = _selectors[i];\n            SelectorToFacet memory oldFacet = ds.selectorToFacet[selector];\n            // Can't delete a non-existent facet\n            if (oldFacet.facetAddress == address(0)) {\n                revert RemoveFunctionFacetAddressZero();\n            }\n\n            _removeOneFunction(oldFacet.facetAddress, selector);\n        }\n    }\n\n    /// @dev Add address to the list of known facets if it is not on the list yet\n    /// NOTE: should be called ONLY before adding a new selector associated with the address\n    function _saveFacetIfNew(address _facet) private {\n        DiamondStorage storage ds = getDiamondStorage();\n\n        uint256 selectorsLength = ds.facetToSelectors[_facet].selectors.length;\n        // If there are no selectors associated with facet then save facet as new one\n        if (selectorsLength == 0) {\n            ds.facetToSelectors[_facet].facetPosition = ds.facets.length.toUint16();\n            ds.facets.push(_facet);\n        }\n    }\n\n    /// @dev Add one function to the already known facet\n    /// NOTE: It is expected but NOT enforced that:\n    /// - `_facet` is NON-ZERO address\n    /// - `_facet` is already stored address in `DiamondStorage.facets`\n    /// - `_selector` is NOT associated by another facet\n    function _addOneFunction(address _facet, bytes4 _selector, bool _isSelectorFreezable) private {\n        DiamondStorage storage ds = getDiamondStorage();\n\n        uint16 selectorPosition = (ds.facetToSelectors[_facet].selectors.length).toUint16();\n\n        // if selectorPosition is nonzero, it means it is not a new facet\n        // so the freezability of the first selector must be matched to _isSelectorFreezable\n        // so all the selectors in a facet will have the same freezability\n        if (selectorPosition != 0) {\n            bytes4 selector0 = ds.facetToSelectors[_facet].selectors[0];\n            if (_isSelectorFreezable != ds.selectorToFacet[selector0].isFreezable) {\n                revert SelectorsMustAllHaveSameFreezability();\n            }\n        }\n\n        ds.selectorToFacet[_selector] = SelectorToFacet({\n            facetAddress: _facet,\n            selectorPosition: selectorPosition,\n            isFreezable: _isSelectorFreezable\n        });\n        ds.facetToSelectors[_facet].selectors.push(_selector);\n    }\n\n    /// @dev Remove one associated function with facet\n    /// NOTE: It is expected but NOT enforced that `_facet` is NON-ZERO address\n    function _removeOneFunction(address _facet, bytes4 _selector) private {\n        DiamondStorage storage ds = getDiamondStorage();\n\n        // Get index of `FacetToSelectors.selectors` of the selector and last element of array\n        uint256 selectorPosition = ds.selectorToFacet[_selector].selectorPosition;\n        uint256 lastSelectorPosition = ds.facetToSelectors[_facet].selectors.length - 1;\n\n        // If the selector is not at the end of the array then move the last element to the selector position\n        if (selectorPosition != lastSelectorPosition) {\n            bytes4 lastSelector = ds.facetToSelectors[_facet].selectors[lastSelectorPosition];\n\n            ds.facetToSelectors[_facet].selectors[selectorPosition] = lastSelector;\n            ds.selectorToFacet[lastSelector].selectorPosition = selectorPosition.toUint16();\n        }\n\n        // Remove last element from the selectors array\n        ds.facetToSelectors[_facet].selectors.pop();\n\n        // Finally, clean up the association with facet\n        delete ds.selectorToFacet[_selector];\n\n        // If there are no selectors for facet then remove the facet from the list of known facets\n        if (lastSelectorPosition == 0) {\n            _removeFacet(_facet);\n        }\n    }\n\n    /// @dev remove facet from the list of known facets\n    /// NOTE: It is expected but NOT enforced that there are no selectors associated with `_facet`\n    function _removeFacet(address _facet) private {\n        DiamondStorage storage ds = getDiamondStorage();\n\n        // Get index of `DiamondStorage.facets` of the facet and last element of array\n        uint256 facetPosition = ds.facetToSelectors[_facet].facetPosition;\n        uint256 lastFacetPosition = ds.facets.length - 1;\n\n        // If the facet is not at the end of the array then move the last element to the facet position\n        if (facetPosition != lastFacetPosition) {\n            address lastFacet = ds.facets[lastFacetPosition];\n\n            ds.facets[facetPosition] = lastFacet;\n            ds.facetToSelectors[lastFacet].facetPosition = facetPosition.toUint16();\n        }\n\n        // Remove last element from the facets array\n        ds.facets.pop();\n    }\n\n    /// @dev Delegates call to the initialization address with provided calldata\n    /// @dev Used as a final step of diamond cut to execute the logic of the initialization for changed facets\n    function _initializeDiamondCut(address _init, bytes memory _calldata) private {\n        if (_init == address(0)) {\n            // Non-empty calldata for zero address\n            if (_calldata.length != 0) {\n                revert NonEmptyCalldata();\n            }\n        } else {\n            // Do not check whether `_init` is a contract since later we check that it returns data.\n            (bool success, bytes memory data) = _init.delegatecall(_calldata);\n            if (!success) {\n                // If the returndata is too small, we still want to produce some meaningful error\n\n                if (data.length < 4) {\n                    revert DelegateCallFailed(data);\n                }\n\n                assembly {\n                    revert(add(data, 0x20), mload(data))\n                }\n            }\n\n            // Check that called contract returns magic value to make sure that contract logic\n            // supposed to be used as diamond cut initializer.\n            if (data.length != 32) {\n                revert DelegateCallFailed(data);\n            }\n            if (abi.decode(data, (bytes32)) != DIAMOND_INIT_SUCCESS_RETURN_VALUE) {\n                revert DelegateCallFailed(data);\n            }\n        }\n    }\n}\n"},{"file_path":"contracts/common/L1ContractErrors.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.21;\n\n// 0x5ecf2d7a\nerror AccessToFallbackDenied(address target, address invoker);\n// 0x3995f750\nerror AccessToFunctionDenied(address target, bytes4 selector, address invoker);\n// 0x0dfb42bf\nerror AddressAlreadySet(address addr);\n// 0x86bb51b8\nerror AddressHasNoCode(address);\n// 0x1f73225f\nerror AddressMismatch(address expected, address supplied);\n// 0x2a5989a0\nerror AlreadyPermanentRollup();\n// 0x0bfcef28\nerror AlreadyWhitelisted(address);\n// 0x5e85ae73\nerror AmountMustBeGreaterThanZero();\n// 0xfde974f4\nerror AssetHandlerDoesNotExist(bytes32 assetId);\n// 0x64107968\nerror AssetHandlerNotRegistered(bytes32 assetId);\n// 0xfe919e28\nerror AssetIdAlreadyRegistered();\n// 0x1294e9e1\nerror AssetIdMismatch(bytes32 expected, bytes32 supplied);\n// 0x04a0b7e9\nerror AssetIdNotSupported(bytes32 assetId);\n// 0x11832de8\nerror AssetRouterAllowanceNotZero();\n// 0x6ef9a972\nerror BaseTokenGasPriceDenominatorNotSet();\n// 0x55ad3fd3\nerror BatchHashMismatch(bytes32 expected, bytes32 actual);\n// 0x2078a6a0\nerror BatchNotExecuted(uint256 batchNumber);\n// 0xbd4455ff\nerror BatchNumberMismatch(uint256 expectedBatchNumber, uint256 providedBatchNumber);\n// 0x6cf12312\nerror BridgeHubAlreadyRegistered();\n// 0xdb538614\nerror BridgeMintNotImplemented();\n// 0xaa5f6180\nerror BurningNativeWETHNotSupported();\n// 0xccdd18d2\nerror BytecodeAlreadyPublished(bytes32 bytecodeHash);\n// 0x25d8333c\nerror CallerNotTimerAdmin();\n// 0x3331e9c0\nerror CallNotAllowed(bytes call);\n// 0xe85392f9\nerror CanOnlyProcessOneBatch();\n// 0x00c6ead2\nerror CantExecuteUnprovenBatches();\n// 0xe18cb383\nerror CantRevertExecutedBatch();\n// 0x78d2ed02\nerror ChainAlreadyLive();\n// 0x24591d89\nerror ChainIdAlreadyExists();\n// 0x717a1656\nerror ChainIdCantBeCurrentChain();\n// 0xa179f8c9\nerror ChainIdMismatch();\n// 0x23f3c357\nerror ChainIdNotRegistered(uint256 chainId);\n// 0x8f620a06\nerror ChainIdTooBig();\n// 0xec273439\nerror CTMAlreadyRegistered();\n// 0xc630ef3c\nerror CTMNotRegistered();\n// 0x907f8e51\nerror DeadlineNotYetPassed();\n// 0xf2885eb3\nerror DefaultAdminTransferNotAllowed();\n// 0xf7a01e4d\nerror DelegateCallFailed(bytes returnData);\n// 0x0a8ed92c\nerror DenominatorIsZero();\n// 0xb4f54111\nerror DeployFailed();\n// 0x138ee1a3\nerror DeployingBridgedTokenForNativeToken();\n// 0xc7c9660f\nerror DepositDoesNotExist();\n// 0xad2fa98e\nerror DepositExists();\n// 0x0e7ee319\nerror DiamondAlreadyFrozen();\n// 0xa7151b9a\nerror DiamondNotFrozen();\n// 0x7138356f\nerror EmptyAddress();\n// 0x2d4d012f\nerror EmptyAssetId();\n// 0x1c25715b\nerror EmptyBytes32();\n// 0x99d8fec9\nerror EmptyData();\n// 0x95b66fe9\nerror EmptyDeposit();\n// 0x84286507\nerror EmptyPrecommitData(uint256 batchNumber);\n// 0x456f8f7a\nerror EmptyProofLength();\n// 0x627e0872\nerror ETHDepositNotSupported();\n// 0xac4a3f98\nerror FacetExists(bytes4 selector, address);\n// 0xc91cf3b1\nerror GasPerPubdataMismatch();\n// 0x6d4a7df8\nerror GenesisBatchCommitmentZero();\n// 0x7940c83f\nerror GenesisBatchHashZero();\n// 0xb4fc6835\nerror GenesisIndexStorageZero();\n// 0x3a1a8589\nerror GenesisUpgradeZero();\n// 0xd356e6ba\nerror HashedLogIsDefault();\n// 0x0b08d5be\nerror HashMismatch(bytes32 expected, bytes32 actual);\n// 0xd7d93e1f\nerror IncorrectBatchBounds(\n    uint256 processFromExpected,\n    uint256 processToExpected,\n    uint256 processFromProvided,\n    uint256 processToProvided\n);\n// 0xdd381a4c\nerror IncorrectBridgeHubAddress(address bridgehub);\n// 0x1929b7de\nerror IncorrectTokenAddressFromNTV(bytes32 assetId, address tokenAddress);\n// 0x826fb11e\nerror InsufficientChainBalance();\n// 0x9bf8b9aa\nerror InvalidBatchNumber(uint256 provided, uint256 expected);\n// 0xcbd9d2e0\nerror InvalidCaller(address);\n// 0x92daded2\nerror InvalidDAForPermanentRollup();\n// 0x4fbe5dba\nerror InvalidDelay();\n// 0xc1780bd6\nerror InvalidLogSender(address sender, uint256 logKey);\n// 0xa1ec1876\nerror InvalidMessageRoot(bytes32 expectedMessageRoot, bytes32 providedMessageRoot);\n// 0xde4c0b96\nerror InvalidNTVBurnData();\n// 0xd8e9405c\nerror InvalidNumberOfBlobs(uint256 expected, uint256 numCommitments, uint256 numHashes);\n// 0x99f6cc22\nerror InvalidPackedPrecommitmentLength(uint256 length);\n// 0x09bde339\nerror InvalidProof();\n// 0x48c5fa28\nerror InvalidProofLengthForFinalNode();\n// 0x5428eae7\nerror InvalidProtocolVersion();\n// 0x6f1cf752\nerror InvalidPubdataPricingMode();\n// 0x12ba286f\nerror InvalidSelector(bytes4 func);\n// 0xbe7193d4\nerror InvalidSystemLogsLength();\n// 0x5f1aa154\nerror InvalidUpgradeTxn(UpgradeTxVerifyParam);\n// 0xfb5c22e6\nerror L2TimestampTooBig();\n// 0x97e1359e\nerror L2WithdrawalMessageWrongLength(uint256 messageLen);\n// 0x8efef97a\nerror LegacyBridgeNotSet();\n// 0x29963361\nerror LegacyBridgeUsesNonNativeToken();\n// 0xfade089a\nerror LegacyEncodingUsedForNonL1Token();\n// 0x767eed08\nerror LegacyMethodForNonL1Token();\n// 0xe37d2c02\nerror LengthIsNotDivisibleBy32(uint256 length);\n// 0x1b6825bb\nerror LogAlreadyProcessed(uint8);\n// 0x43e266b0\nerror MalformedBytecode(BytecodeError);\n// 0xafbb7a4e\nerror MerkleIndexOrHeightMismatch();\n// 0x9bb54c35\nerror MerkleIndexOutOfBounds();\n// 0xc33e6128\nerror MerkleNothingToProve();\n// 0x8e23ac1a\nerror MerklePathEmpty();\n// 0x09aa9830\nerror MerklePathLengthMismatch(uint256 pathLength, uint256 expectedLength);\n// 0x1c500385\nerror MerklePathOutOfBounds();\n// 0x1b582fcf\nerror MerkleWrongIndex(uint256 index, uint256 maxNodeNumber);\n// 0x485cfcaa\nerror MerkleWrongLength(uint256 newLeavesLength, uint256 leafNumber);\n// 0x3312a450\nerror MigrationPaused();\n// 0x4e98b356\nerror MigrationsNotPaused();\n// 0xfa44b527\nerror MissingSystemLogs(uint256 expected, uint256 actual);\n// 0x4a094431\nerror MsgValueMismatch(uint256 expectedMsgValue, uint256 providedMsgValue);\n// 0xb385a3da\nerror MsgValueTooLow(uint256 required, uint256 provided);\n// 0x8b7e144a\nerror NewDeadlineExceedsMaxDeadline();\n// 0x6eef58d1\nerror NewDeadlineNotGreaterThanCurrent();\n// 0x79cc2d22\nerror NoCallsProvided();\n// 0xce63ce17\nerror NoCTMForAssetId(bytes32 assetId);\n// 0xa6fef710\nerror NoFunctionsForDiamondCut();\n// 0xcab098d8\nerror NoFundsTransferred();\n// 0xb20b58ce\nerror NoLegacySharedBridge();\n// 0xc21b1ab7\nerror NonEmptyCalldata();\n// 0x536ec84b\nerror NonEmptyMsgValue();\n// 0xd018e08e\nerror NonIncreasingTimestamp();\n// 0x0105f9c0\nerror NonSequentialBatch();\n// 0x0ac76f01\nerror NonSequentialVersion();\n// 0xfa5cd00f\nerror NotAllowed(address addr);\n// 0x64846fe4\nerror NotARestriction(address addr);\n// 0xb49df1f2\nerror NotAZKChain(address addr);\n// 0xdd7e3621\nerror NotInitializedReentrancyGuard();\n// 0xdf17e316\nerror NotWhitelisted(address);\n// 0xf3ed9dfa\nerror OnlyEraSupported();\n// 0x6c167909\nerror OnlySelfAllowed();\n// 0x1a21feed\nerror OperationExists();\n// 0xeda2fbb1\nerror OperationMustBePending();\n// 0xe1c1ff37\nerror OperationMustBeReady();\n// 0xb926450e\nerror OriginChainIdNotFound();\n// 0x688c63e5\nerror PrecommitmentMismatch(uint256 batchNumber, bytes32 expected, bytes32 found);\n// 0x9b48e060\nerror PreviousOperationNotExecuted();\n// 0xd5a99014\nerror PriorityOperationsRollingHashMismatch();\n// 0x1a4d284a\nerror PriorityTxPubdataExceedsMaxPubDataPerBatch();\n// 0xa461f651\nerror ProtocolIdMismatch(uint256 expectedProtocolVersion, uint256 providedProtocolId);\n// 0x64f94ec2\nerror ProtocolIdNotGreater();\n// 0x959f26fb\nerror PubdataGreaterThanLimit(uint256 limit, uint256 length);\n// 0x63c36549\nerror QueueIsEmpty();\n// 0xab143c06\nerror Reentrancy();\n// 0x667d17de\nerror RemoveFunctionFacetAddressNotZero(address facet);\n// 0xa2d4b16c\nerror RemoveFunctionFacetAddressZero();\n// 0xf6fd7071\nerror RemovingPermanentRestriction();\n// 0x3580370c\nerror ReplaceFunctionFacetAddressZero();\n// 0xf126e113\nerror RestrictionWasAlreadyPresent(address restriction);\n// 0x52e22c98\nerror RestrictionWasNotPresent(address restriction);\n// 0x9a67c1cb\nerror RevertedBatchNotAfterNewLastBatch();\n// 0xfe0aa4f2\nerror RoleAccessDenied(address chainAddress, bytes32 role, address account);\n// 0xd3b6535b\nerror SelectorsMustAllHaveSameFreezability();\n// 0x02181a13\nerror SettlementLayersMustSettleOnL1();\n// 0x856d5b77\nerror SharedBridgeNotSet();\n// 0x7774d2f9\nerror SharedBridgeValueNotSet(SharedBridgeKey);\n// 0xdf3a8fdd\nerror SlotOccupied();\n// 0xae43b424\nerror SystemLogsSizeTooBig();\n// 0x08753982\nerror TimeNotReached(uint256 expectedTimestamp, uint256 actualTimestamp);\n// 0x7a4902ad\nerror TimerAlreadyStarted();\n// 0x2d50c33b\nerror TimestampError();\n// 0xa51fa558\nerror TokenIsLegacy();\n// 0x1850b46b\nerror TokenNotLegacy();\n// 0x06439c6b\nerror TokenNotSupported(address token);\n// 0x23830e28\nerror TokensWithFeesNotSupported();\n// 0x8e3ce3cb\nerror TooHighDeploymentNonce();\n// 0x76da24b9\nerror TooManyFactoryDeps();\n// 0xf0b4e88f\nerror TooMuchGas();\n// 0x00c5a6a9\nerror TransactionNotAllowed();\n// 0x4c991078\nerror TxHashMismatch();\n// 0x2e311df8\nerror TxnBodyGasLimitNotEnoughGas();\n// 0xfcb9b2e1\nerror UnallowedImplementation(bytes32 implementationHash);\n// 0x8e4a23d6\nerror Unauthorized(address caller);\n// 0xe52478c7\nerror UndefinedDiamondCutAction();\n// 0x6aa39880\nerror UnexpectedSystemLog(uint256 logKey);\n// 0xc352bb73\nerror UnknownVerifierType();\n// 0xf3dd1b9c\nerror UnsupportedCommitBatchEncoding(uint8 version);\n// 0x084a1449\nerror UnsupportedEncodingVersion();\n// 0x14d2ed8a\nerror UnsupportedExecuteBatchEncoding(uint8 version);\n// 0xf338f830\nerror UnsupportedProofBatchEncoding(uint8 version);\n// 0xf093c2e5\nerror UpgradeBatchNumberIsNotZero();\n// 0x47b3b145\nerror ValidateTxnNotEnoughGas();\n// 0x626ade30\nerror ValueMismatch(uint256 expected, uint256 actual);\n// 0xe1022469\nerror VerifiedBatchesExceedsCommittedBatches();\n// 0xae899454\nerror WithdrawalAlreadyFinalized();\n// 0x750b219c\nerror WithdrawFailed();\n// 0xf20c5c2a\nerror WrappedBaseTokenAlreadyRegistered();\n// 0x15e8e429\nerror WrongMagicValue(uint256 expectedMagicValue, uint256 providedMagicValue);\n// 0xd92e233d\nerror ZeroAddress();\n// 0xc84885d4\nerror ZeroChainId();\n// 0x601b6882\nerror ZKChainLimitReached();\n\nenum SharedBridgeKey {\n    PostUpgradeFirstBatch,\n    LegacyBridgeFirstBatch,\n    LegacyBridgeLastDepositBatch,\n    LegacyBridgeLastDepositTxn\n}\n\nenum BytecodeError {\n    Version,\n    NumberOfWords,\n    Length,\n    WordsMustBeOdd\n}\n\nenum UpgradeTxVerifyParam {\n    From,\n    To,\n    Paymaster,\n    Value,\n    MaxFeePerGas,\n    MaxPriorityFeePerGas,\n    Reserved0,\n    Reserved1,\n    Reserved2,\n    Reserved3,\n    Signature,\n    PaymasterInput,\n    ReservedDynamic\n}\n"},{"file_path":"contracts/common/libraries/DynamicIncrementalMerkle.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.28;\n\nimport {Merkle} from \"./Merkle.sol\";\nimport {Arrays} from \"@openzeppelin/contracts-v4/utils/Arrays.sol\";\n\n/**\n * @dev Library for managing https://wikipedia.org/wiki/Merkle_Tree[Merkle Tree] data structures.\n *\n * Each tree is a complete binary tree with the ability to sequentially insert leaves, changing them from a zero to a\n * non-zero value and updating its root. This structure allows inserting commitments (or other entries) that are not\n * stored, but can be proven to be part of the tree at a later time if the root is kept. See {MerkleProof}.\n *\n * A tree is defined by the following parameters:\n *\n * * Depth: The number of levels in the tree, it also defines the maximum number of leaves as 2**depth.\n * * Zero value: The value that represents an empty leaf. Used to avoid regular zero values to be part of the tree.\n * * Hashing function: A cryptographic hash function used to produce internal nodes.\n *\n * This is a fork of OpenZeppelin's [`MerkleTree`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/9af280dc4b45ee5bda96ba47ff829b407eaab67e/contracts/utils/structs/MerkleTree.sol)\n * library, with the changes to support dynamic tree growth (doubling the size when full).\n */\nlibrary DynamicIncrementalMerkle {\n    /**\n     * @dev A complete `bytes32` Merkle tree.\n     *\n     * The `sides` and `zero` arrays are set to have a length equal to the depth of the tree during setup.\n     *\n     * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n     * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n     * lead to unexpected behavior.\n     *\n     * NOTE: The `root` and the updates history is not stored within the tree. Consider using a secondary structure to\n     * store a list of historical roots from the values returned from {setup} and {push} (e.g. a mapping, {BitMaps} or\n     * {Checkpoints}).\n     *\n     * WARNING: Updating any of the tree's parameters after the first insertion will result in a corrupted tree.\n     */\n    struct Bytes32PushTree {\n        uint256 _nextLeafIndex;\n        bytes32[] _sides;\n        bytes32[] _zeros;\n    }\n\n    /**\n     * @dev Initialize a {Bytes32PushTree} using {Hashes-Keccak256} to hash internal nodes.\n     * The capacity of the tree (i.e. number of leaves) is set to `2**levels`.\n     *\n     * IMPORTANT: The zero value should be carefully chosen since it will be stored in the tree representing\n     * empty leaves. It should be a value that is not expected to be part of the tree.\n     */\n    function setup(Bytes32PushTree storage self, bytes32 zero) internal returns (bytes32 initialRoot) {\n        self._nextLeafIndex = 0;\n        self._zeros.push(zero);\n        self._sides.push(bytes32(0));\n        return bytes32(0);\n    }\n\n    /**\n     * @dev Resets the tree to a blank state.\n     * Calling this function on MerkleTree that was already setup and used will reset it to a blank state.\n     * @param zero The value that represents an empty leaf.\n     * @return initialRoot The initial root of the tree.\n     */\n    function reset(Bytes32PushTree storage self, bytes32 zero) internal returns (bytes32 initialRoot) {\n        self._nextLeafIndex = 0;\n        uint256 length = self._zeros.length;\n        for (uint256 i = length; 0 < i; --i) {\n            self._zeros.pop();\n        }\n        length = self._sides.length;\n        for (uint256 i = length; 0 < i; --i) {\n            self._sides.pop();\n        }\n        self._zeros.push(zero);\n        self._sides.push(bytes32(0));\n        return bytes32(0);\n    }\n\n    /**\n     * @dev Insert a new leaf in the tree, and compute the new root. Returns the position of the inserted leaf in the\n     * tree, and the resulting root.\n     *\n     * Hashing the leaf before calling this function is recommended as a protection against\n     * second pre-image attacks.\n     */\n    function push(Bytes32PushTree storage self, bytes32 leaf) internal returns (uint256 index, bytes32 newRoot) {\n        // Cache read\n        uint256 levels = self._zeros.length - 1;\n\n        // Get leaf index\n        // solhint-disable-next-line gas-increment-by-one\n        index = self._nextLeafIndex++;\n\n        // Check if tree is full.\n        if (index == 1 << levels) {\n            bytes32 zero = self._zeros[levels];\n            bytes32 newZero = Merkle.efficientHash(zero, zero);\n            self._zeros.push(newZero);\n            self._sides.push(bytes32(0));\n            ++levels;\n        }\n\n        // Rebuild branch from leaf to root\n        uint256 currentIndex = index;\n        bytes32 currentLevelHash = leaf;\n        bool updatedSides = false;\n        for (uint32 i = 0; i < levels; ++i) {\n            // Reaching the parent node, is currentLevelHash the left child?\n            bool isLeft = currentIndex % 2 == 0;\n\n            // If so, next time we will come from the right, so we need to save it\n            if (isLeft && !updatedSides) {\n                Arrays.unsafeAccess(self._sides, i).value = currentLevelHash;\n                updatedSides = true;\n            }\n\n            // Compute the current node hash by using the hash function\n            // with either its sibling (side) or the zero value for that level.\n            currentLevelHash = Merkle.efficientHash(\n                isLeft ? currentLevelHash : Arrays.unsafeAccess(self._sides, i).value,\n                isLeft ? Arrays.unsafeAccess(self._zeros, i).value : currentLevelHash\n            );\n\n            // Update node index\n            currentIndex >>= 1;\n        }\n\n        Arrays.unsafeAccess(self._sides, levels).value = currentLevelHash;\n        return (index, currentLevelHash);\n    }\n\n    /**\n     * @dev Tree's root.\n     */\n    function root(Bytes32PushTree storage self) internal view returns (bytes32) {\n        return Arrays.unsafeAccess(self._sides, self._sides.length - 1).value;\n    }\n\n    /**\n     * @dev Tree's height (does not include the root node).\n     */\n    function height(Bytes32PushTree storage self) internal view returns (uint256) {\n        return self._sides.length - 1;\n    }\n}\n"},{"file_path":"contracts/bridge/interfaces/IL1ERC20Bridge.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {IL1Nullifier} from \"./IL1Nullifier.sol\";\nimport {IL1NativeTokenVault} from \"../ntv/IL1NativeTokenVault.sol\";\nimport {IL1AssetRouter} from \"../asset-router/IL1AssetRouter.sol\";\n\n/// @title L1 Bridge contract legacy interface\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\n/// @notice Legacy Bridge interface before ZK chain migration, used for backward compatibility with ZKsync Era\ninterface IL1ERC20Bridge {\n    event DepositInitiated(\n        bytes32 indexed l2DepositTxHash,\n        address indexed from,\n        address indexed to,\n        address l1Token,\n        uint256 amount\n    );\n\n    event WithdrawalFinalized(address indexed to, address indexed l1Token, uint256 amount);\n\n    event ClaimedFailedDeposit(address indexed to, address indexed l1Token, uint256 amount);\n\n    function isWithdrawalFinalized(uint256 _l2BatchNumber, uint256 _l2MessageIndex) external view returns (bool);\n\n    function deposit(\n        address _l2Receiver,\n        address _l1Token,\n        uint256 _amount,\n        uint256 _l2TxGasLimit,\n        uint256 _l2TxGasPerPubdataByte,\n        address _refundRecipient\n    ) external payable returns (bytes32 txHash);\n\n    function deposit(\n        address _l2Receiver,\n        address _l1Token,\n        uint256 _amount,\n        uint256 _l2TxGasLimit,\n        uint256 _l2TxGasPerPubdataByte\n    ) external payable returns (bytes32 txHash);\n\n    function claimFailedDeposit(\n        address _depositSender,\n        address _l1Token,\n        bytes32 _l2TxHash,\n        uint256 _l2BatchNumber,\n        uint256 _l2MessageIndex,\n        uint16 _l2TxNumberInBatch,\n        bytes32[] calldata _merkleProof\n    ) external;\n\n    function finalizeWithdrawal(\n        uint256 _l2BatchNumber,\n        uint256 _l2MessageIndex,\n        uint16 _l2TxNumberInBatch,\n        bytes calldata _message,\n        bytes32[] calldata _merkleProof\n    ) external;\n\n    function l2TokenAddress(address _l1Token) external view returns (address);\n\n    function L1_NULLIFIER() external view returns (IL1Nullifier);\n\n    function L1_ASSET_ROUTER() external view returns (IL1AssetRouter);\n\n    function L1_NATIVE_TOKEN_VAULT() external view returns (IL1NativeTokenVault);\n\n    function l2TokenBeacon() external view returns (address);\n\n    function l2Bridge() external view returns (address);\n\n    function depositAmount(\n        address _account,\n        address _l1Token,\n        bytes32 _depositL2TxHash\n    ) external view returns (uint256 amount);\n}\n"},{"file_path":"contracts/state-transition/chain-interfaces/IZKChain.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {IAdmin} from \"./IAdmin.sol\";\nimport {IExecutor} from \"./IExecutor.sol\";\nimport {IGetters} from \"./IGetters.sol\";\nimport {IMailbox} from \"./IMailbox.sol\";\n\nimport {Diamond} from \"../libraries/Diamond.sol\";\n\ninterface IZKChain is IAdmin, IExecutor, IGetters, IMailbox {\n    // We need this structure for the server for now\n    event ProposeTransparentUpgrade(\n        Diamond.DiamondCutData diamondCut,\n        uint256 indexed proposalId,\n        bytes32 proposalSalt\n    );\n}\n"},{"file_path":"lib/openzeppelin-contracts-upgradeable-v4/contracts/security/PausableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../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    /**\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    bool private _paused;\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    function __Pausable_init() internal onlyInitializing {\n        __Pausable_init_unchained();\n    }\n\n    function __Pausable_init_unchained() internal onlyInitializing {\n        _paused = false;\n    }\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    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        require(!paused(), \"Pausable: paused\");\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        require(paused(), \"Pausable: not paused\");\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        _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        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"},{"file_path":"contracts/common/Messaging.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\n/// @dev The enum that represents the transaction execution status\n/// @param Failure The transaction execution failed\n/// @param Success The transaction execution succeeded\nenum TxStatus {\n    Failure,\n    Success\n}\n\n/// @dev The log passed from L2\n/// @param l2ShardId The shard identifier, 0 - rollup, 1 - porter\n/// All other values are not used but are reserved for the future\n/// @param isService A boolean flag that is part of the log along with `key`, `value`, and `sender` address.\n/// This field is required formally but does not have any special meaning\n/// @param txNumberInBatch The L2 transaction number in a Batch, in which the log was sent\n/// @param sender The L2 address which sent the log\n/// @param key The 32 bytes of information that was sent in the log\n/// @param value The 32 bytes of information that was sent in the log\n// Both `key` and `value` are arbitrary 32-bytes selected by the log sender\nstruct L2Log {\n    uint8 l2ShardId;\n    bool isService;\n    uint16 txNumberInBatch;\n    address sender;\n    bytes32 key;\n    bytes32 value;\n}\n\n/// @dev An arbitrary length message passed from L2\n/// @notice Under the hood it is `L2Log` sent from the special system L2 contract\n/// @param txNumberInBatch The L2 transaction number in a Batch, in which the message was sent\n/// @param sender The address of the L2 account from which the message was passed\n/// @param data An arbitrary length message\nstruct L2Message {\n    uint16 txNumberInBatch;\n    address sender;\n    bytes data;\n}\n\n/// @dev Internal structure that contains the parameters for the writePriorityOp\n/// internal function.\n/// @param txId The id of the priority transaction.\n/// @param l2GasPrice The gas price for the l2 priority operation.\n/// @param expirationTimestamp The timestamp by which the priority operation must be processed by the operator.\n/// @param request The external calldata request for the priority operation.\nstruct WritePriorityOpParams {\n    uint256 txId;\n    uint256 l2GasPrice;\n    uint64 expirationTimestamp;\n    BridgehubL2TransactionRequest request;\n}\n\n/// @dev Structure that includes all fields of the L2 transaction\n/// @dev The hash of this structure is the \"canonical L2 transaction hash\" and can\n/// be used as a unique identifier of a tx\n/// @param txType The tx type number, depending on which the L2 transaction can be\n/// interpreted differently\n/// @param from The sender's address. `uint256` type for possible address format changes\n/// and maintaining backward compatibility\n/// @param to The recipient's address. `uint256` type for possible address format changes\n/// and maintaining backward compatibility\n/// @param gasLimit The L2 gas limit for L2 transaction. Analog to the `gasLimit` on an\n/// L1 transactions\n/// @param gasPerPubdataByteLimit Maximum number of L2 gas that will cost one byte of pubdata\n/// (every piece of data that will be stored on L1 as calldata)\n/// @param maxFeePerGas The absolute maximum sender willing to pay per unit of L2 gas to get\n/// the transaction included in a Batch. Analog to the EIP-1559 `maxFeePerGas` on an L1 transactions\n/// @param maxPriorityFeePerGas The additional fee that is paid directly to the validator\n/// to incentivize them to include the transaction in a Batch. Analog to the EIP-1559\n/// `maxPriorityFeePerGas` on an L1 transactions\n/// @param paymaster The address of the EIP-4337 paymaster, that will pay fees for the\n/// transaction. `uint256` type for possible address format changes and maintaining backward compatibility\n/// @param nonce The nonce of the transaction. For L1->L2 transactions it is the priority\n/// operation Id\n/// @param value The value to pass with the transaction\n/// @param reserved The fixed-length fields for usage in a future extension of transaction\n/// formats\n/// @param data The calldata that is transmitted for the transaction call\n/// @param signature An abstract set of bytes that are used for transaction authorization\n/// @param factoryDeps The set of L2 bytecode hashes whose preimages were shown on L1\n/// @param paymasterInput The arbitrary-length data that is used as a calldata to the paymaster pre-call\n/// @param reservedDynamic The arbitrary-length field for usage in a future extension of transaction formats\nstruct L2CanonicalTransaction {\n    uint256 txType;\n    uint256 from;\n    uint256 to;\n    uint256 gasLimit;\n    uint256 gasPerPubdataByteLimit;\n    uint256 maxFeePerGas;\n    uint256 maxPriorityFeePerGas;\n    uint256 paymaster;\n    uint256 nonce;\n    uint256 value;\n    // In the future, we might want to add some\n    // new fields to the struct. The `txData` struct\n    // is to be passed to account and any changes to its structure\n    // would mean a breaking change to these accounts. To prevent this,\n    // we should keep some fields as \"reserved\"\n    // It is also recommended that their length is fixed, since\n    // it would allow easier proof integration (in case we will need\n    // some special circuit for preprocessing transactions)\n    uint256[4] reserved;\n    bytes data;\n    bytes signature;\n    uint256[] factoryDeps;\n    bytes paymasterInput;\n    // Reserved dynamic type for the future use-case. Using it should be avoided,\n    // But it is still here, just in case we want to enable some additional functionality\n    bytes reservedDynamic;\n}\n\n/// @param sender The sender's address.\n/// @param contractAddressL2 The address of the contract on L2 to call.\n/// @param valueToMint The amount of base token that should be minted on L2 as the result of this transaction.\n/// @param l2Value The msg.value of the L2 transaction.\n/// @param l2Calldata The calldata for the L2 transaction.\n/// @param l2GasLimit The limit of the L2 gas for the L2 transaction\n/// @param l2GasPerPubdataByteLimit The price for a single pubdata byte in L2 gas.\n/// @param factoryDeps The array of L2 bytecodes that the tx depends on.\n/// @param refundRecipient The recipient of the refund for the transaction on L2. If the transaction fails, then\n/// this address will receive the `l2Value`.\n// solhint-disable-next-line gas-struct-packing\nstruct BridgehubL2TransactionRequest {\n    address sender;\n    address contractL2;\n    uint256 mintValue;\n    uint256 l2Value;\n    bytes l2Calldata;\n    uint256 l2GasLimit;\n    uint256 l2GasPerPubdataByteLimit;\n    bytes[] factoryDeps;\n    address refundRecipient;\n}\n\n/// @dev The structure that contains the parameters for the message root\n/// @param chainId The chain id of the dependency chain\n/// @param blockOrBatchNumber The block number or the batch number where the message root was created\n/// For proof based interop it is block number. For commit based interop it is batch number.\n/// @param sides The sides of the dynamic incremental merkle tree emitted in the L2ToL1Messenger for precommit based interop\n/// For proof and commit based interop, the sides contain a single root.\nstruct InteropRoot {\n    uint256 chainId;\n    uint256 blockOrBatchNumber;\n    // We are double overloading this. The sides of the dynamic incremental merkle tree normally contains the root, as well as the sides of the tree.\n    // Second overloading: if the length is 1, we are importing a chainBatchRoot/messageRoot instead of sides.\n    bytes32[] sides;\n}\n"},{"file_path":"contracts/bridge/interfaces/IL1Nullifier.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.28;\n\nimport {IBridgehub} from \"../../bridgehub/IBridgehub.sol\";\nimport {IL1NativeTokenVault} from \"../ntv/IL1NativeTokenVault.sol\";\nimport {IL1ERC20Bridge} from \"./IL1ERC20Bridge.sol\";\n\n/// @param chainId The chain ID of the transaction to check.\n/// @param l2BatchNumber The L2 batch number where the withdrawal was processed.\n/// @param l2MessageIndex The position in the L2 logs Merkle tree of the l2Log that was sent with the message.\n/// @param l2sender The address of the message sender on L2 (base token system contract address or asset handler)\n/// @param l2TxNumberInBatch The L2 transaction number in the batch, in which the log was sent.\n/// @param message The L2 withdraw data, stored in an L2 -> L1 message.\n/// @param merkleProof The Merkle proof of the inclusion L2 -> L1 message about withdrawal initialization.\nstruct FinalizeL1DepositParams {\n    uint256 chainId;\n    uint256 l2BatchNumber;\n    uint256 l2MessageIndex;\n    address l2Sender;\n    uint16 l2TxNumberInBatch;\n    bytes message;\n    bytes32[] merkleProof;\n}\n\n/// @title L1 Bridge contract interface\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\ninterface IL1Nullifier {\n    event BridgehubDepositFinalized(\n        uint256 indexed chainId,\n        bytes32 indexed txDataHash,\n        bytes32 indexed l2DepositTxHash\n    );\n\n    function isWithdrawalFinalized(\n        uint256 _chainId,\n        uint256 _l2BatchNumber,\n        uint256 _l2MessageIndex\n    ) external view returns (bool);\n\n    function claimFailedDepositLegacyErc20Bridge(\n        address _depositSender,\n        address _l1Token,\n        uint256 _amount,\n        bytes32 _l2TxHash,\n        uint256 _l2BatchNumber,\n        uint256 _l2MessageIndex,\n        uint16 _l2TxNumberInBatch,\n        bytes32[] calldata _merkleProof\n    ) external;\n\n    function claimFailedDeposit(\n        uint256 _chainId,\n        address _depositSender,\n        address _l1Token,\n        uint256 _amount,\n        bytes32 _l2TxHash,\n        uint256 _l2BatchNumber,\n        uint256 _l2MessageIndex,\n        uint16 _l2TxNumberInBatch,\n        bytes32[] calldata _merkleProof\n    ) external;\n\n    function finalizeDeposit(FinalizeL1DepositParams calldata _finalizeWithdrawalParams) external;\n\n    function BRIDGE_HUB() external view returns (IBridgehub);\n\n    function legacyBridge() external view returns (IL1ERC20Bridge);\n\n    function depositHappened(uint256 _chainId, bytes32 _l2TxHash) external view returns (bytes32);\n\n    function bridgehubConfirmL2TransactionForwarded(uint256 _chainId, bytes32 _txDataHash, bytes32 _txHash) external;\n\n    function l1NativeTokenVault() external view returns (IL1NativeTokenVault);\n\n    function setL1NativeTokenVault(IL1NativeTokenVault _nativeTokenVault) external;\n\n    function setL1AssetRouter(address _l1AssetRouter) external;\n\n    function chainBalance(uint256 _chainId, address _token) external view returns (uint256);\n\n    function l2BridgeAddress(uint256 _chainId) external view returns (address);\n\n    function transferTokenToNTV(address _token) external;\n\n    function nullifyChainBalanceByNTV(uint256 _chainId, address _token) external;\n\n    /// @dev Withdraw funds from the initiated deposit, that failed when finalizing on L2.\n    /// @param _chainId The ZK chain id to which deposit was initiated.\n    /// @param _depositSender The address of the entity that initiated the deposit.\n    /// @param _assetId The unique identifier of the deposited L1 token.\n    /// @param _assetData The encoded transfer data, which includes both the deposit amount and the address of the L2 receiver. Might include extra information.\n    /// @param _l2TxHash The L2 transaction hash of the failed deposit finalization.\n    /// @param _l2BatchNumber The L2 batch number where the deposit finalization was processed.\n    /// @param _l2MessageIndex The position in the L2 logs Merkle tree of the l2Log that was sent with the message.\n    /// @param _l2TxNumberInBatch The L2 transaction number in a batch, in which the log was sent.\n    /// @param _merkleProof The Merkle proof of the processing L1 -> L2 transaction with deposit finalization.\n    /// @dev Processes claims of failed deposit, whether they originated from the legacy bridge or the current system.\n    function bridgeRecoverFailedTransfer(\n        uint256 _chainId,\n        address _depositSender,\n        bytes32 _assetId,\n        bytes memory _assetData,\n        bytes32 _l2TxHash,\n        uint256 _l2BatchNumber,\n        uint256 _l2MessageIndex,\n        uint16 _l2TxNumberInBatch,\n        bytes32[] calldata _merkleProof\n    ) external;\n\n    /// @notice Legacy function to finalize withdrawal via the same\n    /// interface as the old L1SharedBridge.\n    /// @dev Note, that we need to keep this interface, since the `L2AssetRouter`\n    /// will continue returning the previous address as the `l1SharedBridge`. The value\n    /// returned by it is used in the SDK for finalizing withdrawals.\n    /// @param _chainId The chain ID of the transaction to check\n    /// @param _l2BatchNumber The L2 batch number where the withdrawal was processed\n    /// @param _l2MessageIndex The position in the L2 logs Merkle tree of the l2Log that was sent with the message\n    /// @param _l2TxNumberInBatch The L2 transaction number in the batch, in which the log was sent\n    /// @param _message The L2 withdraw data, stored in an L2 -> L1 message\n    /// @param _merkleProof The Merkle proof of the inclusion L2 -> L1 message about withdrawal initialization\n    function finalizeWithdrawal(\n        uint256 _chainId,\n        uint256 _l2BatchNumber,\n        uint256 _l2MessageIndex,\n        uint16 _l2TxNumberInBatch,\n        bytes calldata _message,\n        bytes32[] calldata _merkleProof\n    ) external;\n}\n"},{"file_path":"contracts/common/Config.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\n/// @dev `keccak256(\"\")`\nbytes32 constant EMPTY_STRING_KECCAK = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\n\n/// @dev Bytes in raw L2 log\n/// @dev Equal to the bytes size of the tuple - (uint8 ShardId, bool isService, uint16 txNumberInBatch, address sender,\n/// bytes32 key, bytes32 value)\nuint256 constant L2_TO_L1_LOG_SERIALIZE_SIZE = 88;\n\n/// @dev The maximum length of the bytes array with L2 -> L1 logs\nuint256 constant MAX_L2_TO_L1_LOGS_COMMITMENT_BYTES = 4 + L2_TO_L1_LOG_SERIALIZE_SIZE * 512;\n\n/// @dev The value of default leaf hash for L2 -> L1 logs Merkle tree\n/// @dev An incomplete fixed-size tree is filled with this value to be a full binary tree\n/// @dev Actually equal to the `keccak256(new bytes(L2_TO_L1_LOG_SERIALIZE_SIZE))`\nbytes32 constant L2_L1_LOGS_TREE_DEFAULT_LEAF_HASH = 0x72abee45b59e344af8a6e520241c4744aff26ed411f4c4b00f8af09adada43ba;\n\nbytes32 constant DEFAULT_L2_LOGS_TREE_ROOT_HASH = bytes32(0);\n\n/// @dev Denotes the type of the ZKsync transaction that came from L1.\nuint256 constant PRIORITY_OPERATION_L2_TX_TYPE = 255;\n\n/// @dev Denotes the type of the ZKsync transaction that is used for system upgrades.\nuint256 constant SYSTEM_UPGRADE_L2_TX_TYPE = 254;\n\n/// @dev The maximal allowed difference between protocol minor versions in an upgrade. The 100 gap is needed\n/// in case a protocol version has been tested on testnet, but then not launched on mainnet, e.g.\n/// due to a bug found.\n/// We are allowed to jump at most 100 minor versions at a time. The major version is always expected to be 0.\nuint256 constant MAX_ALLOWED_MINOR_VERSION_DELTA = 100;\n\n/// @dev The amount of time in seconds the validator has to process the priority transaction\n/// NOTE: The constant is set to zero for the Alpha release period\nuint256 constant PRIORITY_EXPIRATION = 0 days;\n\n// @dev The chainId of Ethereum Mainnet\nuint256 constant MAINNET_CHAIN_ID = 1;\n\n/// @dev Timestamp - seconds since unix epoch. This value will be used on the mainnet.\nuint256 constant MAINNET_COMMIT_TIMESTAMP_NOT_OLDER = 3 days;\n\n/// @dev Timestamp - seconds since unix epoch. This value will be used on testnets.\nuint256 constant TESTNET_COMMIT_TIMESTAMP_NOT_OLDER = 30 days;\n\n/// @dev Maximum available error between real commit batch timestamp and analog used in the verifier (in seconds)\n/// @dev Must be used cause miner's `block.timestamp` value can differ on some small value (as we know - 12 seconds)\nuint256 constant COMMIT_TIMESTAMP_APPROXIMATION_DELTA = 1 hours;\n\n/// @dev Shift to apply to verify public input before verifying.\nuint256 constant PUBLIC_INPUT_SHIFT = 32;\n\n/// @dev The maximum number of L2 gas that a user can request for an L2 transaction\nuint256 constant MAX_GAS_PER_TRANSACTION = 80_000_000;\n\n/// @dev Even though the price for 1 byte of pubdata is 16 L1 gas, we have a slightly increased\n/// value.\nuint256 constant L1_GAS_PER_PUBDATA_BYTE = 17;\n\n/// @dev The intrinsic cost of the L1->l2 transaction in computational L2 gas\nuint256 constant L1_TX_INTRINSIC_L2_GAS = 167_157;\n\n/// @dev The intrinsic cost of the L1->l2 transaction in pubdata\nuint256 constant L1_TX_INTRINSIC_PUBDATA = 88;\n\n/// @dev The minimal base price for L1 transaction\nuint256 constant L1_TX_MIN_L2_GAS_BASE = 173_484;\n\n/// @dev The number of L2 gas the transaction starts costing more with each 544 bytes of encoding\nuint256 constant L1_TX_DELTA_544_ENCODING_BYTES = 1656;\n\n/// @dev The number of L2 gas an L1->L2 transaction gains with each new factory dependency\nuint256 constant L1_TX_DELTA_FACTORY_DEPS_L2_GAS = 2473;\n\n/// @dev The number of L2 gas an L1->L2 transaction gains with each new factory dependency\nuint256 constant L1_TX_DELTA_FACTORY_DEPS_PUBDATA = 64;\n\n/// @dev The number of pubdata an L1->L2 transaction requires with each new factory dependency\nuint256 constant MAX_NEW_FACTORY_DEPS = 64;\n\n/// @dev The L2 gasPricePerPubdata required to be used in bridges.\nuint256 constant REQUIRED_L2_GAS_PRICE_PER_PUBDATA = 800;\n\n/// @dev The mask which should be applied to the packed batch and L2 block timestamp in order\n/// to obtain the L2 block timestamp. Applying this mask is equivalent to calculating modulo 2**128\nuint256 constant PACKED_L2_BLOCK_TIMESTAMP_MASK = 0xffffffffffffffffffffffffffffffff;\n\n/// @dev Address of the point evaluation precompile used for EIP-4844 blob verification.\naddress constant POINT_EVALUATION_PRECOMPILE_ADDR = address(0x0A);\n\n/// @dev The overhead for a transaction slot in L2 gas.\n/// It is roughly equal to 80kk/MAX_TRANSACTIONS_IN_BATCH, i.e. how many gas would an L1->L2 transaction\n/// need to pay to compensate for the batch being closed.\n/// @dev It is expected that the L1 contracts will enforce that the L2 gas price will be high enough to compensate\n/// the operator in case the batch is closed because of tx slots filling up.\nuint256 constant TX_SLOT_OVERHEAD_L2_GAS = 10000;\n\n/// @dev The overhead for each byte of the bootloader memory that the encoding of the transaction.\n/// It is roughly equal to 80kk/BOOTLOADER_MEMORY_FOR_TXS, i.e. how many gas would an L1->L2 transaction\n/// need to pay to compensate for the batch being closed.\n/// @dev It is expected that the L1 contracts will enforce that the L2 gas price will be high enough to compensate\n/// the operator in case the batch is closed because of the memory for transactions being filled up.\nuint256 constant MEMORY_OVERHEAD_GAS = 10;\n\n/// @dev The maximum gas limit for a priority transaction in L2.\nuint256 constant PRIORITY_TX_MAX_GAS_LIMIT = 72_000_000;\n\n/// @dev the address used to identify eth as the base token for chains.\naddress constant ETH_TOKEN_ADDRESS = address(1);\n\n/// @dev the value returned in bridgehubDeposit in the TwoBridges function.\nbytes32 constant TWO_BRIDGES_MAGIC_VALUE = bytes32(uint256(keccak256(\"TWO_BRIDGES_MAGIC_VALUE\")) - 1);\n\n/// @dev https://eips.ethereum.org/EIPS/eip-1352\naddress constant BRIDGEHUB_MIN_SECOND_BRIDGE_ADDRESS = address(uint160(type(uint16).max));\n\n/// @dev the maximum number of supported chains, this is an arbitrary limit.\n/// @dev Note, that in case of a malicious Bridgehub admin, the total number of chains\n/// can be up to 2 times higher. This may be possible, in case the old ChainTypeManager\n/// had `100` chains and these were migrated to the Bridgehub only after `MAX_NUMBER_OF_ZK_CHAINS`\n/// were added to the bridgehub via creation of new chains.\nuint256 constant MAX_NUMBER_OF_ZK_CHAINS = 100;\n\n/// @dev Used as the `msg.sender` for transactions that relayed via a settlement layer.\naddress constant SETTLEMENT_LAYER_RELAY_SENDER = address(uint160(0x1111111111111111111111111111111111111111));\n\n/// @dev The metadata version that is supported by the ZK Chains to prove that an L2->L1 log was included in a batch.\nuint256 constant SUPPORTED_PROOF_METADATA_VERSION = 1;\n\n/// @dev The virtual address of the L1 settlement layer.\naddress constant L1_SETTLEMENT_LAYER_VIRTUAL_ADDRESS = address(\n    uint160(uint256(keccak256(\"L1_SETTLEMENT_LAYER_VIRTUAL_ADDRESS\")) - 1)\n);\n\nstruct PriorityTreeCommitment {\n    uint256 nextLeafIndex;\n    uint256 startIndex;\n    uint256 unprocessedIndex;\n    bytes32[] sides;\n}\n\n// Info that allows to restore a chain.\nstruct ZKChainCommitment {\n    /// @notice Total number of executed batches i.e. batches[totalBatchesExecuted] points at the latest executed batch\n    /// (batch 0 is genesis)\n    uint256 totalBatchesExecuted;\n    /// @notice Total number of proved batches i.e. batches[totalBatchesProved] points at the latest proved batch\n    uint256 totalBatchesVerified;\n    /// @notice Total number of committed batches i.e. batches[totalBatchesCommitted] points at the latest committed\n    /// batch\n    uint256 totalBatchesCommitted;\n    /// @notice The hash of the L2 system contracts ugpgrade transaction.\n    /// @dev It is non zero if the migration happens while the upgrade is not yet finalized.\n    bytes32 l2SystemContractsUpgradeTxHash;\n    /// @notice The batch when the system contracts upgrade transaction was executed.\n    /// @dev It is non-zero if the migration happens while the batch where the upgrade tx was present\n    /// has not been finalized (executed) yet.\n    uint256 l2SystemContractsUpgradeBatchNumber;\n    /// @notice The hashes of the batches that are needed to keep the blockchain working.\n    /// @dev The length of the array is equal to the `totalBatchesCommitted - totalBatchesExecuted + 1`, i.e. we need\n    /// to store all the unexecuted batches' hashes + 1 latest executed one.\n    bytes32[] batchHashes;\n    /// @notice Commitment to the priority merkle tree.\n    PriorityTreeCommitment priorityTree;\n    /// @notice Whether a chain is a permanent rollup.\n    bool isPermanentRollup;\n    /// @notice The precommitment to the transactions of the latest batch.\n    bytes32 precommitmentForTheLatestBatch;\n}\n\n/// @dev Used as the `msg.sender` for system service transactions.\naddress constant SERVICE_TRANSACTION_SENDER = address(uint160(0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF));\n\n/// @dev To avoid higher costs the writes, we avoid making the slot zero.\n/// This ensures that the cost of writes is always 5k and avoids the 20k initial write from the non-zero value.\nbytes32 constant DEFAULT_PRECOMMITMENT_FOR_THE_LAST_BATCH = bytes32(uint256(1));\n\n/// @dev The length of a packed transaction precommitment in bytes. It consists of two parts: 32-byte tx hash and 1-byte status (0 or 1).\nuint256 constant PACKED_L2_PRECOMMITMENT_LENGTH = 33;\n"},{"file_path":"contracts/common/interfaces/IL2InteropRootStorage.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.24;\n/**\n * @author Matter Labs\n * @custom:security-contact security@matterlabs.dev\n * @notice The interface of the L2 InteropRootStorage contract,\n * responsible for storing the message roots of other chains on the L2.\n */\ninterface IL2InteropRootStorage {\n    /// @notice Mapping of chain ID to block or batch number to message root.\n    function interopRoots(uint256 chainId, uint256 blockOrBatchNumber) external view returns (bytes32);\n}\n"},{"file_path":"contracts/bridgehub/IMessageRoot.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.28;\n\nimport {IBridgehub} from \"./IBridgehub.sol\";\n\n/**\n * @author Matter Labs\n * @notice MessageRoot contract is responsible for storing and aggregating the roots of the batches from different chains into the MessageRoot.\n * @custom:security-contact security@matterlabs.dev\n */\ninterface IMessageRoot {\n    function BRIDGE_HUB() external view returns (IBridgehub);\n\n    function addNewChain(uint256 _chainId) external;\n\n    function addChainBatchRoot(uint256 _chainId, uint256 _batchNumber, bytes32 _chainBatchRoot) external;\n\n    function historicalRoot(uint256 _blockNumber) external view returns (bytes32);\n}\n"},{"file_path":"contracts/state-transition/chain-interfaces/IZKChainBase.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\n/// @title The interface of the ZKsync contract, responsible for the main ZKsync logic.\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\ninterface IZKChainBase {\n    /// @return Returns facet name.\n    function getName() external view returns (string memory);\n}\n"},{"file_path":"lib/openzeppelin-contracts-upgradeable-v4/contracts/proxy/utils/Initializable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\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 Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 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 functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\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 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\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        require(_initializing, \"Initializable: contract is not initializing\");\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        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _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 _initializing;\n    }\n}\n"},{"file_path":"contracts/bridgehub/IBridgehub.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {L2Log, L2Message, TxStatus} from \"../common/Messaging.sol\";\nimport {ICTMDeploymentTracker} from \"./ICTMDeploymentTracker.sol\";\nimport {IMessageRoot} from \"./IMessageRoot.sol\";\n\nstruct L2TransactionRequestDirect {\n    uint256 chainId;\n    uint256 mintValue;\n    address l2Contract;\n    uint256 l2Value;\n    bytes l2Calldata;\n    uint256 l2GasLimit;\n    uint256 l2GasPerPubdataByteLimit;\n    bytes[] factoryDeps;\n    address refundRecipient;\n}\n\nstruct L2TransactionRequestTwoBridgesOuter {\n    uint256 chainId;\n    uint256 mintValue;\n    uint256 l2Value;\n    uint256 l2GasLimit;\n    uint256 l2GasPerPubdataByteLimit;\n    address refundRecipient;\n    address secondBridgeAddress;\n    uint256 secondBridgeValue;\n    bytes secondBridgeCalldata;\n}\n\nstruct L2TransactionRequestTwoBridgesInner {\n    bytes32 magicValue;\n    address l2Contract;\n    bytes l2Calldata;\n    bytes[] factoryDeps;\n    bytes32 txDataHash;\n}\n\nstruct BridgehubMintCTMAssetData {\n    uint256 chainId;\n    bytes32 baseTokenAssetId;\n    bytes ctmData;\n    bytes chainData;\n}\n\nstruct BridgehubBurnCTMAssetData {\n    uint256 chainId;\n    bytes ctmData;\n    bytes chainData;\n}\n\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\ninterface IBridgehub {\n    /// @notice pendingAdmin is changed\n    /// @dev Also emitted when new admin is accepted and in this case, `newPendingAdmin` would be zero address\n    event NewPendingAdmin(address indexed oldPendingAdmin, address indexed newPendingAdmin);\n\n    /// @notice Admin changed\n    event NewAdmin(address indexed oldAdmin, address indexed newAdmin);\n\n    /// @notice CTM asset registered\n    event AssetRegistered(\n        bytes32 indexed assetInfo,\n        address indexed _assetAddress,\n        bytes32 indexed additionalData,\n        address sender\n    );\n\n    event SettlementLayerRegistered(uint256 indexed chainId, bool indexed isWhitelisted);\n\n    /// @notice Starts the transfer of admin rights. Only the current admin or owner can propose a new pending one.\n    /// @notice New admin can accept admin rights by calling `acceptAdmin` function.\n    /// @param _newPendingAdmin Address of the new admin\n    function setPendingAdmin(address _newPendingAdmin) external;\n\n    /// @notice Accepts transfer of admin rights. Only pending admin can accept the role.\n    function acceptAdmin() external;\n\n    /// Getters\n    function chainTypeManagerIsRegistered(address _chainTypeManager) external view returns (bool);\n\n    function chainTypeManager(uint256 _chainId) external view returns (address);\n\n    function assetIdIsRegistered(bytes32 _baseTokenAssetId) external view returns (bool);\n\n    function baseToken(uint256 _chainId) external view returns (address);\n\n    function baseTokenAssetId(uint256 _chainId) external view returns (bytes32);\n\n    function messageRoot() external view returns (IMessageRoot);\n\n    function getZKChain(uint256 _chainId) external view returns (address);\n\n    function getAllZKChains() external view returns (address[] memory);\n\n    function getAllZKChainChainIDs() external view returns (uint256[] memory);\n\n    function migrationPaused() external view returns (bool);\n\n    function admin() external view returns (address);\n\n    function assetRouter() external view returns (address);\n\n    /// Mailbox forwarder\n\n    function proveL2MessageInclusion(\n        uint256 _chainId,\n        uint256 _batchNumber,\n        uint256 _index,\n        L2Message calldata _message,\n        bytes32[] calldata _proof\n    ) external view returns (bool);\n\n    function proveL2LogInclusion(\n        uint256 _chainId,\n        uint256 _batchNumber,\n        uint256 _index,\n        L2Log memory _log,\n        bytes32[] calldata _proof\n    ) external view returns (bool);\n\n    function proveL1ToL2TransactionStatus(\n        uint256 _chainId,\n        bytes32 _l2TxHash,\n        uint256 _l2BatchNumber,\n        uint256 _l2MessageIndex,\n        uint16 _l2TxNumberInBatch,\n        bytes32[] calldata _merkleProof,\n        TxStatus _status\n    ) external view returns (bool);\n\n    function requestL2TransactionDirect(\n        L2TransactionRequestDirect calldata _request\n    ) external payable returns (bytes32 canonicalTxHash);\n\n    function requestL2TransactionTwoBridges(\n        L2TransactionRequestTwoBridgesOuter calldata _request\n    ) external payable returns (bytes32 canonicalTxHash);\n\n    function l2TransactionBaseCost(\n        uint256 _chainId,\n        uint256 _gasPrice,\n        uint256 _l2GasLimit,\n        uint256 _l2GasPerPubdataByteLimit\n    ) external view returns (uint256);\n\n    //// Registry\n\n    function createNewChain(\n        uint256 _chainId,\n        address _chainTypeManager,\n        bytes32 _baseTokenAssetId,\n        uint256 _salt,\n        address _admin,\n        bytes calldata _initData,\n        bytes[] calldata _factoryDeps\n    ) external returns (uint256 chainId);\n\n    function addChainTypeManager(address _chainTypeManager) external;\n\n    function removeChainTypeManager(address _chainTypeManager) external;\n\n    function addTokenAssetId(bytes32 _baseTokenAssetId) external;\n\n    function setAddresses(\n        address _sharedBridge,\n        ICTMDeploymentTracker _l1CtmDeployer,\n        IMessageRoot _messageRoot,\n        address _chainAssetHandler\n    ) external;\n\n    function setChainAssetHandler(address _chainAssetHandler) external;\n\n    event NewChain(uint256 indexed chainId, address chainTypeManager, address indexed chainGovernance);\n\n    event ChainTypeManagerAdded(address indexed chainTypeManager);\n\n    event ChainTypeManagerRemoved(address indexed chainTypeManager);\n\n    event BaseTokenAssetIdRegistered(bytes32 indexed assetId);\n\n    function whitelistedSettlementLayers(uint256 _chainId) external view returns (bool);\n\n    function registerSettlementLayer(uint256 _newSettlementLayerChainId, bool _isWhitelisted) external;\n\n    function settlementLayer(uint256 _chainId) external view returns (uint256);\n\n    // function finalizeMigrationToGateway(\n    //     uint256 _chainId,\n    //     address _baseToken,\n    //     address _sharedBridge,\n    //     address _admin,\n    //     uint256 _expectedProtocolVersion,\n    //     ZKChainCommitment calldata _commitment,\n    //     bytes calldata _diamondCut\n    // ) external;\n\n    function forwardTransactionOnGateway(\n        uint256 _chainId,\n        bytes32 _canonicalTxHash,\n        uint64 _expirationTimestamp\n    ) external;\n\n    function ctmAssetIdFromChainId(uint256 _chainId) external view returns (bytes32);\n\n    function ctmAssetIdFromAddress(address _ctmAddress) external view returns (bytes32);\n\n    function l1CtmDeployer() external view returns (ICTMDeploymentTracker);\n\n    function ctmAssetIdToAddress(bytes32 _assetInfo) external view returns (address);\n\n    function setCTMAssetAddress(bytes32 _additionalData, address _assetAddress) external;\n\n    function L1_CHAIN_ID() external view returns (uint256);\n\n    function chainAssetHandler() external view returns (address);\n\n    function registerAlreadyDeployedZKChain(uint256 _chainId, address _hyperchain) external;\n\n    function registerLegacyChain(uint256 _chainId) external;\n\n    function pauseMigration() external;\n\n    function unpauseMigration() external;\n\n    function forwardedBridgeBurnSetSettlementLayer(\n        uint256 _chainId,\n        uint256 _newSettlementLayerChainId\n    ) external returns (address zkChain, address ctm);\n\n    function forwardedBridgeMint(\n        bytes32 _assetId,\n        uint256 _chainId,\n        bytes32 _baseTokenAssetId\n    ) external returns (address zkChain, address ctm);\n\n    function registerNewZKChain(uint256 _chainId, address _zkChain, bool _checkMaxNumberOfZKChains) external;\n\n    function forwardedBridgeRecoverFailedTransfer(uint256 _chainId) external returns (address zkChain, address ctm);\n}\n"},{"file_path":"contracts/common/libraries/Merkle.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {UncheckedMath} from \"../../common/libraries/UncheckedMath.sol\";\nimport {MerkleIndexOrHeightMismatch, MerkleIndexOutOfBounds, MerkleNothingToProve, MerklePathEmpty, MerklePathLengthMismatch, MerklePathOutOfBounds} from \"../../common/L1ContractErrors.sol\";\n\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\nlibrary Merkle {\n    using UncheckedMath for uint256;\n\n    /// @dev Calculate Merkle root by the provided Merkle proof.\n    /// NOTE: When using this function, check that the _path length is equal to the tree height to prevent shorter/longer paths attack\n    /// however, for chains settling on GW the proof includes the GW proof, so the path increases. See Mailbox for more details.\n    /// @param _path Merkle path from the leaf to the root\n    /// @param _index Leaf index in the tree\n    /// @param _itemHash Hash of leaf content\n    /// @return The Merkle root\n    function calculateRoot(\n        bytes32[] calldata _path,\n        uint256 _index,\n        bytes32 _itemHash\n    ) internal pure returns (bytes32) {\n        uint256 pathLength = _path.length;\n        _validatePathLengthForSingleProof(_index, pathLength);\n\n        bytes32 currentHash = _itemHash;\n        for (uint256 i; i < pathLength; i = i.uncheckedInc()) {\n            currentHash = (_index % 2 == 0)\n                ? efficientHash(currentHash, _path[i])\n                : efficientHash(_path[i], currentHash);\n            _index /= 2;\n        }\n\n        return currentHash;\n    }\n\n    /// @dev Calculate Merkle root by the provided Merkle proof.\n    /// @dev NOTE: When using this function, check that the _path length is appropriate to prevent shorter/longer paths attack\n    /// @param _path Merkle path from the leaf to the root\n    /// @param _index Leaf index in the tree.\n    /// @dev NOTE the tree can be joined. In this case the second tree's leaves indexes increase by the number of leaves in the first tree.\n    /// @param _itemHash Hash of leaf content\n    /// @return The Merkle root\n    function calculateRootMemory(\n        bytes32[] memory _path,\n        uint256 _index,\n        bytes32 _itemHash\n    ) internal pure returns (bytes32) {\n        uint256 pathLength = _path.length;\n        _validatePathLengthForSingleProof(_index, pathLength);\n\n        bytes32 currentHash = _itemHash;\n        for (uint256 i; i < pathLength; i = i.uncheckedInc()) {\n            currentHash = (_index % 2 == 0)\n                ? efficientHash(currentHash, _path[i])\n                : efficientHash(_path[i], currentHash);\n            _index /= 2;\n        }\n\n        return currentHash;\n    }\n\n    /// @dev Calculate Merkle root by the provided Merkle proof for a range of elements\n    /// NOTE: When using this function, check that the _startPath and _endPath lengths are equal to the tree height to prevent shorter/longer paths attack\n    /// @param _startPath Merkle path from the first element of the range to the root\n    /// @param _endPath Merkle path from the last element of the range to the root\n    /// @param _startIndex Index of the first element of the range in the tree\n    /// @param _itemHashes Hashes of the elements in the range\n    /// @return The Merkle root\n    function calculateRootPaths(\n        bytes32[] memory _startPath,\n        bytes32[] memory _endPath,\n        uint256 _startIndex,\n        bytes32[] memory _itemHashes\n    ) internal pure returns (bytes32) {\n        uint256 pathLength = _startPath.length;\n        if (pathLength != _endPath.length) {\n            revert MerklePathLengthMismatch(pathLength, _endPath.length);\n        }\n        if (pathLength >= 256) {\n            revert MerklePathOutOfBounds();\n        }\n        uint256 levelLen = _itemHashes.length;\n        // Edge case: we want to be able to prove an element in a single-node tree.\n        if (pathLength == 0 && (_startIndex != 0 || levelLen != 1)) {\n            revert MerklePathEmpty();\n        }\n        if (levelLen == 0) {\n            revert MerkleNothingToProve();\n        }\n        if (_startIndex + levelLen > (1 << pathLength)) {\n            revert MerkleIndexOrHeightMismatch();\n        }\n        bytes32[] memory itemHashes = _itemHashes;\n\n        for (uint256 level; level < pathLength; level = level.uncheckedInc()) {\n            uint256 parity = _startIndex % 2;\n            // We get an extra element on the next level if on the current level elements either\n            // start on an odd index (`parity == 1`) or end on an even index (`levelLen % 2 == 1`)\n            uint256 nextLevelLen = levelLen / 2 + (parity | (levelLen % 2));\n            for (uint256 i; i < nextLevelLen; i = i.uncheckedInc()) {\n                bytes32 lhs = (i == 0 && parity == 1) ? _startPath[level] : itemHashes[2 * i - parity];\n                bytes32 rhs = (i == nextLevelLen - 1 && (levelLen - parity) % 2 == 1)\n                    ? _endPath[level]\n                    : itemHashes[2 * i + 1 - parity];\n                itemHashes[i] = efficientHash(lhs, rhs);\n            }\n            levelLen = nextLevelLen;\n            _startIndex /= 2;\n        }\n\n        return itemHashes[0];\n    }\n\n    /// @dev Keccak hash of the concatenation of two 32-byte words\n    function efficientHash(bytes32 _lhs, bytes32 _rhs) internal pure returns (bytes32 result) {\n        assembly {\n            mstore(0x00, _lhs)\n            mstore(0x20, _rhs)\n            result := keccak256(0x00, 0x40)\n        }\n    }\n\n    function _validatePathLengthForSingleProof(uint256 _index, uint256 _pathLength) private pure {\n        if (_pathLength >= 256) {\n            revert MerklePathOutOfBounds();\n        }\n        if (_index >= (1 << _pathLength)) {\n            revert MerkleIndexOutOfBounds();\n        }\n    }\n}\n"},{"file_path":"contracts/bridge/ntv/IL1NativeTokenVault.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.28;\n\nimport {IL1Nullifier} from \"../interfaces/IL1Nullifier.sol\";\nimport {INativeTokenVault} from \"./INativeTokenVault.sol\";\nimport {IL1AssetDeploymentTracker} from \"../interfaces/IL1AssetDeploymentTracker.sol\";\n\n/// @title L1 Native token vault contract interface\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\n/// @notice The NTV is an Asset Handler for the L1AssetRouter to handle native tokens\n// is IL1AssetHandler, IL1BaseTokenAssetHandler {\ninterface IL1NativeTokenVault is INativeTokenVault, IL1AssetDeploymentTracker {\n    /// @notice The L1Nullifier contract\n    function L1_NULLIFIER() external view returns (IL1Nullifier);\n\n    /// @notice Returns the total number of specific tokens locked for some chain\n    function chainBalance(uint256 _chainId, bytes32 _assetId) external view returns (uint256);\n\n    /// @notice Registers ETH token\n    function registerEthToken() external;\n\n    event TokenBeaconUpdated(address indexed l2TokenBeacon);\n}\n"},{"file_path":"contracts/common/ReentrancyGuard.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {NotInitializedReentrancyGuard, Reentrancy, SlotOccupied} from \"./L1ContractErrors.sol\";\n\n/**\n * @custom:security-contact security@matterlabs.dev\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 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 *\n * _Since v2.5.0:_ this module is now much more gas efficient, given net gas\n * metering changes introduced in the Istanbul hardfork.\n */\nabstract contract ReentrancyGuard {\n    /// @dev Address of lock flag variable.\n    /// @dev Flag is placed at random memory location to not interfere with Storage contract.\n    // keccak256(\"ReentrancyGuard\") - 1;\n    uint256 private constant LOCK_FLAG_ADDRESS = 0x8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4;\n\n    // solhint-disable-next-line max-line-length\n    // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/566a774222707e424896c0c390a84dc3c13bdcb2/contracts/security/ReentrancyGuard.sol\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    modifier reentrancyGuardInitializer() {\n        _initializeReentrancyGuard();\n        _;\n    }\n\n    function _initializeReentrancyGuard() private {\n        uint256 lockSlotOldValue;\n\n        // Storing an initial non-zero value makes deployment a bit more\n        // expensive but in exchange every call to nonReentrant\n        // will be cheaper.\n        assembly {\n            lockSlotOldValue := sload(LOCK_FLAG_ADDRESS)\n            sstore(LOCK_FLAG_ADDRESS, _NOT_ENTERED)\n        }\n\n        // Check that storage slot for reentrancy guard is empty to rule out possibility of slot conflict\n        if (lockSlotOldValue != 0) {\n            revert SlotOccupied();\n        }\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 make it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        uint256 _status;\n        assembly {\n            _status := sload(LOCK_FLAG_ADDRESS)\n        }\n\n        if (_status == 0) {\n            revert NotInitializedReentrancyGuard();\n        }\n        // On the first call to nonReentrant, _NOT_ENTERED will be true\n        if (_status != _NOT_ENTERED) {\n            revert Reentrancy();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        assembly {\n            sstore(LOCK_FLAG_ADDRESS, _ENTERED)\n        }\n\n        _;\n\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        assembly {\n            sstore(LOCK_FLAG_ADDRESS, _NOT_ENTERED)\n        }\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts-v4/contracts/utils/math/SafeCast.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value >= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n"},{"file_path":"contracts/bridge/asset-router/IL1AssetRouter.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {IL1Nullifier} from \"../interfaces/IL1Nullifier.sol\";\nimport {INativeTokenVault} from \"../ntv/INativeTokenVault.sol\";\nimport {IAssetRouterBase} from \"./IAssetRouterBase.sol\";\nimport {L2TransactionRequestTwoBridgesInner} from \"../../bridgehub/IBridgehub.sol\";\nimport {IL1SharedBridgeLegacy} from \"../interfaces/IL1SharedBridgeLegacy.sol\";\nimport {IL1ERC20Bridge} from \"../interfaces/IL1ERC20Bridge.sol\";\n\n/// @title L1 Bridge contract interface\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\ninterface IL1AssetRouter is IAssetRouterBase, IL1SharedBridgeLegacy {\n    event BridgehubMintData(bytes bridgeMintData);\n\n    event BridgehubDepositFinalized(\n        uint256 indexed chainId,\n        bytes32 indexed txDataHash,\n        bytes32 indexed l2DepositTxHash\n    );\n\n    event ClaimedFailedDepositAssetRouter(uint256 indexed chainId, bytes32 indexed assetId, bytes assetData);\n\n    event AssetDeploymentTrackerSet(\n        bytes32 indexed assetId,\n        address indexed assetDeploymentTracker,\n        bytes32 indexed additionalData\n    );\n\n    event LegacyDepositInitiated(\n        uint256 indexed chainId,\n        bytes32 indexed l2DepositTxHash,\n        address indexed from,\n        address to,\n        address l1Token,\n        uint256 amount\n    );\n\n    /// @notice Initiates a deposit by locking funds on the contract and sending the request\n    /// of processing an L2 transaction where tokens would be minted.\n    /// @dev If the token is bridged for the first time, the L2 token contract will be deployed. Note however, that the\n    /// newly-deployed token does not support any custom logic, i.e. rebase tokens' functionality is not supported.\n    /// @param _originalCaller The `msg.sender` address from the external call that initiated current one.\n    /// @param _l2Receiver The account address that should receive funds on L2.\n    /// @param _l1Token The L1 token address which is deposited.\n    /// @param _amount The total amount of tokens to be bridged.\n    /// @param _l2TxGasLimit The L2 gas limit to be used in the corresponding L2 transaction.\n    /// @param _l2TxGasPerPubdataByte The gasPerPubdataByteLimit to be used in the corresponding L2 transaction.\n    /// @param _refundRecipient The address on L2 that will receive the refund for the transaction.\n    /// @dev If the L2 deposit finalization transaction fails, the `_refundRecipient` will receive the `_l2Value`.\n    /// Please note, the contract may change the refund recipient's address to eliminate sending funds to addresses\n    /// out of control.\n    /// - If `_refundRecipient` is a contract on L1, the refund will be sent to the aliased `_refundRecipient`.\n    /// - If `_refundRecipient` is set to `address(0)` and the sender has NO deployed bytecode on L1, the refund will\n    /// be sent to the `msg.sender` address.\n    /// - If `_refundRecipient` is set to `address(0)` and the sender has deployed bytecode on L1, the refund will be\n    /// sent to the aliased `msg.sender` address.\n    /// @dev The address aliasing of L1 contracts as refund recipient on L2 is necessary to guarantee that the funds\n    /// are controllable through the Mailbox, since the Mailbox applies address aliasing to the from address for the\n    /// L2 tx if the L1 msg.sender is a contract. Without address aliasing for L1 contracts as refund recipients they\n    /// would not be able to make proper L2 tx requests through the Mailbox to use or withdraw the funds from L2, and\n    /// the funds would be lost.\n    /// @return txHash The L2 transaction hash of deposit finalization.\n    function depositLegacyErc20Bridge(\n        address _originalCaller,\n        address _l2Receiver,\n        address _l1Token,\n        uint256 _amount,\n        uint256 _l2TxGasLimit,\n        uint256 _l2TxGasPerPubdataByte,\n        address _refundRecipient\n    ) external payable returns (bytes32 txHash);\n\n    function L1_NULLIFIER() external view returns (IL1Nullifier);\n\n    function L1_WETH_TOKEN() external view returns (address);\n\n    function ETH_TOKEN_ASSET_ID() external view returns (bytes32);\n\n    function nativeTokenVault() external view returns (INativeTokenVault);\n\n    function setAssetDeploymentTracker(bytes32 _assetRegistrationData, address _assetDeploymentTracker) external;\n\n    function setNativeTokenVault(INativeTokenVault _nativeTokenVault) external;\n\n    function setL1Erc20Bridge(IL1ERC20Bridge _legacyBridge) external;\n\n    /// @notice Withdraw funds from the initiated deposit, that failed when finalizing on L2.\n    /// @param _chainId The ZK chain id to which the deposit was initiated.\n    /// @param _depositSender The address of the entity that initiated the deposit.\n    /// @param _assetId The unique identifier of the deposited L1 token.\n    /// @param _assetData The encoded transfer data, which includes both the deposit amount and the address of the L2 receiver. Might include extra information.\n    /// @dev Processes claims of failed deposit, whether they originated from the legacy bridge or the current system.\n    function bridgeRecoverFailedTransfer(\n        uint256 _chainId,\n        address _depositSender,\n        bytes32 _assetId,\n        bytes calldata _assetData\n    ) external;\n\n    /// @dev Withdraw funds from the initiated deposit, that failed when finalizing on L2.\n    /// @param _chainId The ZK chain id to which deposit was initiated.\n    /// @param _depositSender The address of the entity that initiated the deposit.\n    /// @param _assetId The unique identifier of the deposited L1 token.\n    /// @param _assetData The encoded transfer data, which includes both the deposit amount and the address of the L2 receiver. Might include extra information.\n    /// @param _l2TxHash The L2 transaction hash of the failed deposit finalization.\n    /// @param _l2BatchNumber The L2 batch number where the deposit finalization was processed.\n    /// @param _l2MessageIndex The position in the L2 logs Merkle tree of the l2Log that was sent with the message.\n    /// @param _l2TxNumberInBatch The L2 transaction number in a batch, in which the log was sent.\n    /// @param _merkleProof The Merkle proof of the processing L1 -> L2 transaction with deposit finalization.\n    /// @dev Processes claims of failed deposit, whether they originated from the legacy bridge or the current system.\n    function bridgeRecoverFailedTransfer(\n        uint256 _chainId,\n        address _depositSender,\n        bytes32 _assetId,\n        bytes memory _assetData,\n        bytes32 _l2TxHash,\n        uint256 _l2BatchNumber,\n        uint256 _l2MessageIndex,\n        uint16 _l2TxNumberInBatch,\n        bytes32[] calldata _merkleProof\n    ) external;\n\n    /// @notice Transfers funds to Native Token Vault, if the asset is registered with it. Does nothing for ETH or non-registered tokens.\n    /// @dev assetId is not the padded address, but the correct encoded id (NTV stores respective format for IDs)\n    /// @param _amount The asset amount to be transferred to native token vault.\n    /// @param _originalCaller The `msg.sender` address from the external call that initiated current one.\n    function transferFundsToNTV(bytes32 _assetId, uint256 _amount, address _originalCaller) external returns (bool);\n\n    /// @notice Finalize the withdrawal and release funds\n    /// @param _chainId The chain ID of the transaction to check\n    /// @param _l2BatchNumber The L2 batch number where the withdrawal was processed\n    /// @param _l2MessageIndex The position in the L2 logs Merkle tree of the l2Log that was sent with the message\n    /// @param _l2TxNumberInBatch The L2 transaction number in the batch, in which the log was sent\n    /// @param _message The L2 withdraw data, stored in an L2 -> L1 message\n    /// @param _merkleProof The Merkle proof of the inclusion L2 -> L1 message about withdrawal initialization\n    function finalizeWithdrawal(\n        uint256 _chainId,\n        uint256 _l2BatchNumber,\n        uint256 _l2MessageIndex,\n        uint16 _l2TxNumberInBatch,\n        bytes calldata _message,\n        bytes32[] calldata _merkleProof\n    ) external;\n\n    /// @notice Initiates a transfer transaction within Bridgehub, used by `requestL2TransactionTwoBridges`.\n    /// @param _chainId The chain ID of the ZK chain to which deposit.\n    /// @param _originalCaller The `msg.sender` address from the external call that initiated current one.\n    /// @param _value The `msg.value` on the target chain tx.\n    /// @param _data The calldata for the second bridge deposit.\n    /// @return request The data used by the bridgehub to create L2 transaction request to specific ZK chain.\n    /// @dev Data has the following abi encoding for legacy deposits:\n    /// address _l1Token,\n    /// uint256 _amount,\n    /// address _l2Receiver\n    /// for new deposits:\n    /// bytes32 _assetId,\n    /// bytes _transferData\n    function bridgehubDeposit(\n        uint256 _chainId,\n        address _originalCaller,\n        uint256 _value,\n        bytes calldata _data\n    ) external payable returns (L2TransactionRequestTwoBridgesInner memory request);\n\n    /// @notice Generates a calldata for calling the deposit finalization on the L2 native token contract.\n    // / @param _chainId The chain ID of the ZK chain to which deposit.\n    /// @param _sender The address of the deposit initiator.\n    /// @param _assetId The deposited asset ID.\n    /// @param _assetData The encoded data, which is used by the asset handler to determine L2 recipient and amount. Might include extra information.\n    /// @return Returns calldata used on ZK chain.\n    function getDepositCalldata(\n        address _sender,\n        bytes32 _assetId,\n        bytes memory _assetData\n    ) external view returns (bytes memory);\n\n    /// @notice Allows bridgehub to acquire mintValue for L1->L2 transactions.\n    /// @dev If the corresponding L2 transaction fails, refunds are issued to a refund recipient on L2.\n    /// @param _chainId The chain ID of the ZK chain to which deposit.\n    /// @param _assetId The deposited asset ID.\n    /// @param _originalCaller The `msg.sender` address from the external call that initiated current one.\n    /// @param _amount The total amount of tokens to be bridged.\n    function bridgehubDepositBaseToken(\n        uint256 _chainId,\n        bytes32 _assetId,\n        address _originalCaller,\n        uint256 _amount\n    ) external payable;\n\n    /// @notice Routes the confirmation to nullifier for backward compatibility.\n    /// @notice Confirms the acceptance of a transaction by the Mailbox, as part of the L2 transaction process within Bridgehub.\n    /// This function is utilized by `requestL2TransactionTwoBridges` to validate the execution of a transaction.\n    /// @param _chainId The chain ID of the ZK chain to which confirm the deposit.\n    /// @param _txDataHash The keccak256 hash of 0x01 || abi.encode(bytes32, bytes) to identify deposits.\n    /// @param _txHash The hash of the L1->L2 transaction to confirm the deposit.\n    function bridgehubConfirmL2Transaction(uint256 _chainId, bytes32 _txDataHash, bytes32 _txHash) external;\n\n    function isWithdrawalFinalized(\n        uint256 _chainId,\n        uint256 _l2BatchNumber,\n        uint256 _l2MessageIndex\n    ) external view returns (bool);\n}\n"},{"file_path":"contracts/bridge/interfaces/IL1SharedBridgeLegacy.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.28;\n\n/// @title L1 Bridge contract interface\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\ninterface IL1SharedBridgeLegacy {\n    function l2BridgeAddress(uint256 _chainId) external view returns (address);\n}\n"},{"file_path":"contracts/bridge/interfaces/IL1BaseTokenAssetHandler.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.28;\n\n/// @title L1 Base Token Asset Handler contract interface\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\n/// @notice Used for any asset handler and called by the L1AssetRouter\ninterface IL1BaseTokenAssetHandler {\n    /// @notice Used to get the token address of an assetId\n    function tokenAddress(bytes32 _assetId) external view returns (address);\n}\n"},{"file_path":"lib/openzeppelin-contracts-v4/contracts/utils/structs/EnumerableMap.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableMap.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableMap.js.\n\npragma solidity ^0.8.0;\n\nimport \"./EnumerableSet.sol\";\n\n/**\n * @dev Library for managing an enumerable variant of Solidity's\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\n * type.\n *\n * Maps have the following properties:\n *\n * - Entries are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n *     // Add the library methods\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\n *\n *     // Declare a set state variable\n *     EnumerableMap.UintToAddressMap private myMap;\n * }\n * ```\n *\n * The following map types are supported:\n *\n * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0\n * - `address -> uint256` (`AddressToUintMap`) since v4.6.0\n * - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0\n * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0\n * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableMap.\n * ====\n */\nlibrary EnumerableMap {\n    using EnumerableSet for EnumerableSet.Bytes32Set;\n\n    // To implement this library for multiple types with as little code\n    // repetition as possible, we write it in terms of a generic Map type with\n    // bytes32 keys and values.\n    // The Map implementation uses private functions, and user-facing\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\n    // the underlying Map.\n    // This means that we can only create new EnumerableMaps for types that fit\n    // in bytes32.\n\n    struct Bytes32ToBytes32Map {\n        // Storage of keys\n        EnumerableSet.Bytes32Set _keys;\n        mapping(bytes32 => bytes32) _values;\n    }\n\n    /**\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\n     * key. O(1).\n     *\n     * Returns true if the key was added to the map, that is if it was not\n     * already present.\n     */\n    function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) internal returns (bool) {\n        map._values[key] = value;\n        return map._keys.add(key);\n    }\n\n    /**\n     * @dev Removes a key-value pair from a map. O(1).\n     *\n     * Returns true if the key was removed from the map, that is if it was present.\n     */\n    function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) {\n        delete map._values[key];\n        return map._keys.remove(key);\n    }\n\n    /**\n     * @dev Returns true if the key is in the map. O(1).\n     */\n    function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) {\n        return map._keys.contains(key);\n    }\n\n    /**\n     * @dev Returns the number of key-value pairs in the map. O(1).\n     */\n    function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) {\n        return map._keys.length();\n    }\n\n    /**\n     * @dev Returns the key-value pair stored at position `index` in the map. O(1).\n     *\n     * Note that there are no guarantees on the ordering of entries inside the\n     * array, and it may change when more entries are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) {\n        bytes32 key = map._keys.at(index);\n        return (key, map._values[key]);\n    }\n\n    /**\n     * @dev Tries to returns the value associated with `key`. O(1).\n     * Does not revert if `key` is not in the map.\n     */\n    function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) {\n        bytes32 value = map._values[key];\n        if (value == bytes32(0)) {\n            return (contains(map, key), bytes32(0));\n        } else {\n            return (true, value);\n        }\n    }\n\n    /**\n     * @dev Returns the value associated with `key`. O(1).\n     *\n     * Requirements:\n     *\n     * - `key` must be in the map.\n     */\n    function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) {\n        bytes32 value = map._values[key];\n        require(value != 0 || contains(map, key), \"EnumerableMap: nonexistent key\");\n        return value;\n    }\n\n    /**\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryGet}.\n     */\n    function get(\n        Bytes32ToBytes32Map storage map,\n        bytes32 key,\n        string memory errorMessage\n    ) internal view returns (bytes32) {\n        bytes32 value = map._values[key];\n        require(value != 0 || contains(map, key), errorMessage);\n        return value;\n    }\n\n    /**\n     * @dev Return the an array containing all the keys\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) {\n        return map._keys.values();\n    }\n\n    // UintToUintMap\n\n    struct UintToUintMap {\n        Bytes32ToBytes32Map _inner;\n    }\n\n    /**\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\n     * key. O(1).\n     *\n     * Returns true if the key was added to the map, that is if it was not\n     * already present.\n     */\n    function set(UintToUintMap storage map, uint256 key, uint256 value) internal returns (bool) {\n        return set(map._inner, bytes32(key), bytes32(value));\n    }\n\n    /**\n     * @dev Removes a value from a map. O(1).\n     *\n     * Returns true if the key was removed from the map, that is if it was present.\n     */\n    function remove(UintToUintMap storage map, uint256 key) internal returns (bool) {\n        return remove(map._inner, bytes32(key));\n    }\n\n    /**\n     * @dev Returns true if the key is in the map. O(1).\n     */\n    function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) {\n        return contains(map._inner, bytes32(key));\n    }\n\n    /**\n     * @dev Returns the number of elements in the map. O(1).\n     */\n    function length(UintToUintMap storage map) internal view returns (uint256) {\n        return length(map._inner);\n    }\n\n    /**\n     * @dev Returns the element stored at position `index` in the map. O(1).\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) {\n        (bytes32 key, bytes32 value) = at(map._inner, index);\n        return (uint256(key), uint256(value));\n    }\n\n    /**\n     * @dev Tries to returns the value associated with `key`. O(1).\n     * Does not revert if `key` is not in the map.\n     */\n    function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) {\n        (bool success, bytes32 value) = tryGet(map._inner, bytes32(key));\n        return (success, uint256(value));\n    }\n\n    /**\n     * @dev Returns the value associated with `key`. O(1).\n     *\n     * Requirements:\n     *\n     * - `key` must be in the map.\n     */\n    function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) {\n        return uint256(get(map._inner, bytes32(key)));\n    }\n\n    /**\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryGet}.\n     */\n    function get(UintToUintMap storage map, uint256 key, string memory errorMessage) internal view returns (uint256) {\n        return uint256(get(map._inner, bytes32(key), errorMessage));\n    }\n\n    /**\n     * @dev Return the an array containing all the keys\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function keys(UintToUintMap storage map) internal view returns (uint256[] memory) {\n        bytes32[] memory store = keys(map._inner);\n        uint256[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // UintToAddressMap\n\n    struct UintToAddressMap {\n        Bytes32ToBytes32Map _inner;\n    }\n\n    /**\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\n     * key. O(1).\n     *\n     * Returns true if the key was added to the map, that is if it was not\n     * already present.\n     */\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\n        return set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Removes a value from a map. O(1).\n     *\n     * Returns true if the key was removed from the map, that is if it was present.\n     */\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\n        return remove(map._inner, bytes32(key));\n    }\n\n    /**\n     * @dev Returns true if the key is in the map. O(1).\n     */\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\n        return contains(map._inner, bytes32(key));\n    }\n\n    /**\n     * @dev Returns the number of elements in the map. O(1).\n     */\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\n        return length(map._inner);\n    }\n\n    /**\n     * @dev Returns the element stored at position `index` in the map. O(1).\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\n        (bytes32 key, bytes32 value) = at(map._inner, index);\n        return (uint256(key), address(uint160(uint256(value))));\n    }\n\n    /**\n     * @dev Tries to returns the value associated with `key`. O(1).\n     * Does not revert if `key` is not in the map.\n     */\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\n        (bool success, bytes32 value) = tryGet(map._inner, bytes32(key));\n        return (success, address(uint160(uint256(value))));\n    }\n\n    /**\n     * @dev Returns the value associated with `key`. O(1).\n     *\n     * Requirements:\n     *\n     * - `key` must be in the map.\n     */\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\n        return address(uint160(uint256(get(map._inner, bytes32(key)))));\n    }\n\n    /**\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryGet}.\n     */\n    function get(\n        UintToAddressMap storage map,\n        uint256 key,\n        string memory errorMessage\n    ) internal view returns (address) {\n        return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage))));\n    }\n\n    /**\n     * @dev Return the an array containing all the keys\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function keys(UintToAddressMap storage map) internal view returns (uint256[] memory) {\n        bytes32[] memory store = keys(map._inner);\n        uint256[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // AddressToUintMap\n\n    struct AddressToUintMap {\n        Bytes32ToBytes32Map _inner;\n    }\n\n    /**\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\n     * key. O(1).\n     *\n     * Returns true if the key was added to the map, that is if it was not\n     * already present.\n     */\n    function set(AddressToUintMap storage map, address key, uint256 value) internal returns (bool) {\n        return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value));\n    }\n\n    /**\n     * @dev Removes a value from a map. O(1).\n     *\n     * Returns true if the key was removed from the map, that is if it was present.\n     */\n    function remove(AddressToUintMap storage map, address key) internal returns (bool) {\n        return remove(map._inner, bytes32(uint256(uint160(key))));\n    }\n\n    /**\n     * @dev Returns true if the key is in the map. O(1).\n     */\n    function contains(AddressToUintMap storage map, address key) internal view returns (bool) {\n        return contains(map._inner, bytes32(uint256(uint160(key))));\n    }\n\n    /**\n     * @dev Returns the number of elements in the map. O(1).\n     */\n    function length(AddressToUintMap storage map) internal view returns (uint256) {\n        return length(map._inner);\n    }\n\n    /**\n     * @dev Returns the element stored at position `index` in the map. O(1).\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) {\n        (bytes32 key, bytes32 value) = at(map._inner, index);\n        return (address(uint160(uint256(key))), uint256(value));\n    }\n\n    /**\n     * @dev Tries to returns the value associated with `key`. O(1).\n     * Does not revert if `key` is not in the map.\n     */\n    function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) {\n        (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key))));\n        return (success, uint256(value));\n    }\n\n    /**\n     * @dev Returns the value associated with `key`. O(1).\n     *\n     * Requirements:\n     *\n     * - `key` must be in the map.\n     */\n    function get(AddressToUintMap storage map, address key) internal view returns (uint256) {\n        return uint256(get(map._inner, bytes32(uint256(uint160(key)))));\n    }\n\n    /**\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryGet}.\n     */\n    function get(\n        AddressToUintMap storage map,\n        address key,\n        string memory errorMessage\n    ) internal view returns (uint256) {\n        return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage));\n    }\n\n    /**\n     * @dev Return the an array containing all the keys\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function keys(AddressToUintMap storage map) internal view returns (address[] memory) {\n        bytes32[] memory store = keys(map._inner);\n        address[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // Bytes32ToUintMap\n\n    struct Bytes32ToUintMap {\n        Bytes32ToBytes32Map _inner;\n    }\n\n    /**\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\n     * key. O(1).\n     *\n     * Returns true if the key was added to the map, that is if it was not\n     * already present.\n     */\n    function set(Bytes32ToUintMap storage map, bytes32 key, uint256 value) internal returns (bool) {\n        return set(map._inner, key, bytes32(value));\n    }\n\n    /**\n     * @dev Removes a value from a map. O(1).\n     *\n     * Returns true if the key was removed from the map, that is if it was present.\n     */\n    function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) {\n        return remove(map._inner, key);\n    }\n\n    /**\n     * @dev Returns true if the key is in the map. O(1).\n     */\n    function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) {\n        return contains(map._inner, key);\n    }\n\n    /**\n     * @dev Returns the number of elements in the map. O(1).\n     */\n    function length(Bytes32ToUintMap storage map) internal view returns (uint256) {\n        return length(map._inner);\n    }\n\n    /**\n     * @dev Returns the element stored at position `index` in the map. O(1).\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) {\n        (bytes32 key, bytes32 value) = at(map._inner, index);\n        return (key, uint256(value));\n    }\n\n    /**\n     * @dev Tries to returns the value associated with `key`. O(1).\n     * Does not revert if `key` is not in the map.\n     */\n    function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) {\n        (bool success, bytes32 value) = tryGet(map._inner, key);\n        return (success, uint256(value));\n    }\n\n    /**\n     * @dev Returns the value associated with `key`. O(1).\n     *\n     * Requirements:\n     *\n     * - `key` must be in the map.\n     */\n    function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) {\n        return uint256(get(map._inner, key));\n    }\n\n    /**\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryGet}.\n     */\n    function get(\n        Bytes32ToUintMap storage map,\n        bytes32 key,\n        string memory errorMessage\n    ) internal view returns (uint256) {\n        return uint256(get(map._inner, key, errorMessage));\n    }\n\n    /**\n     * @dev Return the an array containing all the keys\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function keys(Bytes32ToUintMap storage map) internal view returns (bytes32[] memory) {\n        bytes32[] memory store = keys(map._inner);\n        bytes32[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts-v4/contracts/utils/Arrays.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Arrays.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./StorageSlot.sol\";\nimport \"./math/Math.sol\";\n\n/**\n * @dev Collection of functions related to array types.\n */\nlibrary Arrays {\n    using StorageSlot for bytes32;\n\n    /**\n     * @dev Searches a sorted `array` and returns the first index that contains\n     * a value greater or equal to `element`. If no such index exists (i.e. all\n     * values in the array are strictly less than `element`), the array length is\n     * returned. Time complexity O(log n).\n     *\n     * `array` is expected to be sorted in ascending order, and to contain no\n     * repeated elements.\n     */\n    function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\n        if (array.length == 0) {\n            return 0;\n        }\n\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds down (it does integer division with truncation).\n            if (unsafeAccess(array, mid).value > element) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n\n        // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.\n        if (low > 0 && unsafeAccess(array, low - 1).value == element) {\n            return low - 1;\n        } else {\n            return low;\n        }\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {\n        bytes32 slot;\n        // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`\n        // following https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html#mappings-and-dynamic-arrays.\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0, arr.slot)\n            slot := add(keccak256(0, 0x20), pos)\n        }\n        return slot.getAddressSlot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {\n        bytes32 slot;\n        // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`\n        // following https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html#mappings-and-dynamic-arrays.\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0, arr.slot)\n            slot := add(keccak256(0, 0x20), pos)\n        }\n        return slot.getBytes32Slot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {\n        bytes32 slot;\n        // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`\n        // following https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html#mappings-and-dynamic-arrays.\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0, arr.slot)\n            slot := add(keccak256(0, 0x20), pos)\n        }\n        return slot.getUint256Slot();\n    }\n}\n"},{"file_path":"contracts/bridge/asset-router/IAssetRouterBase.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.28;\n\nimport {IBridgehub} from \"../../bridgehub/IBridgehub.sol\";\n\n/// @dev The encoding version used for legacy txs.\nbytes1 constant LEGACY_ENCODING_VERSION = 0x00;\n\n/// @dev The encoding version used for new txs.\nbytes1 constant NEW_ENCODING_VERSION = 0x01;\n\n/// @dev The encoding version used for txs that set the asset handler on the counterpart contract.\nbytes1 constant SET_ASSET_HANDLER_COUNTERPART_ENCODING_VERSION = 0x02;\n\n/// @title L1 Bridge contract interface\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\ninterface IAssetRouterBase {\n    event BridgehubDepositBaseTokenInitiated(\n        uint256 indexed chainId,\n        address indexed from,\n        bytes32 assetId,\n        uint256 amount\n    );\n\n    event BridgehubDepositInitiated(\n        uint256 indexed chainId,\n        bytes32 indexed txDataHash,\n        address indexed from,\n        bytes32 assetId,\n        bytes bridgeMintCalldata\n    );\n\n    event BridgehubWithdrawalInitiated(\n        uint256 chainId,\n        address indexed sender,\n        bytes32 indexed assetId,\n        bytes32 assetDataHash // Todo: What's the point of emitting hash?\n    );\n\n    event AssetDeploymentTrackerRegistered(\n        bytes32 indexed assetId,\n        bytes32 indexed additionalData,\n        address assetDeploymentTracker\n    );\n\n    event AssetHandlerRegistered(bytes32 indexed assetId, address indexed _assetHandlerAddress);\n\n    event DepositFinalizedAssetRouter(uint256 indexed chainId, bytes32 indexed assetId, bytes assetData);\n\n    function BRIDGE_HUB() external view returns (IBridgehub);\n\n    function L1_CHAIN_ID() external view returns (uint256);\n\n    /// @notice Sets the asset handler address for a specified asset ID on the chain of the asset deployment tracker.\n    /// @dev The caller of this function is encoded within the `assetId`, therefore, it should be invoked by the asset deployment tracker contract.\n    /// @dev No access control on the caller, as msg.sender is encoded in the assetId.\n    /// @dev Typically, for most tokens, ADT is the native token vault. However, custom tokens may have their own specific asset deployment trackers.\n    /// @dev `setAssetHandlerAddressOnCounterpart` should be called on L1 to set asset handlers on L2 chains for a specific asset ID.\n    /// @param _assetRegistrationData The asset data which may include the asset address and any additional required data or encodings.\n    /// @param _assetHandlerAddress The address of the asset handler to be set for the provided asset.\n    function setAssetHandlerAddressThisChain(bytes32 _assetRegistrationData, address _assetHandlerAddress) external;\n\n    function assetHandlerAddress(bytes32 _assetId) external view returns (address);\n\n    /// @notice Finalize the withdrawal and release funds.\n    /// @param _chainId The chain ID of the transaction to check.\n    /// @param _assetId The bridged asset ID.\n    /// @param _transferData The position in the L2 logs Merkle tree of the l2Log that was sent with the message.\n    /// @dev We have both the legacy finalizeWithdrawal and the new finalizeDeposit functions,\n    /// finalizeDeposit uses the new format. On the L2 we have finalizeDeposit with new and old formats both.\n    function finalizeDeposit(uint256 _chainId, bytes32 _assetId, bytes memory _transferData) external payable;\n}\n"},{"file_path":"contracts/state-transition/chain-interfaces/IExecutor.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {IZKChainBase} from \"./IZKChainBase.sol\";\n\n/// @dev Enum used by L2 System Contracts to differentiate logs.\nenum SystemLogKey {\n    L2_TO_L1_LOGS_TREE_ROOT_KEY,\n    PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEY,\n    CHAINED_PRIORITY_TXN_HASH_KEY,\n    NUMBER_OF_LAYER_1_TXS_KEY,\n    // Note, that it is important that `PREV_BATCH_HASH_KEY` has position\n    // `4` since it is the same as it was in the previous protocol version and\n    // it is the only one that is emitted before the system contracts are upgraded.\n    PREV_BATCH_HASH_KEY,\n    L2_DA_VALIDATOR_OUTPUT_HASH_KEY,\n    USED_L2_DA_VALIDATOR_ADDRESS_KEY,\n    MESSAGE_ROOT_ROLLING_HASH_KEY,\n    L2_TXS_STATUS_ROLLING_HASH_KEY,\n    EXPECTED_SYSTEM_CONTRACT_UPGRADE_TX_HASH_KEY\n}\n\nstruct LogProcessingOutput {\n    uint256 numberOfLayer1Txs;\n    bytes32 chainedPriorityTxsHash;\n    bytes32 previousBatchHash;\n    bytes32 pubdataHash;\n    bytes32 stateDiffHash;\n    bytes32 l2LogsTreeRoot;\n    uint256 packedBatchAndL2BlockTimestamp;\n    bytes32 l2DAValidatorOutputHash;\n    bytes32 l2TxsStatusRollingHash;\n    bytes32 dependencyRootsRollingHash;\n}\n\n/// @dev Maximal value that SystemLogKey variable can have.\nuint256 constant MAX_LOG_KEY = uint256(type(SystemLogKey).max);\n\n/// @dev Offset used to pull Address From Log. Equal to 4 (bytes for shardId, isService and txNumberInBatch)\nuint256 constant L2_LOG_ADDRESS_OFFSET = 4;\n\n/// @dev Offset used to pull Key From Log. Equal to 4 (bytes for shardId, isService and txNumberInBatch) + 20 (bytes for address)\nuint256 constant L2_LOG_KEY_OFFSET = 24;\n\n/// @dev Offset used to pull Value From Log. Equal to 4 (bytes for shardId, isService and txNumberInBatch) + 20 (bytes for address) + 32 (bytes for key)\nuint256 constant L2_LOG_VALUE_OFFSET = 56;\n\n/// @dev Max number of blobs currently supported\nuint256 constant MAX_NUMBER_OF_BLOBS = 6;\n\n/// @dev The number of blobs that must be present in the commitment to a batch.\n/// It represents the maximal number of blobs that circuits can support and can be larger\n/// than the maximal number of blobs supported by the contract (`MAX_NUMBER_OF_BLOBS`).\nuint256 constant TOTAL_BLOBS_IN_COMMITMENT = 16;\n\n/// @title The interface of the ZKsync Executor contract capable of processing events emitted in the ZKsync protocol.\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\ninterface IExecutor is IZKChainBase {\n    /// @notice Rollup batch stored data\n    /// @param batchNumber Rollup batch number\n    /// @param batchHash Hash of L2 batch\n    /// @param indexRepeatedStorageChanges The serial number of the shortcut index that's used as a unique identifier for storage keys that were used twice or more\n    /// @param numberOfLayer1Txs Number of priority operations to be processed\n    /// @param priorityOperationsHash Hash of all priority operations from this batch\n    /// @param l2LogsTreeRoot Root hash of tree that contains L2 -> L1 messages from this batch\n    /// @param timestamp Rollup batch timestamp, have the same format as Ethereum batch constant\n    /// @param commitment Verified input for the ZKsync circuit\n    // solhint-disable-next-line gas-struct-packing\n    struct StoredBatchInfo {\n        uint64 batchNumber;\n        bytes32 batchHash;\n        uint64 indexRepeatedStorageChanges;\n        uint256 numberOfLayer1Txs;\n        bytes32 priorityOperationsHash;\n        bytes32 dependencyRootsRollingHash;\n        bytes32 l2LogsTreeRoot;\n        uint256 timestamp;\n        bytes32 commitment;\n    }\n\n    /// @notice Legacy StoredBatchInfo struct\n    /// @dev dependencyRootsRollingHash is not included in the struct\n    // solhint-disable-next-line gas-struct-packing\n    struct LegacyStoredBatchInfo {\n        uint64 batchNumber;\n        bytes32 batchHash;\n        uint64 indexRepeatedStorageChanges;\n        uint256 numberOfLayer1Txs;\n        bytes32 priorityOperationsHash;\n        bytes32 l2LogsTreeRoot;\n        uint256 timestamp;\n        bytes32 commitment;\n    }\n\n    /// @notice Data needed to commit new batch\n    /// @param batchNumber Number of the committed batch\n    /// @param timestamp Unix timestamp denoting the start of the batch execution\n    /// @param indexRepeatedStorageChanges The serial number of the shortcut index that's used as a unique identifier for storage keys that were used twice or more\n    /// @param newStateRoot The state root of the full state tree\n    /// @param numberOfLayer1Txs Number of priority operations to be processed\n    /// @param priorityOperationsHash Hash of all priority operations from this batch\n    /// @param bootloaderHeapInitialContentsHash Hash of the initial contents of the bootloader heap. In practice it serves as the commitment to the transactions in the batch.\n    /// @param eventsQueueStateHash Hash of the events queue state. In practice it serves as the commitment to the events in the batch.\n    /// @param systemLogs concatenation of all L2 -> L1 system logs in the batch\n    /// @param operatorDAInput Packed pubdata commitments/data.\n    /// @dev pubdataCommitments format: This will always start with a 1 byte pubdataSource flag. Current allowed values are 0 (calldata) or 1 (blobs)\n    ///                             kzg: list of: opening point (16 bytes) || claimed value (32 bytes) || commitment (48 bytes) || proof (48 bytes) = 144 bytes\n    ///                             calldata: pubdataCommitments.length - 1 - 32 bytes of pubdata\n    ///                                       and 32 bytes appended to serve as the blob commitment part for the aux output part of the batch commitment\n    /// @dev For 2 blobs we will be sending 288 bytes of calldata instead of the full amount for pubdata.\n    /// @dev When using calldata, we only need to send one blob commitment since the max number of bytes in calldata fits in a single blob and we can pull the\n    ///     linear hash from the system logs\n    struct CommitBatchInfo {\n        uint64 batchNumber;\n        uint64 timestamp;\n        uint64 indexRepeatedStorageChanges;\n        bytes32 newStateRoot;\n        uint256 numberOfLayer1Txs;\n        bytes32 priorityOperationsHash;\n        bytes32 bootloaderHeapInitialContentsHash;\n        bytes32 eventsQueueStateHash;\n        bytes systemLogs;\n        bytes operatorDAInput;\n    }\n\n    /// @notice Container for a list of transaction statuses to precommit.\n    /// @param txs A packed array of individual transaction status commitments for the batch. Each is expected to be\n    /// of length 33 and have the following format: <32-byte tx hash, 1-byte status>. where status is either 0 (failed) or 1 (success).\n    /// @param untrustedLastL2BlockNumberHint The \"hint\" for what the last L2 block number that these txs represent is.\n    struct PrecommitInfo {\n        bytes packedTxsCommitments;\n        uint256 untrustedLastL2BlockNumberHint;\n    }\n\n    /// @notice Precommits the status of all L2 transactions for the next batch on the shared bridge.\n    /// @param _chainAddress The address of the DiamondProxy of the chain. Note, that it is not used in the implementation,\n    /// because it is expected to be equal to the `address(this)`, but it is kept here to maintain the same interface on both\n    /// `ValidatorTimelock` and `Executor` for easier and cheaper implementation of the timelock.\n    /// @param _batchNumber The sequential batch number to precommit (must equal `s.totalBatchesCommitted + 1`).\n    /// @param _precommitData ABI‐encoded transaction status list for the precommit.\n    function precommitSharedBridge(address _chainAddress, uint256 _batchNumber, bytes calldata _precommitData) external;\n\n    /// @notice Function called by the operator to commit new batches. It is responsible for:\n    /// - Verifying the correctness of their timestamps.\n    /// - Processing their L2->L1 logs.\n    /// - Storing batch commitments.\n    /// @param _chainAddress The address of the DiamondProxy of the chain. Note, that it is not used in the implementation,\n    /// because it is expected to be equal to the `address(this)`, but it is kept here to maintain the same interface on both\n    /// `ValidatorTimelock` and `Executor` for easier and cheaper implementation of the timelock.\n    /// @param _processFrom The batch number from which the processing starts.\n    /// @param _processTo The batch number at which the processing ends.\n    /// @param _commitData The encoded data of the new batches to be committed.\n    function commitBatchesSharedBridge(\n        address _chainAddress,\n        uint256 _processFrom,\n        uint256 _processTo,\n        bytes calldata _commitData\n    ) external;\n\n    /// @notice Batches commitment verification.\n    /// @dev Only verifies batch commitments without any other processing.\n    /// @param _chainAddress The address of the DiamondProxy of the chain. Note, that it is not used in the implementation,\n    /// because it is expected to be equal to the `address(this)`, but it is kept here to maintain the same interface on both\n    /// `ValidatorTimelock` and `Executor` for easier and cheaper implementation of the timelock.\n    /// @param _processBatchFrom The batch number from which the verification starts.\n    /// @param _processBatchTo The batch number at which the verification ends.\n    /// @param _proofData The encoded data of the new batches to be verified.\n    function proveBatchesSharedBridge(\n        address _chainAddress,\n        uint256 _processBatchFrom,\n        uint256 _processBatchTo,\n        bytes calldata _proofData\n    ) external;\n\n    /// @notice The function called by the operator to finalize (execute) batches. It is responsible for:\n    /// - Processing all pending operations (commpleting priority requests).\n    /// - Finalizing this batch (i.e. allowing to withdraw funds from the system)\n    /// @param _chainAddress The address of the DiamondProxy of the chain. Note, that it is not used in the implementation,\n    /// because it is expected to be equal to the `address(this)`, but it is kept here to maintain the same interface on both\n    /// `ValidatorTimelock` and `Executor` for easier and cheaper implementation of the timelock.\n    /// @param _processFrom The batch number from which the execution starts.\n    /// @param _processTo The batch number at which the execution ends.\n    /// @param _executeData The encoded data of the new batches to be executed.\n    function executeBatchesSharedBridge(\n        address _chainAddress,\n        uint256 _processFrom,\n        uint256 _processTo,\n        bytes calldata _executeData\n    ) external;\n\n    /// @notice Reverts unexecuted batches\n    /// @param _chainAddress The address of the DiamondProxy of the chain.\n    /// @param _newLastBatch batch number after which batches should be reverted\n    /// @dev When the _newLastBatch is equal to the number of committed batches,\n    /// only the precommitment is erased.\n    /// NOTE: Doesn't delete the stored data about batches, but only decreases\n    /// counters that are responsible for the number of batches\n    function revertBatchesSharedBridge(address _chainAddress, uint256 _newLastBatch) external;\n\n    /// @notice Event emitted when a batch is committed\n    /// @param batchNumber Number of the batch committed\n    /// @param batchHash Hash of the L2 batch\n    /// @param commitment Calculated input for the ZKsync circuit\n    /// @dev It has the name \"BlockCommit\" and not \"BatchCommit\" due to backward compatibility considerations\n    event BlockCommit(uint256 indexed batchNumber, bytes32 indexed batchHash, bytes32 indexed commitment);\n\n    /// @notice Event emitted when batches are verified\n    /// @param previousLastVerifiedBatch Batch number of the previous last verified batch\n    /// @param currentLastVerifiedBatch Batch number of the current last verified batch\n    /// @dev It has the name \"BlocksVerification\" and not \"BatchesVerification\" due to backward compatibility considerations\n    event BlocksVerification(uint256 indexed previousLastVerifiedBatch, uint256 indexed currentLastVerifiedBatch);\n\n    /// @notice Event emitted when a batch is executed\n    /// @param batchNumber Number of the batch executed\n    /// @param batchHash Hash of the L2 batch\n    /// @param commitment Verified input for the ZKsync circuit\n    /// @dev It has the name \"BlockExecution\" and not \"BatchExecution\" due to backward compatibility considerations\n    event BlockExecution(uint256 indexed batchNumber, bytes32 indexed batchHash, bytes32 indexed commitment);\n\n    /// @notice Event emitted when batches are reverted\n    /// @param totalBatchesCommitted Total number of committed batches after the revert\n    /// @param totalBatchesVerified Total number of verified batches after the revert\n    /// @param totalBatchesExecuted Total number of executed batches\n    /// @dev It has the name \"BlocksRevert\" and not \"BatchesRevert\" due to backward compatibility considerations\n    event BlocksRevert(uint256 totalBatchesCommitted, uint256 totalBatchesVerified, uint256 totalBatchesExecuted);\n\n    /// @notice Emitted when a new precommitment is set for a batch.\n    /// @param batchNumber The batch number for which the precommitment was recorded.\n    /// @param untrustedLastL2BlockNumberHint The hint to what L2 block number the precommitment should correspond to. Note, that there are no\n    /// guarantees on its correctness, it is just a way for the server to make external nodes' indexing simpler.\n    /// @param precommitment The resulting rolling hash of all transaction statuses.\n    event BatchPrecommitmentSet(\n        uint256 indexed batchNumber,\n        uint256 indexed untrustedLastL2BlockNumberHint,\n        bytes32 precommitment\n    );\n}\n"},{"file_path":"lib/openzeppelin-contracts-upgradeable-v4/contracts/utils/AddressUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\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, it is bubbled up by this\n     * function (like regular Solidity function calls).\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     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\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     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) 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            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts-upgradeable-v4/contracts/access/OwnableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../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 * By default, the owner account will be the one that deploys the contract. This\n * can 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    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\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        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\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        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\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        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"},{"file_path":"contracts/bridgehub/L1BridgehubErrors.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.21;\n\n// 0x587df426\nerror AlreadyCurrentSL(uint256 blockChainId);\n// 0x65e8a019\nerror ChainExists();\n// 0xff514c10\nerror ChainIdAlreadyPresent();\n// 0x5de72107\nerror ChainNotLegacy();\n// 0x4bd4ae07\nerror ChainNotPresentInCTM();\n// 0xeab895aa\nerror HyperchainNotRegistered();\n// 0x48857c1d\nerror IncorrectChainAssetId(bytes32 assetId, bytes32 assetIdFromChainId);\n// 0xf5e39c1f\nerror IncorrectSender(address prevMsgSender, address chainAdmin);\n// 0x913183d8\nerror MessageRootNotRegistered();\n// 0x7f4316f3\nerror NoEthAllowed();\n// 0xf306a770\nerror NotAssetRouter(address msgSender, address sharedBridge);\n// 0x8beee3a3\nerror NotChainAssetHandler(address sender, address chainAssetHandler);\n// 0xc0ca9182\nerror NotCurrentSL(uint256 settlementLayerChainId, uint256 blockChainId);\n// 0x472477e2\nerror NotInGatewayMode();\n// 0xecb34449\nerror NotL1(uint256 l1ChainId, uint256 blockChainId);\n// 0x8eb4fc01\nerror NotL2();\n// 0x23295f0e\nerror NotOwner(address sender, address owner);\n// 0x693cd3dc\nerror NotOwnerViaRouter(address msgSender, address originalCaller);\n// 0xa2ac02a0\nerror NotRelayedSender(address msgSender, address settlementLayerRelaySender);\n// 0x527b87c7\nerror OnlyBridgehub(address msgSender, address bridgehub);\n// 0x2d396674\nerror OnlyBridgehubOrChainAssetHandler(address sender, address bridgehub, address chainAssetHandler);\n// 0x73fe6c1b\nerror OnlyChain(address msgSender, address zkChainAddress);\n// 0xb78dbaa7\nerror SecondBridgeAddressTooLow(address secondBridgeAddress, address minSecondBridgeAddress);\n// 0x90c7cbf1\nerror SLNotWhitelisted();\n// 0x36917565\nerror SLHasDifferentCTM();\n// 0x92626457\nerror WrongCounterPart(address addressOnCounterPart, address l2BridgehubAddress);\n"},{"file_path":"contracts/state-transition/chain-interfaces/IVerifier.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\n/// @notice Part of the configuration parameters of ZKP circuits\nstruct VerifierParams {\n    bytes32 recursionNodeLevelVkHash;\n    bytes32 recursionLeafLevelVkHash;\n    bytes32 recursionCircuitsSetVksHash;\n}\n\n/// @title The interface of the Verifier contract, responsible for the zero knowledge proof verification.\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\ninterface IVerifier {\n    /// @dev Verifies a zk-SNARK proof.\n    /// @return A boolean value indicating whether the zk-SNARK proof is valid.\n    /// Note: The function may revert execution instead of returning false in some cases.\n    function verify(uint256[] calldata _publicInputs, uint256[] calldata _proof) external view returns (bool);\n\n    /// @notice Calculates a keccak256 hash of the runtime loaded verification keys.\n    /// @return vkHash The keccak256 hash of the loaded verification keys.\n    function verificationKeyHash() external view returns (bytes32);\n}\n"},{"file_path":"contracts/bridge/ntv/INativeTokenVault.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.28;\n\nimport {IAssetRouterBase} from \"../asset-router/IAssetRouterBase.sol\";\n\n/// @title Base Native token vault contract interface\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\n/// @notice The NTV is an Asset Handler for the L1AssetRouter to handle native tokens\ninterface INativeTokenVault {\n    event BridgedTokenBeaconUpdated(address bridgedTokenBeacon, bytes32 bridgedTokenProxyBytecodeHash);\n\n    /// @notice The Weth token address\n    function WETH_TOKEN() external view returns (address);\n\n    /// @notice The AssetRouter contract\n    function ASSET_ROUTER() external view returns (IAssetRouterBase);\n\n    /// @notice The chain ID of the L1 chain\n    function L1_CHAIN_ID() external view returns (uint256);\n\n    /// @notice Returns the chain ID of the origin chain for a given asset ID\n    function originChainId(bytes32 assetId) external view returns (uint256);\n\n    /// @notice Registers tokens within the NTV.\n    /// @dev The goal is to allow bridging native tokens automatically, by registering them on the fly.\n    /// @notice Allows the bridge to register a token address for the vault.\n    /// @notice No access control is ok, since the bridging of tokens should be permissionless. This requires permissionless registration.\n    function registerToken(address _l1Token) external;\n\n    /// @notice Ensures that the native token is registered with the NTV.\n    /// @dev This function is used to ensure that the token is registered with the NTV.\n    function ensureTokenIsRegistered(address _nativeToken) external returns (bytes32);\n\n    /// @notice Used to get the the ERC20 data for a token\n    function getERC20Getters(address _token, uint256 _originChainId) external view returns (bytes memory);\n\n    /// @notice Used to get the token address of an assetId\n    function tokenAddress(bytes32 assetId) external view returns (address);\n\n    /// @notice Used to get the assetId of a token\n    function assetId(address token) external view returns (bytes32);\n\n    /// @notice Used to get the expected bridged token address corresponding to its native counterpart\n    function calculateCreate2TokenAddress(uint256 _originChainId, address _originToken) external view returns (address);\n\n    /// @notice Tries to register a token from the provided `_burnData` and reverts if it is not possible.\n    function tryRegisterTokenFromBurnData(bytes calldata _burnData, bytes32 _expectedAssetId) external;\n}\n"},{"file_path":"contracts/bridge/interfaces/IL1AssetDeploymentTracker.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.28;\n\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\ninterface IL1AssetDeploymentTracker {\n    function bridgeCheckCounterpartAddress(\n        uint256 _chainId,\n        bytes32 _assetId,\n        address _originalCaller,\n        address _assetHandlerAddressOnCounterpart\n    ) external view;\n}\n"},{"file_path":"contracts/vendor/AddressAliasHelper.sol","source_code":"// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nlibrary AddressAliasHelper {\n    uint160 private constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n    /// @notice Utility function converts the address that submitted a tx\n    /// to the inbox on L1 to the msg.sender viewed on L2\n    /// @param l1Address the address in the L1 that triggered the tx to L2\n    /// @return l2Address L2 address as viewed in msg.sender\n    function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n        unchecked {\n            l2Address = address(uint160(l1Address) + offset);\n        }\n    }\n\n    /// @notice Utility function that converts the msg.sender viewed on L2 to the\n    /// address that submitted a tx to the inbox on L1\n    /// @param l2Address L2 address as viewed in msg.sender\n    /// @return l1Address the address in the L1 that triggered the tx to L2\n    function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n        unchecked {\n            l1Address = address(uint160(l2Address) - offset);\n        }\n    }\n\n    /// @notice Utility function used to calculate the correct refund recipient\n    /// @param _refundRecipient the address that should receive the refund\n    /// @param _originalCaller the address that triggered the tx to L2\n    /// @return _recipient the corrected address that should receive the refund\n    function actualRefundRecipient(\n        address _refundRecipient,\n        address _originalCaller\n    ) internal view returns (address _recipient) {\n        if (_refundRecipient == address(0)) {\n            // If the `_refundRecipient` is not provided, we use the `_originalCaller` as the recipient.\n            // solhint-disable avoid-tx-origin\n            // slither-disable-next-line tx-origin\n            _recipient = _originalCaller == tx.origin\n                ? _originalCaller\n                : AddressAliasHelper.applyL1ToL2Alias(_originalCaller);\n            // solhint-enable avoid-tx-origin\n        } else if (_refundRecipient.code.length > 0) {\n            // If the `_refundRecipient` is a smart contract, we apply the L1 to L2 alias to prevent foot guns.\n            _recipient = AddressAliasHelper.applyL1ToL2Alias(_refundRecipient);\n        } else {\n            _recipient = _refundRecipient;\n        }\n    }\n}\n"},{"file_path":"contracts/common/l2-helpers/IL2ToL1Messenger.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.20;\n\n/// @dev The log passed from L2\n/// @param l2ShardId The shard identifier, 0 - rollup, 1 - porter. All other values are not used but are reserved for the future\n/// @param isService A boolean flag that is part of the log along with `key`, `value`, and `sender` address.\n/// This field is required formally but does not have any special meaning.\n/// @param txNumberInBlock The L2 transaction number in a block, in which the log was sent\n/// @param sender The L2 address which sent the log\n/// @param key The 32 bytes of information that was sent in the log\n/// @param value The 32 bytes of information that was sent in the log\n// Both `key` and `value` are arbitrary 32-bytes selected by the log sender\nstruct L2ToL1Log {\n    uint8 l2ShardId;\n    bool isService;\n    uint16 txNumberInBlock;\n    address sender;\n    bytes32 key;\n    bytes32 value;\n}\n\n/// @dev Bytes in raw L2 to L1 log\n/// @dev Equal to the bytes size of the tuple - (uint8 ShardId, bool isService, uint16 txNumberInBlock, address sender, bytes32 key, bytes32 value)\nuint256 constant L2_TO_L1_LOG_SERIALIZE_SIZE = 88;\n\n/// @dev The value of default leaf hash for L2 to L1 logs Merkle tree\n/// @dev An incomplete fixed-size tree is filled with this value to be a full binary tree\n/// @dev Actually equal to the `keccak256(new bytes(L2_TO_L1_LOG_SERIALIZE_SIZE))`\nbytes32 constant L2_L1_LOGS_TREE_DEFAULT_LEAF_HASH = 0x72abee45b59e344af8a6e520241c4744aff26ed411f4c4b00f8af09adada43ba;\n\n/// @dev The current version of state diff compression being used.\nuint256 constant STATE_DIFF_COMPRESSION_VERSION_NUMBER = 1;\n\n/**\n * @author Matter Labs\n * @custom:security-contact security@matterlabs.dev\n * @notice The interface of the L1 Messenger contract, responsible for sending messages to L1.\n * @dev by default ZkSync can send fixed-length messages on L1.\n * A fixed length message has 4 parameters `senderAddress`, `isService`, `key`, `value`,\n * the first one is taken from the context, the other three are chosen by the sender.\n * @dev To send a variable-length message we use this trick:\n * - This system contract accepts an arbitrary length message and sends a fixed length message with\n * parameters `senderAddress == this`, `isService == true`, `key == msg.sender`, `value == keccak256(message)`.\n * - The contract on L1 accepts all sent messages and if the message came from this system contract\n * it requires the preimage of `value` to be provided.\n */\ninterface IL2ToL1Messenger {\n    // Possibly in the future we will be able to track the messages sent to L1 with\n    // some hooks in the VM. For now, it is much easier to track them with L2 events.\n    event L1MessageSent(address indexed _sender, bytes32 indexed _hash, bytes _message);\n\n    /// @notice Sends an arbitrary length message to L1.\n    /// @param _message The variable length message to be sent to L1.\n    /// @return Returns the keccak256 hashed value of the message.\n    function sendToL1(bytes calldata _message) external returns (bytes32);\n\n    /// @notice Sends L2ToL1Log.\n    /// @param _isService The `isService` flag.\n    /// @param _key The `key` part of the L2Log.\n    /// @param _value The `value` part of the L2Log.\n    /// @dev Can be called only by a system contract.\n    function sendL2ToL1Log(bool _isService, bytes32 _key, bytes32 _value) external returns (uint256 logIdInMerkleTree);\n\n    /// @notice This function is expected to be called only by the KnownCodesStorage system contract\n    function requestBytecodeL1Publication(bytes32 _bytecodeHash) external;\n}\n"},{"file_path":"contracts/common/l2-helpers/L2ContractAddresses.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {IL2ToL1Messenger} from \"./IL2ToL1Messenger.sol\";\nimport {IL2InteropRootStorage} from \"../interfaces/IL2InteropRootStorage.sol\";\nimport {IMessageVerification} from \"../../state-transition/chain-interfaces/IMessageVerification.sol\";\n\n/// @dev the offset for the system contracts\nuint160 constant SYSTEM_CONTRACTS_OFFSET = 0x8000; // 2^15\n\n/// @dev The offset from which the built-in, but user space contracts are located.\nuint160 constant USER_CONTRACTS_OFFSET = 0x10000; // 2^16\n\n/// @dev The formal address of the initial program of the system: the bootloader\naddress constant L2_BOOTLOADER_ADDRESS = address(SYSTEM_CONTRACTS_OFFSET + 0x01);\n\n/// @dev The address of the known code storage system contract\naddress constant L2_KNOWN_CODE_STORAGE_SYSTEM_CONTRACT_ADDR = address(SYSTEM_CONTRACTS_OFFSET + 0x04);\n\n/// @dev The address of the L2 deployer system contract.\naddress constant L2_DEPLOYER_SYSTEM_CONTRACT_ADDR = address(SYSTEM_CONTRACTS_OFFSET + 0x06);\n\n/// @dev The special reserved L2 address. It is located in the system contracts space but doesn't have deployed\n/// bytecode.\n/// @dev The L2 deployer system contract allows changing bytecodes on any address if the `msg.sender` is this address.\n/// @dev So, whenever the governor wants to redeploy system contracts, it just initiates the L1 upgrade call deployer\n/// system contract\n/// via the L1 -> L2 transaction with `sender == L2_FORCE_DEPLOYER_ADDR`. For more details see the\n/// `diamond-initializers` contracts.\naddress constant L2_FORCE_DEPLOYER_ADDR = address(SYSTEM_CONTRACTS_OFFSET + 0x07);\n\n/// @dev The address of the L2ToL1Messenger system contract\naddress constant L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR = address(SYSTEM_CONTRACTS_OFFSET + 0x08);\n/// @dev The address of the special smart contract that can send arbitrary length message as an L2 log\nIL2ToL1Messenger constant L2_TO_L1_MESSENGER_SYSTEM_CONTRACT = IL2ToL1Messenger(\n    L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR\n);\n\n/// @dev The address of the eth token system contract\naddress constant L2_BASE_TOKEN_SYSTEM_CONTRACT_ADDR = address(SYSTEM_CONTRACTS_OFFSET + 0x0a);\n\n/// @dev The address of the context system contract\naddress constant L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR = address(SYSTEM_CONTRACTS_OFFSET + 0x0b);\n\n/// @dev The address of the pubdata chunk publisher contract\naddress constant L2_PUBDATA_CHUNK_PUBLISHER_ADDR = address(SYSTEM_CONTRACTS_OFFSET + 0x11);\n\n/// @dev The address used to execute complex upgragedes, also used for the genesis upgrade\naddress constant L2_COMPLEX_UPGRADER_ADDR = address(SYSTEM_CONTRACTS_OFFSET + 0x0f);\n\n/// @dev the address of the msg value system contract\naddress constant MSG_VALUE_SYSTEM_CONTRACT = address(SYSTEM_CONTRACTS_OFFSET + 0x09);\n\n/// @dev The address of the create2 factory contract\naddress constant L2_CREATE2_FACTORY_ADDR = address(USER_CONTRACTS_OFFSET + 0x00);\n\n/// @dev The address used to execute the genesis upgrade\naddress constant L2_GENESIS_UPGRADE_ADDR = address(USER_CONTRACTS_OFFSET + 0x01);\n\n/// @dev The genesis upgrade address is reused for all version specific upgrades\naddress constant L2_VERSION_SPECIFIC_UPGRADER_ADDR = L2_GENESIS_UPGRADE_ADDR;\n\n/// @dev The address of the L2 bridge hub system contract, used to start L1->L2 transactions\naddress constant L2_BRIDGEHUB_ADDR = address(USER_CONTRACTS_OFFSET + 0x02);\n\n/// @dev the address of the l2 asset router.\naddress constant L2_ASSET_ROUTER_ADDR = address(USER_CONTRACTS_OFFSET + 0x03);\n\n/// @dev An l2 system contract address, used in the assetId calculation for native assets.\n/// This is needed for automatic bridging, i.e. without deploying the AssetHandler contract,\n/// if the assetId can be calculated with this address then it is in fact an NTV asset\naddress constant L2_NATIVE_TOKEN_VAULT_ADDR = address(USER_CONTRACTS_OFFSET + 0x04);\n\n/// @dev the address of the l2 asset router.\naddress constant L2_MESSAGE_ROOT_ADDR = address(USER_CONTRACTS_OFFSET + 0x05);\n\n/// @dev The address of the SloadContract system contract, which provides a method to read values from arbitrary storage slots\naddress constant SLOAD_CONTRACT_ADDR = address(USER_CONTRACTS_OFFSET + 0x06);\n\n/// @dev The address of the WETH implementation contract\naddress constant L2_WETH_IMPL_ADDR = address(USER_CONTRACTS_OFFSET + 0x07);\n\n/// @dev The address of the L2 interop root storage system contract\nIL2InteropRootStorage constant L2_INTEROP_ROOT_STORAGE = IL2InteropRootStorage(address(USER_CONTRACTS_OFFSET + 0x08));\n\n/// @dev The address of the L2 message verification system contract\nIMessageVerification constant L2_MESSAGE_VERIFICATION = IMessageVerification(address(USER_CONTRACTS_OFFSET + 0x09));\n\n/// @dev The address of the L2 chain handler system contract\naddress constant L2_CHAIN_ASSET_HANDLER_ADDR = address(USER_CONTRACTS_OFFSET + 0x0a);\n"},{"file_path":"contracts/state-transition/libraries/PriorityTree.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the zkSync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {DynamicIncrementalMerkle} from \"../../common/libraries/DynamicIncrementalMerkle.sol\";\nimport {Merkle} from \"../../common/libraries/Merkle.sol\";\nimport {PriorityTreeCommitment} from \"../../common/Config.sol\";\nimport {InvalidCommitment, InvalidNextLeafIndex, InvalidStartIndex, InvalidUnprocessedIndex, NotHistoricalRoot} from \"../L1StateTransitionErrors.sol\";\n\nstruct PriorityOpsBatchInfo {\n    bytes32[] leftPath;\n    bytes32[] rightPath;\n    bytes32[] itemHashes;\n}\n\nbytes32 constant ZERO_LEAF_HASH = keccak256(\"\");\n\nlibrary PriorityTree {\n    using PriorityTree for Tree;\n    using DynamicIncrementalMerkle for DynamicIncrementalMerkle.Bytes32PushTree;\n\n    struct Tree {\n        uint256 startIndex; // priority tree started accepting priority ops from this index\n        uint256 unprocessedIndex; // relative to `startIndex`\n        mapping(bytes32 => bool) historicalRoots;\n        DynamicIncrementalMerkle.Bytes32PushTree tree;\n    }\n\n    /// @notice Returns zero if and only if no operations were processed from the tree\n    /// @return Index of the oldest priority operation that wasn't processed yet\n    function getFirstUnprocessedPriorityTx(Tree storage _tree) internal view returns (uint256) {\n        return _tree.startIndex + _tree.unprocessedIndex;\n    }\n\n    /// @return The total number of priority operations that were added to the priority queue, including all processed ones\n    function getTotalPriorityTxs(Tree storage _tree) internal view returns (uint256) {\n        return _tree.startIndex + _tree.tree._nextLeafIndex;\n    }\n\n    /// @return The total number of unprocessed priority operations in a priority queue\n    function getSize(Tree storage _tree) internal view returns (uint256) {\n        return _tree.tree._nextLeafIndex - _tree.unprocessedIndex;\n    }\n\n    /// @notice Add the priority operation to the end of the priority queue\n    function push(Tree storage _tree, bytes32 _hash) internal {\n        (, bytes32 newRoot) = _tree.tree.push(_hash);\n        _tree.historicalRoots[newRoot] = true;\n    }\n\n    /// @notice Set up the tree\n    function setup(Tree storage _tree, uint256 _startIndex) internal {\n        bytes32 initialRoot = _tree.tree.setup(ZERO_LEAF_HASH);\n        _tree.historicalRoots[initialRoot] = true;\n        _tree.startIndex = _startIndex;\n    }\n\n    /// @return Returns the tree root.\n    function getRoot(Tree storage _tree) internal view returns (bytes32) {\n        return _tree.tree.root();\n    }\n\n    /// @param _root The root to check.\n    /// @return Returns true if the root is a historical root.\n    function isHistoricalRoot(Tree storage _tree, bytes32 _root) internal view returns (bool) {\n        return _tree.historicalRoots[_root];\n    }\n\n    /// @notice Process the priority operations of a batch.\n    /// @dev Note, that the function below only checks that a certain segment of items is present in the tree.\n    /// It does not check that e.g. there are no zero items inside the provided `itemHashes`, so in theory proofs\n    /// that include non-existing priority operations could be created. This function relies on the fact\n    /// that the `itemHashes` of `_priorityOpsData` are hashes of valid priority transactions.\n    /// This fact is ensured by the fact the rolling hash of those is sent to the Executor by the bootloader\n    /// and so assuming that zero knowledge proofs are correct, so is the structure of the `itemHashes`.\n    function processBatch(Tree storage _tree, PriorityOpsBatchInfo memory _priorityOpsData) internal {\n        if (_priorityOpsData.itemHashes.length > 0) {\n            bytes32 expectedRoot = Merkle.calculateRootPaths(\n                _priorityOpsData.leftPath,\n                _priorityOpsData.rightPath,\n                _tree.unprocessedIndex,\n                _priorityOpsData.itemHashes\n            );\n            if (!_tree.historicalRoots[expectedRoot]) {\n                revert NotHistoricalRoot(expectedRoot);\n            }\n            _tree.unprocessedIndex += _priorityOpsData.itemHashes.length;\n        }\n    }\n\n    /// @notice Allows to skip a certain number of operations.\n    /// @param _lastUnprocessed The new expected id of the unprocessed transaction.\n    /// @dev It is used when the corresponding transactions have been processed by priority queue.\n    function skipUntil(Tree storage _tree, uint256 _lastUnprocessed) internal {\n        if (_tree.startIndex > _lastUnprocessed) {\n            // Nothing to do, return\n            return;\n        }\n        uint256 newUnprocessedIndex = _lastUnprocessed - _tree.startIndex;\n        if (newUnprocessedIndex <= _tree.unprocessedIndex) {\n            // These transactions were already processed, skip.\n            return;\n        }\n\n        _tree.unprocessedIndex = newUnprocessedIndex;\n    }\n\n    /// @notice Initialize a chain from a commitment.\n    function initFromCommitment(Tree storage _tree, PriorityTreeCommitment memory _commitment) internal {\n        uint256 height = _commitment.sides.length; // Height, including the root node.\n        if (height == 0) {\n            revert InvalidCommitment();\n        }\n        _tree.startIndex = _commitment.startIndex;\n        _tree.unprocessedIndex = _commitment.unprocessedIndex;\n        _tree.tree._nextLeafIndex = _commitment.nextLeafIndex;\n        _tree.tree._sides = _commitment.sides;\n        bytes32 zero = ZERO_LEAF_HASH;\n        _tree.tree._zeros = new bytes32[](height);\n        for (uint256 i; i < height; ++i) {\n            _tree.tree._zeros[i] = zero;\n            zero = Merkle.efficientHash(zero, zero);\n        }\n        _tree.historicalRoots[_tree.tree.root()] = true;\n    }\n\n    /// @notice Reinitialize the tree from a commitment on L1.\n    function l1Reinit(Tree storage _tree, PriorityTreeCommitment memory _commitment) internal {\n        if (_tree.startIndex != _commitment.startIndex) {\n            revert InvalidStartIndex(_tree.startIndex, _commitment.startIndex);\n        }\n        if (_tree.unprocessedIndex > _commitment.unprocessedIndex) {\n            revert InvalidUnprocessedIndex(_tree.unprocessedIndex, _commitment.unprocessedIndex);\n        }\n        if (_tree.tree._nextLeafIndex < _commitment.nextLeafIndex) {\n            revert InvalidNextLeafIndex(_tree.tree._nextLeafIndex, _commitment.nextLeafIndex);\n        }\n\n        _tree.unprocessedIndex = _commitment.unprocessedIndex;\n    }\n\n    /// @notice Reinitialize the tree from a commitment on GW.\n    function checkGWReinit(Tree storage _tree, PriorityTreeCommitment memory _commitment) internal view {\n        if (_tree.startIndex != _commitment.startIndex) {\n            revert InvalidStartIndex(_tree.startIndex, _commitment.startIndex);\n        }\n        if (_tree.unprocessedIndex > _commitment.unprocessedIndex) {\n            revert InvalidUnprocessedIndex(_tree.unprocessedIndex, _commitment.unprocessedIndex);\n        }\n        if (_tree.tree._nextLeafIndex > _commitment.nextLeafIndex) {\n            revert InvalidNextLeafIndex(_tree.tree._nextLeafIndex, _commitment.nextLeafIndex);\n        }\n    }\n\n    /// @notice Returns the commitment to the priority tree.\n    function getCommitment(Tree storage _tree) internal view returns (PriorityTreeCommitment memory commitment) {\n        commitment.nextLeafIndex = _tree.tree._nextLeafIndex;\n        commitment.startIndex = _tree.startIndex;\n        commitment.unprocessedIndex = _tree.unprocessedIndex;\n        commitment.sides = _tree.tree._sides;\n    }\n}\n"},{"file_path":"contracts/state-transition/libraries/PriorityQueue.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {QueueIsEmpty} from \"../../common/L1ContractErrors.sol\";\n\n/// @notice The structure that contains meta information of the L2 transaction that was requested from L1\n/// @dev The weird size of fields was selected specifically to minimize the structure storage size\n/// @param canonicalTxHash Hashed L2 transaction data that is needed to process it\n/// @param expirationTimestamp Expiration timestamp for this request (must be satisfied before)\n/// @param layer2Tip Additional payment to the validator as an incentive to perform the operation\nstruct PriorityOperation {\n    bytes32 canonicalTxHash;\n    uint64 expirationTimestamp;\n    uint192 layer2Tip;\n}\n\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\n/// @dev The library provides the API to interact with the priority queue container\n/// @dev Order of processing operations from queue - FIFO (Fist in - first out)\nlibrary PriorityQueue {\n    using PriorityQueue for Queue;\n\n    /// @notice Container that stores priority operations\n    /// @param data The inner mapping that saves priority operation by its index\n    /// @param head The pointer to the first unprocessed priority operation, equal to the tail if the queue is empty\n    /// @param tail The pointer to the free slot\n    struct Queue {\n        mapping(uint256 priorityOpId => PriorityOperation priorityOp) data;\n        uint256 tail;\n        uint256 head;\n    }\n\n    /// @notice Returns zero if and only if no operations were processed from the queue\n    /// @return Index of the oldest priority operation that wasn't processed yet\n    function getFirstUnprocessedPriorityTx(Queue storage _queue) internal view returns (uint256) {\n        return _queue.head;\n    }\n\n    /// @return The total number of priority operations that were added to the priority queue, including all processed ones\n    function getTotalPriorityTxs(Queue storage _queue) internal view returns (uint256) {\n        return _queue.tail;\n    }\n\n    /// @return The total number of unprocessed priority operations in a priority queue\n    function getSize(Queue storage _queue) internal view returns (uint256) {\n        return uint256(_queue.tail - _queue.head);\n    }\n\n    /// @return Whether the priority queue contains no operations\n    function isEmpty(Queue storage _queue) internal view returns (bool) {\n        return _queue.tail == _queue.head;\n    }\n\n    /// @notice Add the priority operation to the end of the priority queue\n    function pushBack(Queue storage _queue, PriorityOperation memory _operation) internal {\n        // Save value into the stack to avoid double reading from the storage\n        uint256 tail = _queue.tail;\n\n        _queue.data[tail] = _operation;\n        _queue.tail = tail + 1;\n    }\n\n    /// @return The first unprocessed priority operation from the queue\n    function front(Queue storage _queue) internal view returns (PriorityOperation memory) {\n        // priority queue is empty\n        if (_queue.isEmpty()) {\n            revert QueueIsEmpty();\n        }\n\n        return _queue.data[_queue.head];\n    }\n\n    /// @notice Remove the first unprocessed priority operation from the queue\n    /// @return priorityOperation that was popped from the priority queue\n    function popFront(Queue storage _queue) internal returns (PriorityOperation memory priorityOperation) {\n        // priority queue is empty\n        if (_queue.isEmpty()) {\n            revert QueueIsEmpty();\n        }\n\n        // Save value into the stack to avoid double reading from the storage\n        uint256 head = _queue.head;\n\n        priorityOperation = _queue.data[head];\n        delete _queue.data[head];\n        _queue.head = head + 1;\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts-upgradeable-v4/contracts/utils/ContextUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\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    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n"},{"file_path":"contracts/state-transition/chain-interfaces/IGetters.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {VerifierParams} from \"../chain-interfaces/IVerifier.sol\";\nimport {PubdataPricingMode} from \"../chain-deps/ZKChainStorage.sol\";\nimport {IZKChainBase} from \"./IZKChainBase.sol\";\n\n/// @title The interface of the Getters Contract that implements functions for getting contract state from outside the blockchain.\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\n/// @dev Most of the methods simply return the values that correspond to the current diamond proxy and possibly\n/// not to the ZK Chain as a whole. For example, if the chain is migrated to another settlement layer, the values returned\n/// by this facet will correspond to the values stored on this chain and possilbly not the canonical state of the chain.\ninterface IGetters is IZKChainBase {\n    /*//////////////////////////////////////////////////////////////\n                            CUSTOM GETTERS\n    //////////////////////////////////////////////////////////////*/\n\n    /// @return The address of the verifier smart contract\n    function getVerifier() external view returns (address);\n\n    /// @return The address of the current admin\n    function getAdmin() external view returns (address);\n\n    /// @return The address of the pending admin\n    function getPendingAdmin() external view returns (address);\n\n    /// @return The address of the bridgehub\n    function getBridgehub() external view returns (address);\n\n    /// @return The address of the state transition\n    function getChainTypeManager() external view returns (address);\n\n    /// @return The chain ID\n    function getChainId() external view returns (uint256);\n\n    /// @return The address of the base token\n    function getBaseToken() external view returns (address);\n\n    /// @return The address of the base token\n    function getBaseTokenAssetId() external view returns (bytes32);\n\n    /// @return The total number of batches that were committed\n    function getTotalBatchesCommitted() external view returns (uint256);\n\n    /// @return The total number of batches that were committed & verified\n    function getTotalBatchesVerified() external view returns (uint256);\n\n    /// @return The total number of batches that were committed & verified & executed\n    function getTotalBatchesExecuted() external view returns (uint256);\n\n    // @return Address of transaction filterer\n    function getTransactionFilterer() external view returns (address);\n\n    /// @return The total number of priority operations that were added to the priority queue, including all processed ones\n    function getTotalPriorityTxs() external view returns (uint256);\n\n    /// @return The start index of the priority tree, i.e. the index of the first priority operation that\n    /// was included into the priority tree.\n    function getPriorityTreeStartIndex() external view returns (uint256);\n\n    /// @return The root hash of the priority tree\n    function getPriorityTreeRoot() external view returns (bytes32);\n\n    /// @return Whether the priority queue is active, i.e. whether new priority operations are appended to it.\n    /// Once the chain processes all the transactions that were present in the priority queue, all the L1->L2 related\n    /// operations will start to get done using the priority tree.\n    function isPriorityQueueActive() external view returns (bool);\n\n    /// @notice The function that returns the first unprocessed priority transaction.\n    /// @dev Returns zero if and only if no operations were processed from the queue.\n    /// @dev If all the transactions were processed, it will return the last processed index, so\n    /// in case exactly *unprocessed* transactions are needed, one should check that getPriorityQueueSize() is greater than 0.\n    /// @return Index of the oldest priority operation that wasn't processed yet\n    function getFirstUnprocessedPriorityTx() external view returns (uint256);\n\n    /// @return The number of priority operations currently in the queue\n    function getPriorityQueueSize() external view returns (uint256);\n\n    /// @return Whether the address has a validator access\n    function isValidator(address _address) external view returns (bool);\n\n    /// @return merkleRoot Merkle root of the tree with L2 logs for the selected batch\n    function l2LogsRootHash(uint256 _batchNumber) external view returns (bytes32 merkleRoot);\n\n    /// @notice For unfinalized (non executed) batches may change\n    /// @dev returns zero for non-committed batches\n    /// @return The hash of committed L2 batch.\n    function storedBatchHash(uint256 _batchNumber) external view returns (bytes32);\n\n    /// @return Bytecode hash of bootloader program.\n    function getL2BootloaderBytecodeHash() external view returns (bytes32);\n\n    /// @return Bytecode hash of default account (bytecode for EOA).\n    function getL2DefaultAccountBytecodeHash() external view returns (bytes32);\n\n    /// @return Bytecode hash of EVM emulator.\n    function getL2EvmEmulatorBytecodeHash() external view returns (bytes32);\n\n    /// @return Verifier parameters.\n    /// @dev This function is deprecated and will soon be removed.\n    function getVerifierParams() external view returns (VerifierParams memory);\n\n    /// @return Whether the diamond is frozen or not\n    function isDiamondStorageFrozen() external view returns (bool);\n\n    /// @return The current packed protocol version. To access human-readable version, use `getSemverProtocolVersion` function.\n    function getProtocolVersion() external view returns (uint256);\n\n    /// @return The tuple of (major, minor, patch) protocol version.\n    function getSemverProtocolVersion() external view returns (uint32, uint32, uint32);\n\n    /// @return The upgrade system contract transaction hash, 0 if the upgrade is not initialized\n    function getL2SystemContractsUpgradeTxHash() external view returns (bytes32);\n\n    /// @return The L2 batch number in which the upgrade transaction was processed.\n    /// @dev It is equal to 0 in the following two cases:\n    /// - No upgrade transaction has ever been processed.\n    /// - The upgrade transaction has been processed and the batch with such transaction has been\n    /// executed (i.e. finalized).\n    function getL2SystemContractsUpgradeBatchNumber() external view returns (uint256);\n\n    /// @return The maximum number of L2 gas that a user can request for L1 -> L2 transactions\n    function getPriorityTxMaxGasLimit() external view returns (uint256);\n\n    /// @return Whether a withdrawal has been finalized.\n    /// @param _l2BatchNumber The L2 batch number within which the withdrawal happened.\n    /// @param _l2MessageIndex The index of the L2->L1 message denoting the withdrawal.\n    function isEthWithdrawalFinalized(uint256 _l2BatchNumber, uint256 _l2MessageIndex) external view returns (bool);\n\n    /// @return The pubdata pricing mode.\n    function getPubdataPricingMode() external view returns (PubdataPricingMode);\n\n    /// @return the baseTokenGasPriceMultiplierNominator, used to compare the baseTokenPrice to ether for L1->L2 transactions\n    function baseTokenGasPriceMultiplierNominator() external view returns (uint128);\n\n    /// @return the baseTokenGasPriceMultiplierDenominator, used to compare the baseTokenPrice to ether for L1->L2 transactions\n    function baseTokenGasPriceMultiplierDenominator() external view returns (uint128);\n\n    /*//////////////////////////////////////////////////////////////\n                            DIAMOND LOUPE\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Faсet structure compatible with the EIP-2535 diamond loupe\n    /// @param addr The address of the facet contract\n    /// @param selectors The NON-sorted array with selectors associated with facet\n    struct Facet {\n        address addr;\n        bytes4[] selectors;\n    }\n\n    /// @return result All facet addresses and their function selectors\n    function facets() external view returns (Facet[] memory);\n\n    /// @return NON-sorted array with function selectors supported by a specific facet\n    function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory);\n\n    /// @return facets NON-sorted array of facet addresses supported on diamond\n    function facetAddresses() external view returns (address[] memory facets);\n\n    /// @return facet The facet address associated with a selector. Zero if the selector is not added to the diamond\n    function facetAddress(bytes4 _selector) external view returns (address facet);\n\n    /// @return Whether the selector can be frozen by the admin or always accessible\n    function isFunctionFreezable(bytes4 _selector) external view returns (bool);\n\n    /// @return isFreezable Whether the facet can be frozen by the admin or always accessible\n    function isFacetFreezable(address _facet) external view returns (bool isFreezable);\n\n    /// @return The address of the current settlement layer.\n    function getSettlementLayer() external view returns (address);\n}\n"},{"file_path":"contracts/common/libraries/DataEncoding.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.28;\n\nimport {L2_NATIVE_TOKEN_VAULT_ADDR} from \"../l2-helpers/L2ContractAddresses.sol\";\nimport {LEGACY_ENCODING_VERSION, NEW_ENCODING_VERSION} from \"../../bridge/asset-router/IAssetRouterBase.sol\";\nimport {INativeTokenVault} from \"../../bridge/ntv/INativeTokenVault.sol\";\nimport {IncorrectTokenAddressFromNTV, InvalidNTVBurnData, UnsupportedEncodingVersion} from \"../L1ContractErrors.sol\";\n\n/**\n * @author Matter Labs\n * @custom:security-contact security@matterlabs.dev\n * @notice Helper library for transfer data encoding and decoding to reduce possibility of errors.\n */\nlibrary DataEncoding {\n    /// @notice Abi.encodes the data required for bridgeBurn for NativeTokenVault.\n    /// @param _amount The amount of token to be transferred.\n    /// @param _remoteReceiver The address which to receive tokens on remote chain.\n    /// @param _maybeTokenAddress The helper field that should be either equal to 0 (in this case\n    /// it is assumed that the token has been registered within NativeTokenVault already) or it\n    /// can be equal to the address of the token on the current chain. Providing non-zero address\n    /// allows it to be automatically registered in case it is not yet a part of NativeTokenVault.\n    /// @return The encoded bridgeBurn data\n    function encodeBridgeBurnData(\n        uint256 _amount,\n        address _remoteReceiver,\n        address _maybeTokenAddress\n    ) internal pure returns (bytes memory) {\n        return abi.encode(_amount, _remoteReceiver, _maybeTokenAddress);\n    }\n\n    /// @notice Function decoding bridgeBurn data previously encoded with this library.\n    /// @param _data The encoded data for bridgeBurn\n    /// @return amount The amount of token to be transferred.\n    /// @return receiver The address which to receive tokens on remote chain.\n    /// @return maybeTokenAddress The helper field that should be either equal to 0 (in this case\n    /// it is assumed that the token has been registered within NativeTokenVault already) or it\n    /// can be equal to the address of the token on the current chain. Providing non-zero address\n    /// allows it to be automatically registered in case it is not yet a part of NativeTokenVault.\n    function decodeBridgeBurnData(\n        bytes memory _data\n    ) internal pure returns (uint256 amount, address receiver, address maybeTokenAddress) {\n        if (_data.length != 96) {\n            // For better error handling\n            revert InvalidNTVBurnData();\n        }\n\n        (amount, receiver, maybeTokenAddress) = abi.decode(_data, (uint256, address, address));\n    }\n\n    /// @notice Abi.encodes the data required for bridgeMint on remote chain.\n    /// @param _originalCaller The address which initiated the transfer.\n    /// @param _remoteReceiver The address which to receive tokens on remote chain.\n    /// @param _originToken The transferred token address.\n    /// @param _amount The amount of token to be transferred.\n    /// @param _erc20Metadata The transferred token metadata.\n    /// @return The encoded bridgeMint data\n    function encodeBridgeMintData(\n        address _originalCaller,\n        address _remoteReceiver,\n        address _originToken,\n        uint256 _amount,\n        bytes memory _erc20Metadata\n    ) internal pure returns (bytes memory) {\n        // solhint-disable-next-line func-named-parameters\n        return abi.encode(_originalCaller, _remoteReceiver, _originToken, _amount, _erc20Metadata);\n    }\n\n    /// @notice Function decoding transfer data previously encoded with this library.\n    /// @param _bridgeMintData The encoded bridgeMint data\n    /// @return _originalCaller The address which initiated the transfer.\n    /// @return _remoteReceiver The address which to receive tokens on remote chain.\n    /// @return _parsedOriginToken The transferred token address.\n    /// @return _amount The amount of token to be transferred.\n    /// @return _erc20Metadata The transferred token metadata.\n    function decodeBridgeMintData(\n        bytes memory _bridgeMintData\n    )\n        internal\n        pure\n        returns (\n            address _originalCaller,\n            address _remoteReceiver,\n            address _parsedOriginToken,\n            uint256 _amount,\n            bytes memory _erc20Metadata\n        )\n    {\n        (_originalCaller, _remoteReceiver, _parsedOriginToken, _amount, _erc20Metadata) = abi.decode(\n            _bridgeMintData,\n            (address, address, address, uint256, bytes)\n        );\n    }\n\n    /// @notice Encodes the asset data by combining chain id, asset deployment tracker and asset data.\n    /// @param _chainId The id of the chain token is native to.\n    /// @param _assetData The asset data that has to be encoded.\n    /// @param _sender The asset deployment tracker address.\n    /// @return The encoded asset data.\n    function encodeAssetId(uint256 _chainId, bytes32 _assetData, address _sender) internal pure returns (bytes32) {\n        return keccak256(abi.encode(_chainId, _sender, _assetData));\n    }\n\n    /// @notice Encodes the asset data by combining chain id, asset deployment tracker and asset data.\n    /// @param _chainId The id of the chain token is native to.\n    /// @param _tokenAddress The address of token that has to be encoded (asset data is the address itself).\n    /// @param _sender The asset deployment tracker address.\n    /// @return The encoded asset data.\n    function encodeAssetId(uint256 _chainId, address _tokenAddress, address _sender) internal pure returns (bytes32) {\n        return keccak256(abi.encode(_chainId, _sender, _tokenAddress));\n    }\n\n    /// @notice Encodes the asset data by combining chain id, NTV as asset deployment tracker and asset data.\n    /// @param _chainId The id of the chain token is native to.\n    /// @param _assetData The asset data that has to be encoded.\n    /// @return The encoded asset data.\n    function encodeNTVAssetId(uint256 _chainId, bytes32 _assetData) internal pure returns (bytes32) {\n        return keccak256(abi.encode(_chainId, L2_NATIVE_TOKEN_VAULT_ADDR, _assetData));\n    }\n\n    /// @notice Encodes the asset data by combining chain id, NTV as asset deployment tracker and token address.\n    /// @param _chainId The id of the chain token is native to.\n    /// @param _tokenAddress The address of token that has to be encoded (asset data is the address itself).\n    /// @return The encoded asset data.\n    function encodeNTVAssetId(uint256 _chainId, address _tokenAddress) internal pure returns (bytes32) {\n        return keccak256(abi.encode(_chainId, L2_NATIVE_TOKEN_VAULT_ADDR, _tokenAddress));\n    }\n\n    /// @dev Encodes the transaction data hash using either the latest encoding standard or the legacy standard.\n    /// @param _encodingVersion EncodingVersion.\n    /// @param _originalCaller The address of the entity that initiated the deposit.\n    /// @param _assetId The unique identifier of the deposited L1 token.\n    /// @param _nativeTokenVault The address of the token, only used if the encoding version is legacy.\n    /// @param _transferData The encoded transfer data, which includes the deposit amount, the address of the L2 receiver, and potentially the token address.\n    /// @return txDataHash The resulting encoded transaction data hash.\n    function encodeTxDataHash(\n        bytes1 _encodingVersion,\n        address _originalCaller,\n        bytes32 _assetId,\n        address _nativeTokenVault,\n        bytes memory _transferData\n    ) internal view returns (bytes32 txDataHash) {\n        if (_encodingVersion == LEGACY_ENCODING_VERSION) {\n            address tokenAddress = INativeTokenVault(_nativeTokenVault).tokenAddress(_assetId);\n\n            // This is a double check to ensure that the used token for the legacy encoding is correct.\n            // This revert should never be emitted and in real life and should only serve as a guard in\n            // case of inconsistent state of Native Token Vault.\n            bytes32 expectedAssetId = encodeNTVAssetId(block.chainid, tokenAddress);\n            if (_assetId != expectedAssetId) {\n                revert IncorrectTokenAddressFromNTV(_assetId, tokenAddress);\n            }\n\n            (uint256 depositAmount, , ) = decodeBridgeBurnData(_transferData);\n            txDataHash = keccak256(abi.encode(_originalCaller, tokenAddress, depositAmount));\n        } else if (_encodingVersion == NEW_ENCODING_VERSION) {\n            // Similarly to calldata, the txDataHash is collision-resistant.\n            // In the legacy data hash, the first encoded variable was the address, which is padded with zeros during `abi.encode`.\n            txDataHash = keccak256(\n                bytes.concat(_encodingVersion, abi.encode(_originalCaller, _assetId, _transferData))\n            );\n        } else {\n            revert UnsupportedEncodingVersion();\n        }\n    }\n\n    /// @notice Decodes the token data by combining chain id, asset deployment tracker and asset data.\n    function decodeTokenData(\n        bytes calldata _tokenData\n    ) internal pure returns (uint256 chainId, bytes memory name, bytes memory symbol, bytes memory decimals) {\n        bytes1 encodingVersion = _tokenData[0];\n        if (encodingVersion == LEGACY_ENCODING_VERSION) {\n            (name, symbol, decimals) = abi.decode(_tokenData, (bytes, bytes, bytes));\n        } else if (encodingVersion == NEW_ENCODING_VERSION) {\n            return abi.decode(_tokenData[1:], (uint256, bytes, bytes, bytes));\n        } else {\n            revert UnsupportedEncodingVersion();\n        }\n    }\n\n    /// @notice Encodes the token data by combining chain id, and its metadata.\n    /// @dev Note that all the metadata of the token is expected to be ABI encoded.\n    /// @param _chainId The id of the chain token is native to.\n    /// @param _name The name of the token.\n    /// @param _symbol The symbol of the token.\n    /// @param _decimals The decimals of the token.\n    /// @return The encoded token data.\n    function encodeTokenData(\n        uint256 _chainId,\n        bytes memory _name,\n        bytes memory _symbol,\n        bytes memory _decimals\n    ) internal pure returns (bytes memory) {\n        return bytes.concat(NEW_ENCODING_VERSION, abi.encode(_chainId, _name, _symbol, _decimals));\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts-v4/contracts/utils/math/Math.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, \"Math: mulDiv overflow\");\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n}\n"},{"file_path":"contracts/bridgehub/ICTMDeploymentTracker.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.28;\n\nimport {IBridgehub, L2TransactionRequestTwoBridgesInner} from \"./IBridgehub.sol\";\nimport {IAssetRouterBase} from \"../bridge/asset-router/IAssetRouterBase.sol\";\nimport {IL1AssetDeploymentTracker} from \"../bridge/interfaces/IL1AssetDeploymentTracker.sol\";\n\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\ninterface ICTMDeploymentTracker is IL1AssetDeploymentTracker {\n    function bridgehubDeposit(\n        uint256 _chainId,\n        address _originalCaller,\n        uint256 _l2Value,\n        bytes calldata _data\n    ) external payable returns (L2TransactionRequestTwoBridgesInner memory request);\n\n    function BRIDGE_HUB() external view returns (IBridgehub);\n\n    function L1_ASSET_ROUTER() external view returns (IAssetRouterBase);\n\n    function registerCTMAssetOnL1(address _ctmAddress) external;\n\n    function calculateAssetId(address _l1CTM) external view returns (bytes32);\n}\n"},{"file_path":"contracts/state-transition/L1StateTransitionErrors.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.21;\n\n// 0xb325f767\nerror AdminZero();\n// 0xca1c3cbc\nerror AlreadyMigrated();\n// 0x125d99b0\nerror BlobHashBlobCommitmentMismatchValue();\n// 0xafda12bf\nerror CommitBasedInteropNotSupported();\n// 0xc02d3ee3\nerror ContractNotDeployed();\n// 0xdf2c5fa5\nerror DependencyRootsRollingHashMismatch(bytes32 _expected, bytes32 _actual);\n// 0xedae13f3\nerror ExecutedIsNotConsistentWithVerified(uint256 batchesExecuted, uint256 batchesVerified);\n// 0xc866ff2c\nerror InitialForceDeploymentMismatch(bytes32 forceDeploymentHash, bytes32 initialForceDeploymentHash);\n// 0xfbd630b8\nerror InvalidBatchesDataLength(uint256 batchesDataLength, uint256 priorityOpsDataLength);\n// 0x7a47c9a2\nerror InvalidChainId();\n// 0xc06789fa\nerror InvalidCommitment();\n// 0xd2531c15\nerror InvalidL2DAOutputHash(bytes32 l2DAValidatorOutputHash);\n// 0x30043900\nerror InvalidNextLeafIndex(uint256 treeNextLeafIndex, uint256 commitmentNextLeafIndex);\n// 0xfb1a3b59\nerror InvalidNumberOfBatchHashes(uint256 batchHashesLength, uint256 expected);\n// 0xbeb96791\nerror InvalidNumberOfBlobs(uint256 blobsProvided, uint256 maxBlobsSupported);\n// 0x5513177c\nerror InvalidPubdataHash(bytes32 fullPubdataHash, bytes32 providedPubdataHash);\n// 0x5717f940\nerror InvalidPubdataSource(uint8 pubdataSource);\n// 0x90f67ecf\nerror InvalidStartIndex(uint256 treeStartIndex, uint256 commitmentStartIndex);\n// 0x0f67bc0a\nerror InvalidUnprocessedIndex(uint256 treeUnprocessedIndex, uint256 commitmentUnprocessedIndex);\n// 0x2e89f517\nerror L1DAValidatorAddressIsZero();\n// 0x7fbff2dd\nerror L1DAValidatorInvalidSender(address msgSender);\n// 0x944bc075\nerror L2DAValidatorAddressIsZero();\n// 0xa969e486\nerror LocalRootIsZero();\n// 0xbdaf7d42\nerror LocalRootMustBeZero();\n// 0x9b5f85eb\nerror MessageRootIsZero();\n// 0x2237c426\nerror MismatchL2DAValidator();\n// 0x2c01a4af\nerror MismatchNumberOfLayer1Txs(uint256 numberOfLayer1Txs, uint256 expectedLength);\n// 0xf9ba09d6\nerror NotAllBatchesExecuted();\n// 0xf05c64c6\nerror NotChainAdmin(address prevMsgSender, address admin);\n// 0x8fd63d21\nerror NotEraChain();\n// 0xa7050bf6\nerror NotHistoricalRoot(bytes32);\n// 0x32ddf9a2\nerror NotHyperchain();\n// 0x87470e36\nerror NotL1(uint256 blockChainId);\n// 0xd7b2559b\nerror NotMigrated();\n// 0xd0266e26\nerror NotSettlementLayer();\n// 0x04e05fd1\nerror OnlyOneBlobWithCalldataAllowed();\n// 0x885ae069\nerror OperatorDAInputTooSmall(uint256 operatorDAInputLength, uint256 minAllowedLength);\n// 0x681150be\nerror OutdatedProtocolVersion(uint256 protocolVersion, uint256 currentProtocolVersion);\n// 0xc59d372c\nerror ProtocolVersionNotUpToDate(uint256 currentProtocolVersion, uint256 protocolVersion);\n// 0x2dc9747d\nerror PubdataInputTooSmall(uint256 pubdataInputLength, uint256 totalBlobsCommitmentSize);\n// 0x9044dff9\nerror PubdataLengthTooBig(uint256 pubdataLength, uint256 totalBlobSizeBytes);\n// 0x79274f04\nerror UnsupportedProofMetadataVersion(uint256 metadataVersion);\n// 0x52595598\nerror ValL1DAWrongInputLength(uint256 inputLength, uint256 expectedLength);\n// 0x712d02d2\nerror VerifiedIsNotConsistentWithCommitted(uint256 batchesVerified, uint256 batchesCommitted);\n"},{"file_path":"contracts/state-transition/chain-interfaces/IAdmin.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {IZKChainBase} from \"../chain-interfaces/IZKChainBase.sol\";\n\nimport {Diamond} from \"../libraries/Diamond.sol\";\nimport {FeeParams, PubdataPricingMode} from \"../chain-deps/ZKChainStorage.sol\";\nimport {ZKChainCommitment} from \"../../common/Config.sol\";\n\n/// @title The interface of the Admin Contract that controls access rights for contract management.\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\ninterface IAdmin is IZKChainBase {\n    /// @notice Starts the transfer of admin rights. Only the current admin can propose a new pending one.\n    /// @notice New admin can accept admin rights by calling `acceptAdmin` function.\n    /// @param _newPendingAdmin Address of the new admin\n    function setPendingAdmin(address _newPendingAdmin) external;\n\n    /// @notice Accepts transfer of admin rights. Only pending admin can accept the role.\n    function acceptAdmin() external;\n\n    /// @notice Change validator status (active or not active)\n    /// @param _validator Validator address\n    /// @param _active Active flag\n    function setValidator(address _validator, bool _active) external;\n\n    /// @notice Change zk porter availability\n    /// @param _zkPorterIsAvailable The availability of zk porter shard\n    function setPorterAvailability(bool _zkPorterIsAvailable) external;\n\n    /// @notice Change the max L2 gas limit for L1 -> L2 transactions\n    /// @param _newPriorityTxMaxGasLimit The maximum number of L2 gas that a user can request for L1 -> L2 transactions\n    function setPriorityTxMaxGasLimit(uint256 _newPriorityTxMaxGasLimit) external;\n\n    /// @notice Change the fee params for L1->L2 transactions\n    /// @param _newFeeParams The new fee params\n    function changeFeeParams(FeeParams calldata _newFeeParams) external;\n\n    /// @notice Change the token multiplier for L1->L2 transactions\n    function setTokenMultiplier(uint128 _nominator, uint128 _denominator) external;\n\n    /// @notice Change the pubdata pricing mode before the first batch is processed\n    /// @param _pricingMode The new pubdata pricing mode\n    function setPubdataPricingMode(PubdataPricingMode _pricingMode) external;\n\n    /// @notice Set the transaction filterer\n    function setTransactionFilterer(address _transactionFilterer) external;\n\n    /// @notice Allow EVM emulation on chain\n    function allowEvmEmulation() external returns (bytes32 canonicalTxHash);\n\n    /// @notice Perform the upgrade from the current protocol version with the corresponding upgrade data\n    /// @param _protocolVersion The current protocol version from which upgrade is executed\n    /// @param _cutData The diamond cut parameters that is executed in the upgrade\n    function upgradeChainFromVersion(uint256 _protocolVersion, Diamond.DiamondCutData calldata _cutData) external;\n\n    /// @notice Executes a proposed governor upgrade\n    /// @dev Only the ChainTypeManager contract can execute the upgrade\n    /// @param _diamondCut The diamond cut parameters to be executed\n    function executeUpgrade(Diamond.DiamondCutData calldata _diamondCut) external;\n\n    /// @notice Instantly pause the functionality of all freezable facets & their selectors\n    /// @dev Only the governance mechanism may freeze Diamond Proxy\n    function freezeDiamond() external;\n\n    /// @notice Unpause the functionality of all freezable facets & their selectors\n    /// @dev Only the CTM can unfreeze Diamond Proxy\n    function unfreezeDiamond() external;\n\n    function genesisUpgrade(\n        address _l1GenesisUpgrade,\n        address _ctmDeployer,\n        bytes calldata _forceDeploymentData,\n        bytes[] calldata _factoryDeps\n    ) external;\n\n    /// @notice Returns address of the RollupDAManager of the ZK Chain.\n    function getRollupDAManager() external view returns (address);\n\n    /// @notice Set the L1 DA validator address as well as the L2 DA validator address.\n    /// @dev While in principle it is possible that updating only one of the addresses is needed,\n    /// usually these should work in pair and L1 validator typically expects a specific input from the L2 Validator.\n    /// That's why we change those together to prevent admins of chains from shooting themselves in the foot.\n    /// @param _l1DAValidator The address of the L1 DA validator\n    /// @param _l2DAValidator The address of the L2 DA validator\n    function setDAValidatorPair(address _l1DAValidator, address _l2DAValidator) external;\n\n    /// @notice Makes the chain as permanent rollup.\n    /// @dev This is a security feature needed for chains that should be\n    /// trusted to keep their data available even if the chain admin becomes malicious\n    /// and tries to set the DA validator pair to something which does not publish DA to Ethereum.\n    /// @dev DANGEROUS: once activated, there is no way back!\n    function makePermanentRollup() external;\n\n    /// @notice Porter availability status changes\n    event IsPorterAvailableStatusUpdate(bool isPorterAvailable);\n\n    /// @notice Validator's status changed\n    event ValidatorStatusUpdate(address indexed validatorAddress, bool isActive);\n\n    /// @notice pendingAdmin is changed\n    /// @dev Also emitted when new admin is accepted and in this case, `newPendingAdmin` would be zero address\n    event NewPendingAdmin(address indexed oldPendingAdmin, address indexed newPendingAdmin);\n\n    /// @notice Admin changed\n    event NewAdmin(address indexed oldAdmin, address indexed newAdmin);\n\n    /// @notice Priority transaction max L2 gas limit changed\n    event NewPriorityTxMaxGasLimit(uint256 oldPriorityTxMaxGasLimit, uint256 newPriorityTxMaxGasLimit);\n\n    /// @notice Fee params for L1->L2 transactions changed\n    event NewFeeParams(FeeParams oldFeeParams, FeeParams newFeeParams);\n\n    /// @notice Validium mode status changed\n    event PubdataPricingModeUpdate(PubdataPricingMode validiumMode);\n\n    /// @notice The transaction filterer has been updated\n    event NewTransactionFilterer(address oldTransactionFilterer, address newTransactionFilterer);\n\n    /// @notice BaseToken multiplier for L1->L2 transactions changed\n    event NewBaseTokenMultiplier(\n        uint128 oldNominator,\n        uint128 oldDenominator,\n        uint128 newNominator,\n        uint128 newDenominator\n    );\n\n    /// @notice Emitted when an upgrade is executed.\n    event ExecuteUpgrade(Diamond.DiamondCutData diamondCut);\n\n    /// @notice Emitted when the migration to the new settlement layer is complete.\n    event MigrationComplete();\n\n    /// @notice Emitted when the contract is frozen.\n    event Freeze();\n\n    /// @notice Emitted when the contract is unfrozen.\n    event Unfreeze();\n\n    /// @notice The EVM emulator has been enabled\n    event EnableEvmEmulator();\n\n    /// @notice New pair of DA validators set\n    event NewL2DAValidator(address indexed oldL2DAValidator, address indexed newL2DAValidator);\n    event NewL1DAValidator(address indexed oldL1DAValidator, address indexed newL1DAValidator);\n\n    event BridgeMint(address indexed _account, uint256 _amount);\n\n    /// @dev Similar to IL1AssetHandler interface, used to send chains.\n    function forwardedBridgeBurn(\n        address _settlementLayer,\n        address _originalCaller,\n        bytes calldata _data\n    ) external payable returns (bytes memory _bridgeMintData);\n\n    /// @dev Similar to IL1AssetHandler interface, used to claim failed chain transfers.\n    function forwardedBridgeRecoverFailedTransfer(\n        uint256 _chainId,\n        bytes32 _assetInfo,\n        address _originalCaller,\n        bytes calldata _chainData\n    ) external payable;\n\n    /// @dev Similar to IL1AssetHandler interface, used to receive chains.\n    function forwardedBridgeMint(bytes calldata _data, bool _contractAlreadyDeployed) external payable;\n\n    function prepareChainCommitment() external view returns (ZKChainCommitment memory commitment);\n}\n"},{"file_path":"contracts/state-transition/IChainTypeManager.sol","source_code":"// SPDX-License-Identifier: MIT\n// We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version.\npragma solidity ^0.8.21;\n\nimport {Diamond} from \"./libraries/Diamond.sol\";\nimport {L2CanonicalTransaction} from \"../common/Messaging.sol\";\nimport {FeeParams} from \"./chain-deps/ZKChainStorage.sol\";\n\n// import {IBridgehub} from \"../bridgehub/IBridgehub.sol\";\n\n/// @notice Struct that holds all data needed for initializing CTM Proxy.\n/// @dev We use struct instead of raw parameters in `initialize` function to prevent \"Stack too deep\" error\n/// @param owner The address who can manage non-critical updates in the contract\n/// @param validatorTimelock The address that serves as consensus, i.e. can submit blocks to be processed\n/// @param chainCreationParams The struct that contains the fields that define how a new chain should be created\n/// @param protocolVersion The initial protocol version on the newly deployed chain\n/// @param serverNotifier The address that serves as server notifier\n// solhint-disable-next-line gas-struct-packing\nstruct ChainTypeManagerInitializeData {\n    address owner;\n    address validatorTimelock;\n    ChainCreationParams chainCreationParams;\n    uint256 protocolVersion;\n    address serverNotifier;\n}\n\n/// @notice The struct that contains the fields that define how a new chain should be created\n/// within this CTM.\n/// @param genesisUpgrade The address that is used in the diamond cut initialize address on chain creation\n/// @param genesisBatchHash Batch hash of the genesis (initial) batch\n/// @param genesisIndexRepeatedStorageChanges The serial number of the shortcut storage key for the genesis batch\n/// @param genesisBatchCommitment The zk-proof commitment for the genesis batch\n/// @param diamondCut The diamond cut for the first upgrade transaction on the newly deployed chain\n// solhint-disable-next-line gas-struct-packing\nstruct ChainCreationParams {\n    address genesisUpgrade;\n    bytes32 genesisBatchHash;\n    uint64 genesisIndexRepeatedStorageChanges;\n    bytes32 genesisBatchCommitment;\n    Diamond.DiamondCutData diamondCut;\n    bytes forceDeploymentsData;\n}\n\ninterface IChainTypeManager {\n    /// @dev Emitted when a new ZKChain is added\n    event NewZKChain(uint256 indexed _chainId, address indexed _zkChainContract);\n\n    /// @dev emitted when an chain registers and a GenesisUpgrade happens\n    event GenesisUpgrade(\n        address indexed _zkChain,\n        L2CanonicalTransaction _l2Transaction,\n        uint256 indexed _protocolVersion\n    );\n\n    /// @notice pendingAdmin is changed\n    /// @dev Also emitted when new admin is accepted and in this case, `newPendingAdmin` would be zero address\n    event NewPendingAdmin(address indexed oldPendingAdmin, address indexed newPendingAdmin);\n\n    /// @notice Admin changed\n    event NewAdmin(address indexed oldAdmin, address indexed newAdmin);\n\n    /// @notice ValidatorTimelock changed\n    event NewValidatorTimelock(address indexed oldValidatorTimelock, address indexed newValidatorTimelock);\n\n    /// @notice ValidatorTimelockPostV29 changed\n    event NewValidatorTimelockPostV29(\n        address indexed oldValidatorTimelockPostV29,\n        address indexed newvalidatorTimelockPostV29\n    );\n\n    /// @notice ServerNotifier changed\n    event NewServerNotifier(address indexed oldServerNotifier, address indexed newServerNotifier);\n\n    /// @notice chain creation parameters changed\n    event NewChainCreationParams(\n        address genesisUpgrade,\n        bytes32 genesisBatchHash,\n        uint64 genesisIndexRepeatedStorageChanges,\n        bytes32 genesisBatchCommitment,\n        Diamond.DiamondCutData newInitialCut,\n        bytes32 newInitialCutHash,\n        bytes forceDeploymentsData,\n        bytes32 forceDeploymentHash\n    );\n\n    /// @notice New UpgradeCutHash\n    event NewUpgradeCutHash(uint256 indexed protocolVersion, bytes32 indexed upgradeCutHash);\n\n    /// @notice New UpgradeCutData\n    event NewUpgradeCutData(uint256 indexed protocolVersion, Diamond.DiamondCutData diamondCutData);\n\n    /// @notice New ProtocolVersion\n    event NewProtocolVersion(uint256 indexed oldProtocolVersion, uint256 indexed newProtocolVersion);\n\n    /// @notice Updated ProtocolVersion deadline\n    event UpdateProtocolVersionDeadline(uint256 indexed protocolVersion, uint256 deadline);\n\n    function BRIDGE_HUB() external view returns (address);\n\n    function setPendingAdmin(address _newPendingAdmin) external;\n\n    function acceptAdmin() external;\n\n    function getZKChain(uint256 _chainId) external view returns (address);\n\n    function getHyperchain(uint256 _chainId) external view returns (address);\n\n    function getZKChainLegacy(uint256 _chainId) external view returns (address);\n\n    function storedBatchZero() external view returns (bytes32);\n\n    function initialCutHash() external view returns (bytes32);\n\n    function l1GenesisUpgrade() external view returns (address);\n\n    function upgradeCutHash(uint256 _protocolVersion) external view returns (bytes32);\n\n    function protocolVersion() external view returns (uint256);\n\n    function protocolVersionDeadline(uint256 _protocolVersion) external view returns (uint256);\n\n    function protocolVersionIsActive(uint256 _protocolVersion) external view returns (bool);\n\n    function getProtocolVersion(uint256 _chainId) external view returns (uint256);\n\n    function initialize(ChainTypeManagerInitializeData calldata _initializeData) external;\n\n    function setLegacyValidatorTimelock(address _validatorTimelock) external;\n\n    function setValidatorTimelockPostV29(address _validatorTimelockPostV29) external;\n\n    function setChainCreationParams(ChainCreationParams calldata _chainCreationParams) external;\n\n    function getChainAdmin(uint256 _chainId) external view returns (address);\n\n    function createNewChain(\n        uint256 _chainId,\n        bytes32 _baseTokenAssetId,\n        address _admin,\n        bytes calldata _initData,\n        bytes[] calldata _factoryDeps\n    ) external returns (address);\n\n    function setNewVersionUpgrade(\n        Diamond.DiamondCutData calldata _cutData,\n        uint256 _oldProtocolVersion,\n        uint256 _oldProtocolVersionDeadline,\n        uint256 _newProtocolVersion\n    ) external;\n\n    function setUpgradeDiamondCut(Diamond.DiamondCutData calldata _cutData, uint256 _oldProtocolVersion) external;\n\n    function executeUpgrade(uint256 _chainId, Diamond.DiamondCutData calldata _diamondCut) external;\n\n    function setPriorityTxMaxGasLimit(uint256 _chainId, uint256 _maxGasLimit) external;\n\n    function freezeChain(uint256 _chainId) external;\n\n    function unfreezeChain(uint256 _chainId) external;\n\n    function setTokenMultiplier(uint256 _chainId, uint128 _nominator, uint128 _denominator) external;\n\n    function changeFeeParams(uint256 _chainId, FeeParams calldata _newFeeParams) external;\n\n    function setValidator(uint256 _chainId, address _validator, bool _active) external;\n\n    function setPorterAvailability(uint256 _chainId, bool _zkPorterIsAvailable) external;\n\n    function upgradeChainFromVersion(\n        uint256 _chainId,\n        uint256 _oldProtocolVersion,\n        Diamond.DiamondCutData calldata _diamondCut\n    ) external;\n\n    function getSemverProtocolVersion() external view returns (uint32, uint32, uint32);\n\n    function forwardedBridgeBurn(\n        uint256 _chainId,\n        bytes calldata _data\n    ) external returns (bytes memory _bridgeMintData);\n\n    function forwardedBridgeMint(uint256 _chainId, bytes calldata _data) external returns (address);\n\n    function forwardedBridgeRecoverFailedTransfer(\n        uint256 _chainId,\n        bytes32 _assetInfo,\n        address _depositSender,\n        bytes calldata _ctmData\n    ) external;\n}\n"},{"file_path":"lib/openzeppelin-contracts-v4/contracts/utils/StorageSlot.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\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 ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\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(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\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 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        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` with member `value` located at `slot`.\n     */\n    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\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        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := store.slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n     */\n    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\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        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := store.slot\n        }\n    }\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"uint256","name":"_l1ChainId","type":"uint256"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_maxNumberOfZKChains","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"blockChainId","type":"uint256"}],"name":"AlreadyCurrentSL","type":"error"},{"inputs":[{"internalType":"bytes32","name":"assetId","type":"bytes32"}],"name":"AssetHandlerNotRegistered","type":"error"},{"inputs":[],"name":"AssetIdAlreadyRegistered","type":"error"},{"inputs":[{"internalType":"bytes32","name":"assetId","type":"bytes32"}],"name":"AssetIdNotSupported","type":"error"},{"inputs":[],"name":"BridgeHubAlreadyRegistered","type":"error"},{"inputs":[],"name":"CTMAlreadyRegistered","type":"error"},{"inputs":[],"name":"CTMNotRegistered","type":"error"},{"inputs":[],"name":"ChainIdAlreadyExists","type":"error"},{"inputs":[],"name":"ChainIdAlreadyPresent","type":"error"},{"inputs":[],"name":"ChainIdCantBeCurrentChain","type":"error"},{"inputs":[],"name":"ChainIdMismatch","type":"error"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"ChainIdNotRegistered","type":"error"},{"inputs":[],"name":"ChainIdTooBig","type":"error"},{"inputs":[],"name":"ChainNotLegacy","type":"error"},{"inputs":[],"name":"ChainNotPresentInCTM","type":"error"},{"inputs":[],"name":"EmptyAssetId","type":"error"},{"inputs":[{"internalType":"address","name":"bridgehub","type":"address"}],"name":"IncorrectBridgeHubAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedMsgValue","type":"uint256"},{"internalType":"uint256","name":"providedMsgValue","type":"uint256"}],"name":"MsgValueMismatch","type":"error"},{"inputs":[{"internalType":"bytes32","name":"assetId","type":"bytes32"}],"name":"NoCTMForAssetId","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"chainAssetHandler","type":"address"}],"name":"NotChainAssetHandler","type":"error"},{"inputs":[{"internalType":"uint256","name":"settlementLayerChainId","type":"uint256"},{"internalType":"uint256","name":"blockChainId","type":"uint256"}],"name":"NotCurrentSL","type":"error"},{"inputs":[],"name":"NotInGatewayMode","type":"error"},{"inputs":[],"name":"NotInitializedReentrancyGuard","type":"error"},{"inputs":[{"internalType":"uint256","name":"l1ChainId","type":"uint256"},{"internalType":"uint256","name":"blockChainId","type":"uint256"}],"name":"NotL1","type":"error"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"},{"internalType":"address","name":"settlementLayerRelaySender","type":"address"}],"name":"NotRelayedSender","type":"error"},{"inputs":[],"name":"Reentrancy","type":"error"},{"inputs":[],"name":"SLNotWhitelisted","type":"error"},{"inputs":[{"internalType":"address","name":"secondBridgeAddress","type":"address"},{"internalType":"address","name":"minSecondBridgeAddress","type":"address"}],"name":"SecondBridgeAddressTooLow","type":"error"},{"inputs":[],"name":"SettlementLayersMustSettleOnL1","type":"error"},{"inputs":[],"name":"SharedBridgeNotSet","type":"error"},{"inputs":[],"name":"SlotOccupied","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"Unauthorized","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedMagicValue","type":"uint256"},{"internalType":"uint256","name":"providedMagicValue","type":"uint256"}],"name":"WrongMagicValue","type":"error"},{"inputs":[],"name":"ZKChainLimitReached","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroChainId","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"assetInfo","type":"bytes32"},{"indexed":true,"internalType":"address","name":"_assetAddress","type":"address"},{"indexed":true,"internalType":"bytes32","name":"additionalData","type":"bytes32"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"AssetRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"assetId","type":"bytes32"}],"name":"BaseTokenAssetIdRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"chainTypeManager","type":"address"}],"name":"ChainTypeManagerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"chainTypeManager","type":"address"}],"name":"ChainTypeManagerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":false,"internalType":"address","name":"chainTypeManager","type":"address"},{"indexed":true,"internalType":"address","name":"chainGovernance","type":"address"}],"name":"NewChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldPendingAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"NewPendingAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":true,"internalType":"bool","name":"isWhitelisted","type":"bool"}],"name":"SettlementLayerRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"L1_CHAIN_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_NUMBER_OF_ZK_CHAINS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_chainTypeManager","type":"address"}],"name":"addChainTypeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_baseTokenAssetId","type":"bytes32"}],"name":"addTokenAssetId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"baseTokenAssetId","type":"bytes32"}],"name":"assetIdIsRegistered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"}],"name":"baseToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"baseTokenAssetId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainAssetHandler","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"chainTypeManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"chainTypeManager","type":"address"}],"name":"chainTypeManagerIsRegistered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"address","name":"_chainTypeManager","type":"address"},{"internalType":"bytes32","name":"_baseTokenAssetId","type":"bytes32"},{"internalType":"uint256","name":"_salt","type":"uint256"},{"internalType":"address","name":"_admin","type":"address"},{"internalType":"bytes","name":"_initData","type":"bytes"},{"internalType":"bytes[]","name":"_factoryDeps","type":"bytes[]"}],"name":"createNewChain","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"ctmAddress","type":"address"}],"name":"ctmAssetIdFromAddress","outputs":[{"internalType":"bytes32","name":"ctmAssetId","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"}],"name":"ctmAssetIdFromChainId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"ctmAssetId","type":"bytes32"}],"name":"ctmAssetIdToAddress","outputs":[{"internalType":"address","name":"ctmAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"bytes32","name":"_canonicalTxHash","type":"bytes32"},{"internalType":"uint64","name":"_expirationTimestamp","type":"uint64"}],"name":"forwardTransactionOnGateway","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"uint256","name":"_newSettlementLayerChainId","type":"uint256"}],"name":"forwardedBridgeBurnSetSettlementLayer","outputs":[{"internalType":"address","name":"zkChain","type":"address"},{"internalType":"address","name":"ctm","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_assetId","type":"bytes32"},{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"bytes32","name":"_baseTokenAssetId","type":"bytes32"}],"name":"forwardedBridgeMint","outputs":[{"internalType":"address","name":"zkChain","type":"address"},{"internalType":"address","name":"ctm","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"}],"name":"forwardedBridgeRecoverFailedTransfer","outputs":[{"internalType":"address","name":"zkChain","type":"address"},{"internalType":"address","name":"ctm","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllZKChainChainIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllZKChains","outputs":[{"internalType":"address[]","name":"chainAddresses","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"}],"name":"getHyperchain","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"}],"name":"getZKChain","outputs":[{"internalType":"address","name":"chainAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initializeV2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"l1CtmDeployer","outputs":[{"internalType":"contract ICTMDeploymentTracker","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"uint256","name":"_gasPrice","type":"uint256"},{"internalType":"uint256","name":"_l2GasLimit","type":"uint256"},{"internalType":"uint256","name":"_l2GasPerPubdataByteLimit","type":"uint256"}],"name":"l2TransactionBaseCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"messageRoot","outputs":[{"internalType":"contract IMessageRoot","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"migrationPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"bytes32","name":"_l2TxHash","type":"bytes32"},{"internalType":"uint256","name":"_l2BatchNumber","type":"uint256"},{"internalType":"uint256","name":"_l2MessageIndex","type":"uint256"},{"internalType":"uint16","name":"_l2TxNumberInBatch","type":"uint16"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"},{"internalType":"enum TxStatus","name":"_status","type":"uint8"}],"name":"proveL1ToL2TransactionStatus","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"uint256","name":"_batchNumber","type":"uint256"},{"internalType":"uint256","name":"_index","type":"uint256"},{"components":[{"internalType":"uint8","name":"l2ShardId","type":"uint8"},{"internalType":"bool","name":"isService","type":"bool"},{"internalType":"uint16","name":"txNumberInBatch","type":"uint16"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"bytes32","name":"value","type":"bytes32"}],"internalType":"struct L2Log","name":"_log","type":"tuple"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"proveL2LogInclusion","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"uint256","name":"_batchNumber","type":"uint256"},{"internalType":"uint256","name":"_index","type":"uint256"},{"components":[{"internalType":"uint16","name":"txNumberInBatch","type":"uint16"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct L2Message","name":"_message","type":"tuple"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"proveL2MessageInclusion","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"address","name":"_zkChain","type":"address"}],"name":"registerAlreadyDeployedZKChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"}],"name":"registerLegacyChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"address","name":"_zkChain","type":"address"},{"internalType":"bool","name":"_checkMaxNumberOfZKChains","type":"bool"}],"name":"registerNewZKChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newSettlementLayerChainId","type":"uint256"},{"internalType":"bool","name":"_isWhitelisted","type":"bool"}],"name":"registerSettlementLayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_chainTypeManager","type":"address"}],"name":"removeChainTypeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint256","name":"mintValue","type":"uint256"},{"internalType":"address","name":"l2Contract","type":"address"},{"internalType":"uint256","name":"l2Value","type":"uint256"},{"internalType":"bytes","name":"l2Calldata","type":"bytes"},{"internalType":"uint256","name":"l2GasLimit","type":"uint256"},{"internalType":"uint256","name":"l2GasPerPubdataByteLimit","type":"uint256"},{"internalType":"bytes[]","name":"factoryDeps","type":"bytes[]"},{"internalType":"address","name":"refundRecipient","type":"address"}],"internalType":"struct L2TransactionRequestDirect","name":"_request","type":"tuple"}],"name":"requestL2TransactionDirect","outputs":[{"internalType":"bytes32","name":"canonicalTxHash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint256","name":"mintValue","type":"uint256"},{"internalType":"uint256","name":"l2Value","type":"uint256"},{"internalType":"uint256","name":"l2GasLimit","type":"uint256"},{"internalType":"uint256","name":"l2GasPerPubdataByteLimit","type":"uint256"},{"internalType":"address","name":"refundRecipient","type":"address"},{"internalType":"address","name":"secondBridgeAddress","type":"address"},{"internalType":"uint256","name":"secondBridgeValue","type":"uint256"},{"internalType":"bytes","name":"secondBridgeCalldata","type":"bytes"}],"internalType":"struct L2TransactionRequestTwoBridgesOuter","name":"_request","type":"tuple"}],"name":"requestL2TransactionTwoBridges","outputs":[{"internalType":"bytes32","name":"canonicalTxHash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_assetRouter","type":"address"},{"internalType":"contract ICTMDeploymentTracker","name":"_l1CtmDeployer","type":"address"},{"internalType":"contract IMessageRoot","name":"_messageRoot","type":"address"},{"internalType":"address","name":"_chainAssetHandler","type":"address"}],"name":"setAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_additionalData","type":"bytes32"},{"internalType":"address","name":"_assetAddress","type":"address"}],"name":"setCTMAssetAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_chainAssetHandler","type":"address"}],"name":"setChainAssetHandler","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newPendingAdmin","type":"address"}],"name":"setPendingAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"settlementLayer","outputs":[{"internalType":"uint256","name":"activeSettlementLayerChainId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sharedBridge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"whitelistedSettlementLayers","outputs":[{"internalType":"bool","name":"isWhitelistedSettlementLayer","type":"bool"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0x0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000e30dca3047b37dc7d88849de4a4dc07937ad5ab30000000000000000000000000000000000000000000000000000000000000064"}