ETH Price: $2,954.22 (+0.05%)

Contract

0x3e267e071c7e9d0F3A80a0Bf199cbE5F0ff9Da05

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Withdraw133028992025-07-02 16:57:12206 days ago1751475432IN
0x3e267e07...F0ff9Da05
0 ETH0.000004450.046
Transfer98699372025-05-22 13:54:21247 days ago1747922061IN
0x3e267e07...F0ff9Da05
19.9 ETH0.000004980.046
Set Authorized97505732025-05-21 4:06:56248 days ago1747800416IN
0x3e267e07...F0ff9Da05
0 ETH0.000003720.04525
Set Authorized97505732025-05-21 4:06:56248 days ago1747800416IN
0x3e267e07...F0ff9Da05
0 ETH0.000003720.04525
Set Authorized97505732025-05-21 4:06:56248 days ago1747800416IN
0x3e267e07...F0ff9Da05
0 ETH0.000003720.04525
Set Authorized97505732025-05-21 4:06:56248 days ago1747800416IN
0x3e267e07...F0ff9Da05
0 ETH0.000004560.04525
Transfer96976792025-05-20 13:08:49249 days ago1747746529IN
0x3e267e07...F0ff9Da05
0.1 ETH0.000004910.046
Set Authorized96133912025-05-19 13:16:49250 days ago1747660609IN
0x3e267e07...F0ff9Da05
0 ETH0.000004160.046
Set Authorized96133742025-05-19 13:16:32250 days ago1747660592IN
0x3e267e07...F0ff9Da05
0 ETH0.000004160.046
Set Authorized96133352025-05-19 13:15:53250 days ago1747660553IN
0x3e267e07...F0ff9Da05
0 ETH0.000004160.046
Set Authorized96133212025-05-19 13:15:39250 days ago1747660539IN
0x3e267e07...F0ff9Da05
0 ETH0.000004160.046
Set Authorized96132882025-05-19 13:15:06250 days ago1747660506IN
0x3e267e07...F0ff9Da05
0 ETH0.000004080.046
Set Authorized96132752025-05-19 13:14:53250 days ago1747660493IN
0x3e267e07...F0ff9Da05
0 ETH0.000004080.046
Set Authorized96132552025-05-19 13:14:33250 days ago1747660473IN
0x3e267e07...F0ff9Da05
0 ETH0.000004080.046
Set Authorized96132412025-05-19 13:14:19250 days ago1747660459IN
0x3e267e07...F0ff9Da05
0 ETH0.000004860.046
Set Authorized93699802025-05-16 15:45:46253 days ago1747410346IN
0x3e267e07...F0ff9Da05
0 ETH0.000004320.046
Set Authorized93699542025-05-16 15:45:20253 days ago1747410320IN
0x3e267e07...F0ff9Da05
0 ETH0.000004320.046
Set Authorized93697842025-05-16 15:42:30253 days ago1747410150IN
0x3e267e07...F0ff9Da05
0 ETH0.000004320.046
Set Authorized93697712025-05-16 15:42:17253 days ago1747410137IN
0x3e267e07...F0ff9Da05
0 ETH0.000005180.046
Withdraw93695402025-05-16 15:38:15253 days ago1747409895IN
0x3e267e07...F0ff9Da05
0 ETH0.000004350.04525
Transfer93690612025-05-16 15:30:05253 days ago1747409405IN
0x3e267e07...F0ff9Da05
0.00001 ETH0.000004370.046

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
133028992025-07-02 16:57:12206 days ago1751475432
0x3e267e07...F0ff9Da05
16.25100102 ETH
104946322025-05-29 23:56:06240 days ago1748562966
0x3e267e07...F0ff9Da05
0.00001147 ETH
104945622025-05-29 23:54:55240 days ago1748562895
0x3e267e07...F0ff9Da05
0.00001152 ETH
104943952025-05-29 23:51:51240 days ago1748562711
0x3e267e07...F0ff9Da05
0.00001155 ETH
104943562025-05-29 23:51:12240 days ago1748562672
0x3e267e07...F0ff9Da05
0.00001151 ETH
104942802025-05-29 23:49:52240 days ago1748562592
0x3e267e07...F0ff9Da05
0.00001151 ETH
104942412025-05-29 23:49:10240 days ago1748562550
0x3e267e07...F0ff9Da05
0.00001151 ETH
104937622025-05-29 23:41:03240 days ago1748562063
0x3e267e07...F0ff9Da05
0.00001155 ETH
104937542025-05-29 23:40:55240 days ago1748562055
0x3e267e07...F0ff9Da05
0.00001151 ETH
104937452025-05-29 23:40:46240 days ago1748562046
0x3e267e07...F0ff9Da05
0.00001152 ETH
104937392025-05-29 23:40:38240 days ago1748562038
0x3e267e07...F0ff9Da05
0.00001159 ETH
104937302025-05-29 23:40:29240 days ago1748562029
0x3e267e07...F0ff9Da05
0.0000115 ETH
104937192025-05-29 23:40:18240 days ago1748562018
0x3e267e07...F0ff9Da05
0.00001156 ETH
104933892025-05-29 23:34:28240 days ago1748561668
0x3e267e07...F0ff9Da05
0.00001149 ETH
104933672025-05-29 23:34:05240 days ago1748561645
0x3e267e07...F0ff9Da05
0.00001141 ETH
104931322025-05-29 23:30:07240 days ago1748561407
0x3e267e07...F0ff9Da05
0.00001149 ETH
104931032025-05-29 23:29:37240 days ago1748561377
0x3e267e07...F0ff9Da05
0.00001141 ETH
104928282025-05-29 23:24:43240 days ago1748561083
0x3e267e07...F0ff9Da05
0.00001156 ETH
104926892025-05-29 23:22:21240 days ago1748560941
0x3e267e07...F0ff9Da05
0.00001148 ETH
104926382025-05-29 23:21:29240 days ago1748560889
0x3e267e07...F0ff9Da05
0.00001148 ETH
104926282025-05-29 23:21:19240 days ago1748560879
0x3e267e07...F0ff9Da05
0.00001156 ETH
104925522025-05-29 23:20:01240 days ago1748560801
0x3e267e07...F0ff9Da05
0.00001149 ETH
104925342025-05-29 23:19:43240 days ago1748560783
0x3e267e07...F0ff9Da05
0.00001158 ETH
104925082025-05-29 23:19:17240 days ago1748560757
0x3e267e07...F0ff9Da05
0.00001154 ETH
104924922025-05-29 23:19:01240 days ago1748560741
0x3e267e07...F0ff9Da05
0.00001148 ETH
View All Internal Transactions
Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AGWMintPaymaster

Compiler Version
v0.8.28+commit.7893614a

ZkSolc Version
v1.5.11

Optimization Enabled:
Yes with Mode 3

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

import {Transaction} from "@zksync-contracts-0.0.1/contracts/system-contracts/libraries/TransactionHelper.sol";
import {
    IPaymaster,
    ExecutionResult,
    PAYMASTER_VALIDATION_SUCCESS_MAGIC
} from "@zksync-contracts-0.0.1/contracts/system-contracts/interfaces/IPaymaster.sol";
import {BOOTLOADER_FORMAL_ADDRESS} from "@zksync-contracts-0.0.1/contracts/system-contracts/Constants.sol";
import {Ownable} from "solady-0.1.12/src/auth/Ownable.sol";
import {SafeTransferLib} from "solady-0.1.12/src/utils/ext/zksync/SafeTransferLib.sol";
import {IAGWRegistry} from "./interfaces/IAGWRegistry.sol";

contract AGWMintPaymaster is IPaymaster, Ownable {
    using SafeTransferLib for address;
    using SafeTransferLib for address payable;

    error OnlyBootloader();
    error OnlyAGW();
    error WithdrawalFailed();
    error BootloaderCallFailed();
    error UnauthorizedCall();

    mapping(address target => mapping(bytes4 selector => bool authorized)) private _authorizedCalls;

    IAGWRegistry public immutable AGW_REGISTRY = IAGWRegistry(0xd5E3efDA6bB5aB545cc2358796E96D9033496Dda);

    constructor(address _owner) {
        _initializeOwner(_owner);
    }

    function validateAndPayForPaymasterTransaction(bytes32, bytes32, Transaction calldata _transaction)
        external
        payable
        returns (bytes4 magic, bytes memory context)
    {
        if (msg.sender != BOOTLOADER_FORMAL_ADDRESS) {
            revert OnlyBootloader();
        }

        if (!AGW_REGISTRY.isAGW(address(uint160(_transaction.from)))) {
            revert OnlyAGW();
        }

        address target = address(uint160(_transaction.to));

        if (_transaction.data.length == 0) {
            revert UnauthorizedCall();
        }

        bytes4 selector = bytes4(_transaction.data[0:4]);

        if (!isAuthorized(target, selector)) {
            revert UnauthorizedCall();
        }

        context = "";
        magic = PAYMASTER_VALIDATION_SUCCESS_MAGIC;

        uint256 requiredETH = _transaction.gasLimit * _transaction.maxFeePerGas;

        BOOTLOADER_FORMAL_ADDRESS.safeTransferETH(requiredETH);
    }

    function isAuthorized(address target, bytes4 selector) public view returns (bool) {
        return _authorizedCalls[target][selector];
    }

    function setAuthorized(address target, bytes4 selector, bool authorized) external onlyOwner {
        _authorizedCalls[target][selector] = authorized;
    }

    function postTransaction(
        bytes calldata _context,
        Transaction calldata _transaction,
        bytes32 _txHash,
        bytes32 _suggestedSignedHash,
        ExecutionResult _txResult,
        uint256 _maxRefundedGas
    ) external payable {}

    function withdraw() external onlyOwner {
        msg.sender.safeTransferAllETH();
    }

    function withdrawPartial(uint256 amount) external onlyOwner {
        msg.sender.safeTransferETH(amount);
    }

    receive() external payable {}
}

