ETH Price: $2,960.25 (+0.24%)

Contract

0xFaAa6535635c9dc3537985a72FD3D2a6053d2035

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Withdraw309585362025-12-16 14:19:1039 days ago1765894750IN
0xFaAa6535...6053d2035
0 ETH0.000006140.05633
Transfer271781242025-11-25 15:19:5460 days ago1764083994IN
0xFaAa6535...6053d2035
10 ETH0.000004870.04525
Withdraw212332052025-10-14 14:09:19102 days ago1760450959IN
0xFaAa6535...6053d2035
0 ETH0.000005050.046
Transfer201390402025-09-27 19:10:19119 days ago1759000219IN
0xFaAa6535...6053d2035
10 ETH0.000004050.047
Withdraw201390212025-09-27 19:09:55119 days ago1759000195IN
0xFaAa6535...6053d2035
0 ETH0.000005020.046
Transfer133029642025-07-02 16:58:17206 days ago1751475497IN
0xFaAa6535...6053d2035
10 ETH0.000004020.046
Withdraw133028652025-07-02 16:56:38206 days ago1751475398IN
0xFaAa6535...6053d2035
0 ETH0.000005170.046
Transfer133028412025-07-02 16:56:05206 days ago1751475365IN
0xFaAa6535...6053d2035
0.05 ETH0.000003830.04525
Set Approval Tar...133028392025-07-02 16:56:03206 days ago1751475363IN
0xFaAa6535...6053d2035
0 ETH0.000003850.04525
Set Approval Tar...133028362025-07-02 16:56:00206 days ago1751475360IN
0xFaAa6535...6053d2035
0 ETH0.000003850.04525
Set Payment Toke...133028342025-07-02 16:55:58206 days ago1751475358IN
0xFaAa6535...6053d2035
0 ETH0.000003620.04525
Set Payment Toke...133028322025-07-02 16:55:56206 days ago1751475356IN
0xFaAa6535...6053d2035
0 ETH0.000003620.04525
Set Authorized C...133028302025-07-02 16:55:54206 days ago1751475354IN
0xFaAa6535...6053d2035
0 ETH0.000003870.04525
Set Authorized C...133028282025-07-02 16:55:52206 days ago1751475352IN
0xFaAa6535...6053d2035
0 ETH0.000003870.04525
Set Authorized C...133028272025-07-02 16:55:51206 days ago1751475351IN
0xFaAa6535...6053d2035
0 ETH0.000003870.04525
Set Authorized C...133028242025-07-02 16:55:48206 days ago1751475348IN
0xFaAa6535...6053d2035
0 ETH0.00000480.04525
Transfer129670862025-06-28 16:49:58210 days ago1751129398IN
0xFaAa6535...6053d2035
0.05 ETH0.000003830.04525
Set Approval Tar...129670852025-06-28 16:49:57210 days ago1751129397IN
0xFaAa6535...6053d2035
0 ETH0.00000370.04525
Set Approval Tar...129670832025-06-28 16:49:55210 days ago1751129395IN
0xFaAa6535...6053d2035
0 ETH0.00000370.04525
Set Payment Toke...129670812025-06-28 16:49:53210 days ago1751129393IN
0xFaAa6535...6053d2035
0 ETH0.00000370.04525
Set Payment Toke...129670792025-06-28 16:49:51210 days ago1751129391IN
0xFaAa6535...6053d2035
0 ETH0.00000370.04525
Set Authorized C...129670772025-06-28 16:49:49210 days ago1751129389IN
0xFaAa6535...6053d2035
0 ETH0.000003720.04525
Set Authorized C...129670752025-06-28 16:49:47210 days ago1751129387IN
0xFaAa6535...6053d2035
0 ETH0.000003720.04525
Set Authorized C...129670722025-06-28 16:49:44210 days ago1751129384IN
0xFaAa6535...6053d2035
0 ETH0.000003720.04525
Set Authorized C...129670702025-06-28 16:49:42210 days ago1751129382IN
0xFaAa6535...6053d2035
0 ETH0.000003720.04525
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
309585362025-12-16 14:19:1039 days ago1765894750
0xFaAa6535...6053d2035
3.93370597 ETH
301628062025-12-11 17:46:1444 days ago1765475174
0xFaAa6535...6053d2035
0.00001313 ETH
301625572025-12-11 17:44:4644 days ago1765475086
0xFaAa6535...6053d2035
0.00001312 ETH
301006632025-12-11 11:41:1744 days ago1765453277
0xFaAa6535...6053d2035
0.00001312 ETH
301006372025-12-11 11:41:0544 days ago1765453265
0xFaAa6535...6053d2035
0.00001313 ETH
298095122025-12-10 6:41:3845 days ago1765348898
0xFaAa6535...6053d2035
0.00001458 ETH
298094772025-12-10 6:41:1945 days ago1765348879
0xFaAa6535...6053d2035
0.00001457 ETH
298093542025-12-10 6:40:1145 days ago1765348811
0xFaAa6535...6053d2035
0.00001458 ETH
297326952025-12-09 19:37:2346 days ago1765309043
0xFaAa6535...6053d2035
0.00001315 ETH
297326482025-12-09 19:37:0546 days ago1765309025
0xFaAa6535...6053d2035
0.00001315 ETH
297325662025-12-09 19:36:2946 days ago1765308989
0xFaAa6535...6053d2035
0.00001314 ETH
297325242025-12-09 19:36:1146 days ago1765308971
0xFaAa6535...6053d2035
0.00001315 ETH
297182432025-12-09 17:57:2046 days ago1765303040
0xFaAa6535...6053d2035
0.00001318 ETH
297137112025-12-09 17:27:5746 days ago1765301277
0xFaAa6535...6053d2035
0.00001327 ETH
297046402025-12-09 16:26:3346 days ago1765297593
0xFaAa6535...6053d2035
0.00001329 ETH
297045812025-12-09 16:26:1046 days ago1765297570
0xFaAa6535...6053d2035
0.00001302 ETH
297044632025-12-09 16:25:2246 days ago1765297522
0xFaAa6535...6053d2035
0.0000103 ETH
297027782025-12-09 16:12:4246 days ago1765296762
0xFaAa6535...6053d2035
0.00001328 ETH
296804492025-12-09 13:29:5546 days ago1765286995
0xFaAa6535...6053d2035
0.00001314 ETH
296804002025-12-09 13:29:3346 days ago1765286973
0xFaAa6535...6053d2035
0.00001315 ETH
296740312025-12-09 12:39:5046 days ago1765283990
0xFaAa6535...6053d2035
0.00001316 ETH
296656492025-12-09 11:36:3946 days ago1765280199
0xFaAa6535...6053d2035
0.00001315 ETH
296269192025-12-09 5:59:3246 days ago1765259972
0xFaAa6535...6053d2035
0.00001316 ETH
296268912025-12-09 5:59:0346 days ago1765259943
0xFaAa6535...6053d2035
0.00001315 ETH
296268492025-12-09 5:58:3546 days ago1765259915
0xFaAa6535...6053d2035
0.00001315 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;

    mapping(address token => bool isPaymentToken) private _paymentTokens;
    mapping(address target => bool isApprovalTarget) private _approvalTargets;

    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 (selector == 0x095ea7b3) {
            if (!_paymentTokens[target]) {
                revert UnauthorizedCall();
            }
            
            (address approvalTarget,) = abi.decode(_transaction.data[4:], (address, uint256));

            if (!_approvalTargets[approvalTarget]) {
                revert UnauthorizedCall();
            }
        } else 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 setAuthorizedCall(address target, bytes4 selector, bool authorized) external onlyOwner {
        _authorizedCalls[target][selector] = authorized;
    }

    function setPaymentToken(address token, bool isPaymentToken) external onlyOwner {
        _paymentTokens[token] = isPaymentToken;
    }

    function setApprovalTarget(address target, bool isApprovalTarget) external onlyOwner {
        _approvalTargets[target] = isApprovalTarget;
    }

    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":"bool","name":"isApprovalTarget","type":"bool"}],"name":"setApprovalTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"bool","name":"authorized","type":"bool"}],"name":"setAuthorizedCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"isPaymentToken","type":"bool"}],"name":"setPaymentToken","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"}]

