{"file_path":"contracts/bridge/L1ERC20Bridge.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.28;\n\nimport {IERC20} from \"@openzeppelin/contracts-v4/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts-v4/token/ERC20/utils/SafeERC20.sol\";\n\nimport {IL1ERC20Bridge} from \"./interfaces/IL1ERC20Bridge.sol\";\nimport {FinalizeL1DepositParams, IL1Nullifier} from \"./interfaces/IL1Nullifier.sol\";\nimport {IL1NativeTokenVault} from \"./ntv/IL1NativeTokenVault.sol\";\nimport {IL1AssetRouter} from \"./asset-router/IL1AssetRouter.sol\";\n\nimport {L2ContractHelper} from \"../common/l2-helpers/L2ContractHelper.sol\";\nimport {ReentrancyGuard} from \"../common/ReentrancyGuard.sol\";\n\nimport {AssetRouterAllowanceNotZero, ETHDepositNotSupported, EmptyDeposit, TokensWithFeesNotSupported, WithdrawalAlreadyFinalized} from \"../common/L1ContractErrors.sol\";\nimport {ETH_TOKEN_ADDRESS} from \"../common/Config.sol\";\n\n/// @author Matter Labs\n/// @custom:security-contact security@matterlabs.dev\n/// @notice Smart contract that allows depositing ERC20 tokens from Ethereum to ZK chains\n/// @dev It is a legacy bridge from ZKsync Era, that was deprecated in favour of shared bridge.\n/// It is needed for backward compatibility with already integrated projects.\ncontract L1ERC20Bridge is IL1ERC20Bridge, ReentrancyGuard {\n    using SafeERC20 for IERC20;\n\n    /// @dev The shared bridge that is now used for all bridging, replacing the legacy contract.\n    IL1Nullifier public immutable override L1_NULLIFIER;\n\n    /// @dev The asset router, which holds deposited tokens.\n    IL1AssetRouter public immutable override L1_ASSET_ROUTER;\n\n    /// @dev The native token vault, which holds deposited tokens.\n    IL1NativeTokenVault public immutable override L1_NATIVE_TOKEN_VAULT;\n\n    /// @dev The chainId of Era\n    uint256 public immutable ERA_CHAIN_ID;\n\n    /// @dev A mapping L2 batch number => message number => flag.\n    /// @dev Used to indicate that L2 -> L1 message was already processed for ZKsync Era withdrawals.\n    // slither-disable-next-line uninitialized-state\n    mapping(uint256 l2BatchNumber => mapping(uint256 l2ToL1MessageNumber => bool isFinalized))\n        public isWithdrawalFinalized;\n\n    /// @dev A mapping account => L1 token address => L2 deposit transaction hash => amount.\n    /// @dev Used for saving the number of deposited funds, to claim them in case the deposit transaction will fail in ZKsync Era.\n    mapping(address account => mapping(address l1Token => mapping(bytes32 depositL2TxHash => uint256 amount)))\n        public depositAmount;\n\n    /// @dev The address that is used as a L2 bridge counterpart in ZKsync Era.\n    // slither-disable-next-line uninitialized-state\n    address public l2Bridge;\n\n    /// @dev The address that is used as a beacon for L2 tokens in ZKsync Era.\n    // slither-disable-next-line uninitialized-state\n    address public l2TokenBeacon;\n\n    /// @dev Stores the hash of the L2 token proxy contract's bytecode on ZKsync Era.\n    // slither-disable-next-line uninitialized-state\n    bytes32 public l2TokenProxyBytecodeHash;\n\n    /// @dev Deprecated storage variable related to withdrawal limitations.\n    mapping(address => uint256) private __DEPRECATED_lastWithdrawalLimitReset;\n\n    /// @dev Deprecated storage variable related to withdrawal limitations.\n    mapping(address => uint256) private __DEPRECATED_withdrawnAmountInWindow;\n\n    /// @dev Deprecated storage variable related to deposit limitations.\n    mapping(address => mapping(address => uint256)) private __DEPRECATED_totalDepositedAmountPerUser;\n\n    /// @dev Contract is expected to be used as proxy implementation.\n    /// @dev Initialize the implementation to prevent Parity hack.\n    constructor(\n        IL1Nullifier _nullifier,\n        IL1AssetRouter _assetRouter,\n        IL1NativeTokenVault _nativeTokenVault,\n        uint256 _eraChainId\n    ) reentrancyGuardInitializer {\n        L1_NULLIFIER = _nullifier;\n        L1_ASSET_ROUTER = _assetRouter;\n        L1_NATIVE_TOKEN_VAULT = _nativeTokenVault;\n        ERA_CHAIN_ID = _eraChainId;\n    }\n\n    /// @dev Initializes the reentrancy guard. Expected to be used in the proxy.\n    function initialize() external reentrancyGuardInitializer {}\n\n    /*//////////////////////////////////////////////////////////////\n                            ERA LEGACY FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Legacy deposit method with refunding the fee to the caller, use another `deposit` method instead.\n    /// @dev 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 _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    /// @return l2TxHash The L2 transaction hash of deposit finalization\n    /// NOTE: the function doesn't use `nonreentrant` modifier, because the inner method does.\n    function deposit(\n        address _l2Receiver,\n        address _l1Token,\n        uint256 _amount,\n        uint256 _l2TxGasLimit,\n        uint256 _l2TxGasPerPubdataByte\n    ) external payable returns (bytes32 l2TxHash) {\n        l2TxHash = deposit({\n            _l2Receiver: _l2Receiver,\n            _l1Token: _l1Token,\n            _amount: _amount,\n            _l2TxGasLimit: _l2TxGasLimit,\n            _l2TxGasPerPubdataByte: _l2TxGasPerPubdataByte,\n            _refundRecipient: address(0)\n        });\n    }\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 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 _l2BatchNumber,\n        uint256 _l2MessageIndex,\n        uint16 _l2TxNumberInBatch,\n        bytes calldata _message,\n        bytes32[] calldata _merkleProof\n    ) external nonReentrant {\n        if (isWithdrawalFinalized[_l2BatchNumber][_l2MessageIndex]) {\n            revert WithdrawalAlreadyFinalized();\n        }\n        // We don't need to set finalizeWithdrawal here, as we set it in the L1 Nullifier\n\n        FinalizeL1DepositParams memory finalizeWithdrawalParams = FinalizeL1DepositParams({\n            chainId: ERA_CHAIN_ID,\n            l2BatchNumber: _l2BatchNumber,\n            l2MessageIndex: _l2MessageIndex,\n            l2Sender: L1_NULLIFIER.l2BridgeAddress(ERA_CHAIN_ID),\n            l2TxNumberInBatch: _l2TxNumberInBatch,\n            message: _message,\n            merkleProof: _merkleProof\n        });\n        L1_NULLIFIER.finalizeDeposit(finalizeWithdrawalParams);\n    }\n\n    /// @notice Initiates a deposit by locking funds on the contract and sending the request\n    /// @dev 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 _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 l2TxHash The L2 transaction hash of deposit finalization\n    function deposit(\n        address _l2Receiver,\n        address _l1Token,\n        uint256 _amount,\n        uint256 _l2TxGasLimit,\n        uint256 _l2TxGasPerPubdataByte,\n        address _refundRecipient\n    ) public payable nonReentrant returns (bytes32 l2TxHash) {\n        if (_amount == 0) {\n            // empty deposit amount\n            revert EmptyDeposit();\n        }\n        if (_l1Token == ETH_TOKEN_ADDRESS) {\n            revert ETHDepositNotSupported();\n        }\n        uint256 amount = _approveFundsToAssetRouter(msg.sender, IERC20(_l1Token), _amount);\n        if (amount != _amount) {\n            // The token has non-standard transfer logic\n            revert TokensWithFeesNotSupported();\n        }\n\n        l2TxHash = L1_ASSET_ROUTER.depositLegacyErc20Bridge{value: msg.value}({\n            _originalCaller: msg.sender,\n            _l2Receiver: _l2Receiver,\n            _l1Token: _l1Token,\n            _amount: _amount,\n            _l2TxGasLimit: _l2TxGasLimit,\n            _l2TxGasPerPubdataByte: _l2TxGasPerPubdataByte,\n            _refundRecipient: _refundRecipient\n        });\n        // Ensuring that all the funds that were locked into this bridge were spent by the asset router / native token vault.\n        if (IERC20(_l1Token).allowance(address(this), address(L1_ASSET_ROUTER)) != 0) {\n            revert AssetRouterAllowanceNotZero();\n        }\n        depositAmount[msg.sender][_l1Token][l2TxHash] = _amount;\n        emit DepositInitiated({\n            l2DepositTxHash: l2TxHash,\n            from: msg.sender,\n            to: _l2Receiver,\n            l1Token: _l1Token,\n            amount: _amount\n        });\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                            ERA LEGACY FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /// @dev Transfers tokens from the depositor address to this contract and force approves those\n    /// to the asset router address.\n    /// @return The difference between the contract balance before and after the transferring of funds.\n    function _approveFundsToAssetRouter(address _from, IERC20 _token, uint256 _amount) internal returns (uint256) {\n        uint256 balanceBefore = _token.balanceOf(address(this));\n        _token.safeTransferFrom(_from, address(this), _amount);\n        _token.forceApprove(address(L1_ASSET_ROUTER), _amount);\n        uint256 balanceAfter = _token.balanceOf(address(this));\n\n        return balanceAfter - balanceBefore;\n    }\n\n    /// @dev Withdraw funds from the initiated deposit, that failed when finalizing on L2.\n    /// @param _depositSender The address of the deposit initiator\n    /// @param _l1Token The address of the deposited L1 ERC20 token\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    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 nonReentrant {\n        uint256 amount = depositAmount[_depositSender][_l1Token][_l2TxHash];\n        // empty deposit\n        if (amount == 0) {\n            revert EmptyDeposit();\n        }\n        delete depositAmount[_depositSender][_l1Token][_l2TxHash];\n\n        L1_NULLIFIER.claimFailedDepositLegacyErc20Bridge({\n            _depositSender: _depositSender,\n            _l1Token: _l1Token,\n            _amount: amount,\n            _l2TxHash: _l2TxHash,\n            _l2BatchNumber: _l2BatchNumber,\n            _l2MessageIndex: _l2MessageIndex,\n            _l2TxNumberInBatch: _l2TxNumberInBatch,\n            _merkleProof: _merkleProof\n        });\n        emit ClaimedFailedDeposit(_depositSender, _l1Token, amount);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                            ERA LEGACY GETTERS\n    //////////////////////////////////////////////////////////////*/\n\n    /// @return The L2 token address that would be minted for deposit of the given L1 token on ZKsync Era.\n    function l2TokenAddress(address _l1Token) external view returns (address) {\n        bytes32 constructorInputHash = keccak256(abi.encode(l2TokenBeacon, \"\"));\n        bytes32 salt = bytes32(uint256(uint160(_l1Token)));\n        return L2ContractHelper.computeCreate2Address(l2Bridge, salt, l2TokenProxyBytecodeHash, constructorInputHash);\n    }\n}\n","deployed_bytecode":"0x6080604052600436106100e4575f3560e01c8063823f1d9611610087578063e60ccaba11610057578063e60ccaba146102dc578063e8b99b1b1461030f578063ef011dff14610322578063f5f1516814610355575f5ffd5b8063823f1d9614610255578063933999fb1461026a578063ae1f6aaf1461027d578063cdf25430146102a9575f5ffd5b8063293e8520116100c2578063293e8520146101775780634bed8212146101cf5780636dde7209146102155780638129fc1c14610241575f5ffd5b806301eae183146100e857806311a2ccc11461013757806319fa7f6214610158575b5f5ffd5b3480156100f3575f5ffd5b506101246101023660046115a4565b600160209081525f938452604080852082529284528284209052825290205481565b6040519081526020015b60405180910390f35b348015610142575f5ffd5b50610156610151366004611640565b610374565b005b348015610163575f5ffd5b50610156610172366004611701565b6106db565b348015610182575f5ffd5b506101aa7f000000000000000000000000bed1eb542f9a5aa6419ff3deb921a372681111f681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161012e565b3480156101da575f5ffd5b506102056101e9366004611791565b5f60208181529281526040808220909352908152205460ff1681565b604051901515815260200161012e565b348015610220575f5ffd5b506003546101aa9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561024c575f5ffd5b5061015661097b565b348015610260575f5ffd5b5061012460045481565b6101246102783660046117b1565b610985565b348015610288575f5ffd5b506002546101aa9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b4575f5ffd5b506101aa7f0000000000000000000000008829ad80e425c646dab305381ff105169feece5681565b3480156102e7575f5ffd5b506101aa7f000000000000000000000000d7f9f54194c633f36ccd5f3da84ad4a1c38cb2cb81565b61012461031d3660046117fe565b61099e565b34801561032d575f5ffd5b506101247f000000000000000000000000000000000000000000000000000000000000014481565b348015610360575f5ffd5b506101aa61036f366004611861565b610dbf565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f8190036103d0576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001811461040a576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4555f888152602081815260408083208a845290915290205460ff161561047f576040517fae89945400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6040518060e001604052807f000000000000000000000000000000000000000000000000000000000000014481526020018a81526020018981526020017f000000000000000000000000d7f9f54194c633f36ccd5f3da84ad4a1c38cb2cb73ffffffffffffffffffffffffffffffffffffffff166307ee93557f00000000000000000000000000000000000000000000000000000000000001446040518263ffffffff1660e01b815260040161053891815260200190565b602060405180830381865afa158015610553573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105779190611883565b73ffffffffffffffffffffffffffffffffffffffff1681526020018861ffff16815260200187878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050509082525060408051602087810282810182019093528782529283019290918891889182918501908490808284375f9201919091525050509152506040517f74beea8200000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d7f9f54194c633f36ccd5f3da84ad4a1c38cb2cb16906374beea829061067f9084906004016118ea565b5f604051808303815f87803b158015610696575f5ffd5b505af11580156106a8573d5f5f3e3d5ffd5b505050505060017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4555050505050505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f819003610737576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114610771576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45573ffffffffffffffffffffffffffffffffffffffff808a165f908152600160209081526040808320938c1683529281528282208a83529052908120549081900361080b576040517f95b66fe900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808b165f9081526001602090815260408083208d8516845282528083208c845290915280822091909155517f8fbb37110000000000000000000000000000000000000000000000000000000081527f000000000000000000000000d7f9f54194c633f36ccd5f3da84ad4a1c38cb2cb90911690638fbb3711906108b7908d908d9086908e908e908e908e908e908e906004016119c2565b5f604051808303815f87803b1580156108ce575f5ffd5b505af11580156108e0573d5f5f3e3d5ffd5b505050508873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fbe066dc591f4a444f75176d387c3e6c775e5706d9ea9a91d11eb49030c66cf608360405161094391815260200190565b60405180910390a35060017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455505050505050505050565b610983610e85565b565b5f61099486868686865f61099e565b9695505050505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f908082036109fb576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114610a35576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455855f03610a92576040517f95b66fe900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff881601610b01576040517f627e087200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610b0d338989610ee8565b9050868114610b48576040517f23830e2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f9e6ea41700000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8a811660248301528981166044830152606482018990526084820188905260a4820187905285811660c48301527f0000000000000000000000008829ad80e425c646dab305381ff105169feece561690639e6ea41790349060e40160206040518083038185885af1158015610c00573d5f5f3e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190610c259190611a77565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008829ad80e425c646dab305381ff105169feece56811660248301529194509089169063dd62ed3e90604401602060405180830381865afa158015610cb9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cdd9190611a77565b15610d14576040517f11832de800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8d81168086529184528285208986528452938290208c905581519081529182018b9052918c16929186917fdd341179f4edc78148d894d0213a96d212af2cbaf223d19ef6d483bdd47ab81d910160405180910390a45060017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455509695505050505050565b6003546040805173ffffffffffffffffffffffffffffffffffffffff9283166020808301919091528183018390525f6060808401829052845180850390910181526080840185528051908301206002546004547f2020dba91b30cc0006188af794c2fb30dd8520db7e2c088b7fc7c103c00ca49460a087015290871660c086015295871660e0850181905261010085019690965261012080850182905285518086039091018152610140909401909452825192909101919091209092905b949350505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4805460019091558015610ee5576040517fdf3a8fdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa158015610f54573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f789190611a77565b9050610f9c73ffffffffffffffffffffffffffffffffffffffff8516863086611077565b610fdd73ffffffffffffffffffffffffffffffffffffffff85167f0000000000000000000000008829ad80e425c646dab305381ff105169feece5685611159565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa158015611047573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061106b9190611a77565b90506109948282611a8e565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526111539085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611244565b50505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790526111e5848261135b565b6111535760405173ffffffffffffffffffffffffffffffffffffffff841660248201525f604482015261123e9085907f095ea7b300000000000000000000000000000000000000000000000000000000906064016110d1565b61115384825b5f6112a5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166114189092919063ffffffff16565b905080515f14806112c55750808060200190518101906112c59190611ac6565b611356576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b505050565b5f5f5f8473ffffffffffffffffffffffffffffffffffffffff16846040516113839190611ae5565b5f604051808303815f865af19150503d805f81146113bc576040519150601f19603f3d011682016040523d82523d5f602084013e6113c1565b606091505b50915091508180156113eb5750805115806113eb5750808060200190518101906113eb9190611ac6565b801561140d575073ffffffffffffffffffffffffffffffffffffffff85163b15155b925050505b92915050565b6060610e7d84845f85855f5f8673ffffffffffffffffffffffffffffffffffffffff16858760405161144a9190611ae5565b5f6040518083038185875af1925050503d805f8114611484576040519150601f19603f3d011682016040523d82523d5f602084013e611489565b606091505b509150915061149a878383876114a5565b979650505050505050565b6060831561153a5782515f036115335773ffffffffffffffffffffffffffffffffffffffff85163b611533576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161134d565b5081610e7d565b610e7d838381511561154f5781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161134d9190611afb565b73ffffffffffffffffffffffffffffffffffffffff81168114610ee5575f5ffd5b5f5f5f606084860312156115b6575f5ffd5b83356115c181611583565b925060208401356115d181611583565b929592945050506040919091013590565b803561ffff811681146115f3575f5ffd5b919050565b5f5f83601f840112611608575f5ffd5b50813567ffffffffffffffff81111561161f575f5ffd5b6020830191508360208260051b8501011115611639575f5ffd5b9250929050565b5f5f5f5f5f5f5f60a0888a031215611656575f5ffd5b873596506020880135955061166d604089016115e2565b9450606088013567ffffffffffffffff811115611688575f5ffd5b8801601f81018a13611698575f5ffd5b803567ffffffffffffffff8111156116ae575f5ffd5b8a60208284010111156116bf575f5ffd5b60209190910194509250608088013567ffffffffffffffff8111156116e2575f5ffd5b6116ee8a828b016115f8565b989b979a50959850939692959293505050565b5f5f5f5f5f5f5f5f60e0898b031215611718575f5ffd5b883561172381611583565b9750602089013561173381611583565b965060408901359550606089013594506080890135935061175660a08a016115e2565b925060c089013567ffffffffffffffff811115611771575f5ffd5b61177d8b828c016115f8565b999c989b5096995094979396929594505050565b5f5f604083850312156117a2575f5ffd5b50508035926020909101359150565b5f5f5f5f5f60a086880312156117c5575f5ffd5b85356117d081611583565b945060208601356117e081611583565b94979496505050506040830135926060810135926080909101359150565b5f5f5f5f5f5f60c08789031215611813575f5ffd5b863561181e81611583565b9550602087013561182e81611583565b945060408701359350606087013592506080870135915060a087013561185381611583565b809150509295509295509295565b5f60208284031215611871575f5ffd5b813561187c81611583565b9392505050565b5f60208284031215611893575f5ffd5b815161187c81611583565b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815281516020820152602082015160408201526040820151606082015273ffffffffffffffffffffffffffffffffffffffff606083015116608082015261ffff60808301511660a08201525f60a083015160e060c084015261195261010084018261189e565b60c08501518482037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00160e08601528051808352602091820193505f9291909101905b808310156119b85783518252602082019150602084019350600183019250611995565b5095945050505050565b73ffffffffffffffffffffffffffffffffffffffff8a16815273ffffffffffffffffffffffffffffffffffffffff891660208201528760408201528660608201528560808201528460a082015261ffff841660c082015261010060e0820152816101008201525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115611a55575f5ffd5b8260051b808561012085013791909101610120019a9950505050505050505050565b5f60208284031215611a87575f5ffd5b5051919050565b81810381811115611412577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60208284031215611ad6575f5ffd5b8151801515811461187c575f5ffd5b5f82518060208501845e5f920191825250919050565b602081525f61187c602083018461189e56fea2646970667358221220173c3fe2624daeccbce4212524fa1803523631fdfd35859cad05b6ba83d3369a64736f6c634300081c0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":9999999},"outputSelection":{"*":{"":["*"],"*":["*"]}},"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":null,"decoded_constructor_args":[["0xD7f9f54194C633F36CCD5F3da84ad4a1c38cB2cB",{"internalType":"contract IL1Nullifier","name":"_nullifier","type":"address"}],["0x8829AD80E425C646DAB305381ff105169FeEcE56",{"internalType":"contract IL1AssetRouter","name":"_assetRouter","type":"address"}],["0xbeD1EB542f9a5aA6419Ff3deb921A372681111f6",{"internalType":"contract IL1NativeTokenVault","name":"_nativeTokenVault","type":"address"}],["324",{"internalType":"uint256","name":"_eraChainId","type":"uint256"}]],"compiler_version":"v0.8.28+commit.7893614a","is_verified_via_verifier_alliance":false,"verified_at":"2026-02-21T02:21:27.614653Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x610100604052348015610010575f5ffd5b50604051611cb5380380611cb583398101604081905261002f916100b7565b610037610059565b6001600160a01b0393841660805291831660a05290911660c05260e052610107565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf48054600190915580156100a05760405163df3a8fdd60e01b815260040160405180910390fd5b50565b6001600160a01b03811681146100a0575f5ffd5b5f5f5f5f608085870312156100ca575f5ffd5b84516100d5816100a3565b60208601519094506100e6816100a3565b60408601519093506100f7816100a3565b6060959095015193969295505050565b60805160a05160c05160e051611b436101725f395f81816103330152818161048d01526104fb01525f61018801525f81816102ba01528181610bb801528181610c680152610fb801525f81816102ed015281816104bf0152818161064a01526108700152611b435ff3fe6080604052600436106100e4575f3560e01c8063823f1d9611610087578063e60ccaba11610057578063e60ccaba146102dc578063e8b99b1b1461030f578063ef011dff14610322578063f5f1516814610355575f5ffd5b8063823f1d9614610255578063933999fb1461026a578063ae1f6aaf1461027d578063cdf25430146102a9575f5ffd5b8063293e8520116100c2578063293e8520146101775780634bed8212146101cf5780636dde7209146102155780638129fc1c14610241575f5ffd5b806301eae183146100e857806311a2ccc11461013757806319fa7f6214610158575b5f5ffd5b3480156100f3575f5ffd5b506101246101023660046115a4565b600160209081525f938452604080852082529284528284209052825290205481565b6040519081526020015b60405180910390f35b348015610142575f5ffd5b50610156610151366004611640565b610374565b005b348015610163575f5ffd5b50610156610172366004611701565b6106db565b348015610182575f5ffd5b506101aa7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161012e565b3480156101da575f5ffd5b506102056101e9366004611791565b5f60208181529281526040808220909352908152205460ff1681565b604051901515815260200161012e565b348015610220575f5ffd5b506003546101aa9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561024c575f5ffd5b5061015661097b565b348015610260575f5ffd5b5061012460045481565b6101246102783660046117b1565b610985565b348015610288575f5ffd5b506002546101aa9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b4575f5ffd5b506101aa7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102e7575f5ffd5b506101aa7f000000000000000000000000000000000000000000000000000000000000000081565b61012461031d3660046117fe565b61099e565b34801561032d575f5ffd5b506101247f000000000000000000000000000000000000000000000000000000000000000081565b348015610360575f5ffd5b506101aa61036f366004611861565b610dbf565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f8190036103d0576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001811461040a576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4555f888152602081815260408083208a845290915290205460ff161561047f576040517fae89945400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6040518060e001604052807f000000000000000000000000000000000000000000000000000000000000000081526020018a81526020018981526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166307ee93557f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040161053891815260200190565b602060405180830381865afa158015610553573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105779190611883565b73ffffffffffffffffffffffffffffffffffffffff1681526020018861ffff16815260200187878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050509082525060408051602087810282810182019093528782529283019290918891889182918501908490808284375f9201919091525050509152506040517f74beea8200000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906374beea829061067f9084906004016118ea565b5f604051808303815f87803b158015610696575f5ffd5b505af11580156106a8573d5f5f3e3d5ffd5b505050505060017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4555050505050505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f819003610737576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114610771576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45573ffffffffffffffffffffffffffffffffffffffff808a165f908152600160209081526040808320938c1683529281528282208a83529052908120549081900361080b576040517f95b66fe900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808b165f9081526001602090815260408083208d8516845282528083208c845290915280822091909155517f8fbb37110000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000090911690638fbb3711906108b7908d908d9086908e908e908e908e908e908e906004016119c2565b5f604051808303815f87803b1580156108ce575f5ffd5b505af11580156108e0573d5f5f3e3d5ffd5b505050508873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fbe066dc591f4a444f75176d387c3e6c775e5706d9ea9a91d11eb49030c66cf608360405161094391815260200190565b60405180910390a35060017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455505050505050505050565b610983610e85565b565b5f61099486868686865f61099e565b9695505050505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f908082036109fb576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114610a35576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455855f03610a92576040517f95b66fe900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff881601610b01576040517f627e087200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610b0d338989610ee8565b9050868114610b48576040517f23830e2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f9e6ea41700000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8a811660248301528981166044830152606482018990526084820188905260a4820187905285811660c48301527f00000000000000000000000000000000000000000000000000000000000000001690639e6ea41790349060e40160206040518083038185885af1158015610c00573d5f5f3e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190610c259190611a77565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660248301529194509089169063dd62ed3e90604401602060405180830381865afa158015610cb9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cdd9190611a77565b15610d14576040517f11832de800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8d81168086529184528285208986528452938290208c905581519081529182018b9052918c16929186917fdd341179f4edc78148d894d0213a96d212af2cbaf223d19ef6d483bdd47ab81d910160405180910390a45060017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455509695505050505050565b6003546040805173ffffffffffffffffffffffffffffffffffffffff9283166020808301919091528183018390525f6060808401829052845180850390910181526080840185528051908301206002546004547f2020dba91b30cc0006188af794c2fb30dd8520db7e2c088b7fc7c103c00ca49460a087015290871660c086015295871660e0850181905261010085019690965261012080850182905285518086039091018152610140909401909452825192909101919091209092905b949350505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4805460019091558015610ee5576040517fdf3a8fdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa158015610f54573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f789190611a77565b9050610f9c73ffffffffffffffffffffffffffffffffffffffff8516863086611077565b610fdd73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611159565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa158015611047573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061106b9190611a77565b90506109948282611a8e565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526111539085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611244565b50505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790526111e5848261135b565b6111535760405173ffffffffffffffffffffffffffffffffffffffff841660248201525f604482015261123e9085907f095ea7b300000000000000000000000000000000000000000000000000000000906064016110d1565b61115384825b5f6112a5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166114189092919063ffffffff16565b905080515f14806112c55750808060200190518101906112c59190611ac6565b611356576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b505050565b5f5f5f8473ffffffffffffffffffffffffffffffffffffffff16846040516113839190611ae5565b5f604051808303815f865af19150503d805f81146113bc576040519150601f19603f3d011682016040523d82523d5f602084013e6113c1565b606091505b50915091508180156113eb5750805115806113eb5750808060200190518101906113eb9190611ac6565b801561140d575073ffffffffffffffffffffffffffffffffffffffff85163b15155b925050505b92915050565b6060610e7d84845f85855f5f8673ffffffffffffffffffffffffffffffffffffffff16858760405161144a9190611ae5565b5f6040518083038185875af1925050503d805f8114611484576040519150601f19603f3d011682016040523d82523d5f602084013e611489565b606091505b509150915061149a878383876114a5565b979650505050505050565b6060831561153a5782515f036115335773ffffffffffffffffffffffffffffffffffffffff85163b611533576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161134d565b5081610e7d565b610e7d838381511561154f5781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161134d9190611afb565b73ffffffffffffffffffffffffffffffffffffffff81168114610ee5575f5ffd5b5f5f5f606084860312156115b6575f5ffd5b83356115c181611583565b925060208401356115d181611583565b929592945050506040919091013590565b803561ffff811681146115f3575f5ffd5b919050565b5f5f83601f840112611608575f5ffd5b50813567ffffffffffffffff81111561161f575f5ffd5b6020830191508360208260051b8501011115611639575f5ffd5b9250929050565b5f5f5f5f5f5f5f60a0888a031215611656575f5ffd5b873596506020880135955061166d604089016115e2565b9450606088013567ffffffffffffffff811115611688575f5ffd5b8801601f81018a13611698575f5ffd5b803567ffffffffffffffff8111156116ae575f5ffd5b8a60208284010111156116bf575f5ffd5b60209190910194509250608088013567ffffffffffffffff8111156116e2575f5ffd5b6116ee8a828b016115f8565b989b979a50959850939692959293505050565b5f5f5f5f5f5f5f5f60e0898b031215611718575f5ffd5b883561172381611583565b9750602089013561173381611583565b965060408901359550606089013594506080890135935061175660a08a016115e2565b925060c089013567ffffffffffffffff811115611771575f5ffd5b61177d8b828c016115f8565b999c989b5096995094979396929594505050565b5f5f604083850312156117a2575f5ffd5b50508035926020909101359150565b5f5f5f5f5f60a086880312156117c5575f5ffd5b85356117d081611583565b945060208601356117e081611583565b94979496505050506040830135926060810135926080909101359150565b5f5f5f5f5f5f60c08789031215611813575f5ffd5b863561181e81611583565b9550602087013561182e81611583565b945060408701359350606087013592506080870135915060a087013561185381611583565b809150509295509295509295565b5f60208284031215611871575f5ffd5b813561187c81611583565b9392505050565b5f60208284031215611893575f5ffd5b815161187c81611583565b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815281516020820152602082015160408201526040820151606082015273ffffffffffffffffffffffffffffffffffffffff606083015116608082015261ffff60808301511660a08201525f60a083015160e060c084015261195261010084018261189e565b60c08501518482037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00160e08601528051808352602091820193505f9291909101905b808310156119b85783518252602082019150602084019350600183019250611995565b5095945050505050565b73ffffffffffffffffffffffffffffffffffffffff8a16815273ffffffffffffffffffffffffffffffffffffffff891660208201528760408201528660608201528560808201528460a082015261ffff841660c082015261010060e0820152816101008201525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115611a55575f5ffd5b8260051b808561012085013791909101610120019a9950505050505050505050565b5f60208284031215611a87575f5ffd5b5051919050565b81810381811115611412577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60208284031215611ad6575f5ffd5b8151801515811461187c575f5ffd5b5f82518060208501845e5f920191825250919050565b602081525f61187c602083018461189e56fea2646970667358221220173c3fe2624daeccbce4212524fa1803523631fdfd35859cad05b6ba83d3369a64736f6c634300081c0033000000000000000000000000d7f9f54194c633f36ccd5f3da84ad4a1c38cb2cb0000000000000000000000008829ad80e425c646dab305381ff105169feece56000000000000000000000000bed1eb542f9a5aa6419ff3deb921a372681111f60000000000000000000000000000000000000000000000000000000000000144","name":"L1ERC20Bridge","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":false,"additional_sources":[{"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/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/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/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/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/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/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/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/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/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/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/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/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/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/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":"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/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/common/l2-helpers/L2ContractHelper.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 {BytecodeError, LengthIsNotDivisibleBy32, MalformedBytecode} from \"../L1ContractErrors.sol\";\n\nimport {UncheckedMath} from \"../libraries/UncheckedMath.sol\";\nimport {L2_TO_L1_MESSENGER_SYSTEM_CONTRACT} from \"./L2ContractAddresses.sol\";\n\n/**\n * @author Matter Labs\n * @custom:security-contact security@matterlabs.dev\n * @notice Interface for the contract that is used to deploy contracts on L2.\n */\ninterface IContractDeployer {\n    /// @notice A struct that describes a forced deployment on an address.\n    /// @param bytecodeHash The bytecode hash to put on an address.\n    /// @param newAddress The address on which to deploy the bytecodehash to.\n    /// @param callConstructor Whether to run the constructor on the force deployment.\n    /// @param value The `msg.value` with which to initialize a contract.\n    /// @param input The constructor calldata.\n    struct ForceDeployment {\n        bytes32 bytecodeHash;\n        address newAddress;\n        bool callConstructor;\n        uint256 value;\n        bytes input;\n    }\n\n    /// @notice This method is to be used only during an upgrade to set bytecodes on specific addresses.\n    /// @param _deployParams A set of parameters describing force deployment.\n    function forceDeployOnAddresses(ForceDeployment[] calldata _deployParams) external payable;\n\n    /// @notice Creates a new contract at a determined address using the `CREATE2` salt on L2\n    /// @param _salt a unique value to create the deterministic address of the new contract\n    /// @param _bytecodeHash the bytecodehash of the new contract to be deployed\n    /// @param _input the calldata to be sent to the constructor of the new contract\n    function create2(bytes32 _salt, bytes32 _bytecodeHash, bytes calldata _input) external returns (address);\n}\n\n/**\n * @author Matter Labs\n * @custom:security-contact security@matterlabs.dev\n * @notice Helper library for working with L2 contracts on L1.\n */\nlibrary L2ContractHelper {\n    using UncheckedMath for uint256;\n\n    /// @dev The prefix used to create CREATE2 addresses.\n    bytes32 private constant CREATE2_PREFIX = keccak256(\"zksyncCreate2\");\n\n    /// @dev Prefix used during derivation of account addresses using CREATE\n    /// @dev keccak256(\"zksyncCreate\")\n    bytes32 private constant CREATE_PREFIX = 0x63bae3a9951d38e8a3fbb7b70909afc1200610fc5bc55ade242f815974674f23;\n\n    /// @notice Sends L2 -> L1 arbitrary-long message through the system contract messenger.\n    /// @param _message Data to be sent to L1.\n    /// @return keccak256 hash of the sent message.\n    function sendMessageToL1(bytes memory _message) internal returns (bytes32) {\n        return L2_TO_L1_MESSENGER_SYSTEM_CONTRACT.sendToL1(_message);\n    }\n\n    /// @notice Validate the bytecode format and calculate its hash.\n    /// @param _bytecode The bytecode to hash.\n    /// @return hashedBytecode The 32-byte hash of the bytecode.\n    /// Note: The function reverts the execution if the bytecode has non expected format:\n    /// - Bytecode bytes length is not a multiple of 32\n    /// - Bytecode bytes length is not less than 2^21 bytes (2^16 words)\n    /// - Bytecode words length is not odd\n    function hashL2Bytecode(bytes memory _bytecode) internal pure returns (bytes32 hashedBytecode) {\n        // Note that the length of the bytecode must be provided in 32-byte words.\n        if (_bytecode.length % 32 != 0) {\n            revert LengthIsNotDivisibleBy32(_bytecode.length);\n        }\n\n        uint256 bytecodeLenInWords = _bytecode.length / 32;\n        // bytecode length must be less than 2^16 words\n        if (bytecodeLenInWords >= 2 ** 16) {\n            revert MalformedBytecode(BytecodeError.NumberOfWords);\n        }\n        // bytecode length in words must be odd\n        if (bytecodeLenInWords % 2 == 0) {\n            revert MalformedBytecode(BytecodeError.WordsMustBeOdd);\n        }\n        hashedBytecode = sha256(_bytecode) & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n        // Setting the version of the hash\n        hashedBytecode = (hashedBytecode | bytes32(uint256(1 << 248)));\n        // Setting the length\n        hashedBytecode = hashedBytecode | bytes32(bytecodeLenInWords << 224);\n    }\n\n    /// @notice Validate the bytecode format and calculate its hash.\n    /// @param _bytecode The bytecode to hash.\n    /// @return hashedBytecode The 32-byte hash of the bytecode.\n    /// Note: The function reverts the execution if the bytecode has non expected format:\n    /// - Bytecode bytes length is not a multiple of 32\n    /// - Bytecode bytes length is not less than 2^21 bytes (2^16 words)\n    /// - Bytecode words length is not odd\n    function hashL2BytecodeCalldata(bytes calldata _bytecode) internal pure returns (bytes32 hashedBytecode) {\n        // Note that the length of the bytecode must be provided in 32-byte words.\n        if (_bytecode.length % 32 != 0) {\n            revert LengthIsNotDivisibleBy32(_bytecode.length);\n        }\n\n        uint256 bytecodeLenInWords = _bytecode.length / 32;\n        // bytecode length must be less than 2^16 words\n        if (bytecodeLenInWords >= 2 ** 16) {\n            revert MalformedBytecode(BytecodeError.NumberOfWords);\n        }\n        // bytecode length in words must be odd\n        if (bytecodeLenInWords % 2 == 0) {\n            revert MalformedBytecode(BytecodeError.WordsMustBeOdd);\n        }\n        hashedBytecode = sha256(_bytecode) & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n        // Setting the version of the hash\n        hashedBytecode = (hashedBytecode | bytes32(uint256(1 << 248)));\n        // Setting the length\n        hashedBytecode = hashedBytecode | bytes32(bytecodeLenInWords << 224);\n    }\n\n    /// @notice Validates the format of the given bytecode hash.\n    /// @dev Due to the specification of the L2 bytecode hash, not every 32 bytes could be a legit bytecode hash.\n    /// @dev The function reverts on invalid bytecode hash format.\n    /// @param _bytecodeHash The hash of the bytecode to validate.\n    function validateBytecodeHash(bytes32 _bytecodeHash) internal pure {\n        uint8 version = uint8(_bytecodeHash[0]);\n        // Incorrectly formatted bytecodeHash\n        if (version != 1 || _bytecodeHash[1] != bytes1(0)) {\n            revert MalformedBytecode(BytecodeError.Version);\n        }\n\n        // Code length in words must be odd\n        if (bytecodeLen(_bytecodeHash) % 2 == 0) {\n            revert MalformedBytecode(BytecodeError.WordsMustBeOdd);\n        }\n    }\n\n    /// @notice Returns the length of the bytecode associated with the given hash.\n    /// @param _bytecodeHash The hash of the bytecode.\n    /// @return codeLengthInWords The length of the bytecode in words.\n    function bytecodeLen(bytes32 _bytecodeHash) internal pure returns (uint256 codeLengthInWords) {\n        codeLengthInWords = uint256(uint8(_bytecodeHash[2])) * 256 + uint256(uint8(_bytecodeHash[3]));\n    }\n\n    /// @notice Computes the create2 address for a Layer 2 contract.\n    /// @param _sender The address of the sender.\n    /// @param _salt The salt value to use in the create2 address computation.\n    /// @param _bytecodeHash The contract bytecode hash.\n    /// @param _constructorInputHash The hash of the constructor input data.\n    /// @return The create2 address of the contract.\n    /// NOTE: L2 create2 derivation is different from L1 derivation!\n    function computeCreate2Address(\n        address _sender,\n        bytes32 _salt,\n        bytes32 _bytecodeHash,\n        bytes32 _constructorInputHash\n    ) internal pure returns (address) {\n        bytes32 senderBytes = bytes32(uint256(uint160(_sender)));\n        bytes32 data = keccak256(\n            // solhint-disable-next-line func-named-parameters\n            bytes.concat(CREATE2_PREFIX, senderBytes, _salt, _bytecodeHash, _constructorInputHash)\n        );\n\n        return address(uint160(uint256(data)));\n    }\n\n    /// @notice Calculates the address of a deployed contract via create\n    /// @param _sender The account that deploys the contract.\n    /// @param _senderNonce The deploy nonce of the sender's account.\n    /// NOTE: L2 create derivation is different from L1 derivation!\n    function computeCreateAddress(address _sender, uint256 _senderNonce) internal pure returns (address) {\n        // No collision is possible with the Ethereum's CREATE, since\n        // the prefix begins with 0x63....\n        bytes32 hash = keccak256(\n            bytes.concat(CREATE_PREFIX, bytes32(uint256(uint160(_sender))), bytes32(_senderNonce))\n        );\n\n        return address(uint160(uint256(hash)));\n    }\n\n    /// @notice Hashes the L2 bytecodes and returns them in the format in which they are processed by the bootloader\n    function hashFactoryDeps(bytes[] memory _factoryDeps) internal pure returns (uint256[] memory hashedFactoryDeps) {\n        uint256 factoryDepsLen = _factoryDeps.length;\n        hashedFactoryDeps = new uint256[](factoryDepsLen);\n        for (uint256 i = 0; i < factoryDepsLen; i = i.uncheckedInc()) {\n            bytes32 hashedBytecode = hashL2Bytecode(_factoryDeps[i]);\n\n            // Store the resulting hash sequentially in words.\n            assembly {\n                mstore(add(hashedFactoryDeps, mul(add(i, 1), 32)), hashedBytecode)\n            }\n        }\n    }\n}\n"},{"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/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":"lib/openzeppelin-contracts-v4/contracts/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"},{"file_path":"lib/openzeppelin-contracts-v4/contracts/token/ERC20/extensions/IERC20Permit.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n *     doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n *     token.safeTransferFrom(msg.sender, address(this), value);\n *     ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     *\n     * CAUTION: See Security Considerations above.\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"},{"file_path":"lib/openzeppelin-contracts-v4/contracts/token/ERC20/utils/SafeERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(IERC20 token, address spender, uint256 value) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n     * Revert on invalid signature.\n     */\n    function safePermit(\n        IERC20Permit token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return\n            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts-v4/contracts/utils/Address.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 Address {\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"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"contract IL1Nullifier","name":"_nullifier","type":"address"},{"internalType":"contract IL1AssetRouter","name":"_assetRouter","type":"address"},{"internalType":"contract IL1NativeTokenVault","name":"_nativeTokenVault","type":"address"},{"internalType":"uint256","name":"_eraChainId","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AssetRouterAllowanceNotZero","type":"error"},{"inputs":[],"name":"ETHDepositNotSupported","type":"error"},{"inputs":[],"name":"EmptyDeposit","type":"error"},{"inputs":[],"name":"NotInitializedReentrancyGuard","type":"error"},{"inputs":[],"name":"Reentrancy","type":"error"},{"inputs":[],"name":"SlotOccupied","type":"error"},{"inputs":[],"name":"TokensWithFeesNotSupported","type":"error"},{"inputs":[],"name":"WithdrawalAlreadyFinalized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"l1Token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClaimedFailedDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"l2DepositTxHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"l1Token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DepositInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"l1Token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawalFinalized","type":"event"},{"inputs":[],"name":"ERA_CHAIN_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"L1_ASSET_ROUTER","outputs":[{"internalType":"contract IL1AssetRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"L1_NATIVE_TOKEN_VAULT","outputs":[{"internalType":"contract IL1NativeTokenVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"L1_NULLIFIER","outputs":[{"internalType":"contract IL1Nullifier","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_depositSender","type":"address"},{"internalType":"address","name":"_l1Token","type":"address"},{"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[]"}],"name":"claimFailedDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_l2Receiver","type":"address"},{"internalType":"address","name":"_l1Token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_l2TxGasLimit","type":"uint256"},{"internalType":"uint256","name":"_l2TxGasPerPubdataByte","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"bytes32","name":"l2TxHash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_l2Receiver","type":"address"},{"internalType":"address","name":"_l1Token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_l2TxGasLimit","type":"uint256"},{"internalType":"uint256","name":"_l2TxGasPerPubdataByte","type":"uint256"},{"internalType":"address","name":"_refundRecipient","type":"address"}],"name":"deposit","outputs":[{"internalType":"bytes32","name":"l2TxHash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"l1Token","type":"address"},{"internalType":"bytes32","name":"depositL2TxHash","type":"bytes32"}],"name":"depositAmount","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_l2BatchNumber","type":"uint256"},{"internalType":"uint256","name":"_l2MessageIndex","type":"uint256"},{"internalType":"uint16","name":"_l2TxNumberInBatch","type":"uint16"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"finalizeWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"l2BatchNumber","type":"uint256"},{"internalType":"uint256","name":"l2ToL1MessageNumber","type":"uint256"}],"name":"isWithdrawalFinalized","outputs":[{"internalType":"bool","name":"isFinalized","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l2Bridge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_l1Token","type":"address"}],"name":"l2TokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l2TokenBeacon","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l2TokenProxyBytecodeHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"000000000000000000000000d7f9f54194c633f36ccd5f3da84ad4a1c38cb2cb0000000000000000000000008829ad80e425c646dab305381ff105169feece56000000000000000000000000bed1eb542f9a5aa6419ff3deb921a372681111f60000000000000000000000000000000000000000000000000000000000000144"}