File 2 of 23 : TransactionHelper.sol
// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

/// @dev The type id of ZKsync's EIP-712-signed transaction.
uint8 constant EIP_712_TX_TYPE = 0x71;

/// @dev The type id of legacy transactions.
uint8 constant LEGACY_TX_TYPE = 0x0;
/// @dev The type id of legacy transactions.
uint8 constant EIP_2930_TX_TYPE = 0x01;
/// @dev The type id of EIP1559 transactions.
uint8 constant EIP_1559_TX_TYPE = 0x02;

/// @notice Structure used to represent a ZKsync transaction.
struct Transaction {
    // The type of the transaction.
    uint256 txType;
    // The caller.
    uint256 from;
    // The callee.
    uint256 to;
    // The gasLimit to pass with the transaction.
    // It has the same meaning as Ethereum's gasLimit.
    uint256 gasLimit;
    // The maximum amount of gas the user is willing to pay for a byte of pubdata.
    uint256 gasPerPubdataByteLimit;
    // The maximum fee per gas that the user is willing to pay.
    // It is akin to EIP1559's maxFeePerGas.
    uint256 maxFeePerGas;
    // The maximum priority fee per gas that the user is willing to pay.
    // It is akin to EIP1559's maxPriorityFeePerGas.
    uint256 maxPriorityFeePerGas;
    // The transaction's paymaster. If there is no paymaster, it is equal to 0.
    uint256 paymaster;
    // The nonce of the transaction.
    uint256 nonce;
    // The value to pass with the transaction.
    uint256 value;
    // In the future, we might want to add some
    // new fields to the struct. The `txData` struct
    // is to be passed to account and any changes to its structure
    // would mean a breaking change to these accounts. In order to prevent this,
    // we should keep some fields as "reserved".
    // It is also recommended that their length is fixed, since
    // it would allow easier proof integration (in case we will need
    // some special circuit for preprocessing transactions).
    uint256[4] reserved;
    // The transaction's calldata.
    bytes data;
    // The signature of the transaction.
    bytes signature;
    // The properly formatted hashes of bytecodes that must be published on L1
    // with the inclusion of this transaction. Note, that a bytecode has been published
    // before, the user won't pay fees for its republishing.
    bytes32[] factoryDeps;
    // The input to the paymaster.
    bytes paymasterInput;
    // Reserved dynamic type for the future use-case. Using it should be avoided,
    // But it is still here, just in case we want to enable some additional functionality.
    bytes reservedDynamic;
}

// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

import {Transaction} from "../libraries/TransactionHelper.sol";

enum ExecutionResult {
    Revert,
    Success
}

bytes4 constant PAYMASTER_VALIDATION_SUCCESS_MAGIC = IPaymaster
    .validateAndPayForPaymasterTransaction
    .selector;

interface IPaymaster {
    /// @dev Called by the bootloader to verify that the paymaster agrees to pay for the
    /// fee for the transaction. This transaction should also send the necessary amount of funds onto the bootloader
    /// address.
    /// @param _txHash The hash of the transaction
    /// @param _suggestedSignedHash The hash of the transaction that is signed by an EOA
    /// @param _transaction The transaction itself.
    /// @return magic The value that should be equal to the signature of the validateAndPayForPaymasterTransaction
    /// if the paymaster agrees to pay for the transaction.
    /// @return context The "context" of the transaction: an array of bytes of length at most 1024 bytes, which will be
    /// passed to the `postTransaction` method of the account.
    /// @dev The developer should strive to preserve as many steps as possible both for valid
    /// and invalid transactions as this very method is also used during the gas fee estimation
    /// (without some of the necessary data, e.g. signature).
    function validateAndPayForPaymasterTransaction(
        bytes32 _txHash,
        bytes32 _suggestedSignedHash,
        Transaction calldata _transaction
    ) external payable returns (bytes4 magic, bytes memory context);

    /// @dev Called by the bootloader after the execution of the transaction. Please note that
    /// there is no guarantee that this method will be called at all. Unlike the original EIP4337,
    /// this method won't be called if the transaction execution results in out-of-gas.
    /// @param _context, the context of the execution, returned by the "validateAndPayForPaymasterTransaction" method.
    /// @param  _transaction, the users' transaction.
    /// @param _txResult, the result of the transaction execution (success or failure).
    /// @param _maxRefundedGas, the upper bound on the amount of gas that could be refunded to the paymaster.
    /// @dev The exact amount refunded depends on the gas spent by the "postOp" itself and so the developers should
    /// take that into account.
    function postTransaction(
        bytes calldata _context,
        Transaction calldata _transaction,
        bytes32 _txHash,
        bytes32 _suggestedSignedHash,
        ExecutionResult _txResult,
        uint256 _maxRefundedGas
    ) external payable;
}

File 4 of 23 : Constants.sol
// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

import {IAccountCodeStorage} from "./interfaces/IAccountCodeStorage.sol";
import {INonceHolder} from "./interfaces/INonceHolder.sol";
import {IContractDeployer} from "./interfaces/IContractDeployer.sol";
import {IKnownCodesStorage} from "./interfaces/IKnownCodesStorage.sol";
import {IImmutableSimulator} from "./interfaces/IImmutableSimulator.sol";
import {IBaseToken} from "./interfaces/IBaseToken.sol";
import {IBridgehub} from "./interfaces/IBridgehub.sol";
import {IL1Messenger} from "./interfaces/IL1Messenger.sol";
import {ISystemContext} from "./interfaces/ISystemContext.sol";
import {ICompressor} from "./interfaces/ICompressor.sol";
import {IComplexUpgrader} from "./interfaces/IComplexUpgrader.sol";
import {IBootloaderUtilities} from "./interfaces/IBootloaderUtilities.sol";
import {IPubdataChunkPublisher} from "./interfaces/IPubdataChunkPublisher.sol";
import {IMessageRoot} from "./interfaces/IMessageRoot.sol";
import {ICreate2Factory} from "./interfaces/ICreate2Factory.sol";

/// @dev All the system contracts introduced by ZKsync have their addresses
/// started from 2^15 in order to avoid collision with Ethereum precompiles.
uint160 constant SYSTEM_CONTRACTS_OFFSET = 0x8000; // 2^15

/// @dev Unlike the value above, it is not overridden for the purpose of testing and
/// is identical to the constant value actually used as the system contracts offset on
/// mainnet.
uint160 constant REAL_SYSTEM_CONTRACTS_OFFSET = 0x8000;


/// @dev All the system contracts must be located in the kernel space,
/// i.e. their addresses must be below 2^16.
uint160 constant MAX_SYSTEM_CONTRACT_ADDRESS = 0xffff; // 2^16 - 1

/// @dev The offset from which the built-in, but user space contracts are located.
uint160 constant USER_CONTRACTS_OFFSET = MAX_SYSTEM_CONTRACT_ADDRESS + 1;

address constant ECRECOVER_SYSTEM_CONTRACT = address(0x01);
address constant SHA256_SYSTEM_CONTRACT = address(0x02);
address constant ECADD_SYSTEM_CONTRACT = address(0x06);
address constant ECMUL_SYSTEM_CONTRACT = address(0x07);
address constant ECPAIRING_SYSTEM_CONTRACT = address(0x08);


/// @dev The number of gas that need to be spent for a single byte of pubdata regardless of the pubdata price.
/// This variable is used to ensure the following:
/// - That the long-term storage of the operator is compensated properly.
/// - That it is not possible that the pubdata counter grows too high without spending proportional amount of computation.
uint256 constant COMPUTATIONAL_PRICE_FOR_PUBDATA = 80;

/// @dev The maximal possible address of an L1-like precompie. These precompiles maintain the following properties:
/// - Their extcodehash is EMPTY_STRING_KECCAK
/// - Their extcodesize is 0 despite having a bytecode formally deployed there.
uint256 constant CURRENT_MAX_PRECOMPILE_ADDRESS = 0xff;

address payable constant BOOTLOADER_FORMAL_ADDRESS = payable(address(SYSTEM_CONTRACTS_OFFSET + 0x01));
IAccountCodeStorage constant ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT = IAccountCodeStorage(
    address(SYSTEM_CONTRACTS_OFFSET + 0x02)
);
INonceHolder constant NONCE_HOLDER_SYSTEM_CONTRACT = INonceHolder(address(SYSTEM_CONTRACTS_OFFSET + 0x03));
IKnownCodesStorage constant KNOWN_CODE_STORAGE_CONTRACT = IKnownCodesStorage(address(SYSTEM_CONTRACTS_OFFSET + 0x04));
IImmutableSimulator constant IMMUTABLE_SIMULATOR_SYSTEM_CONTRACT = IImmutableSimulator(
    address(SYSTEM_CONTRACTS_OFFSET + 0x05)
);
IContractDeployer constant DEPLOYER_SYSTEM_CONTRACT = IContractDeployer(address(SYSTEM_CONTRACTS_OFFSET + 0x06));
IContractDeployer constant REAL_DEPLOYER_SYSTEM_CONTRACT = IContractDeployer(address(REAL_SYSTEM_CONTRACTS_OFFSET + 0x06));

