ETH Price: $1,946.22 (-2.12%)

Transaction Decoder

Block:
23599504 at Oct-17-2025 07:35:11 PM +UTC
Transaction Fee:
0.000028800132322731 ETH $0.06
Gas Used:
88,727 Gas / 0.324592653 Gwei

Account State Difference:

  Address   Before After State Difference Code
(Titan Builder)
16.36267539550575801 Eth16.36267983185575801 Eth0.00000443635
0x836DaC4f...e7Aaa88a3
(Bundler: 0x836...8a3)
1.449715462838654005 Eth
Nonce: 3560
1.449686662706331274 Eth
Nonce: 3561
0.000028800132322731

Execution Trace

EntryPoint.handleOps( ops=, beneficiary=0x836DaC4f32d4ed1579BDA16B390C182e7Aaa88a3 )
  • 0xa571f7bb23b08b246a036784dc2890625a065b8a.19822f7c( )
    • BizGuard.STATICCALL( )
    • Null: 0x000...001.c557999d( )
      File 1 of 2: EntryPoint
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)
      pragma solidity ^0.8.20;
      import {IERC165} from "./IERC165.sol";
      /**
       * @dev Implementation of the {IERC165} interface.
       *
       * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
       * for the additional interface id that will be supported. For example:
       *
       * ```solidity
       * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
       *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
       * }
       * ```
       */
      abstract contract ERC165 is IERC165 {
          /**
           * @dev See {IERC165-supportsInterface}.
           */
          function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
              return interfaceId == type(IERC165).interfaceId;
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
      pragma solidity ^0.8.20;
      /**
       * @dev Interface of the ERC165 standard, as defined in the
       * https://eips.ethereum.org/EIPS/eip-165[EIP].
       *
       * Implementers can declare support of contract interfaces, which can then be
       * queried by others ({ERC165Checker}).
       *
       * For an implementation, see {ERC165}.
       */
      interface IERC165 {
          /**
           * @dev Returns true if this contract implements the interface defined by
           * `interfaceId`. See the corresponding
           * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
           * to learn more about how these ids are created.
           *
           * This function call must use less than 30 000 gas.
           */
          function supportsInterface(bytes4 interfaceId) external view returns (bool);
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)
      pragma solidity ^0.8.20;
      /**
       * @dev Contract module that helps prevent reentrant calls to a function.
       *
       * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
       * available, which can be applied to functions to make sure there are no nested
       * (reentrant) calls to them.
       *
       * Note that because there is a single `nonReentrant` guard, functions marked as
       * `nonReentrant` may not call one another. This can be worked around by making
       * those functions `private`, and then adding `external` `nonReentrant` entry
       * points to them.
       *
       * TIP: If you would like to learn more about reentrancy and alternative ways
       * to protect against it, check out our blog post
       * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
       */
      abstract contract ReentrancyGuard {
          // Booleans are more expensive than uint256 or any type that takes up a full
          // word because each write operation emits an extra SLOAD to first read the
          // slot's contents, replace the bits taken up by the boolean, and then write
          // back. This is the compiler's defense against contract upgrades and
          // pointer aliasing, and it cannot be disabled.
          // The values being non-zero value makes deployment a bit more expensive,
          // but in exchange the refund on every call to nonReentrant will be lower in
          // amount. Since refunds are capped to a percentage of the total
          // transaction's gas, it is best to keep them low in cases like this one, to
          // increase the likelihood of the full refund coming into effect.
          uint256 private constant NOT_ENTERED = 1;
          uint256 private constant ENTERED = 2;
          uint256 private _status;
          /**
           * @dev Unauthorized reentrant call.
           */
          error ReentrancyGuardReentrantCall();
          constructor() {
              _status = NOT_ENTERED;
          }
          /**
           * @dev Prevents a contract from calling itself, directly or indirectly.
           * Calling a `nonReentrant` function from another `nonReentrant`
           * function is not supported. It is possible to prevent this from happening
           * by making the `nonReentrant` function external, and making it call a
           * `private` function that does the actual work.
           */
          modifier nonReentrant() {
              _nonReentrantBefore();
              _;
              _nonReentrantAfter();
          }
          function _nonReentrantBefore() private {
              // On the first call to nonReentrant, _status will be NOT_ENTERED
              if (_status == ENTERED) {
                  revert ReentrancyGuardReentrantCall();
              }
              // Any calls to nonReentrant after this point will fail
              _status = ENTERED;
          }
          function _nonReentrantAfter() private {
              // By storing the original value once again, a refund is triggered (see
              // https://eips.ethereum.org/EIPS/eip-2200)
              _status = NOT_ENTERED;
          }
          /**
           * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
           * `nonReentrant` function in the call stack.
           */
          function _reentrancyGuardEntered() internal view returns (bool) {
              return _status == ENTERED;
          }
      }
      // SPDX-License-Identifier: GPL-3.0
      pragma solidity ^0.8.23;
      /* solhint-disable avoid-low-level-calls */
      /* solhint-disable no-inline-assembly */
      import "../interfaces/IAccount.sol";
      import "../interfaces/IAccountExecute.sol";
      import "../interfaces/IPaymaster.sol";
      import "../interfaces/IEntryPoint.sol";
      import "../utils/Exec.sol";
      import "./StakeManager.sol";
      import "./SenderCreator.sol";
      import "./Helpers.sol";
      import "./NonceManager.sol";
      import "./UserOperationLib.sol";
      import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
      import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
      /*
       * Account-Abstraction (EIP-4337) singleton EntryPoint implementation.
       * Only one instance required on each chain.
       */
      /// @custom:security-contact https://bounty.ethereum.org
      contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard, ERC165 {
          using UserOperationLib for PackedUserOperation;
          SenderCreator private immutable _senderCreator = new SenderCreator();
          function senderCreator() internal view virtual returns (SenderCreator) {
              return _senderCreator;
          }
          //compensate for innerHandleOps' emit message and deposit refund.
          // allow some slack for future gas price changes.
          uint256 private constant INNER_GAS_OVERHEAD = 10000;
          // Marker for inner call revert on out of gas
          bytes32 private constant INNER_OUT_OF_GAS = hex"deaddead";
          bytes32 private constant INNER_REVERT_LOW_PREFUND = hex"deadaa51";
          uint256 private constant REVERT_REASON_MAX_LEN = 2048;
          uint256 private constant PENALTY_PERCENT = 10;
          /// @inheritdoc IERC165
          function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
              // note: solidity "type(IEntryPoint).interfaceId" is without inherited methods but we want to check everything
              return interfaceId == (type(IEntryPoint).interfaceId ^ type(IStakeManager).interfaceId ^ type(INonceManager).interfaceId) ||
                  interfaceId == type(IEntryPoint).interfaceId ||
                  interfaceId == type(IStakeManager).interfaceId ||
                  interfaceId == type(INonceManager).interfaceId ||
                  super.supportsInterface(interfaceId);
          }
          /**
           * Compensate the caller's beneficiary address with the collected fees of all UserOperations.
           * @param beneficiary - The address to receive the fees.
           * @param amount      - Amount to transfer.
           */
          function _compensate(address payable beneficiary, uint256 amount) internal {
              require(beneficiary != address(0), "AA90 invalid beneficiary");
              (bool success, ) = beneficiary.call{value: amount}("");
              require(success, "AA91 failed send to beneficiary");
          }
          /**
           * Execute a user operation.
           * @param opIndex    - Index into the opInfo array.
           * @param userOp     - The userOp to execute.
           * @param opInfo     - The opInfo filled by validatePrepayment for this userOp.
           * @return collected - The total amount this userOp paid.
           */
          function _executeUserOp(
              uint256 opIndex,
              PackedUserOperation calldata userOp,
              UserOpInfo memory opInfo
          )
          internal
          returns
          (uint256 collected) {
              uint256 preGas = gasleft();
              bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset);
              bool success;
              {
                  uint256 saveFreePtr;
                  assembly ("memory-safe") {
                      saveFreePtr := mload(0x40)
                  }
                  bytes calldata callData = userOp.callData;
                  bytes memory innerCall;
                  bytes4 methodSig;
                  assembly {
                      let len := callData.length
                      if gt(len, 3) {
                          methodSig := calldataload(callData.offset)
                      }
                  }
                  if (methodSig == IAccountExecute.executeUserOp.selector) {
                      bytes memory executeUserOp = abi.encodeCall(IAccountExecute.executeUserOp, (userOp, opInfo.userOpHash));
                      innerCall = abi.encodeCall(this.innerHandleOp, (executeUserOp, opInfo, context));
                  } else
                  {
                      innerCall = abi.encodeCall(this.innerHandleOp, (callData, opInfo, context));
                  }
                  assembly ("memory-safe") {
                      success := call(gas(), address(), 0, add(innerCall, 0x20), mload(innerCall), 0, 32)
                      collected := mload(0)
                      mstore(0x40, saveFreePtr)
                  }
              }
              if (!success) {
                  bytes32 innerRevertCode;
                  assembly ("memory-safe") {
                      let len := returndatasize()
                      if eq(32,len) {
                          returndatacopy(0, 0, 32)
                          innerRevertCode := mload(0)
                      }
                  }
                  if (innerRevertCode == INNER_OUT_OF_GAS) {
                      // handleOps was called with gas limit too low. abort entire bundle.
                      //can only be caused by bundler (leaving not enough gas for inner call)
                      revert FailedOp(opIndex, "AA95 out of gas");
                  } else if (innerRevertCode == INNER_REVERT_LOW_PREFUND) {
                      // innerCall reverted on prefund too low. treat entire prefund as "gas cost"
                      uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;
                      uint256 actualGasCost = opInfo.prefund;
                      emitPrefundTooLow(opInfo);
                      emitUserOperationEvent(opInfo, false, actualGasCost, actualGas);
                      collected = actualGasCost;
                  } else {
                      emit PostOpRevertReason(
                          opInfo.userOpHash,
                          opInfo.mUserOp.sender,
                          opInfo.mUserOp.nonce,
                          Exec.getReturnData(REVERT_REASON_MAX_LEN)
                      );
                      uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;
                      collected = _postExecution(
                          IPaymaster.PostOpMode.postOpReverted,
                          opInfo,
                          context,
                          actualGas
                      );
                  }
              }
          }
          function emitUserOperationEvent(UserOpInfo memory opInfo, bool success, uint256 actualGasCost, uint256 actualGas) internal virtual {
              emit UserOperationEvent(
                  opInfo.userOpHash,
                  opInfo.mUserOp.sender,
                  opInfo.mUserOp.paymaster,
                  opInfo.mUserOp.nonce,
                  success,
                  actualGasCost,
                  actualGas
              );
          }
          function emitPrefundTooLow(UserOpInfo memory opInfo) internal virtual {
              emit UserOperationPrefundTooLow(
                  opInfo.userOpHash,
                  opInfo.mUserOp.sender,
                  opInfo.mUserOp.nonce
              );
          }
          /// @inheritdoc IEntryPoint
          function handleOps(
              PackedUserOperation[] calldata ops,
              address payable beneficiary
          ) public nonReentrant {
              uint256 opslen = ops.length;
              UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);
              unchecked {
                  for (uint256 i = 0; i < opslen; i++) {
                      UserOpInfo memory opInfo = opInfos[i];
                      (
                          uint256 validationData,
                          uint256 pmValidationData
                      ) = _validatePrepayment(i, ops[i], opInfo);
                      _validateAccountAndPaymasterValidationData(
                          i,
                          validationData,
                          pmValidationData,
                          address(0)
                      );
                  }
                  uint256 collected = 0;
                  emit BeforeExecution();
                  for (uint256 i = 0; i < opslen; i++) {
                      collected += _executeUserOp(i, ops[i], opInfos[i]);
                  }
                  _compensate(beneficiary, collected);
              }
          }
          /// @inheritdoc IEntryPoint
          function handleAggregatedOps(
              UserOpsPerAggregator[] calldata opsPerAggregator,
              address payable beneficiary
          ) public nonReentrant {
              uint256 opasLen = opsPerAggregator.length;
              uint256 totalOps = 0;
              for (uint256 i = 0; i < opasLen; i++) {
                  UserOpsPerAggregator calldata opa = opsPerAggregator[i];
                  PackedUserOperation[] calldata ops = opa.userOps;
                  IAggregator aggregator = opa.aggregator;
                  //address(1) is special marker of "signature error"
                  require(
                      address(aggregator) != address(1),
                      "AA96 invalid aggregator"
                  );
                  if (address(aggregator) != address(0)) {
                      // solhint-disable-next-line no-empty-blocks
                      try aggregator.validateSignatures(ops, opa.signature) {} catch {
                          revert SignatureValidationFailed(address(aggregator));
                      }
                  }
                  totalOps += ops.length;
              }
              UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);
              uint256 opIndex = 0;
              for (uint256 a = 0; a < opasLen; a++) {
                  UserOpsPerAggregator calldata opa = opsPerAggregator[a];
                  PackedUserOperation[] calldata ops = opa.userOps;
                  IAggregator aggregator = opa.aggregator;
                  uint256 opslen = ops.length;
                  for (uint256 i = 0; i < opslen; i++) {
                      UserOpInfo memory opInfo = opInfos[opIndex];
                      (
                          uint256 validationData,
                          uint256 paymasterValidationData
                      ) = _validatePrepayment(opIndex, ops[i], opInfo);
                      _validateAccountAndPaymasterValidationData(
                          i,
                          validationData,
                          paymasterValidationData,
                          address(aggregator)
                      );
                      opIndex++;
                  }
              }
              emit BeforeExecution();
              uint256 collected = 0;
              opIndex = 0;
              for (uint256 a = 0; a < opasLen; a++) {
                  UserOpsPerAggregator calldata opa = opsPerAggregator[a];
                  emit SignatureAggregatorChanged(address(opa.aggregator));
                  PackedUserOperation[] calldata ops = opa.userOps;
                  uint256 opslen = ops.length;
                  for (uint256 i = 0; i < opslen; i++) {
                      collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]);
                      opIndex++;
                  }
              }
              emit SignatureAggregatorChanged(address(0));
              _compensate(beneficiary, collected);
          }
          /**
           * A memory copy of UserOp static fields only.
           * Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster.
           */
          struct MemoryUserOp {
              address sender;
              uint256 nonce;
              uint256 verificationGasLimit;
              uint256 callGasLimit;
              uint256 paymasterVerificationGasLimit;
              uint256 paymasterPostOpGasLimit;
              uint256 preVerificationGas;
              address paymaster;
              uint256 maxFeePerGas;
              uint256 maxPriorityFeePerGas;
          }
          struct UserOpInfo {
              MemoryUserOp mUserOp;
              bytes32 userOpHash;
              uint256 prefund;
              uint256 contextOffset;
              uint256 preOpGas;
          }
          /**
           * Inner function to handle a UserOperation.
           * Must be declared "external" to open a call context, but it can only be called by handleOps.
           * @param callData - The callData to execute.
           * @param opInfo   - The UserOpInfo struct.
           * @param context  - The context bytes.
           * @return actualGasCost - the actual cost in eth this UserOperation paid for gas
           */
          function innerHandleOp(
              bytes memory callData,
              UserOpInfo memory opInfo,
              bytes calldata context
          ) external returns (uint256 actualGasCost) {
              uint256 preGas = gasleft();
              require(msg.sender == address(this), "AA92 internal call only");
              MemoryUserOp memory mUserOp = opInfo.mUserOp;
              uint256 callGasLimit = mUserOp.callGasLimit;
              unchecked {
                  // handleOps was called with gas limit too low. abort entire bundle.
                  if (
                      gasleft() * 63 / 64 <
                      callGasLimit +
                      mUserOp.paymasterPostOpGasLimit +
                      INNER_GAS_OVERHEAD
                  ) {
                      assembly ("memory-safe") {
                          mstore(0, INNER_OUT_OF_GAS)
                          revert(0, 32)
                      }
                  }
              }
              IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;
              if (callData.length > 0) {
                  bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);
                  if (!success) {
                      bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);
                      if (result.length > 0) {
                          emit UserOperationRevertReason(
                              opInfo.userOpHash,
                              mUserOp.sender,
                              mUserOp.nonce,
                              result
                          );
                      }
                      mode = IPaymaster.PostOpMode.opReverted;
                  }
              }
              unchecked {
                  uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;
                  return _postExecution(mode, opInfo, context, actualGas);
              }
          }
          /// @inheritdoc IEntryPoint
          function getUserOpHash(
              PackedUserOperation calldata userOp
          ) public view returns (bytes32) {
              return
                  keccak256(abi.encode(userOp.hash(), address(this), block.chainid));
          }
          /**
           * Copy general fields from userOp into the memory opInfo structure.
           * @param userOp  - The user operation.
           * @param mUserOp - The memory user operation.
           */
          function _copyUserOpToMemory(
              PackedUserOperation calldata userOp,
              MemoryUserOp memory mUserOp
          ) internal pure {
              mUserOp.sender = userOp.sender;
              mUserOp.nonce = userOp.nonce;
              (mUserOp.verificationGasLimit, mUserOp.callGasLimit) = UserOperationLib.unpackUints(userOp.accountGasLimits);
              mUserOp.preVerificationGas = userOp.preVerificationGas;
              (mUserOp.maxPriorityFeePerGas, mUserOp.maxFeePerGas) = UserOperationLib.unpackUints(userOp.gasFees);
              bytes calldata paymasterAndData = userOp.paymasterAndData;
              if (paymasterAndData.length > 0) {
                  require(
                      paymasterAndData.length >= UserOperationLib.PAYMASTER_DATA_OFFSET,
                      "AA93 invalid paymasterAndData"
                  );
                  (mUserOp.paymaster, mUserOp.paymasterVerificationGasLimit, mUserOp.paymasterPostOpGasLimit) = UserOperationLib.unpackPaymasterStaticFields(paymasterAndData);
              } else {
                  mUserOp.paymaster = address(0);
                  mUserOp.paymasterVerificationGasLimit = 0;
                  mUserOp.paymasterPostOpGasLimit = 0;
              }
          }
          /**
           * Get the required prefunded gas fee amount for an operation.
           * @param mUserOp - The user operation in memory.
           */
          function _getRequiredPrefund(
              MemoryUserOp memory mUserOp
          ) internal pure returns (uint256 requiredPrefund) {
              unchecked {
                  uint256 requiredGas = mUserOp.verificationGasLimit +
                      mUserOp.callGasLimit +
                      mUserOp.paymasterVerificationGasLimit +
                      mUserOp.paymasterPostOpGasLimit +
                      mUserOp.preVerificationGas;
                  requiredPrefund = requiredGas * mUserOp.maxFeePerGas;
              }
          }
          /**
           * Create sender smart contract account if init code is provided.
           * @param opIndex  - The operation index.
           * @param opInfo   - The operation info.
           * @param initCode - The init code for the smart contract account.
           */
          function _createSenderIfNeeded(
              uint256 opIndex,
              UserOpInfo memory opInfo,
              bytes calldata initCode
          ) internal {
              if (initCode.length != 0) {
                  address sender = opInfo.mUserOp.sender;
                  if (sender.code.length != 0)
                      revert FailedOp(opIndex, "AA10 sender already constructed");
                  address sender1 = senderCreator().createSender{
                      gas: opInfo.mUserOp.verificationGasLimit
                  }(initCode);
                  if (sender1 == address(0))
                      revert FailedOp(opIndex, "AA13 initCode failed or OOG");
                  if (sender1 != sender)
                      revert FailedOp(opIndex, "AA14 initCode must return sender");
                  if (sender1.code.length == 0)
                      revert FailedOp(opIndex, "AA15 initCode must create sender");
                  address factory = address(bytes20(initCode[0:20]));
                  emit AccountDeployed(
                      opInfo.userOpHash,
                      sender,
                      factory,
                      opInfo.mUserOp.paymaster
                  );
              }
          }
          /// @inheritdoc IEntryPoint
          function getSenderAddress(bytes calldata initCode) public {
              address sender = senderCreator().createSender(initCode);
              revert SenderAddressResult(sender);
          }
          /**
           * Call account.validateUserOp.
           * Revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund.
           * Decrement account's deposit if needed.
           * @param opIndex         - The operation index.
           * @param op              - The user operation.
           * @param opInfo          - The operation info.
           * @param requiredPrefund - The required prefund amount.
           */
          function _validateAccountPrepayment(
              uint256 opIndex,
              PackedUserOperation calldata op,
              UserOpInfo memory opInfo,
              uint256 requiredPrefund,
              uint256 verificationGasLimit
          )
              internal
              returns (
                  uint256 validationData
              )
          {
              unchecked {
                  MemoryUserOp memory mUserOp = opInfo.mUserOp;
                  address sender = mUserOp.sender;
                  _createSenderIfNeeded(opIndex, opInfo, op.initCode);
                  address paymaster = mUserOp.paymaster;
                  uint256 missingAccountFunds = 0;
                  if (paymaster == address(0)) {
                      uint256 bal = balanceOf(sender);
                      missingAccountFunds = bal > requiredPrefund
                          ? 0
                          : requiredPrefund - bal;
                  }
                  try
                      IAccount(sender).validateUserOp{
                          gas: verificationGasLimit
                      }(op, opInfo.userOpHash, missingAccountFunds)
                  returns (uint256 _validationData) {
                      validationData = _validationData;
                  } catch {
                      revert FailedOpWithRevert(opIndex, "AA23 reverted", Exec.getReturnData(REVERT_REASON_MAX_LEN));
                  }
                  if (paymaster == address(0)) {
                      DepositInfo storage senderInfo = deposits[sender];
                      uint256 deposit = senderInfo.deposit;
                      if (requiredPrefund > deposit) {
                          revert FailedOp(opIndex, "AA21 didn't pay prefund");
                      }
                      senderInfo.deposit = deposit - requiredPrefund;
                  }
              }
          }
          /**
           * In case the request has a paymaster:
           *  - Validate paymaster has enough deposit.
           *  - Call paymaster.validatePaymasterUserOp.
           *  - Revert with proper FailedOp in case paymaster reverts.
           *  - Decrement paymaster's deposit.
           * @param opIndex                            - The operation index.
           * @param op                                 - The user operation.
           * @param opInfo                             - The operation info.
           * @param requiredPreFund                    - The required prefund amount.
           */
          function _validatePaymasterPrepayment(
              uint256 opIndex,
              PackedUserOperation calldata op,
              UserOpInfo memory opInfo,
              uint256 requiredPreFund
          ) internal returns (bytes memory context, uint256 validationData) {
              unchecked {
                  uint256 preGas = gasleft();
                  MemoryUserOp memory mUserOp = opInfo.mUserOp;
                  address paymaster = mUserOp.paymaster;
                  DepositInfo storage paymasterInfo = deposits[paymaster];
                  uint256 deposit = paymasterInfo.deposit;
                  if (deposit < requiredPreFund) {
                      revert FailedOp(opIndex, "AA31 paymaster deposit too low");
                  }
                  paymasterInfo.deposit = deposit - requiredPreFund;
                  uint256 pmVerificationGasLimit = mUserOp.paymasterVerificationGasLimit;
                  try
                      IPaymaster(paymaster).validatePaymasterUserOp{gas: pmVerificationGasLimit}(
                          op,
                          opInfo.userOpHash,
                          requiredPreFund
                      )
                  returns (bytes memory _context, uint256 _validationData) {
                      context = _context;
                      validationData = _validationData;
                  } catch {
                      revert FailedOpWithRevert(opIndex, "AA33 reverted", Exec.getReturnData(REVERT_REASON_MAX_LEN));
                  }
                  if (preGas - gasleft() > pmVerificationGasLimit) {
                      revert FailedOp(opIndex, "AA36 over paymasterVerificationGasLimit");
                  }
              }
          }
          /**
           * Revert if either account validationData or paymaster validationData is expired.
           * @param opIndex                 - The operation index.
           * @param validationData          - The account validationData.
           * @param paymasterValidationData - The paymaster validationData.
           * @param expectedAggregator      - The expected aggregator.
           */
          function _validateAccountAndPaymasterValidationData(
              uint256 opIndex,
              uint256 validationData,
              uint256 paymasterValidationData,
              address expectedAggregator
          ) internal view {
              (address aggregator, bool outOfTimeRange) = _getValidationData(
                  validationData
              );
              if (expectedAggregator != aggregator) {
                  revert FailedOp(opIndex, "AA24 signature error");
              }
              if (outOfTimeRange) {
                  revert FailedOp(opIndex, "AA22 expired or not due");
              }
              // pmAggregator is not a real signature aggregator: we don't have logic to handle it as address.
              // Non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation).
              address pmAggregator;
              (pmAggregator, outOfTimeRange) = _getValidationData(
                  paymasterValidationData
              );
              if (pmAggregator != address(0)) {
                  revert FailedOp(opIndex, "AA34 signature error");
              }
              if (outOfTimeRange) {
                  revert FailedOp(opIndex, "AA32 paymaster expired or not due");
              }
          }
          /**
           * Parse validationData into its components.
           * @param validationData - The packed validation data (sigFailed, validAfter, validUntil).
           * @return aggregator the aggregator of the validationData
           * @return outOfTimeRange true if current time is outside the time range of this validationData.
           */
          function _getValidationData(
              uint256 validationData
          ) internal view returns (address aggregator, bool outOfTimeRange) {
              if (validationData == 0) {
                  return (address(0), false);
              }
              ValidationData memory data = _parseValidationData(validationData);
              // solhint-disable-next-line not-rely-on-time
              outOfTimeRange = block.timestamp > data.validUntil || block.timestamp < data.validAfter;
              aggregator = data.aggregator;
          }
          /**
           * Validate account and paymaster (if defined) and
           * also make sure total validation doesn't exceed verificationGasLimit.
           * This method is called off-chain (simulateValidation()) and on-chain (from handleOps)
           * @param opIndex - The index of this userOp into the "opInfos" array.
           * @param userOp  - The userOp to validate.
           */
          function _validatePrepayment(
              uint256 opIndex,
              PackedUserOperation calldata userOp,
              UserOpInfo memory outOpInfo
          )
              internal
              returns (uint256 validationData, uint256 paymasterValidationData)
          {
              uint256 preGas = gasleft();
              MemoryUserOp memory mUserOp = outOpInfo.mUserOp;
              _copyUserOpToMemory(userOp, mUserOp);
              outOpInfo.userOpHash = getUserOpHash(userOp);
              // Validate all numeric values in userOp are well below 128 bit, so they can safely be added
              // and multiplied without causing overflow.
              uint256 verificationGasLimit = mUserOp.verificationGasLimit;
              uint256 maxGasValues = mUserOp.preVerificationGas |
                  verificationGasLimit |
                  mUserOp.callGasLimit |
                  mUserOp.paymasterVerificationGasLimit |
                  mUserOp.paymasterPostOpGasLimit |
                  mUserOp.maxFeePerGas |
                  mUserOp.maxPriorityFeePerGas;
              require(maxGasValues <= type(uint120).max, "AA94 gas values overflow");
              uint256 requiredPreFund = _getRequiredPrefund(mUserOp);
              validationData = _validateAccountPrepayment(
                  opIndex,
                  userOp,
                  outOpInfo,
                  requiredPreFund,
                  verificationGasLimit
              );
              if (!_validateAndUpdateNonce(mUserOp.sender, mUserOp.nonce)) {
                  revert FailedOp(opIndex, "AA25 invalid account nonce");
              }
              unchecked {
                  if (preGas - gasleft() > verificationGasLimit) {
                      revert FailedOp(opIndex, "AA26 over verificationGasLimit");
                  }
              }
              bytes memory context;
              if (mUserOp.paymaster != address(0)) {
                  (context, paymasterValidationData) = _validatePaymasterPrepayment(
                      opIndex,
                      userOp,
                      outOpInfo,
                      requiredPreFund
                  );
              }
              unchecked {
                  outOpInfo.prefund = requiredPreFund;
                  outOpInfo.contextOffset = getOffsetOfMemoryBytes(context);
                  outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;
              }
          }
          /**
           * Process post-operation, called just after the callData is executed.
           * If a paymaster is defined and its validation returned a non-empty context, its postOp is called.
           * The excess amount is refunded to the account (or paymaster - if it was used in the request).
           * @param mode      - Whether is called from innerHandleOp, or outside (postOpReverted).
           * @param opInfo    - UserOp fields and info collected during validation.
           * @param context   - The context returned in validatePaymasterUserOp.
           * @param actualGas - The gas used so far by this user operation.
           */
          function _postExecution(
              IPaymaster.PostOpMode mode,
              UserOpInfo memory opInfo,
              bytes memory context,
              uint256 actualGas
          ) private returns (uint256 actualGasCost) {
              uint256 preGas = gasleft();
              unchecked {
                  address refundAddress;
                  MemoryUserOp memory mUserOp = opInfo.mUserOp;
                  uint256 gasPrice = getUserOpGasPrice(mUserOp);
                  address paymaster = mUserOp.paymaster;
                  if (paymaster == address(0)) {
                      refundAddress = mUserOp.sender;
                  } else {
                      refundAddress = paymaster;
                      if (context.length > 0) {
                          actualGasCost = actualGas * gasPrice;
                          if (mode != IPaymaster.PostOpMode.postOpReverted) {
                              try IPaymaster(paymaster).postOp{
                                  gas: mUserOp.paymasterPostOpGasLimit
                              }(mode, context, actualGasCost, gasPrice)
                              // solhint-disable-next-line no-empty-blocks
                              {} catch {
                                  bytes memory reason = Exec.getReturnData(REVERT_REASON_MAX_LEN);
                                  revert PostOpReverted(reason);
                              }
                          }
                      }
                  }
                  actualGas += preGas - gasleft();
                  // Calculating a penalty for unused execution gas
                  {
                      uint256 executionGasLimit = mUserOp.callGasLimit + mUserOp.paymasterPostOpGasLimit;
                      uint256 executionGasUsed = actualGas - opInfo.preOpGas;
                      // this check is required for the gas used within EntryPoint and not covered by explicit gas limits
                      if (executionGasLimit > executionGasUsed) {
                          uint256 unusedGas = executionGasLimit - executionGasUsed;
                          uint256 unusedGasPenalty = (unusedGas * PENALTY_PERCENT) / 100;
                          actualGas += unusedGasPenalty;
                      }
                  }
                  actualGasCost = actualGas * gasPrice;
                  uint256 prefund = opInfo.prefund;
                  if (prefund < actualGasCost) {
                      if (mode == IPaymaster.PostOpMode.postOpReverted) {
                          actualGasCost = prefund;
                          emitPrefundTooLow(opInfo);
                          emitUserOperationEvent(opInfo, false, actualGasCost, actualGas);
                      } else {
                          assembly ("memory-safe") {
                              mstore(0, INNER_REVERT_LOW_PREFUND)
                              revert(0, 32)
                          }
                      }
                  } else {
                      uint256 refund = prefund - actualGasCost;
                      _incrementDeposit(refundAddress, refund);
                      bool success = mode == IPaymaster.PostOpMode.opSucceeded;
                      emitUserOperationEvent(opInfo, success, actualGasCost, actualGas);
                  }
              } // unchecked
          }
          /**
           * The gas price this UserOp agrees to pay.
           * Relayer/block builder might submit the TX with higher priorityFee, but the user should not.
           * @param mUserOp - The userOp to get the gas price from.
           */
          function getUserOpGasPrice(
              MemoryUserOp memory mUserOp
          ) internal view returns (uint256) {
              unchecked {
                  uint256 maxFeePerGas = mUserOp.maxFeePerGas;
                  uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;
                  if (maxFeePerGas == maxPriorityFeePerGas) {
                      //legacy mode (for networks that don't support basefee opcode)
                      return maxFeePerGas;
                  }
                  return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);
              }
          }
          /**
           * The offset of the given bytes in memory.
           * @param data - The bytes to get the offset of.
           */
          function getOffsetOfMemoryBytes(
              bytes memory data
          ) internal pure returns (uint256 offset) {
              assembly {
                  offset := data
              }
          }
          /**
           * The bytes in memory at the given offset.
           * @param offset - The offset to get the bytes from.
           */
          function getMemoryBytesFromOffset(
              uint256 offset
          ) internal pure returns (bytes memory data) {
              assembly ("memory-safe") {
                  data := offset
              }
          }
          /// @inheritdoc IEntryPoint
          function delegateAndRevert(address target, bytes calldata data) external {
              (bool success, bytes memory ret) = target.delegatecall(data);
              revert DelegateAndRevert(success, ret);
          }
      }
      // SPDX-License-Identifier: GPL-3.0
      pragma solidity ^0.8.23;
      /* solhint-disable no-inline-assembly */
       /*
        * For simulation purposes, validateUserOp (and validatePaymasterUserOp)
        * must return this value in case of signature failure, instead of revert.
        */
      uint256 constant SIG_VALIDATION_FAILED = 1;
      /*
       * For simulation purposes, validateUserOp (and validatePaymasterUserOp)
       * return this value on success.
       */
      uint256 constant SIG_VALIDATION_SUCCESS = 0;
      /**
       * Returned data from validateUserOp.
       * validateUserOp returns a uint256, which is created by `_packedValidationData` and
       * parsed by `_parseValidationData`.
       * @param aggregator  - address(0) - The account validated the signature by itself.
       *                      address(1) - The account failed to validate the signature.
       *                      otherwise - This is an address of a signature aggregator that must
       *                                  be used to validate the signature.
       * @param validAfter  - This UserOp is valid only after this timestamp.
       * @param validaUntil - This UserOp is valid only up to this timestamp.
       */
      struct ValidationData {
          address aggregator;
          uint48 validAfter;
          uint48 validUntil;
      }
      /**
       * Extract sigFailed, validAfter, validUntil.
       * Also convert zero validUntil to type(uint48).max.
       * @param validationData - The packed validation data.
       */
      function _parseValidationData(
          uint256 validationData
      ) pure returns (ValidationData memory data) {
          address aggregator = address(uint160(validationData));
          uint48 validUntil = uint48(validationData >> 160);
          if (validUntil == 0) {
              validUntil = type(uint48).max;
          }
          uint48 validAfter = uint48(validationData >> (48 + 160));
          return ValidationData(aggregator, validAfter, validUntil);
      }
      /**
       * Helper to pack the return value for validateUserOp.
       * @param data - The ValidationData to pack.
       */
      function _packValidationData(
          ValidationData memory data
      ) pure returns (uint256) {
          return
              uint160(data.aggregator) |
              (uint256(data.validUntil) << 160) |
              (uint256(data.validAfter) << (160 + 48));
      }
      /**
       * Helper to pack the return value for validateUserOp, when not using an aggregator.
       * @param sigFailed  - True for signature failure, false for success.
       * @param validUntil - Last timestamp this UserOperation is valid (or zero for infinite).
       * @param validAfter - First timestamp this UserOperation is valid.
       */
      function _packValidationData(
          bool sigFailed,
          uint48 validUntil,
          uint48 validAfter
      ) pure returns (uint256) {
          return
              (sigFailed ? 1 : 0) |
              (uint256(validUntil) << 160) |
              (uint256(validAfter) << (160 + 48));
      }
      /**
       * keccak function over calldata.
       * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.
       */
          function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {
              assembly ("memory-safe") {
                  let mem := mload(0x40)
                  let len := data.length
                  calldatacopy(mem, data.offset, len)
                  ret := keccak256(mem, len)
              }
          }
      /**
       * The minimum of two numbers.
       * @param a - First number.
       * @param b - Second number.
       */
          function min(uint256 a, uint256 b) pure returns (uint256) {
              return a < b ? a : b;
          }
      // SPDX-License-Identifier: GPL-3.0
      pragma solidity ^0.8.23;
      import "../interfaces/INonceManager.sol";
      /**
       * nonce management functionality
       */
      abstract contract NonceManager is INonceManager {
          /**
           * The next valid sequence number for a given nonce key.
           */
          mapping(address => mapping(uint192 => uint256)) public nonceSequenceNumber;
          /// @inheritdoc INonceManager
          function getNonce(address sender, uint192 key)
          public view override returns (uint256 nonce) {
              return nonceSequenceNumber[sender][key] | (uint256(key) << 64);
          }
          // allow an account to manually increment its own nonce.
          // (mainly so that during construction nonce can be made non-zero,
          // to "absorb" the gas cost of first nonce increment to 1st transaction (construction),
          // not to 2nd transaction)
          function incrementNonce(uint192 key) public override {
              nonceSequenceNumber[msg.sender][key]++;
          }
          /**
           * validate nonce uniqueness for this account.
           * called just after validateUserOp()
           * @return true if the nonce was incremented successfully.
           *         false if the current nonce doesn't match the given one.
           */
          function _validateAndUpdateNonce(address sender, uint256 nonce) internal returns (bool) {
              uint192 key = uint192(nonce >> 64);
              uint64 seq = uint64(nonce);
              return nonceSequenceNumber[sender][key]++ == seq;
          }
      }
      // SPDX-License-Identifier: GPL-3.0
      pragma solidity ^0.8.23;
      /**
       * Helper contract for EntryPoint, to call userOp.initCode from a "neutral" address,
       * which is explicitly not the entryPoint itself.
       */
      contract SenderCreator {
          /**
           * Call the "initCode" factory to create and return the sender account address.
           * @param initCode - The initCode value from a UserOp. contains 20 bytes of factory address,
           *                   followed by calldata.
           * @return sender  - The returned address of the created account, or zero address on failure.
           */
          function createSender(
              bytes calldata initCode
          ) external returns (address sender) {
              address factory = address(bytes20(initCode[0:20]));
              bytes memory initCallData = initCode[20:];
              bool success;
              /* solhint-disable no-inline-assembly */
              assembly ("memory-safe") {
                  success := call(
                      gas(),
                      factory,
                      0,
                      add(initCallData, 0x20),
                      mload(initCallData),
                      0,
                      32
                  )
                  sender := mload(0)
              }
              if (!success) {
                  sender = address(0);
              }
          }
      }
      // SPDX-License-Identifier: GPL-3.0-only
      pragma solidity ^0.8.23;
      import "../interfaces/IStakeManager.sol";
      /* solhint-disable avoid-low-level-calls */
      /* solhint-disable not-rely-on-time */
      /**
       * Manage deposits and stakes.
       * Deposit is just a balance used to pay for UserOperations (either by a paymaster or an account).
       * Stake is value locked for at least "unstakeDelay" by a paymaster.
       */
      abstract contract StakeManager is IStakeManager {
          /// maps paymaster to their deposits and stakes
          mapping(address => DepositInfo) public deposits;
          /// @inheritdoc IStakeManager
          function getDepositInfo(
              address account
          ) public view returns (DepositInfo memory info) {
              return deposits[account];
          }
          /**
           * Internal method to return just the stake info.
           * @param addr - The account to query.
           */
          function _getStakeInfo(
              address addr
          ) internal view returns (StakeInfo memory info) {
              DepositInfo storage depositInfo = deposits[addr];
              info.stake = depositInfo.stake;
              info.unstakeDelaySec = depositInfo.unstakeDelaySec;
          }
          /// @inheritdoc IStakeManager
          function balanceOf(address account) public view returns (uint256) {
              return deposits[account].deposit;
          }
          receive() external payable {
              depositTo(msg.sender);
          }
          /**
           * Increments an account's deposit.
           * @param account - The account to increment.
           * @param amount  - The amount to increment by.
           * @return the updated deposit of this account
           */
          function _incrementDeposit(address account, uint256 amount) internal returns (uint256) {
              DepositInfo storage info = deposits[account];
              uint256 newAmount = info.deposit + amount;
              info.deposit = newAmount;
              return newAmount;
          }
          /**
           * Add to the deposit of the given account.
           * @param account - The account to add to.
           */
          function depositTo(address account) public virtual payable {
              uint256 newDeposit = _incrementDeposit(account, msg.value);
              emit Deposited(account, newDeposit);
          }
          /**
           * Add to the account's stake - amount and delay
           * any pending unstake is first cancelled.
           * @param unstakeDelaySec The new lock duration before the deposit can be withdrawn.
           */
          function addStake(uint32 unstakeDelaySec) public payable {
              DepositInfo storage info = deposits[msg.sender];
              require(unstakeDelaySec > 0, "must specify unstake delay");
              require(
                  unstakeDelaySec >= info.unstakeDelaySec,
                  "cannot decrease unstake time"
              );
              uint256 stake = info.stake + msg.value;
              require(stake > 0, "no stake specified");
              require(stake <= type(uint112).max, "stake overflow");
              deposits[msg.sender] = DepositInfo(
                  info.deposit,
                  true,
                  uint112(stake),
                  unstakeDelaySec,
                  0
              );
              emit StakeLocked(msg.sender, stake, unstakeDelaySec);
          }
          /**
           * Attempt to unlock the stake.
           * The value can be withdrawn (using withdrawStake) after the unstake delay.
           */
          function unlockStake() external {
              DepositInfo storage info = deposits[msg.sender];
              require(info.unstakeDelaySec != 0, "not staked");
              require(info.staked, "already unstaking");
              uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;
              info.withdrawTime = withdrawTime;
              info.staked = false;
              emit StakeUnlocked(msg.sender, withdrawTime);
          }
          /**
           * Withdraw from the (unlocked) stake.
           * Must first call unlockStake and wait for the unstakeDelay to pass.
           * @param withdrawAddress - The address to send withdrawn value.
           */
          function withdrawStake(address payable withdrawAddress) external {
              DepositInfo storage info = deposits[msg.sender];
              uint256 stake = info.stake;
              require(stake > 0, "No stake to withdraw");
              require(info.withdrawTime > 0, "must call unlockStake() first");
              require(
                  info.withdrawTime <= block.timestamp,
                  "Stake withdrawal is not due"
              );
              info.unstakeDelaySec = 0;
              info.withdrawTime = 0;
              info.stake = 0;
              emit StakeWithdrawn(msg.sender, withdrawAddress, stake);
              (bool success,) = withdrawAddress.call{value: stake}("");
              require(success, "failed to withdraw stake");
          }
          /**
           * Withdraw from the deposit.
           * @param withdrawAddress - The address to send withdrawn value.
           * @param withdrawAmount  - The amount to withdraw.
           */
          function withdrawTo(
              address payable withdrawAddress,
              uint256 withdrawAmount
          ) external {
              DepositInfo storage info = deposits[msg.sender];
              require(withdrawAmount <= info.deposit, "Withdraw amount too large");
              info.deposit = info.deposit - withdrawAmount;
              emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);
              (bool success,) = withdrawAddress.call{value: withdrawAmount}("");
              require(success, "failed to withdraw");
          }
      }
      // SPDX-License-Identifier: GPL-3.0
      pragma solidity ^0.8.23;
      /* solhint-disable no-inline-assembly */
      import "../interfaces/PackedUserOperation.sol";
      import {calldataKeccak, min} from "./Helpers.sol";
      /**
       * Utility functions helpful when working with UserOperation structs.
       */
      library UserOperationLib {
          uint256 public constant PAYMASTER_VALIDATION_GAS_OFFSET = 20;
          uint256 public constant PAYMASTER_POSTOP_GAS_OFFSET = 36;
          uint256 public constant PAYMASTER_DATA_OFFSET = 52;
          /**
           * Get sender from user operation data.
           * @param userOp - The user operation data.
           */
          function getSender(
              PackedUserOperation calldata userOp
          ) internal pure returns (address) {
              address data;
              //read sender from userOp, which is first userOp member (saves 800 gas...)
              assembly {
                  data := calldataload(userOp)
              }
              return address(uint160(data));
          }
          /**
           * Relayer/block builder might submit the TX with higher priorityFee,
           * but the user should not pay above what he signed for.
           * @param userOp - The user operation data.
           */
          function gasPrice(
              PackedUserOperation calldata userOp
          ) internal view returns (uint256) {
              unchecked {
                  (uint256 maxPriorityFeePerGas, uint256 maxFeePerGas) = unpackUints(userOp.gasFees);
                  if (maxFeePerGas == maxPriorityFeePerGas) {
                      //legacy mode (for networks that don't support basefee opcode)
                      return maxFeePerGas;
                  }
                  return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);
              }
          }
          /**
           * Pack the user operation data into bytes for hashing.
           * @param userOp - The user operation data.
           */
          function encode(
              PackedUserOperation calldata userOp
          ) internal pure returns (bytes memory ret) {
              address sender = getSender(userOp);
              uint256 nonce = userOp.nonce;
              bytes32 hashInitCode = calldataKeccak(userOp.initCode);
              bytes32 hashCallData = calldataKeccak(userOp.callData);
              bytes32 accountGasLimits = userOp.accountGasLimits;
              uint256 preVerificationGas = userOp.preVerificationGas;
              bytes32 gasFees = userOp.gasFees;
              bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);
              return abi.encode(
                  sender, nonce,
                  hashInitCode, hashCallData,
                  accountGasLimits, preVerificationGas, gasFees,
                  hashPaymasterAndData
              );
          }
          function unpackUints(
              bytes32 packed
          ) internal pure returns (uint256 high128, uint256 low128) {
              return (uint128(bytes16(packed)), uint128(uint256(packed)));
          }
          //unpack just the high 128-bits from a packed value
          function unpackHigh128(bytes32 packed) internal pure returns (uint256) {
              return uint256(packed) >> 128;
          }
          // unpack just the low 128-bits from a packed value
          function unpackLow128(bytes32 packed) internal pure returns (uint256) {
              return uint128(uint256(packed));
          }
          function unpackMaxPriorityFeePerGas(PackedUserOperation calldata userOp)
          internal pure returns (uint256) {
              return unpackHigh128(userOp.gasFees);
          }
          function unpackMaxFeePerGas(PackedUserOperation calldata userOp)
          internal pure returns (uint256) {
              return unpackLow128(userOp.gasFees);
          }
          function unpackVerificationGasLimit(PackedUserOperation calldata userOp)
          internal pure returns (uint256) {
              return unpackHigh128(userOp.accountGasLimits);
          }
          function unpackCallGasLimit(PackedUserOperation calldata userOp)
          internal pure returns (uint256) {
              return unpackLow128(userOp.accountGasLimits);
          }
          function unpackPaymasterVerificationGasLimit(PackedUserOperation calldata userOp)
          internal pure returns (uint256) {
              return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET]));
          }
          function unpackPostOpGasLimit(PackedUserOperation calldata userOp)
          internal pure returns (uint256) {
              return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET]));
          }
          function unpackPaymasterStaticFields(
              bytes calldata paymasterAndData
          ) internal pure returns (address paymaster, uint256 validationGasLimit, uint256 postOpGasLimit) {
              return (
                  address(bytes20(paymasterAndData[: PAYMASTER_VALIDATION_GAS_OFFSET])),
                  uint128(bytes16(paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET])),
                  uint128(bytes16(paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET]))
              );
          }
          /**
           * Hash the user operation data.
           * @param userOp - The user operation data.
           */
          function hash(
              PackedUserOperation calldata userOp
          ) internal pure returns (bytes32) {
              return keccak256(encode(userOp));
          }
      }
      // SPDX-License-Identifier: GPL-3.0
      pragma solidity >=0.7.5;
      import "./PackedUserOperation.sol";
      interface IAccount {
          /**
           * Validate user's signature and nonce
           * the entryPoint will make the call to the recipient only if this validation call returns successfully.
           * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).
           * This allows making a "simulation call" without a valid signature
           * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.
           *
           * @dev Must validate caller is the entryPoint.
           *      Must validate the signature and nonce
           * @param userOp              - The operation that is about to be executed.
           * @param userOpHash          - Hash of the user's request data. can be used as the basis for signature.
           * @param missingAccountFunds - Missing funds on the account's deposit in the entrypoint.
           *                              This is the minimum amount to transfer to the sender(entryPoint) to be
           *                              able to make the call. The excess is left as a deposit in the entrypoint
           *                              for future calls. Can be withdrawn anytime using "entryPoint.withdrawTo()".
           *                              In case there is a paymaster in the request (or the current deposit is high
           *                              enough), this value will be zero.
           * @return validationData       - Packaged ValidationData structure. use `_packValidationData` and
           *                              `_unpackValidationData` to encode and decode.
           *                              <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,
           *                                 otherwise, an address of an "authorizer" contract.
           *                              <6-byte> validUntil - Last timestamp this operation is valid. 0 for "indefinite"
           *                              <6-byte> validAfter - First timestamp this operation is valid
           *                                                    If an account doesn't use time-range, it is enough to
           *                                                    return SIG_VALIDATION_FAILED value (1) for signature failure.
           *                              Note that the validation code cannot use block.timestamp (or block.number) directly.
           */
          function validateUserOp(
              PackedUserOperation calldata userOp,
              bytes32 userOpHash,
              uint256 missingAccountFunds
          ) external returns (uint256 validationData);
      }
      // SPDX-License-Identifier: GPL-3.0
      pragma solidity >=0.7.5;
      import "./PackedUserOperation.sol";
      interface IAccountExecute {
          /**
           * Account may implement this execute method.
           * passing this methodSig at the beginning of callData will cause the entryPoint to pass the full UserOp (and hash)
           * to the account.
           * The account should skip the methodSig, and use the callData (and optionally, other UserOp fields)
           *
           * @param userOp              - The operation that was just validated.
           * @param userOpHash          - Hash of the user's request data.
           */
          function executeUserOp(
              PackedUserOperation calldata userOp,
              bytes32 userOpHash
          ) external;
      }
      // SPDX-License-Identifier: GPL-3.0
      pragma solidity >=0.7.5;
      import "./PackedUserOperation.sol";
      /**
       * Aggregated Signatures validator.
       */
      interface IAggregator {
          /**
           * Validate aggregated signature.
           * Revert if the aggregated signature does not match the given list of operations.
           * @param userOps   - Array of UserOperations to validate the signature for.
           * @param signature - The aggregated signature.
           */
          function validateSignatures(
              PackedUserOperation[] calldata userOps,
              bytes calldata signature
          ) external view;
          /**
           * Validate signature of a single userOp.
           * This method should be called by bundler after EntryPointSimulation.simulateValidation() returns
           * the aggregator this account uses.
           * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.
           * @param userOp        - The userOperation received from the user.
           * @return sigForUserOp - The value to put into the signature field of the userOp when calling handleOps.
           *                        (usually empty, unless account and aggregator support some kind of "multisig".
           */
          function validateUserOpSignature(
              PackedUserOperation calldata userOp
          ) external view returns (bytes memory sigForUserOp);
          /**
           * Aggregate multiple signatures into a single value.
           * This method is called off-chain to calculate the signature to pass with handleOps()
           * bundler MAY use optimized custom code perform this aggregation.
           * @param userOps              - Array of UserOperations to collect the signatures from.
           * @return aggregatedSignature - The aggregated signature.
           */
          function aggregateSignatures(
              PackedUserOperation[] calldata userOps
          ) external view returns (bytes memory aggregatedSignature);
      }
      /**
       ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.
       ** Only one instance required on each chain.
       **/
      // SPDX-License-Identifier: GPL-3.0
      pragma solidity >=0.7.5;
      /* solhint-disable avoid-low-level-calls */
      /* solhint-disable no-inline-assembly */
      /* solhint-disable reason-string */
      import "./PackedUserOperation.sol";
      import "./IStakeManager.sol";
      import "./IAggregator.sol";
      import "./INonceManager.sol";
      interface IEntryPoint is IStakeManager, INonceManager {
          /***
           * An event emitted after each successful request.
           * @param userOpHash    - Unique identifier for the request (hash its entire content, except signature).
           * @param sender        - The account that generates this request.
           * @param paymaster     - If non-null, the paymaster that pays for this request.
           * @param nonce         - The nonce value from the request.
           * @param success       - True if the sender transaction succeeded, false if reverted.
           * @param actualGasCost - Actual amount paid (by account or paymaster) for this UserOperation.
           * @param actualGasUsed - Total gas used by this UserOperation (including preVerification, creation,
           *                        validation and execution).
           */
          event UserOperationEvent(
              bytes32 indexed userOpHash,
              address indexed sender,
              address indexed paymaster,
              uint256 nonce,
              bool success,
              uint256 actualGasCost,
              uint256 actualGasUsed
          );
          /**
           * Account "sender" was deployed.
           * @param userOpHash - The userOp that deployed this account. UserOperationEvent will follow.
           * @param sender     - The account that is deployed
           * @param factory    - The factory used to deploy this account (in the initCode)
           * @param paymaster  - The paymaster used by this UserOp
           */
          event AccountDeployed(
              bytes32 indexed userOpHash,
              address indexed sender,
              address factory,
              address paymaster
          );
          /**
           * An event emitted if the UserOperation "callData" reverted with non-zero length.
           * @param userOpHash   - The request unique identifier.
           * @param sender       - The sender of this request.
           * @param nonce        - The nonce used in the request.
           * @param revertReason - The return bytes from the (reverted) call to "callData".
           */
          event UserOperationRevertReason(
              bytes32 indexed userOpHash,
              address indexed sender,
              uint256 nonce,
              bytes revertReason
          );
          /**
           * An event emitted if the UserOperation Paymaster's "postOp" call reverted with non-zero length.
           * @param userOpHash   - The request unique identifier.
           * @param sender       - The sender of this request.
           * @param nonce        - The nonce used in the request.
           * @param revertReason - The return bytes from the (reverted) call to "callData".
           */
          event PostOpRevertReason(
              bytes32 indexed userOpHash,
              address indexed sender,
              uint256 nonce,
              bytes revertReason
          );
          /**
           * UserOp consumed more than prefund. The UserOperation is reverted, and no refund is made.
           * @param userOpHash   - The request unique identifier.
           * @param sender       - The sender of this request.
           * @param nonce        - The nonce used in the request.
           */
          event UserOperationPrefundTooLow(
              bytes32 indexed userOpHash,
              address indexed sender,
              uint256 nonce
          );
          /**
           * An event emitted by handleOps(), before starting the execution loop.
           * Any event emitted before this event, is part of the validation.
           */
          event BeforeExecution();
          /**
           * Signature aggregator used by the following UserOperationEvents within this bundle.
           * @param aggregator - The aggregator used for the following UserOperationEvents.
           */
          event SignatureAggregatorChanged(address indexed aggregator);
          /**
           * A custom revert error of handleOps, to identify the offending op.
           * Should be caught in off-chain handleOps simulation and not happen on-chain.
           * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.
           * NOTE: If simulateValidation passes successfully, there should be no reason for handleOps to fail on it.
           * @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero).
           * @param reason  - Revert reason. The string starts with a unique code "AAmn",
           *                  where "m" is "1" for factory, "2" for account and "3" for paymaster issues,
           *                  so a failure can be attributed to the correct entity.
           */
          error FailedOp(uint256 opIndex, string reason);
          /**
           * A custom revert error of handleOps, to report a revert by account or paymaster.
           * @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero).
           * @param reason  - Revert reason. see FailedOp(uint256,string), above
           * @param inner   - data from inner cought revert reason
           * @dev note that inner is truncated to 2048 bytes
           */
          error FailedOpWithRevert(uint256 opIndex, string reason, bytes inner);
          error PostOpReverted(bytes returnData);
          /**
           * Error case when a signature aggregator fails to verify the aggregated signature it had created.
           * @param aggregator The aggregator that failed to verify the signature
           */
          error SignatureValidationFailed(address aggregator);
          // Return value of getSenderAddress.
          error SenderAddressResult(address sender);
          // UserOps handled, per aggregator.
          struct UserOpsPerAggregator {
              PackedUserOperation[] userOps;
              // Aggregator address
              IAggregator aggregator;
              // Aggregated signature
              bytes signature;
          }
          /**
           * Execute a batch of UserOperations.
           * No signature aggregator is used.
           * If any account requires an aggregator (that is, it returned an aggregator when
           * performing simulateValidation), then handleAggregatedOps() must be used instead.
           * @param ops         - The operations to execute.
           * @param beneficiary - The address to receive the fees.
           */
          function handleOps(
              PackedUserOperation[] calldata ops,
              address payable beneficiary
          ) external;
          /**
           * Execute a batch of UserOperation with Aggregators
           * @param opsPerAggregator - The operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts).
           * @param beneficiary      - The address to receive the fees.
           */
          function handleAggregatedOps(
              UserOpsPerAggregator[] calldata opsPerAggregator,
              address payable beneficiary
          ) external;
          /**
           * Generate a request Id - unique identifier for this request.
           * The request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.
           * @param userOp - The user operation to generate the request ID for.
           * @return hash the hash of this UserOperation
           */
          function getUserOpHash(
              PackedUserOperation calldata userOp
          ) external view returns (bytes32);
          /**
           * Gas and return values during simulation.
           * @param preOpGas         - The gas used for validation (including preValidationGas)
           * @param prefund          - The required prefund for this operation
           * @param accountValidationData   - returned validationData from account.
           * @param paymasterValidationData - return validationData from paymaster.
           * @param paymasterContext - Returned by validatePaymasterUserOp (to be passed into postOp)
           */
          struct ReturnInfo {
              uint256 preOpGas;
              uint256 prefund;
              uint256 accountValidationData;
              uint256 paymasterValidationData;
              bytes paymasterContext;
          }
          /**
           * Returned aggregated signature info:
           * The aggregator returned by the account, and its current stake.
           */
          struct AggregatorStakeInfo {
              address aggregator;
              StakeInfo stakeInfo;
          }
          /**
           * Get counterfactual sender address.
           * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.
           * This method always revert, and returns the address in SenderAddressResult error
           * @param initCode - The constructor code to be passed into the UserOperation.
           */
          function getSenderAddress(bytes memory initCode) external;
          error DelegateAndRevert(bool success, bytes ret);
          /**
           * Helper method for dry-run testing.
           * @dev calling this method, the EntryPoint will make a delegatecall to the given data, and report (via revert) the result.
           *  The method always revert, so is only useful off-chain for dry run calls, in cases where state-override to replace
           *  actual EntryPoint code is less convenient.
           * @param target a target contract to make a delegatecall from entrypoint
           * @param data data to pass to target in a delegatecall
           */
          function delegateAndRevert(address target, bytes calldata data) external;
      }
      // SPDX-License-Identifier: GPL-3.0
      pragma solidity >=0.7.5;
      interface INonceManager {
          /**
           * Return the next nonce for this sender.
           * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)
           * But UserOp with different keys can come with arbitrary order.
           *
           * @param sender the account address
           * @param key the high 192 bit of the nonce
           * @return nonce a full nonce to pass for next UserOp with this sender.
           */
          function getNonce(address sender, uint192 key)
          external view returns (uint256 nonce);
          /**
           * Manually increment the nonce of the sender.
           * This method is exposed just for completeness..
           * Account does NOT need to call it, neither during validation, nor elsewhere,
           * as the EntryPoint will update the nonce regardless.
           * Possible use-case is call it with various keys to "initialize" their nonces to one, so that future
           * UserOperations will not pay extra for the first transaction with a given key.
           */
          function incrementNonce(uint192 key) external;
      }
      // SPDX-License-Identifier: GPL-3.0
      pragma solidity >=0.7.5;
      import "./PackedUserOperation.sol";
      /**
       * The interface exposed by a paymaster contract, who agrees to pay the gas for user's operations.
       * A paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.
       */
      interface IPaymaster {
          enum PostOpMode {
              // User op succeeded.
              opSucceeded,
              // User op reverted. Still has to pay for gas.
              opReverted,
              // Only used internally in the EntryPoint (cleanup after postOp reverts). Never calling paymaster with this value
              postOpReverted
          }
          /**
           * Payment validation: check if paymaster agrees to pay.
           * Must verify sender is the entryPoint.
           * Revert to reject this request.
           * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted).
           * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.
           * @param userOp          - The user operation.
           * @param userOpHash      - Hash of the user's request data.
           * @param maxCost         - The maximum cost of this transaction (based on maximum gas and gas price from userOp).
           * @return context        - Value to send to a postOp. Zero length to signify postOp is not required.
           * @return validationData - Signature and time-range of this operation, encoded the same as the return
           *                          value of validateUserOperation.
           *                          <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,
           *                                                    other values are invalid for paymaster.
           *                          <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite"
           *                          <6-byte> validAfter - first timestamp this operation is valid
           *                          Note that the validation code cannot use block.timestamp (or block.number) directly.
           */
          function validatePaymasterUserOp(
              PackedUserOperation calldata userOp,
              bytes32 userOpHash,
              uint256 maxCost
          ) external returns (bytes memory context, uint256 validationData);
          /**
           * Post-operation handler.
           * Must verify sender is the entryPoint.
           * @param mode          - Enum with the following options:
           *                        opSucceeded - User operation succeeded.
           *                        opReverted  - User op reverted. The paymaster still has to pay for gas.
           *                        postOpReverted - never passed in a call to postOp().
           * @param context       - The context value returned by validatePaymasterUserOp
           * @param actualGasCost - Actual gas used so far (without this postOp call).
           * @param actualUserOpFeePerGas - the gas price this UserOp pays. This value is based on the UserOp's maxFeePerGas
           *                        and maxPriorityFee (and basefee)
           *                        It is not the same as tx.gasprice, which is what the bundler pays.
           */
          function postOp(
              PostOpMode mode,
              bytes calldata context,
              uint256 actualGasCost,
              uint256 actualUserOpFeePerGas
          ) external;
      }
      // SPDX-License-Identifier: GPL-3.0-only
      pragma solidity >=0.7.5;
      /**
       * Manage deposits and stakes.
       * Deposit is just a balance used to pay for UserOperations (either by a paymaster or an account).
       * Stake is value locked for at least "unstakeDelay" by the staked entity.
       */
      interface IStakeManager {
          event Deposited(address indexed account, uint256 totalDeposit);
          event Withdrawn(
              address indexed account,
              address withdrawAddress,
              uint256 amount
          );
          // Emitted when stake or unstake delay are modified.
          event StakeLocked(
              address indexed account,
              uint256 totalStaked,
              uint256 unstakeDelaySec
          );
          // Emitted once a stake is scheduled for withdrawal.
          event StakeUnlocked(address indexed account, uint256 withdrawTime);
          event StakeWithdrawn(
              address indexed account,
              address withdrawAddress,
              uint256 amount
          );
          /**
           * @param deposit         - The entity's deposit.
           * @param staked          - True if this entity is staked.
           * @param stake           - Actual amount of ether staked for this entity.
           * @param unstakeDelaySec - Minimum delay to withdraw the stake.
           * @param withdrawTime    - First block timestamp where 'withdrawStake' will be callable, or zero if already locked.
           * @dev Sizes were chosen so that deposit fits into one cell (used during handleOp)
           *      and the rest fit into a 2nd cell (used during stake/unstake)
           *      - 112 bit allows for 10^15 eth
           *      - 48 bit for full timestamp
           *      - 32 bit allows 150 years for unstake delay
           */
          struct DepositInfo {
              uint256 deposit;
              bool staked;
              uint112 stake;
              uint32 unstakeDelaySec;
              uint48 withdrawTime;
          }
          // API struct used by getStakeInfo and simulateValidation.
          struct StakeInfo {
              uint256 stake;
              uint256 unstakeDelaySec;
          }
          /**
           * Get deposit info.
           * @param account - The account to query.
           * @return info   - Full deposit information of given account.
           */
          function getDepositInfo(
              address account
          ) external view returns (DepositInfo memory info);
          /**
           * Get account balance.
           * @param account - The account to query.
           * @return        - The deposit (for gas payment) of the account.
           */
          function balanceOf(address account) external view returns (uint256);
          /**
           * Add to the deposit of the given account.
           * @param account - The account to add to.
           */
          function depositTo(address account) external payable;
          /**
           * Add to the account's stake - amount and delay
           * any pending unstake is first cancelled.
           * @param _unstakeDelaySec - The new lock duration before the deposit can be withdrawn.
           */
          function addStake(uint32 _unstakeDelaySec) external payable;
          /**
           * Attempt to unlock the stake.
           * The value can be withdrawn (using withdrawStake) after the unstake delay.
           */
          function unlockStake() external;
          /**
           * Withdraw from the (unlocked) stake.
           * Must first call unlockStake and wait for the unstakeDelay to pass.
           * @param withdrawAddress - The address to send withdrawn value.
           */
          function withdrawStake(address payable withdrawAddress) external;
          /**
           * Withdraw from the deposit.
           * @param withdrawAddress - The address to send withdrawn value.
           * @param withdrawAmount  - The amount to withdraw.
           */
          function withdrawTo(
              address payable withdrawAddress,
              uint256 withdrawAmount
          ) external;
      }
      // SPDX-License-Identifier: GPL-3.0
      pragma solidity >=0.7.5;
      /**
       * User Operation struct
       * @param sender                - The sender account of this request.
       * @param nonce                 - Unique value the sender uses to verify it is not a replay.
       * @param initCode              - If set, the account contract will be created by this constructor/
       * @param callData              - The method call to execute on this account.
       * @param accountGasLimits      - Packed gas limits for validateUserOp and gas limit passed to the callData method call.
       * @param preVerificationGas    - Gas not calculated by the handleOps method, but added to the gas paid.
       *                                Covers batch overhead.
       * @param gasFees               - packed gas fields maxPriorityFeePerGas and maxFeePerGas - Same as EIP-1559 gas parameters.
       * @param paymasterAndData      - If set, this field holds the paymaster address, verification gas limit, postOp gas limit and paymaster-specific extra data
       *                                The paymaster will pay for the transaction instead of the sender.
       * @param signature             - Sender-verified signature over the entire request, the EntryPoint address and the chain ID.
       */
      struct PackedUserOperation {
          address sender;
          uint256 nonce;
          bytes initCode;
          bytes callData;
          bytes32 accountGasLimits;
          uint256 preVerificationGas;
          bytes32 gasFees;
          bytes paymasterAndData;
          bytes signature;
      }
      // SPDX-License-Identifier: LGPL-3.0-only
      pragma solidity ^0.8.23;
      // solhint-disable no-inline-assembly
      /**
       * Utility functions helpful when making different kinds of contract calls in Solidity.
       */
      library Exec {
          function call(
              address to,
              uint256 value,
              bytes memory data,
              uint256 txGas
          ) internal returns (bool success) {
              assembly ("memory-safe") {
                  success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)
              }
          }
          function staticcall(
              address to,
              bytes memory data,
              uint256 txGas
          ) internal view returns (bool success) {
              assembly ("memory-safe") {
                  success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)
              }
          }
          function delegateCall(
              address to,
              bytes memory data,
              uint256 txGas
          ) internal returns (bool success) {
              assembly ("memory-safe") {
                  success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)
              }
          }
          // get returned data from last call or calldelegate
          function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {
              assembly ("memory-safe") {
                  let len := returndatasize()
                  if gt(len, maxLen) {
                      len := maxLen
                  }
                  let ptr := mload(0x40)
                  mstore(0x40, add(ptr, add(len, 0x20)))
                  mstore(ptr, len)
                  returndatacopy(add(ptr, 0x20), 0, len)
                  returnData := ptr
              }
          }
          // revert with explicit byte array (probably reverted info from call)
          function revertWithData(bytes memory returnData) internal pure {
              assembly ("memory-safe") {
                  revert(add(returnData, 32), mload(returnData))
              }
          }
          function callAndRevert(address to, bytes memory data, uint256 maxLen) internal {
              bool success = call(to,0,data,gasleft());
              if (!success) {
                  revertWithData(getReturnData(maxLen));
              }
          }
      }
      

      File 2 of 2: BizGuard
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
      pragma solidity ^0.8.20;
      import {Context} from "../utils/Context.sol";
      /**
       * @dev Contract module which provides a basic access control mechanism, where
       * there is an account (an owner) that can be granted exclusive access to
       * specific functions.
       *
       * The initial owner is set to the address provided by the deployer. This can
       * later be changed with {transferOwnership}.
       *
       * This module is used through inheritance. It will make available the modifier
       * `onlyOwner`, which can be applied to your functions to restrict their use to
       * the owner.
       */
      abstract contract Ownable is Context {
          address private _owner;
          /**
           * @dev The caller account is not authorized to perform an operation.
           */
          error OwnableUnauthorizedAccount(address account);
          /**
           * @dev The owner is not a valid owner account. (eg. `address(0)`)
           */
          error OwnableInvalidOwner(address owner);
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          /**
           * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
           */
          constructor(address initialOwner) {
              if (initialOwner == address(0)) {
                  revert OwnableInvalidOwner(address(0));
              }
              _transferOwnership(initialOwner);
          }
          /**
           * @dev Throws if called by any account other than the owner.
           */
          modifier onlyOwner() {
              _checkOwner();
              _;
          }
          /**
           * @dev Returns the address of the current owner.
           */
          function owner() public view virtual returns (address) {
              return _owner;
          }
          /**
           * @dev Throws if the sender is not the owner.
           */
          function _checkOwner() internal view virtual {
              if (owner() != _msgSender()) {
                  revert OwnableUnauthorizedAccount(_msgSender());
              }
          }
          /**
           * @dev Leaves the contract without owner. It will not be possible to call
           * `onlyOwner` functions. Can only be called by the current owner.
           *
           * NOTE: Renouncing ownership will leave the contract without an owner,
           * thereby disabling any functionality that is only available to the owner.
           */
          function renounceOwnership() public virtual onlyOwner {
              _transferOwnership(address(0));
          }
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Can only be called by the current owner.
           */
          function transferOwnership(address newOwner) public virtual onlyOwner {
              if (newOwner == address(0)) {
                  revert OwnableInvalidOwner(address(0));
              }
              _transferOwnership(newOwner);
          }
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Internal function without access restriction.
           */
          function _transferOwnership(address newOwner) internal virtual {
              address oldOwner = _owner;
              _owner = newOwner;
              emit OwnershipTransferred(oldOwner, newOwner);
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v5.1.0) (access/Ownable2Step.sol)
      pragma solidity ^0.8.20;
      import {Ownable} from "./Ownable.sol";
      /**
       * @dev Contract module which provides access control mechanism, where
       * there is an account (an owner) that can be granted exclusive access to
       * specific functions.
       *
       * This extension of the {Ownable} contract includes a two-step mechanism to transfer
       * ownership, where the new owner must call {acceptOwnership} in order to replace the
       * old one. This can help prevent common mistakes, such as transfers of ownership to
       * incorrect accounts, or to contracts that are unable to interact with the
       * permission system.
       *
       * The initial owner is specified at deployment time in the constructor for `Ownable`. This
       * can later be changed with {transferOwnership} and {acceptOwnership}.
       *
       * This module is used through inheritance. It will make available all functions
       * from parent (Ownable).
       */
      abstract contract Ownable2Step is Ownable {
          address private _pendingOwner;
          event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
          /**
           * @dev Returns the address of the pending owner.
           */
          function pendingOwner() public view virtual returns (address) {
              return _pendingOwner;
          }
          /**
           * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
           * Can only be called by the current owner.
           *
           * Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer.
           */
          function transferOwnership(address newOwner) public virtual override onlyOwner {
              _pendingOwner = newOwner;
              emit OwnershipTransferStarted(owner(), newOwner);
          }
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
           * Internal function without access restriction.
           */
          function _transferOwnership(address newOwner) internal virtual override {
              delete _pendingOwner;
              super._transferOwnership(newOwner);
          }
          /**
           * @dev The new owner accepts the ownership transfer.
           */
          function acceptOwnership() public virtual {
              address sender = _msgSender();
              if (pendingOwner() != sender) {
                  revert OwnableUnauthorizedAccount(sender);
              }
              _transferOwnership(sender);
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
      pragma solidity ^0.8.20;
      /**
       * @dev Provides information about the current execution context, including the
       * sender of the transaction and its data. While these are generally available
       * via msg.sender and msg.data, they should not be accessed in such a direct
       * manner, since when dealing with meta-transactions the account sending and
       * paying for execution may not be the actual sender (as far as an application
       * is concerned).
       *
       * This contract is only required for intermediate, library-like contracts.
       */
      abstract contract Context {
          function _msgSender() internal view virtual returns (address) {
              return msg.sender;
          }
          function _msgData() internal view virtual returns (bytes calldata) {
              return msg.data;
          }
          function _contextSuffixLength() internal view virtual returns (uint256) {
              return 0;
          }
      }
      // SPDX-License-Identifier: Apache-2.0
      pragma solidity 0.8.28;
      import {Ownable2Step, Ownable} from "@openzeppelin/contracts/access/Ownable2Step.sol";
      /**
       * @title BizGuard - Guard contract for Biz.
       * @dev Most important concepts:
       *      - BizGuard maintains the nonce of all Biz for signature validation.
       *      - BizGuard is an ownable smart contract with 4337 flag to enable/disable ERC-4337 of Biz.
       * @author David Kim - @PowerStream3604
       */
      contract BizGuard is Ownable2Step {
          event FlagSet(bool flag);
          mapping(address => uint256) public accountNonce;
          bool erc4337Flag;
          /**
           * @notice constructor
           * @dev Sets the initial owner of the account.
           * @param owner address.
           */
          constructor(address owner) Ownable(owner) {}
          /**
           * @notice Increment nonce of the msg.sender.
           * @dev Nonce can only increment and not decrement.
           * @return nonce uint256 nonce of the msg.sender.
           */
          function incrementNonce() external returns (uint256 nonce) {
              nonce = accountNonce[msg.sender];
              unchecked {
                  ++accountNonce[msg.sender];
              }
          }
          /**
           * @notice Return if the 4337 flag is enabled.
           * @dev This view function is called by validateUserOp() in all Biz wallet.
           * @return isEnabled bool flag whether 4337 is enabled.
           */
          function is4337Enabled() external view returns (bool isEnabled) {
              isEnabled = erc4337Flag;
          }
          /**
           * @notice Set function to set 4337 Flag.
           * @dev This function can only be called by the owner.
           * @param flag bool value of the flag.
           */
          function set4337Flag(bool flag) external onlyOwner {
              erc4337Flag = flag;
              emit FlagSet(flag);
          }
      }