9c4d535b000000000000000000000000000000000000000000000000000000000000000001000155f97e678847cb3bf14ef132a90131a18616f2d396ac6573c50520299600000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000be7cfa9c97342ca6c689b9fe3f3001c90f2895fd

Deployed Bytecode

0x00020000000000020006000000000002000100000001035500000060031002700000010d0030019d0000010d0330019700000001002001900000002c0000c13d0000008002000039000000400020043f000000040030008c000000680000413d000000000201043b000000e002200270000001160020009c0000006c0000213d000001220020009c0000007a0000213d000001280020009c000000cd0000213d0000012b0020009c000001440000613d0000012c0020009c0000025e0000c13d000000240030008c0000025e0000413d0000000002000416000000000002004b0000025e0000c13d0000011202000041000000000402041a0000000002000411000000000042004b0000026c0000c13d0000000401100370000000000301043b00000000010004140000010d0010009c0000010d01008041000000c001100210000000000003004b000002700000c13d0000000002040019000000ef0000013d0000000002000416000000000002004b0000025e0000c13d0000001f023000390000010e02200197000000a002200039000000400020043f0000001f0430018f0000010f05300198000000a0025000390000003d0000613d000000a006000039000000000701034f000000007807043c0000000006860436000000000026004b000000390000c13d000000000004004b0000004a0000613d000000000151034f0000000304400210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000000200030008c0000025e0000413d000000a00600043d000001100060009c0000025e0000213d0000011101000041000000800010043f0000011201000041000000000061041b00000000010004140000010d0010009c0000010d01008041000000c00110021000000113011001c70000800d02000039000000030300003900000114040000410000000005000019043004260000040f00000001002001900000025e0000613d000000800100043d0000014000000443000001600010044300000020010000390000010000100443000000010100003900000120001004430000011501000041000004310001042e000000000003004b0000025e0000c13d0000000001000019000004310001042e000001170020009c000000980000213d0000011d0020009c000000f00000213d000001200020009c000001a10000613d000001210020009c0000025e0000c13d0000000001000416000000000001004b0000025e0000c13d0000011201000041000000000101041a000001290000013d000001230020009c000001180000213d000001260020009c000001c10000613d000001270020009c0000025e0000c13d0000012d010000410000000c0010043f0000000001000411000000000010043f00000000010004140000010d0010009c0000010d01008041000000c00110021000000131011001c700008010020000390430042b0000040f00000001002001900000025e0000613d000000000101043b000000000001041b00000000010004140000010d0010009c0000010d01008041000000c00110021000000113011001c70000800d0200003900000002030000390000013b04000041000002130000013d000001180020009c0000012d0000213d0000011b0020009c000001d20000613d0000011c0020009c0000025e0000c13d000000240030008c0000025e0000413d0000000401100370000000000101043b000400000001001d000001100010009c0000025e0000213d0000011201000041000000000101041a0000000002000411000000000012004b0000026c0000c13d0000012d010000410000000c0010043f0000000401000029000000000010043f00000000010004140000010d0010009c0000010d01008041000000c00110021000000131011001c700008010020000390430042b0000040f00000001002001900000025e0000613d000000000101043b000200000001001d000000000101041a000300000001001d0000013201000041000000000010044300000000010004140000010d0010009c0000010d01008041000000c00110021000000133011001c70000800b020000390430042b0000040f0000000100200190000002600000613d000000000101043b000000030010006c000002820000a13d0000013401000041000000000010043f00000130010000410000043200010430000001290020009c000001ed0000613d0000012a0020009c0000025e0000c13d0000000001000416000000000001004b0000025e0000c13d0000011201000041000000000201041a0000000001000411000000000021004b0000026c0000c13d000400000002001d0000013c0100004100000000001004430000000001000410000000040010044300000000010004140000010d0010009c0000010d01008041000000c0011002100000013d011001c70000800a020000390430042b0000040f0000000100200190000002600000613d000000000301043b00000000010004140000010d0010009c0000010d01008041000000c001100210000000000003004b000002730000c13d0000000402000029000002770000013d0000011e0020009c000002180000613d0000011f0020009c0000025e0000c13d000000440030008c0000025e0000413d0000000002000416000000000002004b0000025e0000c13d0000000401100370000000000101043b000400000001001d000001100010009c0000025e0000213d043003ca0000040f0000000402000029000000000020043f000000200000043f000400000001001d00000040020000390000000001000019043003f30000040f00000004020000290000013502200197000000000020043f000000200010043f00000000010000190000004002000039043003f30000040f000000000101041a000000ff001001900000000001000039000000010100c039000000400200043d00000000001204350000010d0020009c0000010d02008041000000400120021000000136011001c7000004310001042e000001240020009c000002430000613d000001250020009c0000025e0000c13d0000000001000416000000000001004b0000025e0000c13d0000000001000412000600000001001d000500000000003d000080050100003900000044030000390000000004000415000000060440008a00000005044002100000013a02000041043004080000040f0000011001100197000000800010043f0000012e01000041000004310001042e000001190020009c000002580000613d0000011a0020009c0000025e0000c13d000000240030008c0000025e0000413d0000000002000416000000000002004b0000025e0000c13d0000000401100370000000000101043b000001100010009c0000025e0000213d0000012d020000410000000c0020043f000000000010043f0000000c010000390000002002000039043003f30000040f000000000101041a000000800010043f0000012e01000041000004310001042e000000640030008c0000025e0000413d0000004402100370000000000202043b000400000002001d000001380020009c0000025e0000213d000000040230006a000001390020009c0000025e0000213d000002640020008c0000025e0000413d0000000002000411000080010020008c0000027e0000c13d0000014302000041000000800020043f0000000402000029000300240020003d0000000301100360000000000101043b0000011001100197000000840010043f0000013a01000041000000000010044300000000010004120000000400100443000000240000044300000000010004140000010d0010009c0000010d01008041000000c00110021000000144011001c700008005020000390430042b0000040f0000000100200190000002600000613d000000000101043b000000000300041400000110021001970000010d0030009c0000010d03008041000000c00130021000000145011001c70430042b0000040f00000060031002700000010d03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000000800a000039000001800000613d000000000801034f000000008908043c000000000a9a043600000000005a004b0000017c0000c13d000000000006004b0000018d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000002880000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200030008c0000025e0000413d000000800100043d000000000001004b0000000002000039000000010200c039000000000021004b0000025e0000c13d000000000001004b000002a60000c13d0000014f01000041000000000010043f00000142010000410000043200010430000000c40030008c0000025e0000413d0000000402100370000000000202043b000001380020009c0000025e0000213d0000002304200039000000000034004b0000025e0000813d0000000404200039000000000441034f000000000404043b000001380040009c0000025e0000213d00000000024200190000002402200039000000000032004b0000025e0000213d0000002402100370000000000202043b000001380020009c0000025e0000213d0000000002230049000001390020009c0000025e0000213d000002640020008c0000025e0000413d0000008401100370000000000101043b000000010010008c0000006a0000a13d0000025e0000013d000000440030008c0000025e0000413d0000000002000416000000000002004b0000025e0000c13d0000000401100370000000000101043b000400000001001d000001100010009c0000025e0000213d043003bf0000040f000300000001001d043003d20000040f0000000401000029000000000010043f0000000101000039000001e20000013d000000440030008c0000025e0000413d0000000002000416000000000002004b0000025e0000c13d0000000401100370000000000101043b000400000001001d000001100010009c0000025e0000213d043003bf0000040f000300000001001d043003d20000040f0000000401000029000000000010043f0000000201000039000000200010043f00000040020000390000000001000019043003f30000040f000000000301041a0000015002300197000000030000006b000000010220c1bf000000000021041b0000000001000019000004310001042e0000012d010000410000000c0010043f0000000001000411000000000010043f0000013201000041000000000010044300000000010004140000010d0010009c0000010d01008041000000c00110021000000133011001c70000800b020000390430042b0000040f0000000100200190000002600000613d000000000101043b000400000001001d00000000010004140000010d0010009c0000010d01008041000000c00110021000000131011001c700008010020000390430042b0000040f00000001002001900000025e0000613d000000000101043b00000004020000290000013e0220009a000000000021041b00000000010004140000010d0010009c0000010d01008041000000c00110021000000113011001c70000800d0200003900000002030000390000013f040000410000000005000411043004260000040f00000001002001900000006a0000c13d0000025e0000013d000000640030008c0000025e0000413d0000000002000416000000000002004b0000025e0000c13d0000000402100370000000000202043b000400000002001d000001100020009c0000025e0000213d0000002402100370000000000202043b000300000002001d00000137002001980000025e0000c13d0000004401100370000000000201043b000000000002004b0000000001000039000000010100c039000200000002001d000000000012004b0000025e0000c13d043003d20000040f0000000401000029000000000010043f000000200000043f00000040020000390000000001000019043003f30000040f00000003020000290000013502200197000000000020043f000000200010043f00000000010000190000004002000039043003f30000040f000000000301041a000001500230019700000002022001af000000000021041b0000000001000019000004310001042e0000011201000041000000000501041a0000000001000411000000000051004b0000026c0000c13d00000000010004140000010d0010009c0000010d01008041000000c00110021000000113011001c70000800d02000039000000030300003900000114040000410000000006000019043004260000040f00000001002001900000025e0000613d0000011201000041000000000001041b0000000001000019000004310001042e000000240030008c0000025e0000413d0000000401100370000000000101043b000001100010009c000002610000a13d00000000010000190000043200010430000000000001042f0000011202000041000000000202041a0000000003000411000000000023004b0000026c0000c13d000000000001004b000002850000c13d0000012f01000041000000000010043f000001300100004100000432000104300000014001000041000000000010043f0000013001000041000004320001043000000113011001c70000800902000039000002760000013d00000113011001c7000080090200003900000004040000290000000005000019043004260000040f00000001002001900000006a0000c13d0000014c01000041000000000010043f000001300100004100000432000104300000014101000041000000000010043f000001420100004100000432000104300000000201000029000000000001041b0000000401000029043003dc0000040f0000000001000019000004310001042e0000001f0530018f0000010f06300198000000400200043d0000000004620019000002930000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000028f0000c13d000000000005004b000002a00000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f000000000014043500000060013002100000010d0020009c0000010d020080410000004002200210000000000112019f00000432000104300000000308000029000201a00080003d00000001010003670000000202100360000000000402043b0000000003000031000000040230006a000000230220008a00000146052001970000014606400197000000000756013f000000000056004b00000000050000190000014605004041000000000024004b00000000020000190000014602008041000001460070009c000000000502c0190000002002800039000000000221034f000000000202043b000000000005004b0000025e0000c13d0000000405000029000300040050003d0000000305400029000000000451034f000000000404043b000001380040009c0000025e0000213d0000000006430049000000200350003900000146056001970000014607300197000000000857013f000000000057004b00000000050000190000014605004041000000000063004b00000000060000190000014606002041000001460080009c000000000506c019000000000005004b0000025e0000c13d000000000004004b000002da0000c13d0000014e01000041000000000010043f00000142010000410000043200010430000000040040008c0000025e0000413d0000011002200197000000000131034f000000000101043b000000000020043f0000013501100197000100000001001d000001470010009c000003290000c13d0000000101000039000000200010043f00000000010004140000010d0010009c0000010d01008041000000c00110021000000148011001c700008010020000390430042b0000040f00000001002001900000025e0000613d000000000101043b000000000101041a000000ff00100190000002d60000613d00000001010003670000000202100360000000000202043b0000000003000031000000040430006a000000230440008a00000146054001970000014606200197000000000756013f000000000056004b00000000050000190000014605004041000000000042004b00000000040000190000014604008041000001460070009c000000000504c019000000000005004b0000025e0000c13d0000000302200029000000000421034f000000000404043b000001380040009c0000025e0000213d000000040040008c0000025e0000413d00000000034300490000002005200039000000000035004b0000000006000019000001460600204100000146033001970000014605500197000000000735013f000000000035004b00000000030000190000014603004041000001460070009c000000000306c019000000000003004b0000025e0000c13d000000040340008a000000400030008c0000025e0000413d0000002402200039000000000121034f000000000101043b000001100010009c0000025e0000213d000000000010043f0000000201000039000000200010043f0000000001000414000003380000013d000000200000043f00000000010004140000010d0010009c0000010d01008041000000c00110021000000148011001c700008010020000390430042b0000040f00000001002001900000025e0000613d000000000101043b0000000102000029000000000020043f000000200010043f00000000010004140000010d0010009c0000010d01008041000000c00110021000000148011001c700008010020000390430042b0000040f00000001002001900000025e0000613d000000000101043b000000000101041a000000ff00100190000002d60000613d000000400100043d000400000001001d000001490010009c0000034e0000a13d0000014a01000041000000000010043f0000004101000039000000040010043f0000014b01000041000004320001043000000004020000290000002001200039000300000001001d000000400010043f00000000000204350000000204000029000001600140008a0000000103100367000001200140008a0000000101100367000000000101043b000000000203043b000000000002004b000003830000c13d00000000010004140000010d0010009c0000010d01008041000000c0011002100000800102000039043004260000040f00000001002001900000027a0000613d000000400100043d0000002002100039000000400300003900000000003204350000014d020000410000000000210435000000040200002900000000020204330000004003100039000000000023043500000151062001970000001f0520018f0000006004100039000000030040006b0000039b0000813d000000000006004b0000037f0000613d00000003085000290000000007540019000000200770008a000000200880008a0000000009670019000000000a680019000000000a0a04330000000000a90435000000200660008c000003790000c13d000000000005004b000003b20000613d0000000007040019000003a70000013d00000000032100a900000000022300d9000000000021004b000003950000c13d0000000001000414000000000003004b0000035d0000613d0000010d0010009c0000010d01008041000000c00110021000000113011001c7000080090200003900008001040000390000000005000019043004260000040f00000001002001900000027a0000613d000003640000013d0000014a01000041000000000010043f0000001101000039000000040010043f0000014b0100004100000432000104300000000007640019000000000006004b000003a40000613d00000003080000290000000009040019000000008a0804340000000009a90436000000000079004b000003a00000c13d000000000005004b000003b20000613d000300030060002d0000000305500210000000000607043300000000065601cf000000000656022f000000030800002900000000080804330000010005500089000000000858022f00000000055801cf000000000565019f00000000005704350000001f0520003900000151035001970000000002420019000000000002043500000060023000390000010d0020009c0000010d0200804100000060022002100000010d0010009c0000010d010080410000004001100210000000000112019f000004310001042e00000024010000390000000101100367000000000101043b000000000001004b0000000002000039000000010200c039000000000021004b000003c80000c13d000000000001042d0000000001000019000004320001043000000024010000390000000101100367000000000101043b0000013700100198000003d00000c13d000000000001042d000000000100001900000432000104300000011201000041000000000101041a0000000002000411000000000012004b000003d80000c13d000000000001042d0000014001000041000000000010043f0000013001000041000004320001043000010000000000020000011202000041000000000502041a000000000200041400000110061001970000010d0020009c0000010d02008041000000c00120021000000113011001c70000800d0200003900000003030000390000011404000041000100000006001d043004260000040f0000000100200190000003f00000613d00000112010000410000000102000029000000000021041b000000000001042d00000000010000190000043200010430000000000001042f0000010d0010009c0000010d0100804100000040011002100000010d0020009c0000010d020080410000006002200210000000000112019f00000000020004140000010d0020009c0000010d02008041000000c002200210000000000112019f00000113011001c700008010020000390430042b0000040f0000000100200190000004060000613d000000000101043b000000000001042d0000000001000019000004320001043000000000050100190000000000200443000000050030008c000004160000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b0000040e0000413d0000010d0030009c0000010d03008041000000600130021000000000020004140000010d0020009c0000010d02008041000000c002200210000000000112019f00000152011001c700000000020500190430042b0000040f0000000100200190000004250000613d000000000101043b000000000001042d000000000001042f00000429002104210000000102000039000000000001042d0000000002000019000000000001042d0000042e002104230000000102000039000000000001042d0000000002000019000000000001042d0000043000000432000004310001042e0000043200010430000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000d5e3efda6bb5ab545cc2358796e96d9033496ddaffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392702000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0000000020000000000000000000000000000008000000100000000000000000000000000000000000000000000000000000000000000000000000000817b17ef00000000000000000000000000000000000000000000000000000000e55ff36500000000000000000000000000000000000000000000000000000000f2fde38a00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000fee81cf400000000000000000000000000000000000000000000000000000000e55ff36600000000000000000000000000000000000000000000000000000000f04e283e00000000000000000000000000000000000000000000000000000000b66d348b00000000000000000000000000000000000000000000000000000000b66d348c00000000000000000000000000000000000000000000000000000000d9972b9600000000000000000000000000000000000000000000000000000000817b17f0000000000000000000000000000000000000000000000000000000008da5cb5b00000000000000000000000000000000000000000000000000000000430884ce00000000000000000000000000000000000000000000000000000000715018a500000000000000000000000000000000000000000000000000000000715018a600000000000000000000000000000000000000000000000000000000739d755600000000000000000000000000000000000000000000000000000000430884cf0000000000000000000000000000000000000000000000000000000054d1f13d00000000000000000000000000000000000000000000000000000000256929610000000000000000000000000000000000000000000000000000000025692962000000000000000000000000000000000000000000000000000000003ccfd60b00000000000000000000000000000000000000000000000000000000038a24bc000000000000000000000000000000000000000000000000000000001211540c00000000000000000000000000000000000000000000000000000000389a75e10000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000007448fbae00000000000000000000000000000000000000040000001c000000000000000002000000000000000000000000000000000000200000000c0000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d955391320200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000006f5e8818ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32efa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c929cc7f708afc65944829bd487b90b72536b1951864fbfc14e125fc972a6507f390200000200000000000000000000000000000024000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d00dbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d0000000000000000000000000000000000000000000000000000000082b42900e38026aa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000932bdb4700000000000000000000000000000000000000000000000000000000020000020000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000240000008000000000000000008000000000000000000000000000000000000000000000000000000000000000095ea7b3000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdf4e487b7100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000000000000000000000b12d13eb038a24bc000000000000000000000000000000000000000000000000000000007bf6a16f000000000000000000000000000000000000000000000000000000003ded360c00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00200000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080d48bff695bc9b903dca1a7a3e7682aef3f48ab711ae55354680e95de67d93b

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.