// A contract that is allowed to deploy any codehash
// on any address. To be used only during an upgrade.
address constant FORCE_DEPLOYER = address(SYSTEM_CONTRACTS_OFFSET + 0x07);
IL1Messenger constant L1_MESSENGER_CONTRACT = IL1Messenger(address(SYSTEM_CONTRACTS_OFFSET + 0x08));
address constant MSG_VALUE_SYSTEM_CONTRACT = address(SYSTEM_CONTRACTS_OFFSET + 0x09);

IBaseToken constant BASE_TOKEN_SYSTEM_CONTRACT = IBaseToken(address(SYSTEM_CONTRACTS_OFFSET + 0x0a));
IBaseToken constant REAL_BASE_TOKEN_SYSTEM_CONTRACT = IBaseToken(address(REAL_SYSTEM_CONTRACTS_OFFSET + 0x0a));

ICreate2Factory constant L2_CREATE2_FACTORY = ICreate2Factory(address(USER_CONTRACTS_OFFSET));
address constant L2_ASSET_ROUTER = address(USER_CONTRACTS_OFFSET + 0x03);
IBridgehub constant L2_BRIDGE_HUB = IBridgehub(address(USER_CONTRACTS_OFFSET + 0x02));
address constant L2_NATIVE_TOKEN_VAULT_ADDR = address(USER_CONTRACTS_OFFSET + 0x04);
IMessageRoot constant L2_MESSAGE_ROOT = IMessageRoot(address(USER_CONTRACTS_OFFSET + 0x05));
// Note, that on its own this contract does not provide much functionality, but having it on a constant address
// serves as a convenient storage for its bytecode to be accessible via `extcodehash`.
address constant SLOAD_CONTRACT_ADDRESS = address(USER_CONTRACTS_OFFSET + 0x06);

address constant WRAPPED_BASE_TOKEN_IMPL_ADDRESS = address(USER_CONTRACTS_OFFSET + 0x07);

// Hardcoded because even for tests we should keep the address. (Instead `SYSTEM_CONTRACTS_OFFSET + 0x10`)
// Precompile call depends on it.
// And we don't want to mock this contract.
address constant KECCAK256_SYSTEM_CONTRACT = address(0x8010);

ISystemContext constant SYSTEM_CONTEXT_CONTRACT = ISystemContext(payable(address(SYSTEM_CONTRACTS_OFFSET + 0x0b)));
ISystemContext constant REAL_SYSTEM_CONTEXT_CONTRACT = ISystemContext(payable(address(REAL_SYSTEM_CONTRACTS_OFFSET + 0x0b)));

IBootloaderUtilities constant BOOTLOADER_UTILITIES = IBootloaderUtilities(address(SYSTEM_CONTRACTS_OFFSET + 0x0c));

// It will be a different value for tests, while shouldn't. But for now, this constant is not used by other contracts, so that's fine.
address constant EVENT_WRITER_CONTRACT = address(SYSTEM_CONTRACTS_OFFSET + 0x0d);

ICompressor constant COMPRESSOR_CONTRACT = ICompressor(address(SYSTEM_CONTRACTS_OFFSET + 0x0e));

IComplexUpgrader constant COMPLEX_UPGRADER_CONTRACT = IComplexUpgrader(address(SYSTEM_CONTRACTS_OFFSET + 0x0f));

IPubdataChunkPublisher constant PUBDATA_CHUNK_PUBLISHER = IPubdataChunkPublisher(
    address(SYSTEM_CONTRACTS_OFFSET + 0x11)
);

/// @dev If the bitwise AND of the extraAbi[2] param when calling the MSG_VALUE_SIMULATOR
/// is non-zero, the call will be assumed to be a system one.
uint256 constant MSG_VALUE_SIMULATOR_IS_SYSTEM_BIT = 1;

/// @dev The maximal msg.value that context can have
uint256 constant MAX_MSG_VALUE = type(uint128).max;

/// @dev Prefix used during derivation of account addresses using CREATE2
/// @dev keccak256("zksyncCreate2")
bytes32 constant CREATE2_PREFIX = 0x2020dba91b30cc0006188af794c2fb30dd8520db7e2c088b7fc7c103c00ca494;
/// @dev Prefix used during derivation of account addresses using CREATE
/// @dev keccak256("zksyncCreate")
bytes32 constant CREATE_PREFIX = 0x63bae3a9951d38e8a3fbb7b70909afc1200610fc5bc55ade242f815974674f23;

/// @dev Each state diff consists of 156 bytes of actual data and 116 bytes of unused padding, needed for circuit efficiency.
uint256 constant STATE_DIFF_ENTRY_SIZE = 272;

enum SystemLogKey {
    L2_TO_L1_LOGS_TREE_ROOT_KEY,
    PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEY,
    CHAINED_PRIORITY_TXN_HASH_KEY,
    NUMBER_OF_LAYER_1_TXS_KEY,
    // Note, that it is important that `PREV_BATCH_HASH_KEY` has position
    // `4` since it is the same as it was in the previous protocol version and
    // it is the only one that is emitted before the system contracts are upgraded.
    PREV_BATCH_HASH_KEY,
    L2_DA_VALIDATOR_OUTPUT_HASH_KEY,
    USED_L2_DA_VALIDATOR_ADDRESS_KEY,
    EXPECTED_SYSTEM_CONTRACT_UPGRADE_TX_HASH_KEY
}

/// @dev The number of leaves in the L2->L1 log Merkle tree.
/// While formally a tree of any length is acceptable, the node supports only a constant length of 16384 leaves.
uint256 constant L2_TO_L1_LOGS_MERKLE_TREE_LEAVES = 16_384;

/// @dev The length of the derived key in bytes inside compressed state diffs.
uint256 constant DERIVED_KEY_LENGTH = 32;
/// @dev The length of the enum index in bytes inside compressed state diffs.
uint256 constant ENUM_INDEX_LENGTH = 8;
/// @dev The length of value in bytes inside compressed state diffs.
uint256 constant VALUE_LENGTH = 32;

/// @dev The length of the compressed initial storage write in bytes.
uint256 constant COMPRESSED_INITIAL_WRITE_SIZE = DERIVED_KEY_LENGTH + VALUE_LENGTH;
/// @dev The length of the compressed repeated storage write in bytes.
uint256 constant COMPRESSED_REPEATED_WRITE_SIZE = ENUM_INDEX_LENGTH + VALUE_LENGTH;

/// @dev The position from which the initial writes start in the compressed state diffs.
uint256 constant INITIAL_WRITE_STARTING_POSITION = 4;

/// @dev Each storage diffs consists of the following elements:
/// [20bytes address][32bytes key][32bytes derived key][8bytes enum index][32bytes initial value][32bytes final value]
/// @dev The offset of the derived key in a storage diff.
uint256 constant STATE_DIFF_DERIVED_KEY_OFFSET = 52;
/// @dev The offset of the enum index in a storage diff.
uint256 constant STATE_DIFF_ENUM_INDEX_OFFSET = 84;
/// @dev The offset of the final value in a storage diff.
uint256 constant STATE_DIFF_FINAL_VALUE_OFFSET = 124;

/// @dev Total number of bytes in a blob. Blob = 4096 field elements * 31 bytes per field element
/// @dev EIP-4844 defines it as 131_072 but we use 4096 * 31 within our circuits to always fit within a field element
/// @dev Our circuits will prove that a EIP-4844 blob and our internal blob are the same.
uint256 constant BLOB_SIZE_BYTES = 126_976;

/// @dev Max number of blobs currently supported
uint256 constant MAX_NUMBER_OF_BLOBS = 6;

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

/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The caller is not authorized to call the function.
    error Unauthorized();

    /// @dev The `newOwner` cannot be the zero address.
    error NewOwnerIsZeroAddress();

    /// @dev The `pendingOwner` does not have a valid handover request.
    error NoHandoverRequest();

    /// @dev Cannot double-initialize.
    error AlreadyInitialized();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ownership is transferred from `oldOwner` to `newOwner`.
    /// This event is intentionally kept the same as OpenZeppelin's Ownable to be
    /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
    /// despite it not being as lightweight as a single argument event.
    event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);

    /// @dev An ownership handover to `pendingOwner` has been requested.
    event OwnershipHandoverRequested(address indexed pendingOwner);

    /// @dev The ownership handover to `pendingOwner` has been canceled.
    event OwnershipHandoverCanceled(address indexed pendingOwner);

    /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
    uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
        0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;

    /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
        0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;

    /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
        0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The owner slot is given by:
    /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`.
    /// It is intentionally chosen to be a high value
    /// to avoid collision with lower slots.
    /// The choice of manual storage layout is to enable compatibility
    /// with both regular and upgradeable contracts.
    bytes32 internal constant _OWNER_SLOT =
        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;

    /// The ownership handover slot of `newOwner` is given by:
    /// ```
    ///     mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
    ///     let handoverSlot := keccak256(0x00, 0x20)
    /// ```
    /// It stores the expiry timestamp of the two-step ownership handover.
    uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     INTERNAL FUNCTIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Override to return true to make `_initializeOwner` prevent double-initialization.
    function _guardInitializeOwner() internal pure virtual returns (bool guard) {}

    /// @dev Initializes the owner directly without authorization guard.
    /// This function must be called upon initialization,
    /// regardless of whether the contract is upgradeable or not.
    /// This is to enable generalization to both regular and upgradeable contracts,
    /// and to save gas in case the initial owner is not the caller.
    /// For performance reasons, this function will not check if there
    /// is an existing owner.
    function _initializeOwner(address newOwner) internal virtual {
        if (_guardInitializeOwner()) {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                if sload(ownerSlot) {
                    mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.
                    revert(0x1c, 0x04)
                }
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Store the new value.
                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Store the new value.
                sstore(_OWNER_SLOT, newOwner)
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
            }
        }
    }

    /// @dev Sets the owner directly without authorization guard.
    function _setOwner(address newOwner) internal virtual {
        if (_guardInitializeOwner()) {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                // Store the new value.
                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                // Store the new value.
                sstore(ownerSlot, newOwner)
            }
        }
    }

    /// @dev Throws if the sender is not the owner.
    function _checkOwner() internal view virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // If the caller is not the stored owner, revert.
            if iszero(eq(caller(), sload(_OWNER_SLOT))) {
                mstore(0x00, 0x82b42900) // `Unauthorized()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Returns how long a two-step ownership handover is valid for in seconds.
    /// Override to return a different value if needed.
    /// Made internal to conserve bytecode. Wrap it in a public function if needed.
    function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
        return 48 * 3600;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  PUBLIC UPDATE FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Allows the owner to transfer the ownership to `newOwner`.
    function transferOwnership(address newOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(shl(96, newOwner)) {
                mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
                revert(0x1c, 0x04)
            }
        }
        _setOwner(newOwner);
    }

    /// @dev Allows the owner to renounce their ownership.
    function renounceOwnership() public payable virtual onlyOwner {
        _setOwner(address(0));
    }

    /// @dev Request a two-step ownership handover to the caller.
    /// The request will automatically expire in 48 hours (172800 seconds) by default.
    function requestOwnershipHandover() public payable virtual {
        unchecked {
            uint256 expires = block.timestamp + _ownershipHandoverValidFor();
            /// @solidity memory-safe-assembly
            assembly {
                // Compute and set the handover slot to `expires`.
                mstore(0x0c, _HANDOVER_SLOT_SEED)
                mstore(0x00, caller())
                sstore(keccak256(0x0c, 0x20), expires)
                // Emit the {OwnershipHandoverRequested} event.
                log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
            }
        }
    }

    /// @dev Cancels the two-step ownership handover to the caller, if any.
    function cancelOwnershipHandover() public payable virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x20), 0)
            // Emit the {OwnershipHandoverCanceled} event.
            log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
        }
    }

    /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
    /// Reverts if there is no existing ownership handover requested by `pendingOwner`.
    function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            let handoverSlot := keccak256(0x0c, 0x20)
            // If the handover does not exist, or has expired.
            if gt(timestamp(), sload(handoverSlot)) {
                mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
                revert(0x1c, 0x04)
            }
            // Set the handover slot to 0.
            sstore(handoverSlot, 0)
        }
        _setOwner(pendingOwner);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   PUBLIC READ FUNCTIONS                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the owner of the contract.
    function owner() public view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(_OWNER_SLOT)
        }
    }

    /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
    function ownershipHandoverExpiresAt(address pendingOwner)
        public
        view
        virtual
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the handover slot.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            // Load the handover slot.
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         MODIFIERS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Marks a function as only callable by the owner.
    modifier onlyOwner() virtual {
        _checkOwner();
        _;
    }
}

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

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

/// @notice Library for force safe transferring ETH and ERC20s in ZKsync.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ext/zksync/SafeTransferLib.sol)
library SafeTransferLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev A single use ETH vault has been created for `to`, with `amount`.
    event SingleUseETHVaultCreated(address indexed to, uint256 amount, address vault);

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ETH transfer has failed.
    error ETHTransferFailed();

    /// @dev The ERC20 `transferFrom` has failed.
    error TransferFromFailed();

    /// @dev The ERC20 `transfer` has failed.
    error TransferFailed();

    /// @dev The ERC20 `approve` has failed.
    error ApproveFailed();

    /// @dev The ERC20 `totalSupply` query has failed.
    error TotalSupplyQueryFailed();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Suggested gas stipend for contract receiving ETH to perform a few
    /// storage reads and writes, but low enough to prevent griefing.
    uint256 internal constant GAS_STIPEND_NO_GRIEF = 1000000;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ETH OPERATIONS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.
    //
    // The regular variants:
    // - Forwards all remaining gas to the target.
    // - Reverts if the target reverts.
    // - Reverts if the current contract has insufficient balance.
    //
    // The force variants:
    // - Forwards with an optional gas stipend
    //   (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).
    // - If the target reverts, or if the gas stipend is exhausted,
    //   creates a temporary contract to force send the ETH via `SELFDESTRUCT`.
    //   Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.
    // - Reverts if the current contract has insufficient balance.
    //
    // The try variants:
    // - Forwards with a mandatory gas stipend.
    // - Instead of reverting, returns whether the transfer succeeded.

    /// @dev Sends `amount` (in wei) ETH to `to`.
    function safeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gas(), to, amount, 0x00, 0x00, 0x00, 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`.
    function safeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // Transfer all the ETH and check if it succeeded or not.
            if iszero(call(gas(), to, selfbalance(), 0x00, 0x00, 0x00, 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    /// If force transfer is used, returns the vault. Else returns `address(0)`.
    function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend)
        internal
        returns (address vault)
    {
        if (amount == uint256(0)) return address(0); // Early return if `amount` is zero.
        uint256 selfBalanceBefore = address(this).balance;
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfBalanceBefore, amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            pop(call(gasStipend, to, amount, 0x00, 0x00, 0x00, 0x00))
        }
        if (address(this).balance == selfBalanceBefore) {
            vault = address(new SingleUseETHVault());
            /// @solidity memory-safe-assembly
            assembly {
                mstore(0x00, shr(96, shl(96, to)))
                if iszero(call(gas(), vault, amount, 0x00, 0x20, 0x00, 0x00)) { revert(0x00, 0x00) }
            }
            emit SingleUseETHVaultCreated(to, amount, vault);
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.
    /// If force transfer is used, returns the vault. Else returns `address(0)`.
    function forceSafeTransferAllETH(address to, uint256 gasStipend)
        internal
        returns (address vault)
    {
        vault = forceSafeTransferETH(to, address(this).balance, gasStipend);
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.
    /// If force transfer is used, returns the vault. Else returns `address(0)`.
    function forceSafeTransferETH(address to, uint256 amount) internal returns (address vault) {
        vault = forceSafeTransferETH(to, amount, GAS_STIPEND_NO_GRIEF);
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.
    /// If force transfer is used, returns the vault. Else returns `address(0)`.
    function forceSafeTransferAllETH(address to) internal returns (address vault) {
        vault = forceSafeTransferETH(to, address(this).balance, GAS_STIPEND_NO_GRIEF);
    }

    /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, amount, 0x00, 0x00, 0x00, 0x00)
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function trySafeTransferAllETH(address to, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, selfbalance(), 0x00, 0x00, 0x00, 0x00)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ERC20 OPERATIONS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have at least `amount` approved for
    /// the current contract to manage.
    function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, amount) // Store the `amount` argument.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
            let success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    ///
    /// The `from` account must have at least `amount` approved for the current contract to manage.
    function trySafeTransferFrom(address token, address from, address to, uint256 amount)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, amount) // Store the `amount` argument.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
            success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                success := lt(or(iszero(extcodesize(token)), returndatasize()), success)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends all of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have their entire balance approved for the current contract to manage.
    function safeTransferAllFrom(address token, address from, address to)
        internal
        returns (uint256 amount)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.
            amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.
            // Perform the transfer, reverting upon failure.
            let success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransfer(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sends all of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransferAll(address token, address to) internal returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.
            mstore(0x20, address()) // Store the address of the current contract.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x14, to) // Store the `to` argument.
            amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// Reverts upon failure.
    function safeApprove(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// If the initial attempt to approve fails, attempts to reset the approved amount to zero,
    /// then retries the approval again (some tokens, e.g. USDT, requires this).
    /// Reverts upon failure.
    function safeApproveWithRetry(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            // Perform the approval, retrying upon failure.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x34, 0) // Store 0 for the `amount`.
                    mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
                    pop(call(gas(), token, 0, 0x10, 0x44, 0x00, 0x00)) // Reset the approval.
                    mstore(0x34, amount) // Store back the original `amount`.
                    // Retry the approval, reverting upon failure.
                    success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                    if iszero(and(eq(mload(0x00), 1), success)) {
                        // Check the `extcodesize` again just in case the token selfdestructs lol.
                        if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                            mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                            revert(0x1c, 0x04)
                        }
                    }
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Returns the amount of ERC20 `token` owned by `account`.
    /// Returns zero if the `token` does not exist.
    function balanceOf(address token, address account) internal view returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, account) // Store the `account` argument.
            mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            amount :=
                mul( // The arguments of `mul` are evaluated from right to left.
                    mload(0x20),
                    and( // The arguments of `and` are evaluated from right to left.
                        gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                        staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)
                    )
                )
        }
    }

    /// @dev Returns the total supply of the `token`.
    /// Reverts if the token does not exist or does not implement `totalSupply()`.
    function totalSupply(address token) internal view returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x18160ddd) // `totalSupply()`.
            if iszero(
                and(gt(returndatasize(), 0x1f), staticcall(gas(), token, 0x1c, 0x04, 0x00, 0x20))
            ) {
                mstore(0x00, 0x54cd9435) // `TotalSupplyQueryFailed()`.
                revert(0x1c, 0x04)
            }
            result := mload(0x00)
        }
    }
}

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

interface IAGWRegistry {
    function isAGW(address user) external view returns (bool);
}

// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

interface IAccountCodeStorage {
    function storeAccountConstructingCodeHash(
        address _address,
        bytes32 _hash
    ) external;

    function storeAccountConstructedCodeHash(
        address _address,
        bytes32 _hash
    ) external;

    function markAccountCodeHashAsConstructed(address _address) external;

    function getRawCodeHash(
        address _address
    ) external view returns (bytes32 codeHash);

    function getCodeHash(
        uint256 _input
    ) external view returns (bytes32 codeHash);

    function getCodeSize(
        uint256 _input
    ) external view returns (uint256 codeSize);
}

// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

/**
 * @author Matter Labs
 * @dev Interface of the nonce holder contract -- a contract used by the system to ensure
 * that there is always a unique identifier for a transaction with a particular account (we call it nonce).
 * In other words, the pair of (address, nonce) should always be unique.
 * @dev Custom accounts should use methods of this contract to store nonces or other possible unique identifiers
 * for the transaction.
 */
interface INonceHolder {
    event ValueSetUnderNonce(
        address indexed accountAddress,
        uint256 indexed key,
        uint256 value
    );

    /// @dev Returns the current minimal nonce for account.
    function getMinNonce(address _address) external view returns (uint256);

    /// @dev Returns the raw version of the current minimal nonce
    /// (equal to minNonce + 2^128 * deployment nonce).
    function getRawNonce(address _address) external view returns (uint256);

    /// @dev Increases the minimal nonce for the msg.sender.
    function increaseMinNonce(uint256 _value) external returns (uint256);

    /// @dev Sets the nonce value `key` as used.
    function setValueUnderNonce(uint256 _key, uint256 _value) external;

    /// @dev Gets the value stored inside a custom nonce.
    function getValueUnderNonce(uint256 _key) external view returns (uint256);

    /// @dev A convenience method to increment the minimal nonce if it is equal
    /// to the `_expectedNonce`.
    function incrementMinNonceIfEquals(uint256 _expectedNonce) external;

    /// @dev Returns the deployment nonce for the accounts used for CREATE opcode.
    function getDeploymentNonce(
        address _address
    ) external view returns (uint256);

    /// @dev Increments the deployment nonce for the account and returns the previous one.
    function incrementDeploymentNonce(
        address _address
    ) external returns (uint256);

    /// @dev Determines whether a certain nonce has been already used for an account.
    function validateNonceUsage(
        address _address,
        uint256 _key,
        bool _shouldBeUsed
    ) external view;

    /// @dev Returns whether a nonce has been used for an account.
    function isNonceUsed(
        address _address,
        uint256 _nonce
    ) external view returns (bool);
}

// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

/// @notice A struct that describes a forced deployment on an address
struct ForceDeployment {
    // The bytecode hash to put on an address
    bytes32 bytecodeHash;
    // The address on which to deploy the bytecodehash to
    address newAddress;
    // Whether to run the constructor on the force deployment
    bool callConstructor;
    // The value with which to initialize a contract
    uint256 value;
    // The constructor calldata
    bytes input;
}

interface IContractDeployer {
    /// @notice Defines the version of the account abstraction protocol
    /// that a contract claims to follow.
    /// - `None` means that the account is just a contract and it should never be interacted
    /// with as a custom account
    /// - `Version1` means that the account follows the first version of the account abstraction protocol
    enum AccountAbstractionVersion {
        None,
        Version1
    }

    /// @notice Defines the nonce ordering used by the account
    /// - `Sequential` means that it is expected that the nonces are monotonic and increment by 1
    /// at a time (the same as EOAs).
    /// - `Arbitrary` means that the nonces for the accounts can be arbitrary. The operator
    /// should serve the transactions from such an account on a first-come-first-serve basis.
    /// @dev This ordering is more of a suggestion to the operator on how the AA expects its transactions
    /// to be processed and is not considered as a system invariant.
    enum AccountNonceOrdering {
        Sequential,
        Arbitrary
    }

    struct AccountInfo {
        AccountAbstractionVersion supportedAAVersion;
        AccountNonceOrdering nonceOrdering;
    }

    event ContractDeployed(
        address indexed deployerAddress,
        bytes32 indexed bytecodeHash,
        address indexed contractAddress
    );

    event AccountNonceOrderingUpdated(
        address indexed accountAddress,
        AccountNonceOrdering nonceOrdering
    );

    event AccountVersionUpdated(
        address indexed accountAddress,
        AccountAbstractionVersion aaVersion
    );

    function getNewAddressCreate2(
        address _sender,
        bytes32 _bytecodeHash,
        bytes32 _salt,
        bytes calldata _input
    ) external view returns (address newAddress);

    function getNewAddressCreate(
        address _sender,
        uint256 _senderNonce
    ) external pure returns (address newAddress);

    function create2(
        bytes32 _salt,
        bytes32 _bytecodeHash,
        bytes calldata _input
    ) external payable returns (address newAddress);

    function create2Account(
        bytes32 _salt,
        bytes32 _bytecodeHash,
        bytes calldata _input,
        AccountAbstractionVersion _aaVersion
    ) external payable returns (address newAddress);

    /// @dev While the `_salt` parameter is not used anywhere here,
    /// it is still needed for consistency between `create` and
    /// `create2` functions (required by the compiler).
    function create(
        bytes32 _salt,
        bytes32 _bytecodeHash,
        bytes calldata _input
    ) external payable returns (address newAddress);

    /// @dev While `_salt` is never used here, we leave it here as a parameter
    /// for the consistency with the `create` function.
    function createAccount(
        bytes32 _salt,
        bytes32 _bytecodeHash,
        bytes calldata _input,
        AccountAbstractionVersion _aaVersion
    ) external payable returns (address newAddress);

    /// @notice Returns the information about a certain AA.
    function getAccountInfo(
        address _address
    ) external view returns (AccountInfo memory info);

    /// @notice Can be called by an account to update its account version
    function updateAccountVersion(AccountAbstractionVersion _version) external;

    /// @notice Can be called by an account to update its nonce ordering
    function updateNonceOrdering(AccountNonceOrdering _nonceOrdering) external;

    /// @notice This method is to be used only during an upgrade to set bytecodes on specific addresses.
    function forceDeployOnAddresses(
        ForceDeployment[] calldata _deployments
    ) external payable;
}

// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

/**
 * @author Matter Labs
 * @custom:security-contact [email protected]
 * @notice The interface for the KnownCodesStorage contract, which is responsible
 * for storing the hashes of the bytecodes that have been published to the network.
 */
interface IKnownCodesStorage {
    event MarkedAsKnown(
        bytes32 indexed bytecodeHash,
        bool indexed sendBytecodeToL1
    );

    function markFactoryDeps(
        bool _shouldSendToL1,
        bytes32[] calldata _hashes
    ) external;

    function markBytecodeAsPublished(bytes32 _bytecodeHash) external;

    function getMarker(bytes32 _hash) external view returns (uint256);
}

// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

struct ImmutableData {
    uint256 index;
    bytes32 value;
}

interface IImmutableSimulator {
    function getImmutable(
        address _dest,
        uint256 _index
    ) external view returns (bytes32);

    function setImmutables(
        address _dest,
        ImmutableData[] calldata _immutables
    ) external;
}

// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

interface IBaseToken {
    function balanceOf(uint256) external view returns (uint256);

    function transferFromTo(
        address _from,
        address _to,
        uint256 _amount
    ) external;

    function totalSupply() external view returns (uint256);

    function name() external pure returns (string memory);

    function symbol() external pure returns (string memory);

    function decimals() external pure returns (uint8);

    function mint(address _account, uint256 _amount) external;

    function withdraw(address _l1Receiver) external payable;

    function withdrawWithMessage(
        address _l1Receiver,
        bytes calldata _additionalData
    ) external payable;

    event Mint(address indexed account, uint256 amount);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Withdrawal(
        address indexed _l2Sender,
        address indexed _l1Receiver,
        uint256 _amount
    );

    event WithdrawalWithMessage(
        address indexed _l2Sender,
        address indexed _l1Receiver,
        uint256 _amount,
        bytes _additionalData
    );
}

// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

/// @author Matter Labs
/// @custom:security-contact [email protected]
interface IBridgehub {
    function setAddresses(
        address _assetRouter,
        address _ctmDeployer,
        address _messageRoot
    ) external;

    function owner() external view returns (address);
}

// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

/// @dev The log passed from L2
/// @param l2ShardId The shard identifier, 0 - rollup, 1 - porter. All other values are not used but are reserved for the future
/// @param isService A boolean flag that is part of the log along with `key`, `value`, and `sender` address.
/// This field is required formally but does not have any special meaning.
/// @param txNumberInBlock The L2 transaction number in a block, in which the log was sent
/// @param sender The L2 address which sent the log
/// @param key The 32 bytes of information that was sent in the log
/// @param value The 32 bytes of information that was sent in the log
// Both `key` and `value` are arbitrary 32-bytes selected by the log sender
struct L2ToL1Log {
    uint8 l2ShardId;
    bool isService;
    uint16 txNumberInBlock;
    address sender;
    bytes32 key;
    bytes32 value;
}

/// @dev Bytes in raw L2 to L1 log
/// @dev Equal to the bytes size of the tuple - (uint8 ShardId, bool isService, uint16 txNumberInBlock, address sender, bytes32 key, bytes32 value)
uint256 constant L2_TO_L1_LOG_SERIALIZE_SIZE = 88;

/// @dev The value of default leaf hash for L2 to L1 logs Merkle tree
/// @dev An incomplete fixed-size tree is filled with this value to be a full binary tree
/// @dev Actually equal to the `keccak256(new bytes(L2_TO_L1_LOG_SERIALIZE_SIZE))`
bytes32 constant L2_L1_LOGS_TREE_DEFAULT_LEAF_HASH = 0x72abee45b59e344af8a6e520241c4744aff26ed411f4c4b00f8af09adada43ba;

/// @dev The current version of state diff compression being used.
uint256 constant STATE_DIFF_COMPRESSION_VERSION_NUMBER = 1;

/**
 * @author Matter Labs
 * @custom:security-contact [email protected]
 * @notice The interface of the L1 Messenger contract, responsible for sending messages to L1.
 */
interface IL1Messenger {
    // Possibly in the future we will be able to track the messages sent to L1 with
    // some hooks in the VM. For now, it is much easier to track them with L2 events.
    event L1MessageSent(
        address indexed _sender,
        bytes32 indexed _hash,
        bytes _message
    );

    event L2ToL1LogSent(L2ToL1Log _l2log);

    event BytecodeL1PublicationRequested(bytes32 _bytecodeHash);

    function sendToL1(bytes calldata _message) external returns (bytes32);

    function sendL2ToL1Log(
        bool _isService,
        bytes32 _key,
        bytes32 _value
    ) external returns (uint256 logIdInMerkleTree);

    // This function is expected to be called only by the KnownCodesStorage system contract
    function requestBytecodeL1Publication(bytes32 _bytecodeHash) external;
}

// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

/**
 * @author Matter Labs
 * @custom:security-contact [email protected]
 * @notice Contract that stores some of the context variables, that may be either
 * block-scoped, tx-scoped or system-wide.
 */
interface ISystemContext {
    struct BlockInfo {
        uint128 timestamp;
        uint128 number;
    }

    /// @notice A structure representing the timeline for the upgrade from the batch numbers to the L2 block numbers.
    /// @dev It will be used for the L1 batch -> L2 block migration in Q3 2023 only.
    struct VirtualBlockUpgradeInfo {
        /// @notice In order to maintain consistent results for `blockhash` requests, we'll
        /// have to remember the number of the batch when the upgrade to the virtual blocks has been done.
        /// The hashes for virtual blocks before the upgrade are identical to the hashes of the corresponding batches.
        uint128 virtualBlockStartBatch;
        /// @notice L2 block when the virtual blocks have caught up with the L2 blocks. Starting from this block,
        /// all the information returned to users for block.timestamp/number, etc should be the information about the L2 blocks and
        /// not virtual blocks.
        uint128 virtualBlockFinishL2Block;
    }

    function chainId() external view returns (uint256);

    function origin() external view returns (address);

    function gasPrice() external view returns (uint256);

    function blockGasLimit() external view returns (uint256);

    function coinbase() external view returns (address);

    function difficulty() external view returns (uint256);

    function baseFee() external view returns (uint256);

    function txNumberInBlock() external view returns (uint16);

    function getBlockHashEVM(uint256 _block) external view returns (bytes32);

    function getBatchHash(
        uint256 _batchNumber
    ) external view returns (bytes32 hash);

    function getBlockNumber() external view returns (uint128);

    function getBlockTimestamp() external view returns (uint128);

    function getBatchNumberAndTimestamp()
        external
        view
        returns (uint128 blockNumber, uint128 blockTimestamp);

    function getL2BlockNumberAndTimestamp()
        external
        view
        returns (uint128 blockNumber, uint128 blockTimestamp);

    function gasPerPubdataByte()
        external
        view
        returns (uint256 gasPerPubdataByte);

    function getCurrentPubdataSpent()
        external
        view
        returns (uint256 currentPubdataSpent);

    function setChainId(uint256 _newChainId) external;
}

// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

// The bitmask by applying which to the compressed state diff metadata we retrieve its operation.
uint8 constant OPERATION_BITMASK = 7;
// The number of bits shifting the compressed state diff metadata by which we retrieve its length.
uint8 constant LENGTH_BITS_OFFSET = 3;
// The maximal length in bytes that an enumeration index can have.
uint8 constant MAX_ENUMERATION_INDEX_SIZE = 8;

/**
 * @author Matter Labs
 * @custom:security-contact [email protected]
 * @notice The interface for the Compressor contract, responsible for verifying the correctness of
 * the compression of the state diffs and bytecodes.
 */
interface ICompressor {
    function publishCompressedBytecode(
        bytes calldata _bytecode,
        bytes calldata _rawCompressedData
    ) external returns (bytes32 bytecodeHash);

    function verifyCompressedStateDiffs(
        uint256 _numberOfStateDiffs,
        uint256 _enumerationIndexSize,
        bytes calldata _stateDiffs,
        bytes calldata _compressedStateDiffs
    ) external returns (bytes32 stateDiffHash);
}

// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

import {ForceDeployment} from "./IContractDeployer.sol";

/**
 * @author Matter Labs
 * @custom:security-contact [email protected]
 * @notice The interface for the ComplexUpgrader contract.
 */
interface IComplexUpgrader {
    function forceDeployAndUpgrade(
        ForceDeployment[] calldata _forceDeployments,
        address _delegateTo,
        bytes calldata _calldata
    ) external payable;

    function upgrade(
        address _delegateTo,
        bytes calldata _calldata
    ) external payable;
}

File 19 of 23 : IBootloaderUtilities.sol
// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

import {Transaction} from "../libraries/TransactionHelper.sol";

interface IBootloaderUtilities {
    function getTransactionHashes(
        Transaction calldata _transaction
    ) external view returns (bytes32 txHash, bytes32 signedTxHash);
}

File 20 of 23 : IPubdataChunkPublisher.sol
// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

/**
 * @author Matter Labs
 * @custom:security-contact [email protected]
 * @notice Interface for contract responsible chunking pubdata into the appropriate size for EIP-4844 blobs.
 */
interface IPubdataChunkPublisher {
    /// @notice Chunks pubdata into pieces that can fit into blobs.
    /// @param _pubdata The total l2 to l1 pubdata that will be sent via L1 blobs.
    /// @dev Note: This is an early implementation, in the future we plan to support up to 16 blobs per l1 batch.
    function chunkPubdataToBlobs(
        bytes calldata _pubdata
    ) external pure returns (bytes32[] memory blobLinearHashes);
}

// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

/**
 * @author Matter Labs
 * @notice MessageRoot contract is responsible for storing and aggregating the roots of the batches from different chains into the MessageRoot.
 * @custom:security-contact [email protected]
 */
interface IMessageRoot {
    /// @notice The aggregated root of the batches from different chains.
    /// @return aggregatedRoot of the batches from different chains.
    function getAggregatedRoot() external view returns (bytes32 aggregatedRoot);
}

// SPDX-License-Identifier: MIT
// 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.
pragma solidity ^0.8.0;

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

/// @custom:security-contact [email protected]
/// @author Matter Labs
/// @notice The contract that can be used for deterministic contract deployment.
interface ICreate2Factory {
    /// @notice Function that calls the `create2` method of the `ContractDeployer` contract.
    /// @dev This function accepts the same parameters as the `create2` function of the ContractDeployer system contract,
    /// so that we could efficiently relay the calldata.
    function create2(
        bytes32, // _salt
        bytes32, // _bytecodeHash
        bytes calldata // _input
    ) external payable returns (address);

    /// @notice Function that calls the `create2Account` method of the `ContractDeployer` contract.
    /// @dev This function accepts the same parameters as the `create2Account` function of the ContractDeployer system contract,
    /// so that we could efficiently relay the calldata.
    function create2Account(
        bytes32, // _salt
        bytes32, // _bytecodeHash
        bytes calldata, // _input
        IContractDeployer.AccountAbstractionVersion // _aaVersion
    ) external payable returns (address);
}

File 23 of 23 : SingleUseETHVault.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice A single-use vault that allows a designated caller to withdraw all ETH in it.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ext/zksync/SingleUseETHVault.sol)
contract SingleUseETHVault {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Unable to withdraw all.
    error WithdrawAllFailed();

    /// @dev Not authorized.
    error Unauthorized();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        WITHDRAW ALL                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    fallback() external payable virtual {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x40, 0) // Optimization trick to remove free memory pointer initialization.
            let owner := sload(0)
            // Initialization.
            if iszero(owner) {
                sstore(0, calldataload(0x00)) // Store the owner.
                return(0x00, 0x00) // Early return.
            }
            // Authorization check.
            if iszero(eq(caller(), owner)) {
                mstore(0x00, 0x82b42900) // `Unauthorized()`.
                revert(0x1c, 0x04)
            }
            let to := calldataload(0x00)
            // If the calldata is less than 32 bytes, zero-left-pad it to 32 bytes.
            // Then use the rightmost 20 bytes of the word as the `to` address.
            // This allows for the calldata to be `abi.encode(to)` or `abi.encodePacked(to)`.
            to := shr(mul(lt(calldatasize(), 0x20), shl(3, sub(0x20, calldatasize()))), to)
            // If `to` is `address(0)`, set it to `msg.sender`.
            to := xor(mul(xor(to, caller()), iszero(to)), to)
            // Transfers the whole balance to `to`.
            if iszero(call(gas(), to, selfbalance(), 0x00, 0x00, 0x00, 0x00)) {
                mstore(0x00, 0x651aee10) // `WithdrawAllFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }
}

Settings
{
  "viaIR": false,
  "codegen": "yul",
  "remappings": [
    "@zksync-contracts-0.0.1/=dependencies/@zksync-contracts-0.0.1/",
    "forge-std-1.9.6/=dependencies/forge-std-1.9.6/",
    "solady-0.1.12/=dependencies/solady-0.1.12/",
    "forge-std/=lib/forge-std/src/",
    "forge-zksync-std/=dependencies/@zksync-contracts-0.0.1/dependencies/forge-zksync-std-0.0.1/",
    "openzeppelin-contracts/=dependencies/@zksync-contracts-0.0.1/dependencies/openzeppelin-contracts-5.2.0/"
  ],
  "evmVersion": "cancun",
  "outputSelection": {
    "*": {
      "*": [
        "abi"
      ]
    }
  },
  "optimizer": {
    "enabled": true,
    "mode": "3",
    "size_fallback": false,
    "disable_system_request_memoization": true
  },
  "metadata": {},
  "libraries": {},
  "enableEraVMExtensions": false,
  "forceEVMLA": false
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"BootloaderCallFailed","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"OnlyAGW","type":"error"},{"inputs":[],"name":"OnlyBootloader","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnauthorizedCall","type":"error"},{"inputs":[],"name":"WithdrawalFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"AGW_REGISTRY","outputs":[{"internalType":"contract IAGWRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"isAuthorized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_context","type":"bytes"},{"components":[{"internalType":"uint256","name":"txType","type":"uint256"},{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"to","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"gasPerPubdataByteLimit","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"uint256","name":"paymaster","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256[4]","name":"reserved","type":"uint256[4]"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32[]","name":"factoryDeps","type":"bytes32[]"},{"internalType":"bytes","name":"paymasterInput","type":"bytes"},{"internalType":"bytes","name":"reservedDynamic","type":"bytes"}],"internalType":"struct Transaction","name":"_transaction","type":"tuple"},{"internalType":"bytes32","name":"_txHash","type":"bytes32"},{"internalType":"bytes32","name":"_suggestedSignedHash","type":"bytes32"},{"internalType":"enum ExecutionResult","name":"_txResult","type":"uint8"},{"internalType":"uint256","name":"_maxRefundedGas","type":"uint256"}],"name":"postTransaction","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"bool","name":"authorized","type":"bool"}],"name":"setAuthorized","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes32","name":"","type":"bytes32"},{"components":[{"internalType":"uint256","name":"txType","type":"uint256"},{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"to","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"gasPerPubdataByteLimit","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"uint256","name":"paymaster","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256[4]","name":"reserved","type":"uint256[4]"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32[]","name":"factoryDeps","type":"bytes32[]"},{"internalType":"bytes","name":"paymasterInput","type":"bytes"},{"internalType":"bytes","name":"reservedDynamic","type":"bytes"}],"internalType":"struct Transaction","name":"_transaction","type":"tuple"}],"name":"validateAndPayForPaymasterTransaction","outputs":[{"internalType":"bytes4","name":"magic","type":"bytes4"},{"internalType":"bytes","name":"context","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawPartial","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

9c4d535b00000000000000000000000000000000000000000000000000000000000000000100012d7795e6ea4719d61803198871506fb463bc6d58ceacc1180003e8e4c400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000be7cfa9c97342ca6c689b9fe3f3001c90f2895fd

Deployed Bytecode

0x0002000000000002000500000000000200010000000103550000006003100270000000eb0030019d000000eb033001970000000100200190000000300000c13d0000008002000039000000400020043f000000040030008c0000006c0000413d000000000201043b000000e002200270000000f40020009c000000700000213d000000fe0020009c000000a60000a13d000000ff0020009c000000e30000213d000001020020009c000001130000613d000001030020009c000002280000c13d00000107010000410000000c0010043f0000000001000411000000000010043f0000000001000414000000eb0010009c000000eb01008041000000c0011002100000010b011001c7000080100200003903a803a30000040f0000000100200190000002280000613d000000000101043b000000000001041b0000000001000414000000eb0010009c000000eb01008041000000c001100210000000f1011001c70000800d0200003900000002030000390000011504000041000000d20000013d0000000002000416000000000002004b000002280000c13d0000001f02300039000000ec02200197000000a002200039000000400020043f0000001f0430018f000000ed05300198000000a002500039000000410000613d000000a006000039000000000701034f000000007807043c0000000006860436000000000026004b0000003d0000c13d000000000004004b0000004e0000613d000000000151034f0000000304400210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000000200030008c000002280000413d000000a00600043d000000ee0060009c000002280000213d000000ef01000041000000800010043f000000f001000041000000000061041b0000000001000414000000eb0010009c000000eb01008041000000c001100210000000f1011001c70000800d020000390000000303000039000000f204000041000000000500001903a8039e0000040f0000000100200190000002280000613d000000800100043d000001400000044300000160001004430000002001000039000001000010044300000001010000390000012000100443000000f301000041000003a90001042e000000000003004b000002280000c13d0000000001000019000003a90001042e000000f50020009c000000d70000a13d000000f60020009c000000fc0000213d000000f90020009c000001320000613d000000fa0020009c000002280000c13d000000240030008c000002280000413d0000000401100370000000000301043b000000ee0030009c000002280000213d000000f001000041000000000101041a0000000002000411000000000012004b000002360000c13d00000107010000410000000c0010043f000000000030043f0000000001000414000000eb0010009c000000eb01008041000000c0011002100000010b011001c70000801002000039000300000003001d03a803a30000040f0000000100200190000002280000613d000000000101043b000100000001001d000000000101041a000200000001001d0000010c0100004100000000001004430000000001000414000000eb0010009c000000eb01008041000000c0011002100000010d011001c70000800b0200003903a803a30000040f00000001002001900000022a0000613d000000000101043b000000020010006c0000024c0000a13d0000010e01000041000000000010043f0000010a01000041000003aa00010430000001040020009c000001560000613d000001050020009c000001b20000613d000001060020009c000002280000c13d00000107010000410000000c0010043f0000000001000411000000000010043f0000010c0100004100000000001004430000000001000414000000eb0010009c000000eb01008041000000c0011002100000010d011001c70000800b0200003903a803a30000040f00000001002001900000022a0000613d000000000101043b000300000001001d0000000001000414000000eb0010009c000000eb01008041000000c0011002100000010b011001c7000080100200003903a803a30000040f0000000100200190000002280000613d000000000101043b0000000302000029000001180220009a000000000021041b0000000001000414000000eb0010009c000000eb01008041000000c001100210000000f1011001c70000800d0200003900000002030000390000011904000041000000000500041103a8039e0000040f00000001002001900000006e0000c13d000002280000013d000000fb0020009c000001c60000613d000000fc0020009c000001d70000613d000000fd0020009c000002280000c13d0000000001000416000000000001004b000002280000c13d000000f001000041000000000101041a000001d30000013d000001000020009c000001f70000613d000001010020009c000002280000c13d000000f001000041000000000501041a0000000001000411000000000051004b000002360000c13d0000000001000414000000eb0010009c000000eb01008041000000c001100210000000f1011001c70000800d020000390000000303000039000000f204000041000000000600001903a8039e0000040f0000000100200190000002280000613d000000f001000041000000000001041b0000000001000019000003a90001042e000000f70020009c000002220000613d000000f80020009c000002280000c13d000000240030008c000002280000413d0000000002000416000000000002004b000002280000c13d0000000401100370000000000101043b000000ee0010009c000002280000213d00000107020000410000000c0020043f000000000010043f0000000c01000039000000200200003903a8036b0000040f000000000101041a000000800010043f0000010801000041000003a90001042e0000000001000416000000000001004b000002280000c13d000000f001000041000000000201041a0000000001000411000000000021004b000002360000c13d000300000002001d00000116010000410000000000100443000000000100041000000004001004430000000001000414000000eb0010009c000000eb01008041000000c00110021000000117011001c70000800a0200003903a803a30000040f00000001002001900000022a0000613d000000000301043b0000000001000414000000eb0010009c000000eb01008041000000c001100210000000000003004b0000023d0000c13d0000000302000029000001c50000013d000000440030008c000002280000413d0000000002000416000000000002004b000002280000c13d0000000401100370000000000101043b000000ee0010009c000002280000213d000300000001001d03a803420000040f0000000302000029000000000020043f000000200000043f000300000001001d0000004002000039000000000100001903a8036b0000040f00000003020000290000010f02200197000000000020043f000000200010043f0000000001000019000000400200003903a8036b0000040f000000000101041a000000ff001001900000000001000039000000010100c039000000400200043d0000000000120435000000eb0020009c000000eb02008041000000400120021000000110011001c7000003a90001042e000000640030008c000002280000413d0000004402100370000000000402043b000001110040009c000002280000213d0000000002430049000001120020009c000002280000213d000002640020008c000002280000413d0000000002000411000080010020008c000002480000c13d0000011d02000041000000800020043f000300000004001d000200240040003d0000000201100360000000000101043b000000ee01100197000000840010043f000001130100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000000eb0010009c000000eb01008041000000c0011002100000011e011001c7000080050200003903a803a30000040f00000001002001900000022a0000613d000000000101043b0000000003000414000000ee02100197000000eb0030009c000000eb03008041000000c0013002100000011f011001c703a803a30000040f0000006003100270000000eb03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000000800a000039000001910000613d000000000801034f000000008908043c000000000a9a043600000000005a004b0000018d0000c13d000000000006004b0000019e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000002520000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200030008c000002280000413d000000800100043d000000000001004b0000000002000039000000010200c039000000000021004b000002280000c13d000000000001004b000002700000c13d0000012801000041000000000010043f0000011c01000041000003aa00010430000000240030008c000002280000413d0000000002000416000000000002004b000002280000c13d000000f002000041000000000402041a0000000002000411000000000042004b000002360000c13d0000000401100370000000000301043b0000000001000414000000eb0010009c000000eb01008041000000c001100210000000000003004b0000023a0000c13d0000000002040019000002410000013d0000000001000416000000000001004b000002280000c13d0000000001000412000500000001001d000400000000003d000080050100003900000044030000390000000004000415000000050440008a0000000504400210000001130200004103a803800000040f000000ee01100197000000800010043f0000010801000041000003a90001042e000000c40030008c000002280000413d0000000402100370000000000202043b000001110020009c000002280000213d0000002304200039000000000034004b000002280000813d0000000404200039000000000441034f000000000404043b000001110040009c000002280000213d00000000024200190000002402200039000000000032004b000002280000213d0000002402100370000000000202043b000001110020009c000002280000213d0000000002230049000001120020009c000002280000213d000002640020008c000002280000413d0000008401100370000000000101043b000000010010008c0000006e0000a13d000002280000013d000000640030008c000002280000413d0000000002000416000000000002004b000002280000c13d0000000402100370000000000402043b000000ee0040009c000002280000213d0000002402100370000000000302043b0000011400300198000002280000c13d0000004401100370000000000201043b000000000002004b0000000001000039000000010100c039000000000012004b000002280000c13d000300000002001d000200000003001d000100000004001d03a8034a0000040f0000000101000029000000000010043f000000200000043f0000004002000039000000000100001903a8036b0000040f00000002020000290000010f02200197000000000020043f000000200010043f0000000001000019000000400200003903a8036b0000040f000000000301041a000001290230019700000003022001af000000000021041b0000000001000019000003a90001042e000000240030008c000002280000413d0000000401100370000000000101043b000000ee0010009c0000022b0000a13d0000000001000019000003aa00010430000000000001042f000000f002000041000000000202041a0000000003000411000000000023004b000002360000c13d000000000001004b0000024f0000c13d0000010901000041000000000010043f0000010a01000041000003aa000104300000011a01000041000000000010043f0000010a01000041000003aa00010430000000f1011001c70000800902000039000002400000013d000000f1011001c700008009020000390000000304000029000000000500001903a8039e0000040f00000001002001900000006e0000c13d0000012501000041000000000010043f0000010a01000041000003aa000104300000011b01000041000000000010043f0000011c01000041000003aa000104300000000101000029000000000001041b000000030100002903a803540000040f0000000001000019000003a90001042e0000001f0530018f000000ed06300198000000400200043d00000000046200190000025d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000002590000c13d000000000005004b0000026a0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000000eb0020009c000000eb020080410000004002200210000000000112019f000003aa000104300000000201000029000001a0021000390000000101000367000000000321034f000000000403043b000000000300003100000003090000290000000005930049000000230550008a00000120065001970000012007400197000000000867013f000000000067004b00000000060000190000012006004041000000000054004b00000000050000190000012005008041000001200080009c000000000605c019000000000006004b000002280000c13d00000004059000390000000005450019000000000451034f000000000404043b000001110040009c000002280000213d0000000003430049000000200850003900000120053001970000012006800197000000000756013f000000000056004b00000000050000190000012005004041000300000008001d000000000038004b00000000030000190000012003002041000001200070009c000000000503c019000000000005004b000002280000c13d000000000004004b000002a20000c13d0000012701000041000000000010043f0000011c01000041000003aa00010430000000040040008c000002280000413d00020180002000920000000201100360000000000101043b000000ee01100197000000000010043f000000200000043f0000000001000414000000eb0010009c000000eb01008041000000c00110021000000121011001c7000080100200003903a803a30000040f0000000100200190000002280000613d000000000101043b00000003020000290000000102200367000000000202043b0000010f02200197000000000020043f000000200010043f0000000001000414000000eb0010009c000000eb01008041000000c00110021000000121011001c7000080100200003903a803a30000040f0000000100200190000002280000613d000000000101043b000000000101041a000000ff001001900000029e0000613d000000400100043d000300000001001d000001220010009c000002d10000413d0000012301000041000000000010043f0000004101000039000000040010043f0000012401000041000003aa0001043000000003020000290000002001200039000100000001001d000000400010043f000000000002043500000002040000290000002001400039000000010310036700000060014000390000000101100367000000000101043b000000000203043b000000000002004b000003060000c13d0000000001000414000000eb0010009c000000eb01008041000000c001100210000080010200003903a8039e0000040f0000000100200190000002440000613d000000400100043d0000002002100039000000400300003900000000003204350000012602000041000000000021043500000003020000290000000002020433000000400310003900000000002304350000012a062001970000001f0520018f0000006004100039000000010040006b0000031e0000813d000000000006004b000003020000613d00000001085000290000000007540019000000200770008a000000200880008a0000000009670019000000000a680019000000000a0a04330000000000a90435000000200660008c000002fc0000c13d000000000005004b000003350000613d00000000070400190000032a0000013d00000000032100a900000000022300d9000000000021004b000003180000c13d0000000001000414000000000003004b000002e00000613d000000eb0010009c000000eb01008041000000c001100210000000f1011001c700008009020000390000800104000039000000000500001903a8039e0000040f0000000100200190000002440000613d000002e70000013d0000012301000041000000000010043f0000001101000039000000040010043f0000012401000041000003aa000104300000000007640019000000000006004b000003270000613d00000001080000290000000009040019000000008a0804340000000009a90436000000000079004b000003230000c13d000000000005004b000003350000613d000100010060002d0000000305500210000000000607043300000000065601cf000000000656022f000000010800002900000000080804330000010005500089000000000858022f00000000055801cf000000000565019f00000000005704350000001f052000390000012a03500197000000000242001900000000000204350000006002300039000000eb0020009c000000eb020080410000006002200210000000eb0010009c000000eb010080410000004001100210000000000112019f000003a90001042e00000024010000390000000101100367000000000101043b0000011400100198000003480000c13d000000000001042d0000000001000019000003aa00010430000000f001000041000000000101041a0000000002000411000000000012004b000003500000c13d000000000001042d0000011a01000041000000000010043f0000010a01000041000003aa000104300001000000000002000000f002000041000000000502041a0000000002000414000000ee06100197000000eb0020009c000000eb02008041000000c001200210000000f1011001c70000800d020000390000000303000039000000f204000041000100000006001d03a8039e0000040f0000000100200190000003680000613d000000f0010000410000000102000029000000000021041b000000000001042d0000000001000019000003aa00010430000000000001042f000000eb0010009c000000eb010080410000004001100210000000eb0020009c000000eb020080410000006002200210000000000112019f0000000002000414000000eb0020009c000000eb02008041000000c002200210000000000112019f000000f1011001c7000080100200003903a803a30000040f00000001002001900000037e0000613d000000000101043b000000000001042d0000000001000019000003aa0001043000000000050100190000000000200443000000050030008c0000038e0000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b000003860000413d000000eb0030009c000000eb0300804100000060013002100000000002000414000000eb0020009c000000eb02008041000000c002200210000000000112019f0000012b011001c7000000000205001903a803a30000040f00000001002001900000039d0000613d000000000101043b000000000001042d000000000001042f000003a1002104210000000102000039000000000001042d0000000002000019000000000001042d000003a6002104230000000102000039000000000001042d0000000002000019000000000001042d000003a800000432000003a90001042e000003aa00010430000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000d5e3efda6bb5ab545cc2358796e96d9033496ddaffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392702000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0000000020000000000000000000000000000008000000100000000000000000000000000000000000000000000000000000000000000000000000000739d755500000000000000000000000000000000000000000000000000000000d9972b9500000000000000000000000000000000000000000000000000000000f2fde38a00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000fee81cf400000000000000000000000000000000000000000000000000000000d9972b9600000000000000000000000000000000000000000000000000000000f04e283e00000000000000000000000000000000000000000000000000000000739d755600000000000000000000000000000000000000000000000000000000817b17f0000000000000000000000000000000000000000000000000000000008da5cb5b000000000000000000000000000000000000000000000000000000003ccfd60a0000000000000000000000000000000000000000000000000000000057c6ecdc0000000000000000000000000000000000000000000000000000000057c6ecdd00000000000000000000000000000000000000000000000000000000715018a6000000000000000000000000000000000000000000000000000000003ccfd60b0000000000000000000000000000000000000000000000000000000054d1f13d00000000000000000000000000000000000000000000000000000000038a24bc000000000000000000000000000000000000000000000000000000001211540c000000000000000000000000000000000000000000000000000000002569296200000000000000000000000000000000000000000000000000000000389a75e10000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000007448fbae00000000000000000000000000000000000000040000001c000000000000000002000000000000000000000000000000000000200000000c0000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d955391320200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000006f5e8818ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e00000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c929cc7f708afc65944829bd487b90b72536b1951864fbfc14e125fc972a6507f390200000200000000000000000000000000000024000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d00dbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d0000000000000000000000000000000000000000000000000000000082b42900e38026aa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000932bdb47000000000000000000000000000000000000000000000000000000000200000200000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000002400000080000000000000000080000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffe04e487b7100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000000000000000000000b12d13eb038a24bc000000000000000000000000000000000000000000000000000000007bf6a16f000000000000000000000000000000000000000000000000000000003ded360c00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00200000200000000000000000000000000000000000000000000000000000000091e0d6308913da5417802fd2fcd12a23ab02f5c2d802f8df54fd7b9b307d87e

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

000000000000000000000000be7cfa9c97342ca6c689b9fe3f3001c90f2895fd

-----Decoded View---------------
Arg [0] : _owner (address): 0xbe7cFA9C97342CA6c689b9fe3F3001c90f2895fd

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000be7cfa9c97342ca6c689b9fe3f3001c90f2895fd


Block Transaction Gas Used Reward
view all blocks produced

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

Validator Index Block Amount
View All Withdrawals

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

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