ETH Price: $1,860.38 (-5.72%)

Transaction Decoder

Block:
23384191 at Sep-17-2025 05:07:59 PM +UTC
Transaction Fee:
0.000194524851727832 ETH $0.36
Gas Used:
180,307 Gas / 1.078853576 Gwei

Emitted Events:

648 0xaef96fee81a5a6eaedd22a7d3f45d0e71f3b21d9.0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0( 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000006360437ad8db8f14098ed90c6acfd717351c8678 )
649 0xaef96fee81a5a6eaedd22a7d3f45d0e71f3b21d9.0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2( 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2, 0000000000000000000000000000000000000000000000000000000000000001 )
650 MagicDropCloneFactory.NewContractInitialized( contractAddress=0xaef96fee81a5a6eaedd22a7d3f45d0e71f3b21d9, initialOwner=[Sender] 0x6360437ad8db8f14098ed90c6acfd717351c8678, implId=0, standard=0, name=Munchin Bunch, symbol=munchin_bunch )

Account State Difference:

  Address   Before After State Difference Code
0x00000000...Cd4b68aC4
(Titan Builder)
19.658175781789433138 Eth19.658175781791055901 Eth0.000000000001622763
0x6360437a...7351C8678
0.01 Eth
Nonce: 0
0.009805475148272168 Eth
Nonce: 1
0.000194524851727832
0xAef96FeE...71F3b21d9
0 Eth
Nonce: 0
0 Eth
Nonce: 1
From: 0 To: 2194563381516407626324453258647895721532871818597638701666055957952859058032459381987876594145776849738739

Execution Trace

MagicDropCloneFactory.createContract( name=Munchin Bunch, symbol=munchin_bunch, standard=0, initialOwner=0x6360437aD8db8f14098eD90c6ACFD717351C8678, implId=0 ) => ( 0xAef96FeE81a5a6EaEdD22A7d3f45d0E71F3b21d9 )
  • MagicDropTokenImplRegistry.getDefaultImplementation( standard=0 ) => ( implAddress=0x000000006258f75b058fc70CefE28f0d55432d26 )
  • MagicDropTokenImplRegistry.getDeploymentFee( standard=0, implId=0 ) => ( deploymentFee=0 )
  • 0xaef96fee81a5a6eaedd22a7d3f45d0e71f3b21d9.602c3d81( )
  • 0xaef96fee81a5a6eaedd22a7d3f45d0e71f3b21d9.077f224a( )
    • 0x000000006258f75b058fc70cefe28f0d55432d26.077f224a( )
      File 1 of 2: MagicDropCloneFactory
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.22;
      import {UUPSUpgradeable} from "solady/src/utils/UUPSUpgradeable.sol";
      import {Ownable} from "solady/src/auth/Ownable.sol";
      import {LibClone} from "solady/src/utils/LibClone.sol";
      import {TokenStandard} from "../common/Structs.sol";
      import {MagicDropTokenImplRegistry} from "../registry/MagicDropTokenImplRegistry.sol";
      /// @title MagicDropCloneFactory
      /// @notice A factory contract for creating and managing clones of MagicDrop contracts
      /// @dev This contract uses the UUPS proxy pattern
      contract MagicDropCloneFactory is Ownable, UUPSUpgradeable {
          /*==============================================================
          =                           CONSTANTS                          =
          ==============================================================*/
          MagicDropTokenImplRegistry private _registry;
          bytes4 private constant INITIALIZE_SELECTOR = bytes4(keccak256("initialize(string,string,address)"));
          /*==============================================================
          =                             EVENTS                           =
          ==============================================================*/
          event MagicDropFactoryInitialized();
          event NewContractInitialized(
              address contractAddress, address initialOwner, uint32 implId, TokenStandard standard, string name, string symbol
          );
          event Withdrawal(address to, uint256 amount);
          /*==============================================================
          =                             ERRORS                           =
          ==============================================================*/
          error InitializationFailed();
          error RegistryAddressCannotBeZero();
          error InsufficientDeploymentFee();
          error WithdrawalFailed();
          error InitialOwnerCannotBeZero();
          /*==============================================================
          =                          CONSTRUCTOR                         =
          ==============================================================*/
          /// @param initialOwner The address of the initial owner
          /// @param registry The address of the registry contract
          constructor(address initialOwner, address registry) public {
              if (registry == address(0)) {
                  revert RegistryAddressCannotBeZero();
              }
              _registry = MagicDropTokenImplRegistry(registry);
              _initializeOwner(initialOwner);
              emit MagicDropFactoryInitialized();
          }
          /*==============================================================
          =                      PUBLIC WRITE METHODS                    =
          ==============================================================*/
          /// @notice Creates a new deterministic clone of a MagicDrop contract
          /// @param name The name of the new contract
          /// @param symbol The symbol of the new contract
          /// @param standard The token standard of the new contract
          /// @param initialOwner The initial owner of the new contract
          /// @param implId The implementation ID
          /// @param salt A unique salt for deterministic address generation
          /// @return The address of the newly created contract
          function createContractDeterministic(
              string calldata name,
              string calldata symbol,
              TokenStandard standard,
              address payable initialOwner,
              uint32 implId,
              bytes32 salt
          ) external payable returns (address) {
              address impl;
              // Retrieve the implementation address from the registry
              if (implId == 0) {
                  impl = _registry.getDefaultImplementation(standard);
              } else {
                  impl = _registry.getImplementation(standard, implId);
              }
              if (initialOwner == address(0)) {
                  revert InitialOwnerCannotBeZero();
              }
              // Retrieve the deployment fee for the implementation and ensure the caller has sent the correct amount
              uint256 deploymentFee = _registry.getDeploymentFee(standard, implId);
              if (msg.value < deploymentFee) {
                  revert InsufficientDeploymentFee();
              }
              // Create a deterministic clone of the implementation contract
              address instance = LibClone.cloneDeterministic(impl, salt);
              // Initialize the newly created contract
              (bool success,) = instance.call(abi.encodeWithSelector(INITIALIZE_SELECTOR, name, symbol, initialOwner));
              if (!success) {
                  revert InitializationFailed();
              }
              emit NewContractInitialized({
                  contractAddress: instance,
                  initialOwner: initialOwner,
                  implId: implId,
                  standard: standard,
                  name: name,
                  symbol: symbol
              });
              return instance;
          }
          /// @notice Creates a new clone of a MagicDrop contract
          /// @param name The name of the new contract
          /// @param symbol The symbol of the new contract
          /// @param standard The token standard of the new contract
          /// @param initialOwner The initial owner of the new contract
          /// @param implId The implementation ID
          /// @return The address of the newly created contract
          function createContract(
              string calldata name,
              string calldata symbol,
              TokenStandard standard,
              address payable initialOwner,
              uint32 implId
          ) external payable returns (address) {
              address impl;
              // Retrieve the implementation address from the registry
              if (implId == 0) {
                  impl = _registry.getDefaultImplementation(standard);
              } else {
                  impl = _registry.getImplementation(standard, implId);
              }
              if (initialOwner == address(0)) {
                  revert InitialOwnerCannotBeZero();
              }
              // Retrieve the deployment fee for the implementation and ensure the caller has sent the correct amount
              uint256 deploymentFee = _registry.getDeploymentFee(standard, implId);
              if (msg.value < deploymentFee) {
                  revert InsufficientDeploymentFee();
              }
              // Create a non-deterministic clone of the implementation contract
              address instance = LibClone.clone(impl);
              // Initialize the newly created contract
              (bool success,) = instance.call(abi.encodeWithSelector(INITIALIZE_SELECTOR, name, symbol, initialOwner));
              if (!success) {
                  revert InitializationFailed();
              }
              emit NewContractInitialized({
                  contractAddress: instance,
                  initialOwner: initialOwner,
                  implId: implId,
                  standard: standard,
                  name: name,
                  symbol: symbol
              });
              return instance;
          }
          /*==============================================================
          =                      PUBLIC VIEW METHODS                     =
          ==============================================================*/
          /// @notice Predicts the deployment address of a deterministic clone
          /// @param standard The token standard of the contract
          /// @param implId The implementation ID
          /// @param salt The salt used for address generation
          /// @return The predicted deployment address
          function predictDeploymentAddress(TokenStandard standard, uint32 implId, bytes32 salt)
              external
              view
              returns (address)
          {
              address impl;
              if (implId == 0) {
                  impl = _registry.getDefaultImplementation(standard);
              } else {
                  impl = _registry.getImplementation(standard, implId);
              }
              return LibClone.predictDeterministicAddress(impl, salt, address(this));
          }
          /// @notice Retrieves the address of the registry contract
          /// @return The address of the registry contract
          function getRegistry() external view returns (address) {
              return address(_registry);
          }
          /*==============================================================
          =                      ADMIN OPERATIONS                        =
          ==============================================================*/
          ///@dev Internal function to authorize an upgrade.
          ///@param newImplementation Address of the new implementation.
          ///@notice Only the contract owner can upgrade the contract.
          function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
          /// @notice Withdraws the contract's balance
          function withdraw(address to) external onlyOwner {
              (bool success,) = to.call{value: address(this).balance}("");
              if (!success) {
                  revert WithdrawalFailed();
              }
              emit Withdrawal(to, address(this).balance);
          }
          /// @dev Overriden to prevent double-initialization of the owner.
          function _guardInitializeOwner() internal pure virtual override returns (bool) {
              return true;
          }
          /// @notice Receives ETH
          receive() external payable {}
          /// @notice Fallback function to receive ETH
          fallback() external payable {}
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.4;
      /// @notice UUPS proxy mixin.
      /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/UUPSUpgradeable.sol)
      /// @author Modified from OpenZeppelin
      /// (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/utils/UUPSUpgradeable.sol)
      ///
      /// @dev Note:
      /// - This implementation is intended to be used with ERC1967 proxies.
      /// See: `LibClone.deployERC1967` and related functions.
      /// - This implementation is NOT compatible with legacy OpenZeppelin proxies
      /// which do not store the implementation at `_ERC1967_IMPLEMENTATION_SLOT`.
      abstract contract UUPSUpgradeable {
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                       CUSTOM ERRORS                        */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev The upgrade failed.
          error UpgradeFailed();
          /// @dev The call is from an unauthorized call context.
          error UnauthorizedCallContext();
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                         IMMUTABLES                         */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev For checking if the context is a delegate call.
          uint256 private immutable __self = uint256(uint160(address(this)));
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                           EVENTS                           */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Emitted when the proxy's implementation is upgraded.
          event Upgraded(address indexed implementation);
          /// @dev `keccak256(bytes("Upgraded(address)"))`.
          uint256 private constant _UPGRADED_EVENT_SIGNATURE =
              0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b;
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                          STORAGE                           */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev The ERC-1967 storage slot for the implementation in the proxy.
          /// `uint256(keccak256("eip1967.proxy.implementation")) - 1`.
          bytes32 internal constant _ERC1967_IMPLEMENTATION_SLOT =
              0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                      UUPS OPERATIONS                       */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Please override this function to check if `msg.sender` is authorized
          /// to upgrade the proxy to `newImplementation`, reverting if not.
          /// ```
          ///     function _authorizeUpgrade(address) internal override onlyOwner {}
          /// ```
          function _authorizeUpgrade(address newImplementation) internal virtual;
          /// @dev Returns the storage slot used by the implementation,
          /// as specified in [ERC1822](https://eips.ethereum.org/EIPS/eip-1822).
          ///
          /// Note: The `notDelegated` modifier prevents accidental upgrades to
          /// an implementation that is a proxy contract.
          function proxiableUUID() public view virtual notDelegated returns (bytes32) {
              // This function must always return `_ERC1967_IMPLEMENTATION_SLOT` to comply with ERC1967.
              return _ERC1967_IMPLEMENTATION_SLOT;
          }
          /// @dev Upgrades the proxy's implementation to `newImplementation`.
          /// Emits a {Upgraded} event.
          ///
          /// Note: Passing in empty `data` skips the delegatecall to `newImplementation`.
          function upgradeToAndCall(address newImplementation, bytes calldata data)
              public
              payable
              virtual
              onlyProxy
          {
              _authorizeUpgrade(newImplementation);
              /// @solidity memory-safe-assembly
              assembly {
                  newImplementation := shr(96, shl(96, newImplementation)) // Clears upper 96 bits.
                  mstore(0x01, 0x52d1902d) // `proxiableUUID()`.
                  let s := _ERC1967_IMPLEMENTATION_SLOT
                  // Check if `newImplementation` implements `proxiableUUID` correctly.
                  if iszero(eq(mload(staticcall(gas(), newImplementation, 0x1d, 0x04, 0x01, 0x20)), s)) {
                      mstore(0x01, 0x55299b49) // `UpgradeFailed()`.
                      revert(0x1d, 0x04)
                  }
                  // Emit the {Upgraded} event.
                  log2(codesize(), 0x00, _UPGRADED_EVENT_SIGNATURE, newImplementation)
                  sstore(s, newImplementation) // Updates the implementation.
                  // Perform a delegatecall to `newImplementation` if `data` is non-empty.
                  if data.length {
                      // Forwards the `data` to `newImplementation` via delegatecall.
                      let m := mload(0x40)
                      calldatacopy(m, data.offset, data.length)
                      if iszero(delegatecall(gas(), newImplementation, m, data.length, codesize(), 0x00))
                      {
                          // Bubble up the revert if the call reverts.
                          returndatacopy(m, 0x00, returndatasize())
                          revert(m, returndatasize())
                      }
                  }
              }
          }
          /// @dev Requires that the execution is performed through a proxy.
          modifier onlyProxy() {
              uint256 s = __self;
              /// @solidity memory-safe-assembly
              assembly {
                  // To enable use cases with an immutable default implementation in the bytecode,
                  // (see: ERC6551Proxy), we don't require that the proxy address must match the
                  // value stored in the implementation slot, which may not be initialized.
                  if eq(s, address()) {
                      mstore(0x00, 0x9f03a026) // `UnauthorizedCallContext()`.
                      revert(0x1c, 0x04)
                  }
              }
              _;
          }
          /// @dev Requires that the execution is NOT performed via delegatecall.
          /// This is the opposite of `onlyProxy`.
          modifier notDelegated() {
              uint256 s = __self;
              /// @solidity memory-safe-assembly
              assembly {
                  if iszero(eq(s, address())) {
                      mstore(0x00, 0x9f03a026) // `UnauthorizedCallContext()`.
                      revert(0x1c, 0x04)
                  }
              }
              _;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.4;
      /// @notice Simple single owner authorization mixin.
      /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
      ///
      /// @dev Note:
      /// This implementation does NOT auto-initialize the owner to `msg.sender`.
      /// You MUST call the `_initializeOwner` in the constructor / initializer.
      ///
      /// While the ownable portion follows
      /// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
      /// the nomenclature for the 2-step ownership handover may be unique to this codebase.
      abstract contract Ownable {
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                       CUSTOM ERRORS                        */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev The caller is not authorized to call the function.
          error Unauthorized();
          /// @dev The `newOwner` cannot be the zero address.
          error NewOwnerIsZeroAddress();
          /// @dev The `pendingOwner` does not have a valid handover request.
          error NoHandoverRequest();
          /// @dev Cannot double-initialize.
          error AlreadyInitialized();
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                           EVENTS                           */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev The ownership is transferred from `oldOwner` to `newOwner`.
          /// This event is intentionally kept the same as OpenZeppelin's Ownable to be
          /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
          /// despite it not being as lightweight as a single argument event.
          event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);
          /// @dev An ownership handover to `pendingOwner` has been requested.
          event OwnershipHandoverRequested(address indexed pendingOwner);
          /// @dev The ownership handover to `pendingOwner` has been canceled.
          event OwnershipHandoverCanceled(address indexed pendingOwner);
          /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
          uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
              0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;
          /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
          uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
              0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;
          /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
          uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
              0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                          STORAGE                           */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev The owner slot is given by:
          /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`.
          /// It is intentionally chosen to be a high value
          /// to avoid collision with lower slots.
          /// The choice of manual storage layout is to enable compatibility
          /// with both regular and upgradeable contracts.
          bytes32 internal constant _OWNER_SLOT =
              0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;
          /// The ownership handover slot of `newOwner` is given by:
          /// ```
          ///     mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
          ///     let handoverSlot := keccak256(0x00, 0x20)
          /// ```
          /// It stores the expiry timestamp of the two-step ownership handover.
          uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                     INTERNAL FUNCTIONS                     */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Override to return true to make `_initializeOwner` prevent double-initialization.
          function _guardInitializeOwner() internal pure virtual returns (bool guard) {}
          /// @dev Initializes the owner directly without authorization guard.
          /// This function must be called upon initialization,
          /// regardless of whether the contract is upgradeable or not.
          /// This is to enable generalization to both regular and upgradeable contracts,
          /// and to save gas in case the initial owner is not the caller.
          /// For performance reasons, this function will not check if there
          /// is an existing owner.
          function _initializeOwner(address newOwner) internal virtual {
              if (_guardInitializeOwner()) {
                  /// @solidity memory-safe-assembly
                  assembly {
                      let ownerSlot := _OWNER_SLOT
                      if sload(ownerSlot) {
                          mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.
                          revert(0x1c, 0x04)
                      }
                      // Clean the upper 96 bits.
                      newOwner := shr(96, shl(96, newOwner))
                      // Store the new value.
                      sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
                      // Emit the {OwnershipTransferred} event.
                      log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
                  }
              } else {
                  /// @solidity memory-safe-assembly
                  assembly {
                      // Clean the upper 96 bits.
                      newOwner := shr(96, shl(96, newOwner))
                      // Store the new value.
                      sstore(_OWNER_SLOT, newOwner)
                      // Emit the {OwnershipTransferred} event.
                      log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
                  }
              }
          }
          /// @dev Sets the owner directly without authorization guard.
          function _setOwner(address newOwner) internal virtual {
              if (_guardInitializeOwner()) {
                  /// @solidity memory-safe-assembly
                  assembly {
                      let ownerSlot := _OWNER_SLOT
                      // Clean the upper 96 bits.
                      newOwner := shr(96, shl(96, newOwner))
                      // Emit the {OwnershipTransferred} event.
                      log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                      // Store the new value.
                      sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
                  }
              } else {
                  /// @solidity memory-safe-assembly
                  assembly {
                      let ownerSlot := _OWNER_SLOT
                      // Clean the upper 96 bits.
                      newOwner := shr(96, shl(96, newOwner))
                      // Emit the {OwnershipTransferred} event.
                      log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                      // Store the new value.
                      sstore(ownerSlot, newOwner)
                  }
              }
          }
          /// @dev Throws if the sender is not the owner.
          function _checkOwner() internal view virtual {
              /// @solidity memory-safe-assembly
              assembly {
                  // If the caller is not the stored owner, revert.
                  if iszero(eq(caller(), sload(_OWNER_SLOT))) {
                      mstore(0x00, 0x82b42900) // `Unauthorized()`.
                      revert(0x1c, 0x04)
                  }
              }
          }
          /// @dev Returns how long a two-step ownership handover is valid for in seconds.
          /// Override to return a different value if needed.
          /// Made internal to conserve bytecode. Wrap it in a public function if needed.
          function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
              return 48 * 3600;
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                  PUBLIC UPDATE FUNCTIONS                   */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Allows the owner to transfer the ownership to `newOwner`.
          function transferOwnership(address newOwner) public payable virtual onlyOwner {
              /// @solidity memory-safe-assembly
              assembly {
                  if iszero(shl(96, newOwner)) {
                      mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
                      revert(0x1c, 0x04)
                  }
              }
              _setOwner(newOwner);
          }
          /// @dev Allows the owner to renounce their ownership.
          function renounceOwnership() public payable virtual onlyOwner {
              _setOwner(address(0));
          }
          /// @dev Request a two-step ownership handover to the caller.
          /// The request will automatically expire in 48 hours (172800 seconds) by default.
          function requestOwnershipHandover() public payable virtual {
              unchecked {
                  uint256 expires = block.timestamp + _ownershipHandoverValidFor();
                  /// @solidity memory-safe-assembly
                  assembly {
                      // Compute and set the handover slot to `expires`.
                      mstore(0x0c, _HANDOVER_SLOT_SEED)
                      mstore(0x00, caller())
                      sstore(keccak256(0x0c, 0x20), expires)
                      // Emit the {OwnershipHandoverRequested} event.
                      log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
                  }
              }
          }
          /// @dev Cancels the two-step ownership handover to the caller, if any.
          function cancelOwnershipHandover() public payable virtual {
              /// @solidity memory-safe-assembly
              assembly {
                  // Compute and set the handover slot to 0.
                  mstore(0x0c, _HANDOVER_SLOT_SEED)
                  mstore(0x00, caller())
                  sstore(keccak256(0x0c, 0x20), 0)
                  // Emit the {OwnershipHandoverCanceled} event.
                  log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
              }
          }
          /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
          /// Reverts if there is no existing ownership handover requested by `pendingOwner`.
          function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
              /// @solidity memory-safe-assembly
              assembly {
                  // Compute and set the handover slot to 0.
                  mstore(0x0c, _HANDOVER_SLOT_SEED)
                  mstore(0x00, pendingOwner)
                  let handoverSlot := keccak256(0x0c, 0x20)
                  // If the handover does not exist, or has expired.
                  if gt(timestamp(), sload(handoverSlot)) {
                      mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
                      revert(0x1c, 0x04)
                  }
                  // Set the handover slot to 0.
                  sstore(handoverSlot, 0)
              }
              _setOwner(pendingOwner);
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                   PUBLIC READ FUNCTIONS                    */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Returns the owner of the contract.
          function owner() public view virtual returns (address result) {
              /// @solidity memory-safe-assembly
              assembly {
                  result := sload(_OWNER_SLOT)
              }
          }
          /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
          function ownershipHandoverExpiresAt(address pendingOwner)
              public
              view
              virtual
              returns (uint256 result)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  // Compute the handover slot.
                  mstore(0x0c, _HANDOVER_SLOT_SEED)
                  mstore(0x00, pendingOwner)
                  // Load the handover slot.
                  result := sload(keccak256(0x0c, 0x20))
              }
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                         MODIFIERS                          */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Marks a function as only callable by the owner.
          modifier onlyOwner() virtual {
              _checkOwner();
              _;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.4;
      /// @notice Minimal proxy library.
      /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol)
      /// @author Minimal proxy by 0age (https://github.com/0age)
      /// @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie
      /// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args)
      /// @author Minimal ERC1967 proxy by jtriley-eth (https://github.com/jtriley-eth/minimum-viable-proxy)
      ///
      /// @dev Minimal proxy:
      /// Although the sw0nt pattern saves 5 gas over the ERC1167 pattern during runtime,
      /// it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern,
      /// which saves 4 gas over the ERC1167 pattern during runtime, and has the smallest bytecode.
      /// - Automatically verified on Etherscan.
      ///
      /// @dev Minimal proxy (PUSH0 variant):
      /// This is a new minimal proxy that uses the PUSH0 opcode introduced during Shanghai.
      /// It is optimized first for minimal runtime gas, then for minimal bytecode.
      /// The PUSH0 clone functions are intentionally postfixed with a jarring "_PUSH0" as
      /// many EVM chains may not support the PUSH0 opcode in the early months after Shanghai.
      /// Please use with caution.
      /// - Automatically verified on Etherscan.
      ///
      /// @dev Clones with immutable args (CWIA):
      /// The implementation of CWIA here is does NOT append the immutable args into the calldata
      /// passed into delegatecall. It is simply an ERC1167 minimal proxy with the immutable arguments
      /// appended to the back of the runtime bytecode.
      /// - Uses the identity precompile (0x4) to copy args during deployment.
      ///
      /// @dev Minimal ERC1967 proxy:
      /// An minimal ERC1967 proxy, intended to be upgraded with UUPS.
      /// This is NOT the same as ERC1967Factory's transparent proxy, which includes admin logic.
      /// - Automatically verified on Etherscan.
      ///
      /// @dev Minimal ERC1967 proxy with immutable args:
      /// - Uses the identity precompile (0x4) to copy args during deployment.
      /// - Automatically verified on Etherscan.
      ///
      /// @dev ERC1967I proxy:
      /// An variant of the minimal ERC1967 proxy, with a special code path that activates
      /// if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the
      /// `implementation` address. The returned implementation is guaranteed to be valid if the
      /// keccak256 of the proxy's code is equal to `ERC1967I_CODE_HASH`.
      ///
      /// @dev ERC1967I proxy with immutable args:
      /// An variant of the minimal ERC1967 proxy, with a special code path that activates
      /// if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the
      /// - Uses the identity precompile (0x4) to copy args during deployment.
      ///
      /// @dev Minimal ERC1967 beacon proxy:
      /// A minimal beacon proxy, intended to be upgraded with an upgradable beacon.
      /// - Automatically verified on Etherscan.
      ///
      /// @dev Minimal ERC1967 beacon proxy with immutable args:
      /// - Uses the identity precompile (0x4) to copy args during deployment.
      /// - Automatically verified on Etherscan.
      ///
      /// @dev ERC1967I beacon proxy:
      /// An variant of the minimal ERC1967 beacon proxy, with a special code path that activates
      /// if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the
      /// `implementation` address. The returned implementation is guaranteed to be valid if the
      /// keccak256 of the proxy's code is equal to `ERC1967I_CODE_HASH`.
      ///
      /// @dev ERC1967I proxy with immutable args:
      /// An variant of the minimal ERC1967 beacon proxy, with a special code path that activates
      /// if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the
      /// - Uses the identity precompile (0x4) to copy args during deployment.
      library LibClone {
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                         CONSTANTS                          */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev The keccak256 of deployed code for the clone proxy,
          /// with the implementation set to `address(0)`.
          bytes32 internal constant CLONE_CODE_HASH =
              0x48db2cfdb2853fce0b464f1f93a1996469459df3ab6c812106074c4106a1eb1f;
          /// @dev The keccak256 of deployed code for the PUSH0 proxy,
          /// with the implementation set to `address(0)`.
          bytes32 internal constant PUSH0_CLONE_CODE_HASH =
              0x67bc6bde1b84d66e267c718ba44cf3928a615d29885537955cb43d44b3e789dc;
          /// @dev The keccak256 of deployed code for the ERC-1167 CWIA proxy,
          /// with the implementation set to `address(0)`.
          bytes32 internal constant CWIA_CODE_HASH =
              0x3cf92464268225a4513da40a34d967354684c32cd0edd67b5f668dfe3550e940;
          /// @dev The keccak256 of the deployed code for the ERC1967 proxy.
          bytes32 internal constant ERC1967_CODE_HASH =
              0xaaa52c8cc8a0e3fd27ce756cc6b4e70c51423e9b597b11f32d3e49f8b1fc890d;
          /// @dev The keccak256 of the deployed code for the ERC1967I proxy.
          bytes32 internal constant ERC1967I_CODE_HASH =
              0xce700223c0d4cea4583409accfc45adac4a093b3519998a9cbbe1504dadba6f7;
          /// @dev The keccak256 of the deployed code for the ERC1967 beacon proxy.
          bytes32 internal constant ERC1967_BEACON_PROXY_CODE_HASH =
              0x14044459af17bc4f0f5aa2f658cb692add77d1302c29fe2aebab005eea9d1162;
          /// @dev The keccak256 of the deployed code for the ERC1967 beacon proxy.
          bytes32 internal constant ERC1967I_BEACON_PROXY_CODE_HASH =
              0xf8c46d2793d5aa984eb827aeaba4b63aedcab80119212fce827309788735519a;
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                       CUSTOM ERRORS                        */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Unable to deploy the clone.
          error DeploymentFailed();
          /// @dev The salt must start with either the zero address or `by`.
          error SaltDoesNotStartWith();
          /// @dev The ETH transfer has failed.
          error ETHTransferFailed();
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                  MINIMAL PROXY OPERATIONS                  */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Deploys a clone of `implementation`.
          function clone(address implementation) internal returns (address instance) {
              instance = clone(0, implementation);
          }
          /// @dev Deploys a clone of `implementation`.
          /// Deposits `value` ETH during deployment.
          function clone(uint256 value, address implementation) internal returns (address instance) {
              /// @solidity memory-safe-assembly
              assembly {
                  /**
                   * --------------------------------------------------------------------------+
                   * CREATION (9 bytes)                                                        |
                   * --------------------------------------------------------------------------|
                   * Opcode     | Mnemonic          | Stack     | Memory                       |
                   * --------------------------------------------------------------------------|
                   * 60 runSize | PUSH1 runSize     | r         |                              |
                   * 3d         | RETURNDATASIZE    | 0 r       |                              |
                   * 81         | DUP2              | r 0 r     |                              |
                   * 60 offset  | PUSH1 offset      | o r 0 r   |                              |
                   * 3d         | RETURNDATASIZE    | 0 o r 0 r |                              |
                   * 39         | CODECOPY          | 0 r       | [0..runSize): runtime code   |
                   * f3         | RETURN            |           | [0..runSize): runtime code   |
                   * --------------------------------------------------------------------------|
                   * RUNTIME (44 bytes)                                                        |
                   * --------------------------------------------------------------------------|
                   * Opcode  | Mnemonic       | Stack                  | Memory                |
                   * --------------------------------------------------------------------------|
                   *                                                                           |
                   * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |
                   * 3d      | RETURNDATASIZE | 0                      |                       |
                   * 3d      | RETURNDATASIZE | 0 0                    |                       |
                   * 3d      | RETURNDATASIZE | 0 0 0                  |                       |
                   * 3d      | RETURNDATASIZE | 0 0 0 0                |                       |
                   *                                                                           |
                   * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |
                   * 36      | CALLDATASIZE   | cds 0 0 0 0            |                       |
                   * 3d      | RETURNDATASIZE | 0 cds 0 0 0 0          |                       |
                   * 3d      | RETURNDATASIZE | 0 0 cds 0 0 0 0        |                       |
                   * 37      | CALLDATACOPY   | 0 0 0 0                | [0..cds): calldata    |
                   *                                                                           |
                   * ::: delegate call to the implementation contract :::::::::::::::::::::::: |
                   * 36      | CALLDATASIZE   | cds 0 0 0 0            | [0..cds): calldata    |
                   * 3d      | RETURNDATASIZE | 0 cds 0 0 0 0          | [0..cds): calldata    |
                   * 73 addr | PUSH20 addr    | addr 0 cds 0 0 0 0     | [0..cds): calldata    |
                   * 5a      | GAS            | gas addr 0 cds 0 0 0 0 | [0..cds): calldata    |
                   * f4      | DELEGATECALL   | success 0 0            | [0..cds): calldata    |
                   *                                                                           |
                   * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |
                   * 3d      | RETURNDATASIZE | rds success 0 0        | [0..cds): calldata    |
                   * 3d      | RETURNDATASIZE | rds rds success 0 0    | [0..cds): calldata    |
                   * 93      | SWAP4          | 0 rds success 0 rds    | [0..cds): calldata    |
                   * 80      | DUP1           | 0 0 rds success 0 rds  | [0..cds): calldata    |
                   * 3e      | RETURNDATACOPY | success 0 rds          | [0..rds): returndata  |
                   *                                                                           |
                   * 60 0x2a | PUSH1 0x2a     | 0x2a success 0 rds     | [0..rds): returndata  |
                   * 57      | JUMPI          | 0 rds                  | [0..rds): returndata  |
                   *                                                                           |
                   * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
                   * fd      | REVERT         |                        | [0..rds): returndata  |
                   *                                                                           |
                   * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 5b      | JUMPDEST       | 0 rds                  | [0..rds): returndata  |
                   * f3      | RETURN         |                        | [0..rds): returndata  |
                   * --------------------------------------------------------------------------+
                   */
                  mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)
                  mstore(0x14, implementation)
                  mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
                  instance := create(value, 0x0c, 0x35)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
                  mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
              }
          }
          /// @dev Deploys a deterministic clone of `implementation` with `salt`.
          function cloneDeterministic(address implementation, bytes32 salt)
              internal
              returns (address instance)
          {
              instance = cloneDeterministic(0, implementation, salt);
          }
          /// @dev Deploys a deterministic clone of `implementation` with `salt`.
          /// Deposits `value` ETH during deployment.
          function cloneDeterministic(uint256 value, address implementation, bytes32 salt)
              internal
              returns (address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)
                  mstore(0x14, implementation)
                  mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
                  instance := create2(value, 0x0c, 0x35, salt)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
                  mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
              }
          }
          /// @dev Returns the initialization code of the clone of `implementation`.
          function initCode(address implementation) internal pure returns (bytes memory c) {
              /// @solidity memory-safe-assembly
              assembly {
                  c := mload(0x40)
                  mstore(add(c, 0x40), 0x5af43d3d93803e602a57fd5bf30000000000000000000000)
                  mstore(add(c, 0x28), implementation)
                  mstore(add(c, 0x14), 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
                  mstore(c, 0x35) // Store the length.
                  mstore(0x40, add(c, 0x60)) // Allocate memory.
              }
          }
          /// @dev Returns the initialization code hash of the clone of `implementation`.
          function initCodeHash(address implementation) internal pure returns (bytes32 hash) {
              /// @solidity memory-safe-assembly
              assembly {
                  mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)
                  mstore(0x14, implementation)
                  mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
                  hash := keccak256(0x0c, 0x35)
                  mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
              }
          }
          /// @dev Returns the address of the clone of `implementation`, with `salt` by `deployer`.
          /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
          function predictDeterministicAddress(address implementation, bytes32 salt, address deployer)
              internal
              pure
              returns (address predicted)
          {
              bytes32 hash = initCodeHash(implementation);
              predicted = predictDeterministicAddress(hash, salt, deployer);
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*          MINIMAL PROXY OPERATIONS (PUSH0 VARIANT)          */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Deploys a PUSH0 clone of `implementation`.
          function clone_PUSH0(address implementation) internal returns (address instance) {
              instance = clone_PUSH0(0, implementation);
          }
          /// @dev Deploys a PUSH0 clone of `implementation`.
          /// Deposits `value` ETH during deployment.
          function clone_PUSH0(uint256 value, address implementation)
              internal
              returns (address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  /**
                   * --------------------------------------------------------------------------+
                   * CREATION (9 bytes)                                                        |
                   * --------------------------------------------------------------------------|
                   * Opcode     | Mnemonic          | Stack     | Memory                       |
                   * --------------------------------------------------------------------------|
                   * 60 runSize | PUSH1 runSize     | r         |                              |
                   * 5f         | PUSH0             | 0 r       |                              |
                   * 81         | DUP2              | r 0 r     |                              |
                   * 60 offset  | PUSH1 offset      | o r 0 r   |                              |
                   * 5f         | PUSH0             | 0 o r 0 r |                              |
                   * 39         | CODECOPY          | 0 r       | [0..runSize): runtime code   |
                   * f3         | RETURN            |           | [0..runSize): runtime code   |
                   * --------------------------------------------------------------------------|
                   * RUNTIME (45 bytes)                                                        |
                   * --------------------------------------------------------------------------|
                   * Opcode  | Mnemonic       | Stack                  | Memory                |
                   * --------------------------------------------------------------------------|
                   *                                                                           |
                   * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |
                   * 5f      | PUSH0          | 0                      |                       |
                   * 5f      | PUSH0          | 0 0                    |                       |
                   *                                                                           |
                   * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |
                   * 36      | CALLDATASIZE   | cds 0 0                |                       |
                   * 5f      | PUSH0          | 0 cds 0 0              |                       |
                   * 5f      | PUSH0          | 0 0 cds 0 0            |                       |
                   * 37      | CALLDATACOPY   | 0 0                    | [0..cds): calldata    |
                   *                                                                           |
                   * ::: delegate call to the implementation contract :::::::::::::::::::::::: |
                   * 36      | CALLDATASIZE   | cds 0 0                | [0..cds): calldata    |
                   * 5f      | PUSH0          | 0 cds 0 0              | [0..cds): calldata    |
                   * 73 addr | PUSH20 addr    | addr 0 cds 0 0         | [0..cds): calldata    |
                   * 5a      | GAS            | gas addr 0 cds 0 0     | [0..cds): calldata    |
                   * f4      | DELEGATECALL   | success                | [0..cds): calldata    |
                   *                                                                           |
                   * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |
                   * 3d      | RETURNDATASIZE | rds success            | [0..cds): calldata    |
                   * 5f      | PUSH0          | 0 rds success          | [0..cds): calldata    |
                   * 5f      | PUSH0          | 0 0 rds success        | [0..cds): calldata    |
                   * 3e      | RETURNDATACOPY | success                | [0..rds): returndata  |
                   *                                                                           |
                   * 60 0x29 | PUSH1 0x29     | 0x29 success           | [0..rds): returndata  |
                   * 57      | JUMPI          |                        | [0..rds): returndata  |
                   *                                                                           |
                   * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 3d      | RETURNDATASIZE | rds                    | [0..rds): returndata  |
                   * 5f      | PUSH0          | 0 rds                  | [0..rds): returndata  |
                   * fd      | REVERT         |                        | [0..rds): returndata  |
                   *                                                                           |
                   * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 5b      | JUMPDEST       |                        | [0..rds): returndata  |
                   * 3d      | RETURNDATASIZE | rds                    | [0..rds): returndata  |
                   * 5f      | PUSH0          | 0 rds                  | [0..rds): returndata  |
                   * f3      | RETURN         |                        | [0..rds): returndata  |
                   * --------------------------------------------------------------------------+
                   */
                  mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16
                  mstore(0x14, implementation) // 20
                  mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
                  instance := create(value, 0x0e, 0x36)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
                  mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.
              }
          }
          /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.
          function cloneDeterministic_PUSH0(address implementation, bytes32 salt)
              internal
              returns (address instance)
          {
              instance = cloneDeterministic_PUSH0(0, implementation, salt);
          }
          /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.
          /// Deposits `value` ETH during deployment.
          function cloneDeterministic_PUSH0(uint256 value, address implementation, bytes32 salt)
              internal
              returns (address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16
                  mstore(0x14, implementation) // 20
                  mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
                  instance := create2(value, 0x0e, 0x36, salt)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
                  mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.
              }
          }
          /// @dev Returns the initialization code of the PUSH0 clone of `implementation`.
          function initCode_PUSH0(address implementation) internal pure returns (bytes memory c) {
              /// @solidity memory-safe-assembly
              assembly {
                  c := mload(0x40)
                  mstore(add(c, 0x40), 0x5af43d5f5f3e6029573d5ffd5b3d5ff300000000000000000000) // 16
                  mstore(add(c, 0x26), implementation) // 20
                  mstore(add(c, 0x12), 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
                  mstore(c, 0x36) // Store the length.
                  mstore(0x40, add(c, 0x60)) // Allocate memory.
              }
          }
          /// @dev Returns the initialization code hash of the PUSH0 clone of `implementation`.
          function initCodeHash_PUSH0(address implementation) internal pure returns (bytes32 hash) {
              /// @solidity memory-safe-assembly
              assembly {
                  mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16
                  mstore(0x14, implementation) // 20
                  mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
                  hash := keccak256(0x0e, 0x36)
                  mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.
              }
          }
          /// @dev Returns the address of the PUSH0 clone of `implementation`, with `salt` by `deployer`.
          /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
          function predictDeterministicAddress_PUSH0(
              address implementation,
              bytes32 salt,
              address deployer
          ) internal pure returns (address predicted) {
              bytes32 hash = initCodeHash_PUSH0(implementation);
              predicted = predictDeterministicAddress(hash, salt, deployer);
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*           CLONES WITH IMMUTABLE ARGS OPERATIONS            */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Deploys a clone of `implementation` with immutable arguments encoded in `args`.
          function clone(address implementation, bytes memory args) internal returns (address instance) {
              instance = clone(0, implementation, args);
          }
          /// @dev Deploys a clone of `implementation` with immutable arguments encoded in `args`.
          /// Deposits `value` ETH during deployment.
          function clone(uint256 value, address implementation, bytes memory args)
              internal
              returns (address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  /**
                   * ---------------------------------------------------------------------------+
                   * CREATION (10 bytes)                                                        |
                   * ---------------------------------------------------------------------------|
                   * Opcode     | Mnemonic          | Stack     | Memory                        |
                   * ---------------------------------------------------------------------------|
                   * 61 runSize | PUSH2 runSize     | r         |                               |
                   * 3d         | RETURNDATASIZE    | 0 r       |                               |
                   * 81         | DUP2              | r 0 r     |                               |
                   * 60 offset  | PUSH1 offset      | o r 0 r   |                               |
                   * 3d         | RETURNDATASIZE    | 0 o r 0 r |                               |
                   * 39         | CODECOPY          | 0 r       | [0..runSize): runtime code    |
                   * f3         | RETURN            |           | [0..runSize): runtime code    |
                   * ---------------------------------------------------------------------------|
                   * RUNTIME (45 bytes + extraLength)                                           |
                   * ---------------------------------------------------------------------------|
                   * Opcode   | Mnemonic       | Stack                  | Memory                |
                   * ---------------------------------------------------------------------------|
                   *                                                                            |
                   * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::: |
                   * 36       | CALLDATASIZE   | cds                    |                       |
                   * 3d       | RETURNDATASIZE | 0 cds                  |                       |
                   * 3d       | RETURNDATASIZE | 0 0 cds                |                       |
                   * 37       | CALLDATACOPY   |                        | [0..cds): calldata    |
                   *                                                                            |
                   * ::: delegate call to the implementation contract ::::::::::::::::::::::::: |
                   * 3d       | RETURNDATASIZE | 0                      | [0..cds): calldata    |
                   * 3d       | RETURNDATASIZE | 0 0                    | [0..cds): calldata    |
                   * 3d       | RETURNDATASIZE | 0 0 0                  | [0..cds): calldata    |
                   * 36       | CALLDATASIZE   | cds 0 0 0              | [0..cds): calldata    |
                   * 3d       | RETURNDATASIZE | 0 cds 0 0 0 0          | [0..cds): calldata    |
                   * 73 addr  | PUSH20 addr    | addr 0 cds 0 0 0 0     | [0..cds): calldata    |
                   * 5a       | GAS            | gas addr 0 cds 0 0 0 0 | [0..cds): calldata    |
                   * f4       | DELEGATECALL   | success 0 0            | [0..cds): calldata    |
                   *                                                                            |
                   * ::: copy return data to memory ::::::::::::::::::::::::::::::::::::::::::: |
                   * 3d       | RETURNDATASIZE | rds success 0          | [0..cds): calldata    |
                   * 82       | DUP3           | 0 rds success 0         | [0..cds): calldata   |
                   * 80       | DUP1           | 0 0 rds success 0      | [0..cds): calldata    |
                   * 3e       | RETURNDATACOPY | success 0              | [0..rds): returndata  |
                   * 90       | SWAP1          | 0 success              | [0..rds): returndata  |
                   * 3d       | RETURNDATASIZE | rds 0 success          | [0..rds): returndata  |
                   * 91       | SWAP2          | success 0 rds          | [0..rds): returndata  |
                   *                                                                            |
                   * 60 0x2b  | PUSH1 0x2b     | 0x2b success 0 rds     | [0..rds): returndata  |
                   * 57       | JUMPI          | 0 rds                  | [0..rds): returndata  |
                   *                                                                            |
                   * ::: revert ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
                   * fd       | REVERT         |                        | [0..rds): returndata  |
                   *                                                                            |
                   * ::: return ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 5b       | JUMPDEST       | 0 rds                  | [0..rds): returndata  |
                   * f3       | RETURN         |                        | [0..rds): returndata  |
                   * ---------------------------------------------------------------------------+
                   */
                  let m := mload(0x40)
                  let n := mload(args)
                  pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x43), n))
                  mstore(add(m, 0x23), 0x5af43d82803e903d91602b57fd5bf3)
                  mstore(add(m, 0x14), implementation)
                  mstore(m, add(0xfe61002d3d81600a3d39f3363d3d373d3d3d363d73, shl(0x88, n)))
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x2d = 0xffd2`.
                  instance := create(value, add(m, add(0x0b, lt(n, 0xffd3))), add(n, 0x37))
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
              }
          }
          // 0,0x5e17b14ADd6c386305A32928F985b29bbA34Eff5, hex"01020304"
          /// @dev Deploys a deterministic clone of `implementation`
          /// with immutable arguments encoded in `args` and `salt`.
          function cloneDeterministic(address implementation, bytes memory args, bytes32 salt)
              internal
              returns (address instance)
          {
              instance = cloneDeterministic(0, implementation, args, salt);
          }
          /// @dev Deploys a deterministic clone of `implementation`
          /// with immutable arguments encoded in `args` and `salt`.
          function cloneDeterministic(
              uint256 value,
              address implementation,
              bytes memory args,
              bytes32 salt
          ) internal returns (address instance) {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40)
                  let n := mload(args)
                  pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x43), n))
                  mstore(add(m, 0x23), 0x5af43d82803e903d91602b57fd5bf3)
                  mstore(add(m, 0x14), implementation)
                  mstore(m, add(0xfe61002d3d81600a3d39f3363d3d373d3d3d363d73, shl(0x88, n)))
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x2d = 0xffd2`.
                  instance := create2(value, add(m, add(0x0b, lt(n, 0xffd3))), add(n, 0x37), salt)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
              }
          }
          /// @dev Returns the initialization code hash of the clone of `implementation`
          /// using immutable arguments encoded in `args`.
          function initCode(address implementation, bytes memory args)
              internal
              pure
              returns (bytes memory c)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  c := mload(0x40)
                  let n := mload(args)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x2d = 0xffd2`.
                  returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffd2))
                  for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
                      mstore(add(add(c, 0x57), i), mload(add(add(args, 0x20), i)))
                  }
                  mstore(add(c, 0x37), 0x5af43d82803e903d91602b57fd5bf3)
                  mstore(add(c, 0x28), implementation)
                  mstore(add(c, 0x14), add(0x61002d3d81600a3d39f3363d3d373d3d3d363d73, shl(0x88, n)))
                  mstore(c, add(0x37, n)) // Store the length.
                  mstore(add(c, add(n, 0x57)), 0) // Zeroize the slot after the bytes.
                  mstore(0x40, add(c, add(n, 0x77))) // Allocate memory.
              }
          }
          /// @dev Returns the initialization code hash of the clone of `implementation`
          /// using immutable arguments encoded in `args`.
          function initCodeHash(address implementation, bytes memory args)
              internal
              pure
              returns (bytes32 hash)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40)
                  let n := mload(args)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x2d = 0xffd2`.
                  returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffd2))
                  for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
                      mstore(add(add(m, 0x43), i), mload(add(add(args, 0x20), i)))
                  }
                  mstore(add(m, 0x23), 0x5af43d82803e903d91602b57fd5bf3)
                  mstore(add(m, 0x14), implementation)
                  mstore(m, add(0x61002d3d81600a3d39f3363d3d373d3d3d363d73, shl(0x88, n)))
                  hash := keccak256(add(m, 0x0c), add(n, 0x37))
              }
          }
          /// @dev Returns the address of the clone of
          /// `implementation` using immutable arguments encoded in `args`, with `salt`, by `deployer`.
          /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
          function predictDeterministicAddress(
              address implementation,
              bytes memory data,
              bytes32 salt,
              address deployer
          ) internal pure returns (address predicted) {
              bytes32 hash = initCodeHash(implementation, data);
              predicted = predictDeterministicAddress(hash, salt, deployer);
          }
          /// @dev Equivalent to `argsOnClone(instance, 0, 2 ** 256 - 1)`.
          function argsOnClone(address instance) internal view returns (bytes memory args) {
              /// @solidity memory-safe-assembly
              assembly {
                  args := mload(0x40)
                  mstore(args, sub(extcodesize(instance), 0x2d)) // Store the length.
                  extcodecopy(instance, add(args, 0x20), 0x2d, add(mload(args), 0x20))
                  mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.
              }
          }
          /// @dev Equivalent to `argsOnClone(instance, start, 2 ** 256 - 1)`.
          function argsOnClone(address instance, uint256 start)
              internal
              view
              returns (bytes memory args)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  args := mload(0x40)
                  let n := sub(extcodesize(instance), 0x2d)
                  extcodecopy(instance, add(args, 0x20), add(start, 0x2d), add(n, 0x20))
                  mstore(args, mul(sub(n, start), lt(start, n))) // Store the length.
                  mstore(0x40, add(args, add(0x40, mload(args)))) // Allocate memory.
              }
          }
          /// @dev Returns a slice of the immutable arguments on `instance` from `start` to `end`.
          /// `start` and `end` will be clamped to the range `[0, args.length]`.
          /// The `instance` MUST be deployed via the clone with immutable args functions.
          /// Otherwise, the behavior is undefined.
          /// Out-of-gas reverts if `instance` does not have any code.
          function argsOnClone(address instance, uint256 start, uint256 end)
              internal
              view
              returns (bytes memory args)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  args := mload(0x40)
                  if iszero(lt(end, 0xffff)) { end := 0xffff }
                  let d := mul(sub(end, start), lt(start, end))
                  extcodecopy(instance, args, add(start, 0x0d), add(d, 0x20))
                  if iszero(and(0xff, mload(add(args, d)))) {
                      let n := sub(extcodesize(instance), 0x2d)
                      returndatacopy(returndatasize(), returndatasize(), shr(64, n))
                      d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))
                  }
                  mstore(args, d) // Store the length.
                  mstore(add(add(args, 0x20), d), 0) // Zeroize the slot after the bytes.
                  mstore(0x40, add(add(args, 0x40), d)) // Allocate memory.
              }
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*              MINIMAL ERC1967 PROXY OPERATIONS              */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          // Note: The ERC1967 proxy here is intended to be upgraded with UUPS.
          // This is NOT the same as ERC1967Factory's transparent proxy, which includes admin logic.
          /// @dev Deploys a minimal ERC1967 proxy with `implementation`.
          function deployERC1967(address implementation) internal returns (address instance) {
              instance = deployERC1967(0, implementation);
          }
          /// @dev Deploys a minimal ERC1967 proxy with `implementation`.
          /// Deposits `value` ETH during deployment.
          function deployERC1967(uint256 value, address implementation)
              internal
              returns (address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  /**
                   * ---------------------------------------------------------------------------------+
                   * CREATION (34 bytes)                                                              |
                   * ---------------------------------------------------------------------------------|
                   * Opcode     | Mnemonic       | Stack            | Memory                          |
                   * ---------------------------------------------------------------------------------|
                   * 60 runSize | PUSH1 runSize  | r                |                                 |
                   * 3d         | RETURNDATASIZE | 0 r              |                                 |
                   * 81         | DUP2           | r 0 r            |                                 |
                   * 60 offset  | PUSH1 offset   | o r 0 r          |                                 |
                   * 3d         | RETURNDATASIZE | 0 o r 0 r        |                                 |
                   * 39         | CODECOPY       | 0 r              | [0..runSize): runtime code      |
                   * 73 impl    | PUSH20 impl    | impl 0 r         | [0..runSize): runtime code      |
                   * 60 slotPos | PUSH1 slotPos  | slotPos impl 0 r | [0..runSize): runtime code      |
                   * 51         | MLOAD          | slot impl 0 r    | [0..runSize): runtime code      |
                   * 55         | SSTORE         | 0 r              | [0..runSize): runtime code      |
                   * f3         | RETURN         |                  | [0..runSize): runtime code      |
                   * ---------------------------------------------------------------------------------|
                   * RUNTIME (61 bytes)                                                               |
                   * ---------------------------------------------------------------------------------|
                   * Opcode     | Mnemonic       | Stack            | Memory                          |
                   * ---------------------------------------------------------------------------------|
                   *                                                                                  |
                   * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 36         | CALLDATASIZE   | cds              |                                 |
                   * 3d         | RETURNDATASIZE | 0 cds            |                                 |
                   * 3d         | RETURNDATASIZE | 0 0 cds          |                                 |
                   * 37         | CALLDATACOPY   |                  | [0..calldatasize): calldata     |
                   *                                                                                  |
                   * ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |
                   * 3d         | RETURNDATASIZE | 0                |                                 |
                   * 3d         | RETURNDATASIZE | 0 0              |                                 |
                   * 36         | CALLDATASIZE   | cds 0 0          | [0..calldatasize): calldata     |
                   * 3d         | RETURNDATASIZE | 0 cds 0 0        | [0..calldatasize): calldata     |
                   * 7f slot    | PUSH32 slot    | s 0 cds 0 0      | [0..calldatasize): calldata     |
                   * 54         | SLOAD          | i 0 cds 0 0      | [0..calldatasize): calldata     |
                   * 5a         | GAS            | g i 0 cds 0 0    | [0..calldatasize): calldata     |
                   * f4         | DELEGATECALL   | succ             | [0..calldatasize): calldata     |
                   *                                                                                  |
                   * ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 3d         | RETURNDATASIZE | rds succ         | [0..calldatasize): calldata     |
                   * 60 0x00    | PUSH1 0x00     | 0 rds succ       | [0..calldatasize): calldata     |
                   * 80         | DUP1           | 0 0 rds succ     | [0..calldatasize): calldata     |
                   * 3e         | RETURNDATACOPY | succ             | [0..returndatasize): returndata |
                   *                                                                                  |
                   * ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |
                   * 60 0x38    | PUSH1 0x38     | dest succ        | [0..returndatasize): returndata |
                   * 57         | JUMPI          |                  | [0..returndatasize): returndata |
                   *                                                                                  |
                   * ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 3d         | RETURNDATASIZE | rds              | [0..returndatasize): returndata |
                   * 60 0x00    | PUSH1 0x00     | 0 rds            | [0..returndatasize): returndata |
                   * fd         | REVERT         |                  | [0..returndatasize): returndata |
                   *                                                                                  |
                   * ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |
                   * 5b         | JUMPDEST       |                  | [0..returndatasize): returndata |
                   * 3d         | RETURNDATASIZE | rds              | [0..returndatasize): returndata |
                   * 60 0x00    | PUSH1 0x00     | 0 rds            | [0..returndatasize): returndata |
                   * f3         | RETURN         |                  | [0..returndatasize): returndata |
                   * ---------------------------------------------------------------------------------+
                   */
                  let m := mload(0x40) // Cache the free memory pointer.
                  mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
                  mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
                  mstore(0x20, 0x6009)
                  mstore(0x1e, implementation)
                  mstore(0x0a, 0x603d3d8160223d3973)
                  instance := create(value, 0x21, 0x5f)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
                  mstore(0x40, m) // Restore the free memory pointer.
                  mstore(0x60, 0) // Restore the zero slot.
              }
          }
          /// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation` and `salt`.
          function deployDeterministicERC1967(address implementation, bytes32 salt)
              internal
              returns (address instance)
          {
              instance = deployDeterministicERC1967(0, implementation, salt);
          }
          /// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation` and `salt`.
          /// Deposits `value` ETH during deployment.
          function deployDeterministicERC1967(uint256 value, address implementation, bytes32 salt)
              internal
              returns (address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40) // Cache the free memory pointer.
                  mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
                  mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
                  mstore(0x20, 0x6009)
                  mstore(0x1e, implementation)
                  mstore(0x0a, 0x603d3d8160223d3973)
                  instance := create2(value, 0x21, 0x5f, salt)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
                  mstore(0x40, m) // Restore the free memory pointer.
                  mstore(0x60, 0) // Restore the zero slot.
              }
          }
          /// @dev Creates a deterministic minimal ERC1967 proxy with `implementation` and `salt`.
          /// Note: This method is intended for use in ERC4337 factories,
          /// which are expected to NOT revert if the proxy is already deployed.
          function createDeterministicERC1967(address implementation, bytes32 salt)
              internal
              returns (bool alreadyDeployed, address instance)
          {
              return createDeterministicERC1967(0, implementation, salt);
          }
          /// @dev Creates a deterministic minimal ERC1967 proxy with `implementation` and `salt`.
          /// Deposits `value` ETH during deployment.
          /// Note: This method is intended for use in ERC4337 factories,
          /// which are expected to NOT revert if the proxy is already deployed.
          function createDeterministicERC1967(uint256 value, address implementation, bytes32 salt)
              internal
              returns (bool alreadyDeployed, address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40) // Cache the free memory pointer.
                  mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
                  mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
                  mstore(0x20, 0x6009)
                  mstore(0x1e, implementation)
                  mstore(0x0a, 0x603d3d8160223d3973)
                  // Compute and store the bytecode hash.
                  mstore(add(m, 0x35), keccak256(0x21, 0x5f))
                  mstore(m, shl(88, address()))
                  mstore8(m, 0xff) // Write the prefix.
                  mstore(add(m, 0x15), salt)
                  instance := keccak256(m, 0x55)
                  for {} 1 {} {
                      if iszero(extcodesize(instance)) {
                          instance := create2(value, 0x21, 0x5f, salt)
                          if iszero(instance) {
                              mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                              revert(0x1c, 0x04)
                          }
                          break
                      }
                      alreadyDeployed := 1
                      if iszero(value) { break }
                      if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
                          mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                          revert(0x1c, 0x04)
                      }
                      break
                  }
                  mstore(0x40, m) // Restore the free memory pointer.
                  mstore(0x60, 0) // Restore the zero slot.
              }
          }
          /// @dev Returns the initialization code of the minimal ERC1967 proxy of `implementation`.
          function initCodeERC1967(address implementation) internal pure returns (bytes memory c) {
              /// @solidity memory-safe-assembly
              assembly {
                  c := mload(0x40)
                  mstore(add(c, 0x60), 0x3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f300)
                  mstore(add(c, 0x40), 0x55f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc)
                  mstore(add(c, 0x20), or(shl(24, implementation), 0x600951))
                  mstore(add(c, 0x09), 0x603d3d8160223d3973)
                  mstore(c, 0x5f) // Store the length.
                  mstore(0x40, add(c, 0x80)) // Allocate memory.
              }
          }
          /// @dev Returns the initialization code hash of the minimal ERC1967 proxy of `implementation`.
          function initCodeHashERC1967(address implementation) internal pure returns (bytes32 hash) {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40) // Cache the free memory pointer.
                  mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
                  mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
                  mstore(0x20, 0x6009)
                  mstore(0x1e, implementation)
                  mstore(0x0a, 0x603d3d8160223d3973)
                  hash := keccak256(0x21, 0x5f)
                  mstore(0x40, m) // Restore the free memory pointer.
                  mstore(0x60, 0) // Restore the zero slot.
              }
          }
          /// @dev Returns the address of the ERC1967 proxy of `implementation`, with `salt` by `deployer`.
          /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
          function predictDeterministicAddressERC1967(
              address implementation,
              bytes32 salt,
              address deployer
          ) internal pure returns (address predicted) {
              bytes32 hash = initCodeHashERC1967(implementation);
              predicted = predictDeterministicAddress(hash, salt, deployer);
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*    MINIMAL ERC1967 PROXY WITH IMMUTABLE ARGS OPERATIONS    */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Deploys a minimal ERC1967 proxy with `implementation` and `args`.
          function deployERC1967(address implementation, bytes memory args)
              internal
              returns (address instance)
          {
              instance = deployERC1967(0, implementation, args);
          }
          /// @dev Deploys a minimal ERC1967 proxy with `implementation` and `args`.
          /// Deposits `value` ETH during deployment.
          function deployERC1967(uint256 value, address implementation, bytes memory args)
              internal
              returns (address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40)
                  let n := mload(args)
                  pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x60), n))
                  mstore(add(m, 0x40), 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
                  mstore(add(m, 0x20), 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
                  mstore(0x16, 0x6009)
                  mstore(0x14, implementation)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x3d = 0xffc2`.
                  mstore(gt(n, 0xffc2), add(0xfe61003d3d8160233d3973, shl(56, n)))
                  mstore(m, mload(0x16))
                  instance := create(value, m, add(n, 0x60))
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
              }
          }
          /// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation`, `args` and `salt`.
          function deployDeterministicERC1967(address implementation, bytes memory args, bytes32 salt)
              internal
              returns (address instance)
          {
              instance = deployDeterministicERC1967(0, implementation, args, salt);
          }
          /// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation`, `args` and `salt`.
          /// Deposits `value` ETH during deployment.
          function deployDeterministicERC1967(
              uint256 value,
              address implementation,
              bytes memory args,
              bytes32 salt
          ) internal returns (address instance) {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40)
                  let n := mload(args)
                  pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x60), n))
                  mstore(add(m, 0x40), 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
                  mstore(add(m, 0x20), 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
                  mstore(0x16, 0x6009)
                  mstore(0x14, implementation)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x3d = 0xffc2`.
                  mstore(gt(n, 0xffc2), add(0xfe61003d3d8160233d3973, shl(56, n)))
                  mstore(m, mload(0x16))
                  instance := create2(value, m, add(n, 0x60), salt)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
              }
          }
          /// @dev Creates a deterministic minimal ERC1967 proxy with `implementation`, `args` and `salt`.
          /// Note: This method is intended for use in ERC4337 factories,
          /// which are expected to NOT revert if the proxy is already deployed.
          function createDeterministicERC1967(address implementation, bytes memory args, bytes32 salt)
              internal
              returns (bool alreadyDeployed, address instance)
          {
              return createDeterministicERC1967(0, implementation, args, salt);
          }
          /// @dev Creates a deterministic minimal ERC1967 proxy with `implementation`, `args` and `salt`.
          /// Deposits `value` ETH during deployment.
          /// Note: This method is intended for use in ERC4337 factories,
          /// which are expected to NOT revert if the proxy is already deployed.
          function createDeterministicERC1967(
              uint256 value,
              address implementation,
              bytes memory args,
              bytes32 salt
          ) internal returns (bool alreadyDeployed, address instance) {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40)
                  let n := mload(args)
                  pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x60), n))
                  mstore(add(m, 0x40), 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
                  mstore(add(m, 0x20), 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
                  mstore(0x16, 0x6009)
                  mstore(0x14, implementation)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x3d = 0xffc2`.
                  mstore(gt(n, 0xffc2), add(0xfe61003d3d8160233d3973, shl(56, n)))
                  mstore(m, mload(0x16))
                  // Compute and store the bytecode hash.
                  mstore8(0x00, 0xff) // Write the prefix.
                  mstore(0x35, keccak256(m, add(n, 0x60)))
                  mstore(0x01, shl(96, address()))
                  mstore(0x15, salt)
                  instance := keccak256(0x00, 0x55)
                  for {} 1 {} {
                      if iszero(extcodesize(instance)) {
                          instance := create2(value, m, add(n, 0x60), salt)
                          if iszero(instance) {
                              mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                              revert(0x1c, 0x04)
                          }
                          break
                      }
                      alreadyDeployed := 1
                      if iszero(value) { break }
                      if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
                          mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                          revert(0x1c, 0x04)
                      }
                      break
                  }
                  mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.
              }
          }
          /// @dev Returns the initialization code of the minimal ERC1967 proxy of `implementation` and `args`.
          function initCodeERC1967(address implementation, bytes memory args)
              internal
              pure
              returns (bytes memory c)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  c := mload(0x40)
                  let n := mload(args)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x3d = 0xffc2`.
                  returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffc2))
                  for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
                      mstore(add(add(c, 0x80), i), mload(add(add(args, 0x20), i)))
                  }
                  mstore(add(c, 0x60), 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
                  mstore(add(c, 0x40), 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
                  mstore(add(c, 0x20), 0x6009)
                  mstore(add(c, 0x1e), implementation)
                  mstore(add(c, 0x0a), add(0x61003d3d8160233d3973, shl(56, n)))
                  mstore(c, add(n, 0x60)) // Store the length.
                  mstore(add(c, add(n, 0x80)), 0) // Zeroize the slot after the bytes.
                  mstore(0x40, add(c, add(n, 0xa0))) // Allocate memory.
              }
          }
          /// @dev Returns the initialization code hash of the minimal ERC1967 proxy of `implementation` and `args`.
          function initCodeHashERC1967(address implementation, bytes memory args)
              internal
              pure
              returns (bytes32 hash)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40)
                  let n := mload(args)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x3d = 0xffc2`.
                  returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffc2))
                  for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
                      mstore(add(add(m, 0x60), i), mload(add(add(args, 0x20), i)))
                  }
                  mstore(add(m, 0x40), 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
                  mstore(add(m, 0x20), 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
                  mstore(0x16, 0x6009)
                  mstore(0x14, implementation)
                  mstore(0x00, add(0x61003d3d8160233d3973, shl(56, n)))
                  mstore(m, mload(0x16))
                  hash := keccak256(m, add(n, 0x60))
              }
          }
          /// @dev Returns the address of the ERC1967 proxy of `implementation`, `args`, with `salt` by `deployer`.
          /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
          function predictDeterministicAddressERC1967(
              address implementation,
              bytes memory args,
              bytes32 salt,
              address deployer
          ) internal pure returns (address predicted) {
              bytes32 hash = initCodeHashERC1967(implementation, args);
              predicted = predictDeterministicAddress(hash, salt, deployer);
          }
          /// @dev Equivalent to `argsOnERC1967(instance, start, 2 ** 256 - 1)`.
          function argsOnERC1967(address instance) internal view returns (bytes memory args) {
              /// @solidity memory-safe-assembly
              assembly {
                  args := mload(0x40)
                  mstore(args, sub(extcodesize(instance), 0x3d)) // Store the length.
                  extcodecopy(instance, add(args, 0x20), 0x3d, add(mload(args), 0x20))
                  mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.
              }
          }
          /// @dev Equivalent to `argsOnERC1967(instance, start, 2 ** 256 - 1)`.
          function argsOnERC1967(address instance, uint256 start)
              internal
              view
              returns (bytes memory args)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  args := mload(0x40)
                  let n := sub(extcodesize(instance), 0x3d)
                  extcodecopy(instance, add(args, 0x20), add(start, 0x3d), add(n, 0x20))
                  mstore(args, mul(sub(n, start), lt(start, n))) // Store the length.
                  mstore(0x40, add(args, add(0x40, mload(args)))) // Allocate memory.
              }
          }
          /// @dev Returns a slice of the immutable arguments on `instance` from `start` to `end`.
          /// `start` and `end` will be clamped to the range `[0, args.length]`.
          /// The `instance` MUST be deployed via the ERC1967 with immutable args functions.
          /// Otherwise, the behavior is undefined.
          /// Out-of-gas reverts if `instance` does not have any code.
          function argsOnERC1967(address instance, uint256 start, uint256 end)
              internal
              view
              returns (bytes memory args)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  args := mload(0x40)
                  if iszero(lt(end, 0xffff)) { end := 0xffff }
                  let d := mul(sub(end, start), lt(start, end))
                  extcodecopy(instance, args, add(start, 0x1d), add(d, 0x20))
                  if iszero(and(0xff, mload(add(args, d)))) {
                      let n := sub(extcodesize(instance), 0x3d)
                      returndatacopy(returndatasize(), returndatasize(), shr(64, n))
                      d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))
                  }
                  mstore(args, d) // Store the length.
                  mstore(add(add(args, 0x20), d), 0) // Zeroize the slot after the bytes.
                  mstore(0x40, add(add(args, 0x40), d)) // Allocate memory.
              }
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                 ERC1967I PROXY OPERATIONS                  */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          // Note: This proxy has a special code path that activates if `calldatasize() == 1`.
          // This code path skips the delegatecall and directly returns the `implementation` address.
          // The returned implementation is guaranteed to be valid if the keccak256 of the
          // proxy's code is equal to `ERC1967I_CODE_HASH`.
          /// @dev Deploys a ERC1967I proxy with `implementation`.
          function deployERC1967I(address implementation) internal returns (address instance) {
              instance = deployERC1967I(0, implementation);
          }
          /// @dev Deploys a ERC1967I proxy with `implementation`.
          /// Deposits `value` ETH during deployment.
          function deployERC1967I(uint256 value, address implementation)
              internal
              returns (address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  /**
                   * ---------------------------------------------------------------------------------+
                   * CREATION (34 bytes)                                                              |
                   * ---------------------------------------------------------------------------------|
                   * Opcode     | Mnemonic       | Stack            | Memory                          |
                   * ---------------------------------------------------------------------------------|
                   * 60 runSize | PUSH1 runSize  | r                |                                 |
                   * 3d         | RETURNDATASIZE | 0 r              |                                 |
                   * 81         | DUP2           | r 0 r            |                                 |
                   * 60 offset  | PUSH1 offset   | o r 0 r          |                                 |
                   * 3d         | RETURNDATASIZE | 0 o r 0 r        |                                 |
                   * 39         | CODECOPY       | 0 r              | [0..runSize): runtime code      |
                   * 73 impl    | PUSH20 impl    | impl 0 r         | [0..runSize): runtime code      |
                   * 60 slotPos | PUSH1 slotPos  | slotPos impl 0 r | [0..runSize): runtime code      |
                   * 51         | MLOAD          | slot impl 0 r    | [0..runSize): runtime code      |
                   * 55         | SSTORE         | 0 r              | [0..runSize): runtime code      |
                   * f3         | RETURN         |                  | [0..runSize): runtime code      |
                   * ---------------------------------------------------------------------------------|
                   * RUNTIME (82 bytes)                                                               |
                   * ---------------------------------------------------------------------------------|
                   * Opcode     | Mnemonic       | Stack            | Memory                          |
                   * ---------------------------------------------------------------------------------|
                   *                                                                                  |
                   * ::: check calldatasize ::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 36         | CALLDATASIZE   | cds              |                                 |
                   * 58         | PC             | 1 cds            |                                 |
                   * 14         | EQ             | eqs              |                                 |
                   * 60 0x43    | PUSH1 0x43     | dest eqs         |                                 |
                   * 57         | JUMPI          |                  |                                 |
                   *                                                                                  |
                   * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 36         | CALLDATASIZE   | cds              |                                 |
                   * 3d         | RETURNDATASIZE | 0 cds            |                                 |
                   * 3d         | RETURNDATASIZE | 0 0 cds          |                                 |
                   * 37         | CALLDATACOPY   |                  | [0..calldatasize): calldata     |
                   *                                                                                  |
                   * ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |
                   * 3d         | RETURNDATASIZE | 0                |                                 |
                   * 3d         | RETURNDATASIZE | 0 0              |                                 |
                   * 36         | CALLDATASIZE   | cds 0 0          | [0..calldatasize): calldata     |
                   * 3d         | RETURNDATASIZE | 0 cds 0 0        | [0..calldatasize): calldata     |
                   * 7f slot    | PUSH32 slot    | s 0 cds 0 0      | [0..calldatasize): calldata     |
                   * 54         | SLOAD          | i 0 cds 0 0      | [0..calldatasize): calldata     |
                   * 5a         | GAS            | g i 0 cds 0 0    | [0..calldatasize): calldata     |
                   * f4         | DELEGATECALL   | succ             | [0..calldatasize): calldata     |
                   *                                                                                  |
                   * ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 3d         | RETURNDATASIZE | rds succ         | [0..calldatasize): calldata     |
                   * 60 0x00    | PUSH1 0x00     | 0 rds succ       | [0..calldatasize): calldata     |
                   * 80         | DUP1           | 0 0 rds succ     | [0..calldatasize): calldata     |
                   * 3e         | RETURNDATACOPY | succ             | [0..returndatasize): returndata |
                   *                                                                                  |
                   * ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |
                   * 60 0x3E    | PUSH1 0x3E     | dest succ        | [0..returndatasize): returndata |
                   * 57         | JUMPI          |                  | [0..returndatasize): returndata |
                   *                                                                                  |
                   * ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 3d         | RETURNDATASIZE | rds              | [0..returndatasize): returndata |
                   * 60 0x00    | PUSH1 0x00     | 0 rds            | [0..returndatasize): returndata |
                   * fd         | REVERT         |                  | [0..returndatasize): returndata |
                   *                                                                                  |
                   * ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |
                   * 5b         | JUMPDEST       |                  | [0..returndatasize): returndata |
                   * 3d         | RETURNDATASIZE | rds              | [0..returndatasize): returndata |
                   * 60 0x00    | PUSH1 0x00     | 0 rds            | [0..returndatasize): returndata |
                   * f3         | RETURN         |                  | [0..returndatasize): returndata |
                   *                                                                                  |
                   * ::: implementation , return :::::::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 5b         | JUMPDEST       |                  |                                 |
                   * 60 0x20    | PUSH1 0x20     | 32               |                                 |
                   * 60 0x0F    | PUSH1 0x0F     | o 32             |                                 |
                   * 3d         | RETURNDATASIZE | 0 o 32           |                                 |
                   * 39         | CODECOPY       |                  | [0..32): implementation slot    |
                   * 3d         | RETURNDATASIZE | 0                | [0..32): implementation slot    |
                   * 51         | MLOAD          | slot             | [0..32): implementation slot    |
                   * 54         | SLOAD          | impl             | [0..32): implementation slot    |
                   * 3d         | RETURNDATASIZE | 0 impl           | [0..32): implementation slot    |
                   * 52         | MSTORE         |                  | [0..32): implementation address |
                   * 59         | MSIZE          | 32               | [0..32): implementation address |
                   * 3d         | RETURNDATASIZE | 0 32             | [0..32): implementation address |
                   * f3         | RETURN         |                  | [0..32): implementation address |
                   * ---------------------------------------------------------------------------------+
                   */
                  let m := mload(0x40) // Cache the free memory pointer.
                  mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
                  mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
                  mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)
                  mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))
                  instance := create(value, 0x0c, 0x74)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
                  mstore(0x40, m) // Restore the free memory pointer.
                  mstore(0x60, 0) // Restore the zero slot.
              }
          }
          /// @dev Deploys a deterministic ERC1967I proxy with `implementation` and `salt`.
          function deployDeterministicERC1967I(address implementation, bytes32 salt)
              internal
              returns (address instance)
          {
              instance = deployDeterministicERC1967I(0, implementation, salt);
          }
          /// @dev Deploys a deterministic ERC1967I proxy with `implementation` and `salt`.
          /// Deposits `value` ETH during deployment.
          function deployDeterministicERC1967I(uint256 value, address implementation, bytes32 salt)
              internal
              returns (address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40) // Cache the free memory pointer.
                  mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
                  mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
                  mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)
                  mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))
                  instance := create2(value, 0x0c, 0x74, salt)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
                  mstore(0x40, m) // Restore the free memory pointer.
                  mstore(0x60, 0) // Restore the zero slot.
              }
          }
          /// @dev Creates a deterministic ERC1967I proxy with `implementation` and `salt`.
          /// Note: This method is intended for use in ERC4337 factories,
          /// which are expected to NOT revert if the proxy is already deployed.
          function createDeterministicERC1967I(address implementation, bytes32 salt)
              internal
              returns (bool alreadyDeployed, address instance)
          {
              return createDeterministicERC1967I(0, implementation, salt);
          }
          /// @dev Creates a deterministic ERC1967I proxy with `implementation` and `salt`.
          /// Deposits `value` ETH during deployment.
          /// Note: This method is intended for use in ERC4337 factories,
          /// which are expected to NOT revert if the proxy is already deployed.
          function createDeterministicERC1967I(uint256 value, address implementation, bytes32 salt)
              internal
              returns (bool alreadyDeployed, address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40) // Cache the free memory pointer.
                  mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
                  mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
                  mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)
                  mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))
                  // Compute and store the bytecode hash.
                  mstore(add(m, 0x35), keccak256(0x0c, 0x74))
                  mstore(m, shl(88, address()))
                  mstore8(m, 0xff) // Write the prefix.
                  mstore(add(m, 0x15), salt)
                  instance := keccak256(m, 0x55)
                  for {} 1 {} {
                      if iszero(extcodesize(instance)) {
                          instance := create2(value, 0x0c, 0x74, salt)
                          if iszero(instance) {
                              mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                              revert(0x1c, 0x04)
                          }
                          break
                      }
                      alreadyDeployed := 1
                      if iszero(value) { break }
                      if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
                          mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                          revert(0x1c, 0x04)
                      }
                      break
                  }
                  mstore(0x40, m) // Restore the free memory pointer.
                  mstore(0x60, 0) // Restore the zero slot.
              }
          }
          /// @dev Returns the initialization code of the ERC1967I proxy of `implementation`.
          function initCodeERC1967I(address implementation) internal pure returns (bytes memory c) {
              /// @solidity memory-safe-assembly
              assembly {
                  c := mload(0x40)
                  mstore(add(c, 0x74), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
                  mstore(add(c, 0x54), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
                  mstore(add(c, 0x34), 0x600f5155f3365814604357363d3d373d3d363d7f360894)
                  mstore(add(c, 0x1d), implementation)
                  mstore(add(c, 0x09), 0x60523d8160223d3973)
                  mstore(add(c, 0x94), 0)
                  mstore(c, 0x74) // Store the length.
                  mstore(0x40, add(c, 0xa0)) // Allocate memory.
              }
          }
          /// @dev Returns the initialization code hash of the ERC1967I proxy of `implementation`.
          function initCodeHashERC1967I(address implementation) internal pure returns (bytes32 hash) {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40) // Cache the free memory pointer.
                  mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
                  mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
                  mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)
                  mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))
                  hash := keccak256(0x0c, 0x74)
                  mstore(0x40, m) // Restore the free memory pointer.
                  mstore(0x60, 0) // Restore the zero slot.
              }
          }
          /// @dev Returns the address of the ERC1967I proxy of `implementation`, with `salt` by `deployer`.
          /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
          function predictDeterministicAddressERC1967I(
              address implementation,
              bytes32 salt,
              address deployer
          ) internal pure returns (address predicted) {
              bytes32 hash = initCodeHashERC1967I(implementation);
              predicted = predictDeterministicAddress(hash, salt, deployer);
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*       ERC1967I PROXY WITH IMMUTABLE ARGS OPERATIONS        */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Deploys a minimal ERC1967I proxy with `implementation` and `args`.
          function deployERC1967I(address implementation, bytes memory args) internal returns (address) {
              return deployERC1967I(0, implementation, args);
          }
          /// @dev Deploys a minimal ERC1967I proxy with `implementation` and `args`.
          /// Deposits `value` ETH during deployment.
          function deployERC1967I(uint256 value, address implementation, bytes memory args)
              internal
              returns (address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40)
                  let n := mload(args)
                  pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x8b), n))
                  mstore(add(m, 0x6b), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
                  mstore(add(m, 0x4b), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
                  mstore(add(m, 0x2b), 0x600f5155f3365814604357363d3d373d3d363d7f360894)
                  mstore(add(m, 0x14), implementation)
                  mstore(m, add(0xfe6100523d8160233d3973, shl(56, n)))
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
                  instance := create(value, add(m, add(0x15, lt(n, 0xffae))), add(0x75, n))
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
              }
          }
          /// @dev Deploys a deterministic ERC1967I proxy with `implementation`, `args`, and `salt`.
          function deployDeterministicERC1967I(address implementation, bytes memory args, bytes32 salt)
              internal
              returns (address instance)
          {
              instance = deployDeterministicERC1967I(0, implementation, args, salt);
          }
          /// @dev Deploys a deterministic ERC1967I proxy with `implementation`,`args`,  and `salt`.
          /// Deposits `value` ETH during deployment.
          function deployDeterministicERC1967I(
              uint256 value,
              address implementation,
              bytes memory args,
              bytes32 salt
          ) internal returns (address instance) {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40)
                  let n := mload(args)
                  pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x8b), n))
                  mstore(add(m, 0x6b), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
                  mstore(add(m, 0x4b), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
                  mstore(add(m, 0x2b), 0x600f5155f3365814604357363d3d373d3d363d7f360894)
                  mstore(add(m, 0x14), implementation)
                  mstore(m, add(0xfe6100523d8160233d3973, shl(56, n)))
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
                  instance := create2(value, add(m, add(0x15, lt(n, 0xffae))), add(0x75, n), salt)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
              }
          }
          /// @dev Creates a deterministic ERC1967I proxy with `implementation`, `args` and `salt`.
          /// Note: This method is intended for use in ERC4337 factories,
          /// which are expected to NOT revert if the proxy is already deployed.
          function createDeterministicERC1967I(address implementation, bytes memory args, bytes32 salt)
              internal
              returns (bool alreadyDeployed, address instance)
          {
              return createDeterministicERC1967I(0, implementation, args, salt);
          }
          /// @dev Creates a deterministic ERC1967I proxy with `implementation`,`args` and `salt`.
          /// Deposits `value` ETH during deployment.
          /// Note: This method is intended for use in ERC4337 factories,
          /// which are expected to NOT revert if the proxy is already deployed.
          function createDeterministicERC1967I(
              uint256 value,
              address implementation,
              bytes memory args,
              bytes32 salt
          ) internal returns (bool alreadyDeployed, address instance) {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40)
                  let n := mload(args)
                  pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x75), n))
                  mstore(add(m, 0x55), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
                  mstore(add(m, 0x35), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
                  mstore(add(m, 0x15), 0x5155f3365814604357363d3d373d3d363d7f360894)
                  mstore(0x16, 0x600f)
                  mstore(0x14, implementation)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
                  mstore(gt(n, 0xffad), add(0xfe6100523d8160233d3973, shl(56, n)))
                  mstore(m, mload(0x16))
                  // Compute and store the bytecode hash.
                  mstore8(0x00, 0xff) // Write the prefix.
                  mstore(0x35, keccak256(m, add(n, 0x75)))
                  mstore(0x01, shl(96, address()))
                  mstore(0x15, salt)
                  instance := keccak256(0x00, 0x55)
                  for {} 1 {} {
                      if iszero(extcodesize(instance)) {
                          instance := create2(value, m, add(0x75, n), salt)
                          if iszero(instance) {
                              mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                              revert(0x1c, 0x04)
                          }
                          break
                      }
                      alreadyDeployed := 1
                      if iszero(value) { break }
                      if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
                          mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                          revert(0x1c, 0x04)
                      }
                      break
                  }
                  mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.
              }
          }
          /// @dev Returns the initialization code of the ERC1967I proxy of `implementation`and `args`.
          function initCodeERC1967I(address implementation, bytes memory args)
              internal
              pure
              returns (bytes memory c)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  c := mload(0x40)
                  let n := mload(args)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
                  returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffad))
                  for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
                      mstore(add(add(c, 0x95), i), mload(add(add(args, 0x20), i)))
                  }
                  mstore(add(c, 0x75), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
                  mstore(add(c, 0x55), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
                  mstore(add(c, 0x35), 0x600f5155f3365814604357363d3d373d3d363d7f360894)
                  mstore(add(c, 0x1e), implementation)
                  mstore(add(c, 0x0a), add(0x6100523d8160233d3973, shl(56, n)))
                  mstore(add(c, add(n, 0x95)), 0)
                  mstore(c, add(0x75, n)) // Store the length.
                  mstore(0x40, add(c, add(n, 0xb5))) // Allocate memory.
              }
          }
          /// @dev Returns the initialization code hash of the ERC1967I proxy of `implementation` and `args.
          function initCodeHashERC1967I(address implementation, bytes memory args)
              internal
              pure
              returns (bytes32 hash)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40) // Cache the free memory pointer.
                  let n := mload(args)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
                  returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffad))
                  for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
                      mstore(add(add(m, 0x75), i), mload(add(add(args, 0x20), i)))
                  }
                  mstore(add(m, 0x55), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
                  mstore(add(m, 0x35), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
                  mstore(add(m, 0x15), 0x5155f3365814604357363d3d373d3d363d7f360894)
                  mstore(0x16, 0x600f)
                  mstore(0x14, implementation)
                  mstore(0x00, add(0x6100523d8160233d3973, shl(56, n)))
                  mstore(m, mload(0x16))
                  hash := keccak256(m, add(0x75, n))
              }
          }
          /// @dev Returns the address of the ERC1967I proxy of `implementation`, 'args` with `salt` by `deployer`.
          /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
          function predictDeterministicAddressERC1967I(
              address implementation,
              bytes memory args,
              bytes32 salt,
              address deployer
          ) internal pure returns (address predicted) {
              bytes32 hash = initCodeHashERC1967I(implementation, args);
              predicted = predictDeterministicAddress(hash, salt, deployer);
          }
          /// @dev Equivalent to `argsOnERC1967I(instance, start, 2 ** 256 - 1)`.
          function argsOnERC1967I(address instance) internal view returns (bytes memory args) {
              /// @solidity memory-safe-assembly
              assembly {
                  args := mload(0x40)
                  mstore(args, sub(extcodesize(instance), 0x52)) // Store the length.
                  extcodecopy(instance, add(args, 0x20), 0x52, add(mload(args), 0x20))
                  mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.
              }
          }
          /// @dev Equivalent to `argsOnERC1967I(instance, start, 2 ** 256 - 1)`.
          function argsOnERC1967I(address instance, uint256 start)
              internal
              view
              returns (bytes memory args)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  args := mload(0x40)
                  let n := sub(extcodesize(instance), 0x52)
                  extcodecopy(instance, add(args, 0x20), add(start, 0x52), add(n, 0x20))
                  mstore(args, mul(sub(n, start), lt(start, n))) // Store the length.
                  mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.
              }
          }
          /// @dev Returns a slice of the immutable arguments on `instance` from `start` to `end`.
          /// `start` and `end` will be clamped to the range `[0, args.length]`.
          /// The `instance` MUST be deployed via the ERC1967 with immutable args functions.
          /// Otherwise, the behavior is undefined.
          /// Out-of-gas reverts if `instance` does not have any code.
          function argsOnERC1967I(address instance, uint256 start, uint256 end)
              internal
              view
              returns (bytes memory args)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  args := mload(0x40)
                  if iszero(lt(end, 0xffff)) { end := 0xffff }
                  let d := mul(sub(end, start), lt(start, end))
                  extcodecopy(instance, args, add(start, 0x32), add(d, 0x20))
                  if iszero(and(0xff, mload(add(args, d)))) {
                      let n := sub(extcodesize(instance), 0x52)
                      returndatacopy(returndatasize(), returndatasize(), shr(64, n))
                      d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))
                  }
                  mstore(args, d) // Store the length.
                  mstore(add(add(args, 0x20), d), 0) // Zeroize the slot after the bytes.
                  mstore(0x40, add(add(args, 0x40), d)) // Allocate memory.
              }
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*            CONSTANT ERC1967 BOOTSTRAP OPERATIONS           */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          // Note: This enables an ERC1967 proxy to be deployed at a deterministic address
          // independent of the implementation:
          // ```
          //     address bootstrap = LibClone.constantERC1967Bootstrap();
          //     address instance = LibClone.deployDeterministicERC1967(0, bootstrap, salt);
          //     LibClone.bootstrapConstantERC1967(bootstrap, implementation);
          // ```
          /// @dev Deploys the constant ERC1967 bootstrap if it has not been deployed.
          function constantERC1967Bootstrap() internal returns (address bootstrap) {
              bootstrap = constantERC1967BootstrapAddress();
              /// @solidity memory-safe-assembly
              assembly {
                  if iszero(extcodesize(bootstrap)) {
                      mstore(0x20, 0x0894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55)
                      mstore(0x00, 0x60258060093d393df358357f36)
                      if iszero(create2(0, 0x13, 0x2e, 0)) {
                          mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                          revert(0x1c, 0x04)
                      }
                  }
              }
          }
          /// @dev Returns the implementation address of the ERC1967 bootstrap for this contract.
          function constantERC1967BootstrapAddress() internal view returns (address bootstrap) {
              bytes32 hash = 0xfe1a42b9c571a6a8c083c94ac67b9cfd74e2582923426aa3b762e3431d717cd1;
              bootstrap = predictDeterministicAddress(hash, bytes32(0), address(this));
          }
          /// @dev Replaces the implementation at `instance`.
          function bootstrapERC1967(address instance, address implementation) internal {
              /// @solidity memory-safe-assembly
              assembly {
                  mstore(0x00, shr(96, shl(96, implementation)))
                  if iszero(call(gas(), instance, 0, 0x00, 0x20, codesize(), 0x00)) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
              }
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*          MINIMAL ERC1967 BEACON PROXY OPERATIONS           */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          // Note: If you use this proxy, you MUST make sure that the beacon is a
          // valid ERC1967 beacon. This means that the beacon must always return a valid
          // address upon a staticcall to `implementation()`, given sufficient gas.
          // For performance, the deployment operations and the proxy assumes that the
          // beacon is always valid and will NOT validate it.
          /// @dev Deploys a minimal ERC1967 beacon proxy.
          function deployERC1967BeaconProxy(address beacon) internal returns (address instance) {
              instance = deployERC1967BeaconProxy(0, beacon);
          }
          /// @dev Deploys a minimal ERC1967 beacon proxy.
          /// Deposits `value` ETH during deployment.
          function deployERC1967BeaconProxy(uint256 value, address beacon)
              internal
              returns (address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  /**
                   * ---------------------------------------------------------------------------------+
                   * CREATION (34 bytes)                                                              |
                   * ---------------------------------------------------------------------------------|
                   * Opcode     | Mnemonic       | Stack            | Memory                          |
                   * ---------------------------------------------------------------------------------|
                   * 60 runSize | PUSH1 runSize  | r                |                                 |
                   * 3d         | RETURNDATASIZE | 0 r              |                                 |
                   * 81         | DUP2           | r 0 r            |                                 |
                   * 60 offset  | PUSH1 offset   | o r 0 r          |                                 |
                   * 3d         | RETURNDATASIZE | 0 o r 0 r        |                                 |
                   * 39         | CODECOPY       | 0 r              | [0..runSize): runtime code      |
                   * 73 beac    | PUSH20 beac    | beac 0 r         | [0..runSize): runtime code      |
                   * 60 slotPos | PUSH1 slotPos  | slotPos beac 0 r | [0..runSize): runtime code      |
                   * 51         | MLOAD          | slot beac 0 r    | [0..runSize): runtime code      |
                   * 55         | SSTORE         | 0 r              | [0..runSize): runtime code      |
                   * f3         | RETURN         |                  | [0..runSize): runtime code      |
                   * ---------------------------------------------------------------------------------|
                   * RUNTIME (82 bytes)                                                               |
                   * ---------------------------------------------------------------------------------|
                   * Opcode     | Mnemonic       | Stack            | Memory                          |
                   * ---------------------------------------------------------------------------------|
                   *                                                                                  |
                   * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 36         | CALLDATASIZE   | cds              |                                 |
                   * 3d         | RETURNDATASIZE | 0 cds            |                                 |
                   * 3d         | RETURNDATASIZE | 0 0 cds          |                                 |
                   * 37         | CALLDATACOPY   |                  | [0..calldatasize): calldata     |
                   *                                                                                  |
                   * ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |
                   * 3d         | RETURNDATASIZE | 0                |                                 |
                   * 3d         | RETURNDATASIZE | 0 0              |                                 |
                   * 36         | CALLDATASIZE   | cds 0 0          | [0..calldatasize): calldata     |
                   * 3d         | RETURNDATASIZE | 0 cds 0 0        | [0..calldatasize): calldata     |
                   *                                                                                  |
                   * ~~~~~~~ beacon staticcall sub procedure ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
                   * 60 0x20       | PUSH1 0x20       | 32                          |                 |
                   * 36            | CALLDATASIZE     | cds 32                      |                 |
                   * 60 0x04       | PUSH1 0x04       | 4 cds 32                    |                 |
                   * 36            | CALLDATASIZE     | cds 4 cds 32                |                 |
                   * 63 0x5c60da1b | PUSH4 0x5c60da1b | 0x5c60da1b cds 4 cds 32     |                 |
                   * 60 0xe0       | PUSH1 0xe0       | 224 0x5c60da1b cds 4 cds 32 |                 |
                   * 1b            | SHL              | sel cds 4 cds 32            |                 |
                   * 36            | CALLDATASIZE     | cds sel cds 4 cds 32        |                 |
                   * 52            | MSTORE           | cds 4 cds 32                | sel             |
                   * 7f slot       | PUSH32 slot      | s cds 4 cds 32              | sel             |
                   * 54            | SLOAD            | beac cds 4 cds 32           | sel             |
                   * 5a            | GAS              | g beac cds 4 cds 32         | sel             |
                   * fa            | STATICCALL       | succ                        | impl            |
                   * 50            | POP              |                             | impl            |
                   * 36            | CALLDATASIZE     | cds                         | impl            |
                   * 51            | MLOAD            | impl                        | impl            |
                   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
                   * 5a         | GAS            | g impl 0 cds 0 0 | [0..calldatasize): calldata     |
                   * f4         | DELEGATECALL   | succ             | [0..calldatasize): calldata     |
                   *                                                                                  |
                   * ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 3d         | RETURNDATASIZE | rds succ         | [0..calldatasize): calldata     |
                   * 60 0x00    | PUSH1 0x00     | 0 rds succ       | [0..calldatasize): calldata     |
                   * 80         | DUP1           | 0 0 rds succ     | [0..calldatasize): calldata     |
                   * 3e         | RETURNDATACOPY | succ             | [0..returndatasize): returndata |
                   *                                                                                  |
                   * ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |
                   * 60 0x4d    | PUSH1 0x4d     | dest succ        | [0..returndatasize): returndata |
                   * 57         | JUMPI          |                  | [0..returndatasize): returndata |
                   *                                                                                  |
                   * ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 3d         | RETURNDATASIZE | rds              | [0..returndatasize): returndata |
                   * 60 0x00    | PUSH1 0x00     | 0 rds            | [0..returndatasize): returndata |
                   * fd         | REVERT         |                  | [0..returndatasize): returndata |
                   *                                                                                  |
                   * ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |
                   * 5b         | JUMPDEST       |                  | [0..returndatasize): returndata |
                   * 3d         | RETURNDATASIZE | rds              | [0..returndatasize): returndata |
                   * 60 0x00    | PUSH1 0x00     | 0 rds            | [0..returndatasize): returndata |
                   * f3         | RETURN         |                  | [0..returndatasize): returndata |
                   * ---------------------------------------------------------------------------------+
                   */
                  let m := mload(0x40) // Cache the free memory pointer.
                  mstore(0x60, 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
                  mstore(0x40, 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
                  mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da)
                  mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, beacon))))
                  instance := create(value, 0x0c, 0x74)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
                  mstore(0x40, m) // Restore the free memory pointer.
                  mstore(0x60, 0) // Restore the zero slot.
              }
          }
          /// @dev Deploys a deterministic minimal ERC1967 beacon proxy with `salt`.
          function deployDeterministicERC1967BeaconProxy(address beacon, bytes32 salt)
              internal
              returns (address instance)
          {
              instance = deployDeterministicERC1967BeaconProxy(0, beacon, salt);
          }
          /// @dev Deploys a deterministic minimal ERC1967 beacon proxy with `salt`.
          /// Deposits `value` ETH during deployment.
          function deployDeterministicERC1967BeaconProxy(uint256 value, address beacon, bytes32 salt)
              internal
              returns (address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40) // Cache the free memory pointer.
                  mstore(0x60, 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
                  mstore(0x40, 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
                  mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da)
                  mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, beacon))))
                  instance := create2(value, 0x0c, 0x74, salt)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
                  mstore(0x40, m) // Restore the free memory pointer.
                  mstore(0x60, 0) // Restore the zero slot.
              }
          }
          /// @dev Creates a deterministic minimal ERC1967 beacon proxy with `salt`.
          /// Note: This method is intended for use in ERC4337 factories,
          /// which are expected to NOT revert if the proxy is already deployed.
          function createDeterministicERC1967BeaconProxy(address beacon, bytes32 salt)
              internal
              returns (bool alreadyDeployed, address instance)
          {
              return createDeterministicERC1967BeaconProxy(0, beacon, salt);
          }
          /// @dev Creates a deterministic minimal ERC1967 beacon proxy with `salt`.
          /// Deposits `value` ETH during deployment.
          /// Note: This method is intended for use in ERC4337 factories,
          /// which are expected to NOT revert if the proxy is already deployed.
          function createDeterministicERC1967BeaconProxy(uint256 value, address beacon, bytes32 salt)
              internal
              returns (bool alreadyDeployed, address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40) // Cache the free memory pointer.
                  mstore(0x60, 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
                  mstore(0x40, 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
                  mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da)
                  mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, beacon))))
                  // Compute and store the bytecode hash.
                  mstore(add(m, 0x35), keccak256(0x0c, 0x74))
                  mstore(m, shl(88, address()))
                  mstore8(m, 0xff) // Write the prefix.
                  mstore(add(m, 0x15), salt)
                  instance := keccak256(m, 0x55)
                  for {} 1 {} {
                      if iszero(extcodesize(instance)) {
                          instance := create2(value, 0x0c, 0x74, salt)
                          if iszero(instance) {
                              mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                              revert(0x1c, 0x04)
                          }
                          break
                      }
                      alreadyDeployed := 1
                      if iszero(value) { break }
                      if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
                          mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                          revert(0x1c, 0x04)
                      }
                      break
                  }
                  mstore(0x40, m) // Restore the free memory pointer.
                  mstore(0x60, 0) // Restore the zero slot.
              }
          }
          /// @dev Returns the initialization code of the minimal ERC1967 beacon proxy.
          function initCodeERC1967BeaconProxy(address beacon) internal pure returns (bytes memory c) {
              /// @solidity memory-safe-assembly
              assembly {
                  c := mload(0x40)
                  mstore(add(c, 0x74), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
                  mstore(add(c, 0x54), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
                  mstore(add(c, 0x34), 0x60195155f3363d3d373d3d363d602036600436635c60da)
                  mstore(add(c, 0x1d), beacon)
                  mstore(add(c, 0x09), 0x60523d8160223d3973)
                  mstore(add(c, 0x94), 0)
                  mstore(c, 0x74) // Store the length.
                  mstore(0x40, add(c, 0xa0)) // Allocate memory.
              }
          }
          /// @dev Returns the initialization code hash of the minimal ERC1967 beacon proxy.
          function initCodeHashERC1967BeaconProxy(address beacon) internal pure returns (bytes32 hash) {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40) // Cache the free memory pointer.
                  mstore(0x60, 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
                  mstore(0x40, 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
                  mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da)
                  mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, beacon))))
                  hash := keccak256(0x0c, 0x74)
                  mstore(0x40, m) // Restore the free memory pointer.
                  mstore(0x60, 0) // Restore the zero slot.
              }
          }
          /// @dev Returns the address of the ERC1967 beacon proxy, with `salt` by `deployer`.
          /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
          function predictDeterministicAddressERC1967BeaconProxy(
              address beacon,
              bytes32 salt,
              address deployer
          ) internal pure returns (address predicted) {
              bytes32 hash = initCodeHashERC1967BeaconProxy(beacon);
              predicted = predictDeterministicAddress(hash, salt, deployer);
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*    ERC1967 BEACON PROXY WITH IMMUTABLE ARGS OPERATIONS     */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Deploys a minimal ERC1967 beacon proxy with `args`.
          function deployERC1967BeaconProxy(address beacon, bytes memory args)
              internal
              returns (address instance)
          {
              instance = deployERC1967BeaconProxy(0, beacon, args);
          }
          /// @dev Deploys a minimal ERC1967 beacon proxy with `args`.
          /// Deposits `value` ETH during deployment.
          function deployERC1967BeaconProxy(uint256 value, address beacon, bytes memory args)
              internal
              returns (address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40)
                  let n := mload(args)
                  pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x8b), n))
                  mstore(add(m, 0x6b), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
                  mstore(add(m, 0x4b), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
                  mstore(add(m, 0x2b), 0x60195155f3363d3d373d3d363d602036600436635c60da)
                  mstore(add(m, 0x14), beacon)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
                  mstore(add(m, gt(n, 0xffad)), add(0xfe6100523d8160233d3973, shl(56, n)))
                  instance := create(value, add(m, 0x16), add(n, 0x75))
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
              }
          }
          /// @dev Deploys a deterministic minimal ERC1967 beacon proxy with `args` and `salt`.
          function deployDeterministicERC1967BeaconProxy(address beacon, bytes memory args, bytes32 salt)
              internal
              returns (address instance)
          {
              instance = deployDeterministicERC1967BeaconProxy(0, beacon, args, salt);
          }
          /// @dev Deploys a deterministic minimal ERC1967 beacon proxy with `args` and `salt`.
          /// Deposits `value` ETH during deployment.
          function deployDeterministicERC1967BeaconProxy(
              uint256 value,
              address beacon,
              bytes memory args,
              bytes32 salt
          ) internal returns (address instance) {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40)
                  let n := mload(args)
                  pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x8b), n))
                  mstore(add(m, 0x6b), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
                  mstore(add(m, 0x4b), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
                  mstore(add(m, 0x2b), 0x60195155f3363d3d373d3d363d602036600436635c60da)
                  mstore(add(m, 0x14), beacon)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
                  mstore(add(m, gt(n, 0xffad)), add(0xfe6100523d8160233d3973, shl(56, n)))
                  instance := create2(value, add(m, 0x16), add(n, 0x75), salt)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
              }
          }
          /// @dev Creates a deterministic minimal ERC1967 beacon proxy with `args` and `salt`.
          /// Note: This method is intended for use in ERC4337 factories,
          /// which are expected to NOT revert if the proxy is already deployed.
          function createDeterministicERC1967BeaconProxy(address beacon, bytes memory args, bytes32 salt)
              internal
              returns (bool alreadyDeployed, address instance)
          {
              return createDeterministicERC1967BeaconProxy(0, beacon, args, salt);
          }
          /// @dev Creates a deterministic minimal ERC1967 beacon proxy with `args` and `salt`.
          /// Deposits `value` ETH during deployment.
          /// Note: This method is intended for use in ERC4337 factories,
          /// which are expected to NOT revert if the proxy is already deployed.
          function createDeterministicERC1967BeaconProxy(
              uint256 value,
              address beacon,
              bytes memory args,
              bytes32 salt
          ) internal returns (bool alreadyDeployed, address instance) {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40)
                  let n := mload(args)
                  pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x8b), n))
                  mstore(add(m, 0x6b), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
                  mstore(add(m, 0x4b), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
                  mstore(add(m, 0x2b), 0x60195155f3363d3d373d3d363d602036600436635c60da)
                  mstore(add(m, 0x14), beacon)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
                  mstore(add(m, gt(n, 0xffad)), add(0xfe6100523d8160233d3973, shl(56, n)))
                  // Compute and store the bytecode hash.
                  mstore8(0x00, 0xff) // Write the prefix.
                  mstore(0x35, keccak256(add(m, 0x16), add(n, 0x75)))
                  mstore(0x01, shl(96, address()))
                  mstore(0x15, salt)
                  instance := keccak256(0x00, 0x55)
                  for {} 1 {} {
                      if iszero(extcodesize(instance)) {
                          instance := create2(value, add(m, 0x16), add(n, 0x75), salt)
                          if iszero(instance) {
                              mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                              revert(0x1c, 0x04)
                          }
                          break
                      }
                      alreadyDeployed := 1
                      if iszero(value) { break }
                      if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
                          mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                          revert(0x1c, 0x04)
                      }
                      break
                  }
                  mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.
              }
          }
          /// @dev Returns the initialization code of the minimal ERC1967 beacon proxy.
          function initCodeERC1967BeaconProxy(address beacon, bytes memory args)
              internal
              pure
              returns (bytes memory c)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  c := mload(0x40)
                  let n := mload(args)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
                  returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffad))
                  for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
                      mstore(add(add(c, 0x95), i), mload(add(add(args, 0x20), i)))
                  }
                  mstore(add(c, 0x75), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
                  mstore(add(c, 0x55), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
                  mstore(add(c, 0x35), 0x60195155f3363d3d373d3d363d602036600436635c60da)
                  mstore(add(c, 0x1e), beacon)
                  mstore(add(c, 0x0a), add(0x6100523d8160233d3973, shl(56, n)))
                  mstore(c, add(n, 0x75)) // Store the length.
                  mstore(add(c, add(n, 0x95)), 0) // Zeroize the slot after the bytes.
                  mstore(0x40, add(c, add(n, 0xb5))) // Allocate memory.
              }
          }
          /// @dev Returns the initialization code hash of the minimal ERC1967 beacon proxy with `args`.
          function initCodeHashERC1967BeaconProxy(address beacon, bytes memory args)
              internal
              pure
              returns (bytes32 hash)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40)
                  let n := mload(args)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
                  returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffad))
                  for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
                      mstore(add(add(m, 0x8b), i), mload(add(add(args, 0x20), i)))
                  }
                  mstore(add(m, 0x6b), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
                  mstore(add(m, 0x4b), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
                  mstore(add(m, 0x2b), 0x60195155f3363d3d373d3d363d602036600436635c60da)
                  mstore(add(m, 0x14), beacon)
                  mstore(m, add(0x6100523d8160233d3973, shl(56, n)))
                  hash := keccak256(add(m, 0x16), add(n, 0x75))
              }
          }
          /// @dev Returns the address of the ERC1967 beacon proxy with `args`, with `salt` by `deployer`.
          /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
          function predictDeterministicAddressERC1967BeaconProxy(
              address beacon,
              bytes memory args,
              bytes32 salt,
              address deployer
          ) internal pure returns (address predicted) {
              bytes32 hash = initCodeHashERC1967BeaconProxy(beacon, args);
              predicted = predictDeterministicAddress(hash, salt, deployer);
          }
          /// @dev Equivalent to `argsOnERC1967BeaconProxy(instance, start, 2 ** 256 - 1)`.
          function argsOnERC1967BeaconProxy(address instance) internal view returns (bytes memory args) {
              /// @solidity memory-safe-assembly
              assembly {
                  args := mload(0x40)
                  mstore(args, sub(extcodesize(instance), 0x52)) // Store the length.
                  extcodecopy(instance, add(args, 0x20), 0x52, add(mload(args), 0x20))
                  mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.
              }
          }
          /// @dev Equivalent to `argsOnERC1967BeaconProxy(instance, start, 2 ** 256 - 1)`.
          function argsOnERC1967BeaconProxy(address instance, uint256 start)
              internal
              view
              returns (bytes memory args)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  args := mload(0x40)
                  let n := sub(extcodesize(instance), 0x52)
                  extcodecopy(instance, add(args, 0x20), add(start, 0x52), add(n, 0x20))
                  mstore(args, mul(sub(n, start), lt(start, n))) // Store the length.
                  mstore(0x40, add(args, add(0x40, mload(args)))) // Allocate memory.
              }
          }
          /// @dev Returns a slice of the immutable arguments on `instance` from `start` to `end`.
          /// `start` and `end` will be clamped to the range `[0, args.length]`.
          /// The `instance` MUST be deployed via the ERC1967 beacon proxy with immutable args functions.
          /// Otherwise, the behavior is undefined.
          /// Out-of-gas reverts if `instance` does not have any code.
          function argsOnERC1967BeaconProxy(address instance, uint256 start, uint256 end)
              internal
              view
              returns (bytes memory args)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  args := mload(0x40)
                  if iszero(lt(end, 0xffff)) { end := 0xffff }
                  let d := mul(sub(end, start), lt(start, end))
                  extcodecopy(instance, args, add(start, 0x32), add(d, 0x20))
                  if iszero(and(0xff, mload(add(args, d)))) {
                      let n := sub(extcodesize(instance), 0x52)
                      returndatacopy(returndatasize(), returndatasize(), shr(64, n))
                      d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))
                  }
                  mstore(args, d) // Store the length.
                  mstore(add(add(args, 0x20), d), 0) // Zeroize the slot after the bytes.
                  mstore(0x40, add(add(args, 0x40), d)) // Allocate memory.
              }
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*              ERC1967I BEACON PROXY OPERATIONS              */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          // Note: This proxy has a special code path that activates if `calldatasize() == 1`.
          // This code path skips the delegatecall and directly returns the `implementation` address.
          // The returned implementation is guaranteed to be valid if the keccak256 of the
          // proxy's code is equal to `ERC1967_BEACON_PROXY_CODE_HASH`.
          //
          // If you use this proxy, you MUST make sure that the beacon is a
          // valid ERC1967 beacon. This means that the beacon must always return a valid
          // address upon a staticcall to `implementation()`, given sufficient gas.
          // For performance, the deployment operations and the proxy assumes that the
          // beacon is always valid and will NOT validate it.
          /// @dev Deploys a ERC1967I beacon proxy.
          function deployERC1967IBeaconProxy(address beacon) internal returns (address instance) {
              instance = deployERC1967IBeaconProxy(0, beacon);
          }
          /// @dev Deploys a ERC1967I beacon proxy.
          /// Deposits `value` ETH during deployment.
          function deployERC1967IBeaconProxy(uint256 value, address beacon)
              internal
              returns (address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  /**
                   * ---------------------------------------------------------------------------------+
                   * CREATION (34 bytes)                                                              |
                   * ---------------------------------------------------------------------------------|
                   * Opcode     | Mnemonic       | Stack            | Memory                          |
                   * ---------------------------------------------------------------------------------|
                   * 60 runSize | PUSH1 runSize  | r                |                                 |
                   * 3d         | RETURNDATASIZE | 0 r              |                                 |
                   * 81         | DUP2           | r 0 r            |                                 |
                   * 60 offset  | PUSH1 offset   | o r 0 r          |                                 |
                   * 3d         | RETURNDATASIZE | 0 o r 0 r        |                                 |
                   * 39         | CODECOPY       | 0 r              | [0..runSize): runtime code      |
                   * 73 beac    | PUSH20 beac    | beac 0 r         | [0..runSize): runtime code      |
                   * 60 slotPos | PUSH1 slotPos  | slotPos beac 0 r | [0..runSize): runtime code      |
                   * 51         | MLOAD          | slot beac 0 r    | [0..runSize): runtime code      |
                   * 55         | SSTORE         | 0 r              | [0..runSize): runtime code      |
                   * f3         | RETURN         |                  | [0..runSize): runtime code      |
                   * ---------------------------------------------------------------------------------|
                   * RUNTIME (87 bytes)                                                               |
                   * ---------------------------------------------------------------------------------|
                   * Opcode     | Mnemonic       | Stack            | Memory                          |
                   * ---------------------------------------------------------------------------------|
                   *                                                                                  |
                   * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 36         | CALLDATASIZE   | cds              |                                 |
                   * 3d         | RETURNDATASIZE | 0 cds            |                                 |
                   * 3d         | RETURNDATASIZE | 0 0 cds          |                                 |
                   * 37         | CALLDATACOPY   |                  | [0..calldatasize): calldata     |
                   *                                                                                  |
                   * ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |
                   * 3d         | RETURNDATASIZE | 0                |                                 |
                   * 3d         | RETURNDATASIZE | 0 0              |                                 |
                   * 36         | CALLDATASIZE   | cds 0 0          | [0..calldatasize): calldata     |
                   * 3d         | RETURNDATASIZE | 0 cds 0 0        | [0..calldatasize): calldata     |
                   *                                                                                  |
                   * ~~~~~~~ beacon staticcall sub procedure ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
                   * 60 0x20       | PUSH1 0x20       | 32                          |                 |
                   * 36            | CALLDATASIZE     | cds 32                      |                 |
                   * 60 0x04       | PUSH1 0x04       | 4 cds 32                    |                 |
                   * 36            | CALLDATASIZE     | cds 4 cds 32                |                 |
                   * 63 0x5c60da1b | PUSH4 0x5c60da1b | 0x5c60da1b cds 4 cds 32     |                 |
                   * 60 0xe0       | PUSH1 0xe0       | 224 0x5c60da1b cds 4 cds 32 |                 |
                   * 1b            | SHL              | sel cds 4 cds 32            |                 |
                   * 36            | CALLDATASIZE     | cds sel cds 4 cds 32        |                 |
                   * 52            | MSTORE           | cds 4 cds 32                | sel             |
                   * 7f slot       | PUSH32 slot      | s cds 4 cds 32              | sel             |
                   * 54            | SLOAD            | beac cds 4 cds 32           | sel             |
                   * 5a            | GAS              | g beac cds 4 cds 32         | sel             |
                   * fa            | STATICCALL       | succ                        | impl            |
                   * ~~~~~~ check calldatasize ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
                   * 36            | CALLDATASIZE     | cds succ                    |                 |
                   * 14            | EQ               |                             | impl            |
                   * 60 0x52       | PUSH1 0x52       |                             | impl            |
                   * 57            | JUMPI            |                             | impl            |
                   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
                   * 36            | CALLDATASIZE     | cds                         | impl            |
                   * 51            | MLOAD            | impl                        | impl            |
                   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
                   * 5a         | GAS            | g impl 0 cds 0 0 | [0..calldatasize): calldata     |
                   * f4         | DELEGATECALL   | succ             | [0..calldatasize): calldata     |
                   *                                                                                  |
                   * ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 3d         | RETURNDATASIZE | rds succ         | [0..calldatasize): calldata     |
                   * 60 0x00    | PUSH1 0x00     | 0 rds succ       | [0..calldatasize): calldata     |
                   * 60 0x01    | PUSH1 0x01     | 1 0 rds succ     | [0..calldatasize): calldata     |
                   * 3e         | RETURNDATACOPY | succ             | [1..returndatasize): returndata |
                   *                                                                                  |
                   * ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |
                   * 60 0x52    | PUSH1 0x52     | dest succ        | [1..returndatasize): returndata |
                   * 57         | JUMPI          |                  | [1..returndatasize): returndata |
                   *                                                                                  |
                   * ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |
                   * 3d         | RETURNDATASIZE | rds              | [1..returndatasize): returndata |
                   * 60 0x01    | PUSH1 0x01     | 1 rds            | [1..returndatasize): returndata |
                   * fd         | REVERT         |                  | [1..returndatasize): returndata |
                   *                                                                                  |
                   * ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |
                   * 5b         | JUMPDEST       |                  | [1..returndatasize): returndata |
                   * 3d         | RETURNDATASIZE | rds              | [1..returndatasize): returndata |
                   * 60 0x01    | PUSH1 0x01     | 1 rds            | [1..returndatasize): returndata |
                   * f3         | RETURN         |                  | [1..returndatasize): returndata |
                   * ---------------------------------------------------------------------------------+
                   */
                  let m := mload(0x40) // Cache the free memory pointer.
                  mstore(0x60, 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
                  mstore(0x40, 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
                  mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
                  mstore(0x04, or(shl(160, 0x60573d8160223d3973), shr(96, shl(96, beacon))))
                  instance := create(value, 0x07, 0x79)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
                  mstore(0x40, m) // Restore the free memory pointer.
                  mstore(0x60, 0) // Restore the zero slot.
              }
          }
          /// @dev Deploys a deterministic ERC1967I beacon proxy with `salt`.
          function deployDeterministicERC1967IBeaconProxy(address beacon, bytes32 salt)
              internal
              returns (address instance)
          {
              instance = deployDeterministicERC1967IBeaconProxy(0, beacon, salt);
          }
          /// @dev Deploys a deterministic ERC1967I beacon proxy with `salt`.
          /// Deposits `value` ETH during deployment.
          function deployDeterministicERC1967IBeaconProxy(uint256 value, address beacon, bytes32 salt)
              internal
              returns (address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40) // Cache the free memory pointer.
                  mstore(0x60, 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
                  mstore(0x40, 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
                  mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
                  mstore(0x04, or(shl(160, 0x60573d8160223d3973), shr(96, shl(96, beacon))))
                  instance := create2(value, 0x07, 0x79, salt)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
                  mstore(0x40, m) // Restore the free memory pointer.
                  mstore(0x60, 0) // Restore the zero slot.
              }
          }
          /// @dev Creates a deterministic ERC1967I beacon proxy with `salt`.
          /// Note: This method is intended for use in ERC4337 factories,
          /// which are expected to NOT revert if the proxy is already deployed.
          function createDeterministicERC1967IBeaconProxy(address beacon, bytes32 salt)
              internal
              returns (bool alreadyDeployed, address instance)
          {
              return createDeterministicERC1967IBeaconProxy(0, beacon, salt);
          }
          /// @dev Creates a deterministic ERC1967I beacon proxy with `salt`.
          /// Deposits `value` ETH during deployment.
          /// Note: This method is intended for use in ERC4337 factories,
          /// which are expected to NOT revert if the proxy is already deployed.
          function createDeterministicERC1967IBeaconProxy(uint256 value, address beacon, bytes32 salt)
              internal
              returns (bool alreadyDeployed, address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40) // Cache the free memory pointer.
                  mstore(0x60, 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
                  mstore(0x40, 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
                  mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
                  mstore(0x04, or(shl(160, 0x60573d8160223d3973), shr(96, shl(96, beacon))))
                  // Compute and store the bytecode hash.
                  mstore(add(m, 0x35), keccak256(0x07, 0x79))
                  mstore(m, shl(88, address()))
                  mstore8(m, 0xff) // Write the prefix.
                  mstore(add(m, 0x15), salt)
                  instance := keccak256(m, 0x55)
                  for {} 1 {} {
                      if iszero(extcodesize(instance)) {
                          instance := create2(value, 0x07, 0x79, salt)
                          if iszero(instance) {
                              mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                              revert(0x1c, 0x04)
                          }
                          break
                      }
                      alreadyDeployed := 1
                      if iszero(value) { break }
                      if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
                          mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                          revert(0x1c, 0x04)
                      }
                      break
                  }
                  mstore(0x40, m) // Restore the free memory pointer.
                  mstore(0x60, 0) // Restore the zero slot.
              }
          }
          /// @dev Returns the initialization code of the ERC1967I beacon proxy.
          function initCodeERC1967IBeaconProxy(address beacon) internal pure returns (bytes memory c) {
              /// @solidity memory-safe-assembly
              assembly {
                  c := mload(0x40)
                  mstore(add(c, 0x79), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
                  mstore(add(c, 0x59), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
                  mstore(add(c, 0x39), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
                  mstore(add(c, 0x1d), beacon)
                  mstore(add(c, 0x09), 0x60573d8160223d3973)
                  mstore(add(c, 0x99), 0)
                  mstore(c, 0x79) // Store the length.
                  mstore(0x40, add(c, 0xa0)) // Allocate memory.
              }
          }
          /// @dev Returns the initialization code hash of the ERC1967I beacon proxy.
          function initCodeHashERC1967IBeaconProxy(address beacon) internal pure returns (bytes32 hash) {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40) // Cache the free memory pointer.
                  mstore(0x60, 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
                  mstore(0x40, 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
                  mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
                  mstore(0x04, or(shl(160, 0x60573d8160223d3973), shr(96, shl(96, beacon))))
                  hash := keccak256(0x07, 0x79)
                  mstore(0x40, m) // Restore the free memory pointer.
                  mstore(0x60, 0) // Restore the zero slot.
              }
          }
          /// @dev Returns the address of the ERC1967I beacon proxy, with `salt` by `deployer`.
          /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
          function predictDeterministicAddressERC1967IBeaconProxy(
              address beacon,
              bytes32 salt,
              address deployer
          ) internal pure returns (address predicted) {
              bytes32 hash = initCodeHashERC1967IBeaconProxy(beacon);
              predicted = predictDeterministicAddress(hash, salt, deployer);
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*    ERC1967I BEACON PROXY WITH IMMUTABLE ARGS OPERATIONS    */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Deploys a ERC1967I beacon proxy with `args.
          function deployERC1967IBeaconProxy(address beacon, bytes memory args)
              internal
              returns (address instance)
          {
              instance = deployERC1967IBeaconProxy(0, beacon, args);
          }
          /// @dev Deploys a ERC1967I beacon proxy with `args.
          /// Deposits `value` ETH during deployment.
          function deployERC1967IBeaconProxy(uint256 value, address beacon, bytes memory args)
              internal
              returns (address instance)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40) // Cache the free memory pointer.
                  let n := mload(args)
                  pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x90), n))
                  mstore(add(m, 0x70), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
                  mstore(add(m, 0x50), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
                  mstore(add(m, 0x30), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
                  mstore(add(m, 0x14), beacon)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x57 = 0xffa8`.
                  mstore(add(m, gt(n, 0xffa8)), add(0xfe6100573d8160233d3973, shl(56, n)))
                  instance := create(value, add(m, 0x16), add(n, 0x7a))
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
              }
          }
          /// @dev Deploys a deterministic ERC1967I beacon proxy with `args` and `salt`.
          function deployDeterministicERC1967IBeaconProxy(address beacon, bytes memory args, bytes32 salt)
              internal
              returns (address instance)
          {
              instance = deployDeterministicERC1967IBeaconProxy(0, beacon, args, salt);
          }
          /// @dev Deploys a deterministic ERC1967I beacon proxy with `args` and `salt`.
          /// Deposits `value` ETH during deployment.
          function deployDeterministicERC1967IBeaconProxy(
              uint256 value,
              address beacon,
              bytes memory args,
              bytes32 salt
          ) internal returns (address instance) {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40) // Cache the free memory pointer.
                  let n := mload(args)
                  pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x90), n))
                  mstore(add(m, 0x70), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
                  mstore(add(m, 0x50), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
                  mstore(add(m, 0x30), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
                  mstore(add(m, 0x14), beacon)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x57 = 0xffa8`.
                  mstore(add(m, gt(n, 0xffa8)), add(0xfe6100573d8160233d3973, shl(56, n)))
                  instance := create2(value, add(m, 0x16), add(n, 0x7a), salt)
                  if iszero(instance) {
                      mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                      revert(0x1c, 0x04)
                  }
              }
          }
          /// @dev Creates a deterministic ERC1967I beacon proxy with `args` and `salt`.
          /// Note: This method is intended for use in ERC4337 factories,
          /// which are expected to NOT revert if the proxy is already deployed.
          function createDeterministicERC1967IBeaconProxy(address beacon, bytes memory args, bytes32 salt)
              internal
              returns (bool alreadyDeployed, address instance)
          {
              return createDeterministicERC1967IBeaconProxy(0, beacon, args, salt);
          }
          /// @dev Creates a deterministic ERC1967I beacon proxy with `args` and `salt`.
          /// Deposits `value` ETH during deployment.
          /// Note: This method is intended for use in ERC4337 factories,
          /// which are expected to NOT revert if the proxy is already deployed.
          function createDeterministicERC1967IBeaconProxy(
              uint256 value,
              address beacon,
              bytes memory args,
              bytes32 salt
          ) internal returns (bool alreadyDeployed, address instance) {
              /// @solidity memory-safe-assembly
              assembly {
                  let m := mload(0x40)
                  let n := mload(args)
                  pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x90), n))
                  mstore(add(m, 0x70), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
                  mstore(add(m, 0x50), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
                  mstore(add(m, 0x30), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
                  mstore(add(m, 0x14), beacon)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x57 = 0xffa8`.
                  mstore(add(m, gt(n, 0xffa8)), add(0xfe6100573d8160233d3973, shl(56, n)))
                  // Compute and store the bytecode hash.
                  mstore8(0x00, 0xff) // Write the prefix.
                  mstore(0x35, keccak256(add(m, 0x16), add(n, 0x7a)))
                  mstore(0x01, shl(96, address()))
                  mstore(0x15, salt)
                  instance := keccak256(0x00, 0x55)
                  for {} 1 {} {
                      if iszero(extcodesize(instance)) {
                          instance := create2(value, add(m, 0x16), add(n, 0x7a), salt)
                          if iszero(instance) {
                              mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                              revert(0x1c, 0x04)
                          }
                          break
                      }
                      alreadyDeployed := 1
                      if iszero(value) { break }
                      if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
                          mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                          revert(0x1c, 0x04)
                      }
                      break
                  }
                  mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.
              }
          }
          /// @dev Returns the initialization code of the ERC1967I beacon proxy with `args`.
          function initCodeERC1967IBeaconProxy(address beacon, bytes memory args)
              internal
              pure
              returns (bytes memory c)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  c := mload(0x40)
                  let n := mload(args)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x57 = 0xffa8`.
                  returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffa8))
                  for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
                      mstore(add(add(c, 0x9a), i), mload(add(add(args, 0x20), i)))
                  }
                  mstore(add(c, 0x7a), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
                  mstore(add(c, 0x5a), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
                  mstore(add(c, 0x3a), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
                  mstore(add(c, 0x1e), beacon)
                  mstore(add(c, 0x0a), add(0x6100573d8160233d3973, shl(56, n)))
                  mstore(add(c, add(n, 0x9a)), 0)
                  mstore(c, add(n, 0x7a)) // Store the length.
                  mstore(0x40, add(c, add(n, 0xba))) // Allocate memory.
              }
          }
          /// @dev Returns the initialization code hash of the ERC1967I beacon proxy with `args`.
          function initCodeHashERC1967IBeaconProxy(address beacon, bytes memory args)
              internal
              pure
              returns (bytes32 hash)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  let c := mload(0x40) // Cache the free memory pointer.
                  let n := mload(args)
                  // Do a out-of-gas revert if `n` is greater than `0xffff - 0x57 = 0xffa8`.
                  returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffa8))
                  for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
                      mstore(add(add(c, 0x90), i), mload(add(add(args, 0x20), i)))
                  }
                  mstore(add(c, 0x70), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
                  mstore(add(c, 0x50), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
                  mstore(add(c, 0x30), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
                  mstore(add(c, 0x14), beacon)
                  mstore(c, add(0x6100573d8160233d3973, shl(56, n)))
                  hash := keccak256(add(c, 0x16), add(n, 0x7a))
              }
          }
          /// @dev Returns the address of the ERC1967I beacon proxy, with  `args` and salt` by `deployer`.
          /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
          function predictDeterministicAddressERC1967IBeaconProxy(
              address beacon,
              bytes memory args,
              bytes32 salt,
              address deployer
          ) internal pure returns (address predicted) {
              bytes32 hash = initCodeHashERC1967IBeaconProxy(beacon, args);
              predicted = predictDeterministicAddress(hash, salt, deployer);
          }
          /// @dev Equivalent to `argsOnERC1967IBeaconProxy(instance, start, 2 ** 256 - 1)`.
          function argsOnERC1967IBeaconProxy(address instance)
              internal
              view
              returns (bytes memory args)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  args := mload(0x40)
                  mstore(args, sub(extcodesize(instance), 0x57)) // Store the length.
                  extcodecopy(instance, add(args, 0x20), 0x57, add(mload(args), 0x20))
                  mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.
              }
          }
          /// @dev Equivalent to `argsOnERC1967IBeaconProxy(instance, start, 2 ** 256 - 1)`.
          function argsOnERC1967IBeaconProxy(address instance, uint256 start)
              internal
              view
              returns (bytes memory args)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  args := mload(0x40)
                  let n := sub(extcodesize(instance), 0x57)
                  extcodecopy(instance, add(args, 0x20), add(start, 0x57), add(n, 0x20))
                  mstore(args, mul(sub(n, start), lt(start, n))) // Store the length.
                  mstore(0x40, add(args, add(0x40, mload(args)))) // Allocate memory.
              }
          }
          /// @dev Returns a slice of the immutable arguments on `instance` from `start` to `end`.
          /// `start` and `end` will be clamped to the range `[0, args.length]`.
          /// The `instance` MUST be deployed via the ERC1967I beacon proxy with immutable args functions.
          /// Otherwise, the behavior is undefined.
          /// Out-of-gas reverts if `instance` does not have any code.
          function argsOnERC1967IBeaconProxy(address instance, uint256 start, uint256 end)
              internal
              view
              returns (bytes memory args)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  args := mload(0x40)
                  if iszero(lt(end, 0xffff)) { end := 0xffff }
                  let d := mul(sub(end, start), lt(start, end))
                  extcodecopy(instance, args, add(start, 0x37), add(d, 0x20))
                  if iszero(and(0xff, mload(add(args, d)))) {
                      let n := sub(extcodesize(instance), 0x57)
                      returndatacopy(returndatasize(), returndatasize(), shr(64, n))
                      d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))
                  }
                  mstore(args, d) // Store the length.
                  mstore(add(add(args, 0x20), d), 0) // Zeroize the slot after the bytes.
                  mstore(0x40, add(add(args, 0x40), d)) // Allocate memory.
              }
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                      OTHER OPERATIONS                      */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Returns `address(0)` if the implementation address cannot be determined.
          function implementationOf(address instance) internal view returns (address result) {
              /// @solidity memory-safe-assembly
              assembly {
                  for { extcodecopy(instance, 0x00, 0x00, 0x57) } 1 {} {
                      if mload(0x2d) {
                          // ERC1967I and ERC1967IBeaconProxy detection.
                          if or(
                              eq(keccak256(0x00, 0x52), ERC1967I_CODE_HASH),
                              eq(keccak256(0x00, 0x57), ERC1967I_BEACON_PROXY_CODE_HASH)
                          ) {
                              pop(staticcall(gas(), instance, 0x00, 0x01, 0x00, 0x20))
                              result := mload(0x0c)
                              break
                          }
                      }
                      // 0age clone detection.
                      result := mload(0x0b)
                      codecopy(0x0b, codesize(), 0x14) // Zeroize the 20 bytes for the address.
                      if iszero(xor(keccak256(0x00, 0x2c), CLONE_CODE_HASH)) { break }
                      mstore(0x0b, result) // Restore the zeroized memory.
                      // CWIA detection.
                      result := mload(0x0a)
                      codecopy(0x0a, codesize(), 0x14) // Zeroize the 20 bytes for the address.
                      if iszero(xor(keccak256(0x00, 0x2d), CWIA_CODE_HASH)) { break }
                      mstore(0x0a, result) // Restore the zeroized memory.
                      // PUSH0 clone detection.
                      result := mload(0x09)
                      codecopy(0x09, codesize(), 0x14) // Zeroize the 20 bytes for the address.
                      result := shr(xor(keccak256(0x00, 0x2d), PUSH0_CLONE_CODE_HASH), result)
                      break
                  }
                  result := shr(96, result)
                  mstore(0x37, 0) // Restore the overwritten part of the free memory pointer.
              }
          }
          /// @dev Returns the address when a contract with initialization code hash,
          /// `hash`, is deployed with `salt`, by `deployer`.
          /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
          function predictDeterministicAddress(bytes32 hash, bytes32 salt, address deployer)
              internal
              pure
              returns (address predicted)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  // Compute and store the bytecode hash.
                  mstore8(0x00, 0xff) // Write the prefix.
                  mstore(0x35, hash)
                  mstore(0x01, shl(96, deployer))
                  mstore(0x15, salt)
                  predicted := keccak256(0x00, 0x55)
                  mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.
              }
          }
          /// @dev Requires that `salt` starts with either the zero address or `by`.
          function checkStartsWith(bytes32 salt, address by) internal pure {
              /// @solidity memory-safe-assembly
              assembly {
                  // If the salt does not start with the zero address or `by`.
                  if iszero(or(iszero(shr(96, salt)), eq(shr(96, shl(96, by)), shr(96, salt)))) {
                      mstore(0x00, 0x0c4549ef) // `SaltDoesNotStartWith()`.
                      revert(0x1c, 0x04)
                  }
              }
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.22;
      enum TokenStandard {
          ERC721,
          ERC1155,
          ERC20
      }
      struct MintStageInfo {
          uint80 price;
          uint80 mintFee;
          uint32 walletLimit; // 0 for unlimited
          bytes32 merkleRoot; // 0x0 for no presale enforced
          uint24 maxStageSupply; // 0 for unlimited
          uint256 startTimeUnixSeconds;
          uint256 endTimeUnixSeconds;
      }
      struct MintStageInfo1155 {
          uint80[] price;
          uint80[] mintFee;
          uint32[] walletLimit; // 0 for unlimited
          bytes32[] merkleRoot; // 0x0 for no presale enforced
          uint24[] maxStageSupply; // 0 for unlimited
          uint256 startTimeUnixSeconds;
          uint256 endTimeUnixSeconds;
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.22;
      import {Ownable} from "solady/src/auth/Ownable.sol";
      import {UUPSUpgradeable} from "solady/src/utils/UUPSUpgradeable.sol";
      import {IMagicDropTokenImplRegistry, TokenStandard} from "./interfaces/IMagicDropTokenImplRegistry.sol";
      import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
      /// @title MagicDropTokenImplRegistry
      /// @dev A registry for managing token implementation addresses for different token standards.
      /// This contract is upgradeable and uses the UUPS pattern.
      contract MagicDropTokenImplRegistry is UUPSUpgradeable, Ownable, IMagicDropTokenImplRegistry {
          /*==============================================================
          =                            STRUCTS                           =
          ==============================================================*/
          struct RegistryData {
              bytes4 interfaceId;
              uint32 nextImplId;
              uint32 defaultImplId;
              mapping(uint256 => address) implementations;
              mapping(uint256 => uint256) deploymentFees; //implementationId => deploymentFee
          }
          struct RegistryStorage {
              mapping(TokenStandard => RegistryData) tokenStandardData;
          }
          /*==============================================================
          =                            STORAGE                           =
          ==============================================================*/
          // keccak256(abi.encode(uint256(keccak256("magicdrop.registry.MagicDropTokenImplRegistry")) - 1)) & ~bytes32(uint256(0xff))
          bytes32 private constant MAGICDROP_REGISTRY_STORAGE =
              0xfd008fcd1deb21680f735a35fafc51691c5fb3daec313cfea4dc62938bee9000;
          /*==============================================================
          =                            EVENTS                            =
          ==============================================================*/
          event ImplementationRegistered(TokenStandard standard, address impl, uint32 implId, uint256 deploymentFee);
          event ImplementationUnregistered(TokenStandard standard, uint32 implId);
          event DefaultImplementationSet(TokenStandard standard, uint32 implId);
          event DeploymentFeeSet(TokenStandard standard, uint32 implId, uint256 deploymentFee);
          /*==============================================================
          =                            ERRORS                            =
          ==============================================================*/
          error InvalidImplementation();
          error ImplementationDoesNotSupportStandard();
          error UnsupportedTokenStandard();
          error DefaultImplementationNotRegistered();
          /*==============================================================
          =                          CONSTRUCTOR                         =
          ==============================================================*/
          /// @param initialOwner The address of the initial owner
          constructor(address initialOwner) public {
              _initializeOwner(initialOwner);
              // Initialize nextImplId and interface IDs for each token standard
              RegistryStorage storage $ = _loadRegistryStorage();
              $.tokenStandardData[TokenStandard.ERC721].nextImplId = 1;
              $.tokenStandardData[TokenStandard.ERC721].interfaceId = 0x80ac58cd; // ERC721 interface ID
              $.tokenStandardData[TokenStandard.ERC1155].nextImplId = 1;
              $.tokenStandardData[TokenStandard.ERC1155].interfaceId = 0xd9b67a26; // ERC1155 interface ID
          }
          /*==============================================================
          =                      PUBLIC VIEW METHODS                     =
          ==============================================================*/
          /// @dev Retrieves the implementation address for a given token standard and implementation ID.
          /// @param standard The token standard (ERC721, ERC1155).
          /// @param implId The ID of the implementation.
          /// @notice Reverts if the implementation is not registered.
          /// @return implAddress The address of the implementation contract.
          function getImplementation(TokenStandard standard, uint32 implId) external view returns (address implAddress) {
              assembly {
                  // Compute s1 = keccak256(abi.encode(standard, MAGICDROP_REGISTRY_STORAGE))
                  mstore(0x00, standard)
                  mstore(0x20, MAGICDROP_REGISTRY_STORAGE)
                  let s1 := keccak256(0x00, 0x40)
                  // Compute storage slot for implementations[implId]
                  mstore(0x00, implId)
                  mstore(0x20, add(s1, 1))
                  let implSlot := keccak256(0x00, 0x40)
                  implAddress := sload(implSlot)
                  // Revert if the implementation is not registered
                  if iszero(implAddress) {
                      mstore(0x00, 0x68155f9a) // revert InvalidImplementation()
                      revert(0x1c, 0x04)
                  }
              }
          }
          /// @dev Gets the default implementation ID for a given token standard
          /// @param standard The token standard (ERC721, ERC1155)
          /// @notice Reverts if the default implementation is not registered.
          /// @return defaultImplId The default implementation ID for the given standard
          function getDefaultImplementationID(TokenStandard standard) external view returns (uint32 defaultImplId) {
              assembly {
                  // Compute storage slot for tokenStandardData[standard]
                  mstore(0x00, standard)
                  mstore(0x20, MAGICDROP_REGISTRY_STORAGE)
                  let slot := keccak256(0x00, 0x40)
                  // Extract 'defaultImplId' by shifting and masking
                  // Shift right by 64 bits to bring 'defaultImplId' to bits 0-31
                  let shiftedData := shr(64, sload(slot))
                  // Mask to extract the lower 32 bits
                  defaultImplId := and(shiftedData, 0xffffffff)
                  // Check if defaultImplId is 0 and revert if so
                  if iszero(defaultImplId) {
                      // revert DefaultImplementationNotRegistered()
                      mstore(0x00, 0x161378fc)
                      revert(0x1c, 0x04)
                  }
              }
          }
          /// @dev Gets the default implementation address for a given token standard
          /// @param standard The token standard (ERC721, ERC1155)
          /// @notice Reverts if the default implementation is not registered.
          /// @return implAddress The default implementation address for the given standard
          function getDefaultImplementation(TokenStandard standard) external view returns (address implAddress) {
              assembly {
                  mstore(0x00, standard)
                  mstore(0x20, MAGICDROP_REGISTRY_STORAGE)
                  let slot := keccak256(0x00, 0x40)
                  // Extract 'defaultImplId' by shifting and masking
                  // Shift right by 64 bits to bring 'defaultImplId' to bits 0-31
                  let shiftedData := shr(64, sload(slot))
                  // Mask to extract the lower 32 bits
                  let defaultImplId := and(shiftedData, 0xffffffff)
                  // Revert if the default implementation is not registered
                  if iszero(defaultImplId) {
                      // revert DefaultImplementationNotRegistered()
                      mstore(0x00, 0x161378fc)
                      revert(0x1c, 0x04)
                  }
                  // Compute storage slot for implementations[defaultImplId]
                  mstore(0x00, defaultImplId)
                  mstore(0x20, add(slot, 1))
                  let implSlot := keccak256(0x00, 0x40)
                  implAddress := sload(implSlot)
              }
          }
          /// @dev Gets the deployment fee for a given token standard
          /// @param standard The token standard (ERC721, ERC1155, ERC20)
          /// @param implId The implementation ID
          /// @return deploymentFee The deployment fee for the given standard
          function getDeploymentFee(TokenStandard standard, uint32 implId) external view returns (uint256 deploymentFee) {
              assembly {
                  mstore(0x00, standard)
                  mstore(0x20, MAGICDROP_REGISTRY_STORAGE)
                  let slot := keccak256(0x00, 0x40)
                  mstore(0x00, implId)
                  mstore(0x20, add(slot, 2))
                  let implSlot := keccak256(0x00, 0x40)
                  deploymentFee := sload(implSlot)
              }
          }
          /*==============================================================
          =                       INTERNAL HELPERS                       =
          ==============================================================*/
          /// @dev Loads the registry storage.
          /// @return $ The registry storage.
          function _loadRegistryStorage() internal pure returns (RegistryStorage storage $) {
              assembly {
                  $.slot := MAGICDROP_REGISTRY_STORAGE
              }
          }
          /*==============================================================
          =                      ADMIN OPERATIONS                        =
          ==============================================================*/
          /// @dev Registers a new implementation for a given token standard.
          /// @param standard The token standard (ERC721, ERC1155, ERC20).
          /// @param impl The address of the implementation contract.
          /// @param isDefault Whether the implementation should be set as the default implementation
          /// @param deploymentFee The deployment fee for the implementation
          /// @notice Only the contract owner can call this function.
          /// @notice Reverts if an implementation with the same name is already registered.
          /// @return The ID of the newly registered implementation
          function registerImplementation(TokenStandard standard, address impl, bool isDefault, uint256 deploymentFee)
              external
              onlyOwner
              returns (uint32)
          {
              RegistryStorage storage $ = _loadRegistryStorage();
              bytes4 interfaceId = $.tokenStandardData[standard].interfaceId;
              if (interfaceId == 0) {
                  revert UnsupportedTokenStandard();
              }
              if (!IERC165(impl).supportsInterface(interfaceId)) {
                  revert ImplementationDoesNotSupportStandard();
              }
              uint32 implId = $.tokenStandardData[standard].nextImplId;
              $.tokenStandardData[standard].implementations[implId] = impl;
              $.tokenStandardData[standard].nextImplId = implId + 1;
              $.tokenStandardData[standard].deploymentFees[implId] = deploymentFee;
              emit ImplementationRegistered(standard, impl, implId, deploymentFee);
              emit DeploymentFeeSet(standard, implId, deploymentFee);
              if (isDefault) {
                  $.tokenStandardData[standard].defaultImplId = implId;
                  emit DefaultImplementationSet(standard, implId);
              }
              return implId;
          }
          /// @dev Unregisters an implementation for a given token standard.
          /// @param standard The token standard (ERC721, ERC1155).
          /// @param implId The ID of the implementation to unregister.
          /// @notice Only the contract owner can call this function.
          /// @notice Reverts if the implementation is not registered.
          function unregisterImplementation(TokenStandard standard, uint32 implId) external onlyOwner {
              RegistryStorage storage $ = _loadRegistryStorage();
              address implData = $.tokenStandardData[standard].implementations[implId];
              if (implData == address(0)) {
                  revert InvalidImplementation();
              }
              $.tokenStandardData[standard].implementations[implId] = address(0);
              if ($.tokenStandardData[standard].defaultImplId == implId) {
                  $.tokenStandardData[standard].defaultImplId = 0;
                  emit DefaultImplementationSet(standard, 0);
              }
              emit ImplementationUnregistered(standard, implId);
          }
          /// @dev Sets the default implementation ID for a given token standard
          /// @param standard The token standard (ERC721, ERC1155, ERC20)
          /// @param implId The ID of the implementation to set as default
          /// @notice Reverts if the implementation is not registered.
          /// @notice Only the contract owner can call this function
          function setDefaultImplementation(TokenStandard standard, uint32 implId) external onlyOwner {
              RegistryStorage storage $ = _loadRegistryStorage();
              address implData = $.tokenStandardData[standard].implementations[implId];
              if (implData == address(0)) {
                  revert InvalidImplementation();
              }
              $.tokenStandardData[standard].defaultImplId = implId;
              emit DefaultImplementationSet(standard, implId);
          }
          /// @dev Sets the deployment fee for an implementation
          /// @param standard The token standard (ERC721, ERC1155, ERC20)
          /// @param implId The implementation ID
          /// @param deploymentFee The deployment fee to set
          /// @notice Only the contract owner can call this function
          function setDeploymentFee(TokenStandard standard, uint32 implId, uint256 deploymentFee) external onlyOwner {
              RegistryStorage storage $ = _loadRegistryStorage();
              $.tokenStandardData[standard].deploymentFees[implId] = deploymentFee;
              emit DeploymentFeeSet(standard, implId, deploymentFee);
          }
          /// @dev Internal function to authorize an upgrade.
          /// @param newImplementation Address of the new implementation.
          /// @notice Only the contract owner can upgrade the contract.
          function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
          /// @dev Overriden to prevent double-initialization of the owner.
          function _guardInitializeOwner() internal pure virtual override returns (bool) {
              return true;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.22;
      import {TokenStandard} from "../../common/Structs.sol";
      interface IMagicDropTokenImplRegistry {
          function registerImplementation(TokenStandard standard, address impl, bool isDefault, uint256 deploymentFee)
              external
              returns (uint32);
          function unregisterImplementation(TokenStandard standard, uint32 implId) external;
          function getImplementation(TokenStandard standard, uint32 implId) external view returns (address);
          function getDeploymentFee(TokenStandard standard, uint32 implId) external view returns (uint256);
          function setDeploymentFee(TokenStandard standard, uint32 implId, uint256 deploymentFee) external;
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
      pragma solidity ^0.8.0;
      /**
       * @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);
      }
      

      File 2 of 2: MagicDropTokenImplRegistry
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.22;
      import {Ownable} from "solady/src/auth/Ownable.sol";
      import {UUPSUpgradeable} from "solady/src/utils/UUPSUpgradeable.sol";
      import {IMagicDropTokenImplRegistry, TokenStandard} from "./interfaces/IMagicDropTokenImplRegistry.sol";
      import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
      /// @title MagicDropTokenImplRegistry
      /// @dev A registry for managing token implementation addresses for different token standards.
      /// This contract is upgradeable and uses the UUPS pattern.
      contract MagicDropTokenImplRegistry is UUPSUpgradeable, Ownable, IMagicDropTokenImplRegistry {
          /*==============================================================
          =                            STRUCTS                           =
          ==============================================================*/
          struct RegistryData {
              bytes4 interfaceId;
              uint32 nextImplId;
              uint32 defaultImplId;
              mapping(uint256 => address) implementations;
              mapping(uint256 => uint256) deploymentFees; //implementationId => deploymentFee
          }
          struct RegistryStorage {
              mapping(TokenStandard => RegistryData) tokenStandardData;
          }
          /*==============================================================
          =                            STORAGE                           =
          ==============================================================*/
          // keccak256(abi.encode(uint256(keccak256("magicdrop.registry.MagicDropTokenImplRegistry")) - 1)) & ~bytes32(uint256(0xff))
          bytes32 private constant MAGICDROP_REGISTRY_STORAGE =
              0xfd008fcd1deb21680f735a35fafc51691c5fb3daec313cfea4dc62938bee9000;
          /*==============================================================
          =                            EVENTS                            =
          ==============================================================*/
          event ImplementationRegistered(TokenStandard standard, address impl, uint32 implId, uint256 deploymentFee);
          event ImplementationUnregistered(TokenStandard standard, uint32 implId);
          event DefaultImplementationSet(TokenStandard standard, uint32 implId);
          event DeploymentFeeSet(TokenStandard standard, uint32 implId, uint256 deploymentFee);
          /*==============================================================
          =                            ERRORS                            =
          ==============================================================*/
          error InvalidImplementation();
          error ImplementationDoesNotSupportStandard();
          error UnsupportedTokenStandard();
          error DefaultImplementationNotRegistered();
          /*==============================================================
          =                          CONSTRUCTOR                         =
          ==============================================================*/
          /// @param initialOwner The address of the initial owner
          constructor(address initialOwner) public {
              _initializeOwner(initialOwner);
              // Initialize nextImplId and interface IDs for each token standard
              RegistryStorage storage $ = _loadRegistryStorage();
              $.tokenStandardData[TokenStandard.ERC721].nextImplId = 1;
              $.tokenStandardData[TokenStandard.ERC721].interfaceId = 0x80ac58cd; // ERC721 interface ID
              $.tokenStandardData[TokenStandard.ERC1155].nextImplId = 1;
              $.tokenStandardData[TokenStandard.ERC1155].interfaceId = 0xd9b67a26; // ERC1155 interface ID
          }
          /*==============================================================
          =                      PUBLIC VIEW METHODS                     =
          ==============================================================*/
          /// @dev Retrieves the implementation address for a given token standard and implementation ID.
          /// @param standard The token standard (ERC721, ERC1155).
          /// @param implId The ID of the implementation.
          /// @notice Reverts if the implementation is not registered.
          /// @return implAddress The address of the implementation contract.
          function getImplementation(TokenStandard standard, uint32 implId) external view returns (address implAddress) {
              assembly {
                  // Compute s1 = keccak256(abi.encode(standard, MAGICDROP_REGISTRY_STORAGE))
                  mstore(0x00, standard)
                  mstore(0x20, MAGICDROP_REGISTRY_STORAGE)
                  let s1 := keccak256(0x00, 0x40)
                  // Compute storage slot for implementations[implId]
                  mstore(0x00, implId)
                  mstore(0x20, add(s1, 1))
                  let implSlot := keccak256(0x00, 0x40)
                  implAddress := sload(implSlot)
                  // Revert if the implementation is not registered
                  if iszero(implAddress) {
                      mstore(0x00, 0x68155f9a) // revert InvalidImplementation()
                      revert(0x1c, 0x04)
                  }
              }
          }
          /// @dev Gets the default implementation ID for a given token standard
          /// @param standard The token standard (ERC721, ERC1155)
          /// @notice Reverts if the default implementation is not registered.
          /// @return defaultImplId The default implementation ID for the given standard
          function getDefaultImplementationID(TokenStandard standard) external view returns (uint32 defaultImplId) {
              assembly {
                  // Compute storage slot for tokenStandardData[standard]
                  mstore(0x00, standard)
                  mstore(0x20, MAGICDROP_REGISTRY_STORAGE)
                  let slot := keccak256(0x00, 0x40)
                  // Extract 'defaultImplId' by shifting and masking
                  // Shift right by 64 bits to bring 'defaultImplId' to bits 0-31
                  let shiftedData := shr(64, sload(slot))
                  // Mask to extract the lower 32 bits
                  defaultImplId := and(shiftedData, 0xffffffff)
                  // Check if defaultImplId is 0 and revert if so
                  if iszero(defaultImplId) {
                      // revert DefaultImplementationNotRegistered()
                      mstore(0x00, 0x161378fc)
                      revert(0x1c, 0x04)
                  }
              }
          }
          /// @dev Gets the default implementation address for a given token standard
          /// @param standard The token standard (ERC721, ERC1155)
          /// @notice Reverts if the default implementation is not registered.
          /// @return implAddress The default implementation address for the given standard
          function getDefaultImplementation(TokenStandard standard) external view returns (address implAddress) {
              assembly {
                  mstore(0x00, standard)
                  mstore(0x20, MAGICDROP_REGISTRY_STORAGE)
                  let slot := keccak256(0x00, 0x40)
                  // Extract 'defaultImplId' by shifting and masking
                  // Shift right by 64 bits to bring 'defaultImplId' to bits 0-31
                  let shiftedData := shr(64, sload(slot))
                  // Mask to extract the lower 32 bits
                  let defaultImplId := and(shiftedData, 0xffffffff)
                  // Revert if the default implementation is not registered
                  if iszero(defaultImplId) {
                      // revert DefaultImplementationNotRegistered()
                      mstore(0x00, 0x161378fc)
                      revert(0x1c, 0x04)
                  }
                  // Compute storage slot for implementations[defaultImplId]
                  mstore(0x00, defaultImplId)
                  mstore(0x20, add(slot, 1))
                  let implSlot := keccak256(0x00, 0x40)
                  implAddress := sload(implSlot)
              }
          }
          /// @dev Gets the deployment fee for a given token standard
          /// @param standard The token standard (ERC721, ERC1155, ERC20)
          /// @param implId The implementation ID
          /// @return deploymentFee The deployment fee for the given standard
          function getDeploymentFee(TokenStandard standard, uint32 implId) external view returns (uint256 deploymentFee) {
              assembly {
                  mstore(0x00, standard)
                  mstore(0x20, MAGICDROP_REGISTRY_STORAGE)
                  let slot := keccak256(0x00, 0x40)
                  mstore(0x00, implId)
                  mstore(0x20, add(slot, 2))
                  let implSlot := keccak256(0x00, 0x40)
                  deploymentFee := sload(implSlot)
              }
          }
          /*==============================================================
          =                       INTERNAL HELPERS                       =
          ==============================================================*/
          /// @dev Loads the registry storage.
          /// @return $ The registry storage.
          function _loadRegistryStorage() internal pure returns (RegistryStorage storage $) {
              assembly {
                  $.slot := MAGICDROP_REGISTRY_STORAGE
              }
          }
          /*==============================================================
          =                      ADMIN OPERATIONS                        =
          ==============================================================*/
          /// @dev Registers a new implementation for a given token standard.
          /// @param standard The token standard (ERC721, ERC1155, ERC20).
          /// @param impl The address of the implementation contract.
          /// @param isDefault Whether the implementation should be set as the default implementation
          /// @param deploymentFee The deployment fee for the implementation
          /// @notice Only the contract owner can call this function.
          /// @notice Reverts if an implementation with the same name is already registered.
          /// @return The ID of the newly registered implementation
          function registerImplementation(TokenStandard standard, address impl, bool isDefault, uint256 deploymentFee)
              external
              onlyOwner
              returns (uint32)
          {
              RegistryStorage storage $ = _loadRegistryStorage();
              bytes4 interfaceId = $.tokenStandardData[standard].interfaceId;
              if (interfaceId == 0) {
                  revert UnsupportedTokenStandard();
              }
              if (!IERC165(impl).supportsInterface(interfaceId)) {
                  revert ImplementationDoesNotSupportStandard();
              }
              uint32 implId = $.tokenStandardData[standard].nextImplId;
              $.tokenStandardData[standard].implementations[implId] = impl;
              $.tokenStandardData[standard].nextImplId = implId + 1;
              $.tokenStandardData[standard].deploymentFees[implId] = deploymentFee;
              emit ImplementationRegistered(standard, impl, implId, deploymentFee);
              emit DeploymentFeeSet(standard, implId, deploymentFee);
              if (isDefault) {
                  $.tokenStandardData[standard].defaultImplId = implId;
                  emit DefaultImplementationSet(standard, implId);
              }
              return implId;
          }
          /// @dev Unregisters an implementation for a given token standard.
          /// @param standard The token standard (ERC721, ERC1155).
          /// @param implId The ID of the implementation to unregister.
          /// @notice Only the contract owner can call this function.
          /// @notice Reverts if the implementation is not registered.
          function unregisterImplementation(TokenStandard standard, uint32 implId) external onlyOwner {
              RegistryStorage storage $ = _loadRegistryStorage();
              address implData = $.tokenStandardData[standard].implementations[implId];
              if (implData == address(0)) {
                  revert InvalidImplementation();
              }
              $.tokenStandardData[standard].implementations[implId] = address(0);
              if ($.tokenStandardData[standard].defaultImplId == implId) {
                  $.tokenStandardData[standard].defaultImplId = 0;
                  emit DefaultImplementationSet(standard, 0);
              }
              emit ImplementationUnregistered(standard, implId);
          }
          /// @dev Sets the default implementation ID for a given token standard
          /// @param standard The token standard (ERC721, ERC1155, ERC20)
          /// @param implId The ID of the implementation to set as default
          /// @notice Reverts if the implementation is not registered.
          /// @notice Only the contract owner can call this function
          function setDefaultImplementation(TokenStandard standard, uint32 implId) external onlyOwner {
              RegistryStorage storage $ = _loadRegistryStorage();
              address implData = $.tokenStandardData[standard].implementations[implId];
              if (implData == address(0)) {
                  revert InvalidImplementation();
              }
              $.tokenStandardData[standard].defaultImplId = implId;
              emit DefaultImplementationSet(standard, implId);
          }
          /// @dev Sets the deployment fee for an implementation
          /// @param standard The token standard (ERC721, ERC1155, ERC20)
          /// @param implId The implementation ID
          /// @param deploymentFee The deployment fee to set
          /// @notice Only the contract owner can call this function
          function setDeploymentFee(TokenStandard standard, uint32 implId, uint256 deploymentFee) external onlyOwner {
              RegistryStorage storage $ = _loadRegistryStorage();
              $.tokenStandardData[standard].deploymentFees[implId] = deploymentFee;
              emit DeploymentFeeSet(standard, implId, deploymentFee);
          }
          /// @dev Internal function to authorize an upgrade.
          /// @param newImplementation Address of the new implementation.
          /// @notice Only the contract owner can upgrade the contract.
          function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
          /// @dev Overriden to prevent double-initialization of the owner.
          function _guardInitializeOwner() internal pure virtual override returns (bool) {
              return true;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.4;
      /// @notice Simple single owner authorization mixin.
      /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
      ///
      /// @dev Note:
      /// This implementation does NOT auto-initialize the owner to `msg.sender`.
      /// You MUST call the `_initializeOwner` in the constructor / initializer.
      ///
      /// While the ownable portion follows
      /// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
      /// the nomenclature for the 2-step ownership handover may be unique to this codebase.
      abstract contract Ownable {
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                       CUSTOM ERRORS                        */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev The caller is not authorized to call the function.
          error Unauthorized();
          /// @dev The `newOwner` cannot be the zero address.
          error NewOwnerIsZeroAddress();
          /// @dev The `pendingOwner` does not have a valid handover request.
          error NoHandoverRequest();
          /// @dev Cannot double-initialize.
          error AlreadyInitialized();
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                           EVENTS                           */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev The ownership is transferred from `oldOwner` to `newOwner`.
          /// This event is intentionally kept the same as OpenZeppelin's Ownable to be
          /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
          /// despite it not being as lightweight as a single argument event.
          event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);
          /// @dev An ownership handover to `pendingOwner` has been requested.
          event OwnershipHandoverRequested(address indexed pendingOwner);
          /// @dev The ownership handover to `pendingOwner` has been canceled.
          event OwnershipHandoverCanceled(address indexed pendingOwner);
          /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
          uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
              0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;
          /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
          uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
              0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;
          /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
          uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
              0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                          STORAGE                           */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev The owner slot is given by:
          /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`.
          /// It is intentionally chosen to be a high value
          /// to avoid collision with lower slots.
          /// The choice of manual storage layout is to enable compatibility
          /// with both regular and upgradeable contracts.
          bytes32 internal constant _OWNER_SLOT =
              0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;
          /// The ownership handover slot of `newOwner` is given by:
          /// ```
          ///     mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
          ///     let handoverSlot := keccak256(0x00, 0x20)
          /// ```
          /// It stores the expiry timestamp of the two-step ownership handover.
          uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                     INTERNAL FUNCTIONS                     */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Override to return true to make `_initializeOwner` prevent double-initialization.
          function _guardInitializeOwner() internal pure virtual returns (bool guard) {}
          /// @dev Initializes the owner directly without authorization guard.
          /// This function must be called upon initialization,
          /// regardless of whether the contract is upgradeable or not.
          /// This is to enable generalization to both regular and upgradeable contracts,
          /// and to save gas in case the initial owner is not the caller.
          /// For performance reasons, this function will not check if there
          /// is an existing owner.
          function _initializeOwner(address newOwner) internal virtual {
              if (_guardInitializeOwner()) {
                  /// @solidity memory-safe-assembly
                  assembly {
                      let ownerSlot := _OWNER_SLOT
                      if sload(ownerSlot) {
                          mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.
                          revert(0x1c, 0x04)
                      }
                      // Clean the upper 96 bits.
                      newOwner := shr(96, shl(96, newOwner))
                      // Store the new value.
                      sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
                      // Emit the {OwnershipTransferred} event.
                      log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
                  }
              } else {
                  /// @solidity memory-safe-assembly
                  assembly {
                      // Clean the upper 96 bits.
                      newOwner := shr(96, shl(96, newOwner))
                      // Store the new value.
                      sstore(_OWNER_SLOT, newOwner)
                      // Emit the {OwnershipTransferred} event.
                      log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
                  }
              }
          }
          /// @dev Sets the owner directly without authorization guard.
          function _setOwner(address newOwner) internal virtual {
              if (_guardInitializeOwner()) {
                  /// @solidity memory-safe-assembly
                  assembly {
                      let ownerSlot := _OWNER_SLOT
                      // Clean the upper 96 bits.
                      newOwner := shr(96, shl(96, newOwner))
                      // Emit the {OwnershipTransferred} event.
                      log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                      // Store the new value.
                      sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
                  }
              } else {
                  /// @solidity memory-safe-assembly
                  assembly {
                      let ownerSlot := _OWNER_SLOT
                      // Clean the upper 96 bits.
                      newOwner := shr(96, shl(96, newOwner))
                      // Emit the {OwnershipTransferred} event.
                      log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                      // Store the new value.
                      sstore(ownerSlot, newOwner)
                  }
              }
          }
          /// @dev Throws if the sender is not the owner.
          function _checkOwner() internal view virtual {
              /// @solidity memory-safe-assembly
              assembly {
                  // If the caller is not the stored owner, revert.
                  if iszero(eq(caller(), sload(_OWNER_SLOT))) {
                      mstore(0x00, 0x82b42900) // `Unauthorized()`.
                      revert(0x1c, 0x04)
                  }
              }
          }
          /// @dev Returns how long a two-step ownership handover is valid for in seconds.
          /// Override to return a different value if needed.
          /// Made internal to conserve bytecode. Wrap it in a public function if needed.
          function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
              return 48 * 3600;
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                  PUBLIC UPDATE FUNCTIONS                   */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Allows the owner to transfer the ownership to `newOwner`.
          function transferOwnership(address newOwner) public payable virtual onlyOwner {
              /// @solidity memory-safe-assembly
              assembly {
                  if iszero(shl(96, newOwner)) {
                      mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
                      revert(0x1c, 0x04)
                  }
              }
              _setOwner(newOwner);
          }
          /// @dev Allows the owner to renounce their ownership.
          function renounceOwnership() public payable virtual onlyOwner {
              _setOwner(address(0));
          }
          /// @dev Request a two-step ownership handover to the caller.
          /// The request will automatically expire in 48 hours (172800 seconds) by default.
          function requestOwnershipHandover() public payable virtual {
              unchecked {
                  uint256 expires = block.timestamp + _ownershipHandoverValidFor();
                  /// @solidity memory-safe-assembly
                  assembly {
                      // Compute and set the handover slot to `expires`.
                      mstore(0x0c, _HANDOVER_SLOT_SEED)
                      mstore(0x00, caller())
                      sstore(keccak256(0x0c, 0x20), expires)
                      // Emit the {OwnershipHandoverRequested} event.
                      log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
                  }
              }
          }
          /// @dev Cancels the two-step ownership handover to the caller, if any.
          function cancelOwnershipHandover() public payable virtual {
              /// @solidity memory-safe-assembly
              assembly {
                  // Compute and set the handover slot to 0.
                  mstore(0x0c, _HANDOVER_SLOT_SEED)
                  mstore(0x00, caller())
                  sstore(keccak256(0x0c, 0x20), 0)
                  // Emit the {OwnershipHandoverCanceled} event.
                  log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
              }
          }
          /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
          /// Reverts if there is no existing ownership handover requested by `pendingOwner`.
          function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
              /// @solidity memory-safe-assembly
              assembly {
                  // Compute and set the handover slot to 0.
                  mstore(0x0c, _HANDOVER_SLOT_SEED)
                  mstore(0x00, pendingOwner)
                  let handoverSlot := keccak256(0x0c, 0x20)
                  // If the handover does not exist, or has expired.
                  if gt(timestamp(), sload(handoverSlot)) {
                      mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
                      revert(0x1c, 0x04)
                  }
                  // Set the handover slot to 0.
                  sstore(handoverSlot, 0)
              }
              _setOwner(pendingOwner);
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                   PUBLIC READ FUNCTIONS                    */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Returns the owner of the contract.
          function owner() public view virtual returns (address result) {
              /// @solidity memory-safe-assembly
              assembly {
                  result := sload(_OWNER_SLOT)
              }
          }
          /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
          function ownershipHandoverExpiresAt(address pendingOwner)
              public
              view
              virtual
              returns (uint256 result)
          {
              /// @solidity memory-safe-assembly
              assembly {
                  // Compute the handover slot.
                  mstore(0x0c, _HANDOVER_SLOT_SEED)
                  mstore(0x00, pendingOwner)
                  // Load the handover slot.
                  result := sload(keccak256(0x0c, 0x20))
              }
          }
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                         MODIFIERS                          */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Marks a function as only callable by the owner.
          modifier onlyOwner() virtual {
              _checkOwner();
              _;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.4;
      /// @notice UUPS proxy mixin.
      /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/UUPSUpgradeable.sol)
      /// @author Modified from OpenZeppelin
      /// (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/utils/UUPSUpgradeable.sol)
      ///
      /// @dev Note:
      /// - This implementation is intended to be used with ERC1967 proxies.
      /// See: `LibClone.deployERC1967` and related functions.
      /// - This implementation is NOT compatible with legacy OpenZeppelin proxies
      /// which do not store the implementation at `_ERC1967_IMPLEMENTATION_SLOT`.
      abstract contract UUPSUpgradeable {
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                       CUSTOM ERRORS                        */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev The upgrade failed.
          error UpgradeFailed();
          /// @dev The call is from an unauthorized call context.
          error UnauthorizedCallContext();
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                         IMMUTABLES                         */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev For checking if the context is a delegate call.
          uint256 private immutable __self = uint256(uint160(address(this)));
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                           EVENTS                           */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Emitted when the proxy's implementation is upgraded.
          event Upgraded(address indexed implementation);
          /// @dev `keccak256(bytes("Upgraded(address)"))`.
          uint256 private constant _UPGRADED_EVENT_SIGNATURE =
              0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b;
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                          STORAGE                           */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev The ERC-1967 storage slot for the implementation in the proxy.
          /// `uint256(keccak256("eip1967.proxy.implementation")) - 1`.
          bytes32 internal constant _ERC1967_IMPLEMENTATION_SLOT =
              0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
          /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
          /*                      UUPS OPERATIONS                       */
          /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
          /// @dev Please override this function to check if `msg.sender` is authorized
          /// to upgrade the proxy to `newImplementation`, reverting if not.
          /// ```
          ///     function _authorizeUpgrade(address) internal override onlyOwner {}
          /// ```
          function _authorizeUpgrade(address newImplementation) internal virtual;
          /// @dev Returns the storage slot used by the implementation,
          /// as specified in [ERC1822](https://eips.ethereum.org/EIPS/eip-1822).
          ///
          /// Note: The `notDelegated` modifier prevents accidental upgrades to
          /// an implementation that is a proxy contract.
          function proxiableUUID() public view virtual notDelegated returns (bytes32) {
              // This function must always return `_ERC1967_IMPLEMENTATION_SLOT` to comply with ERC1967.
              return _ERC1967_IMPLEMENTATION_SLOT;
          }
          /// @dev Upgrades the proxy's implementation to `newImplementation`.
          /// Emits a {Upgraded} event.
          ///
          /// Note: Passing in empty `data` skips the delegatecall to `newImplementation`.
          function upgradeToAndCall(address newImplementation, bytes calldata data)
              public
              payable
              virtual
              onlyProxy
          {
              _authorizeUpgrade(newImplementation);
              /// @solidity memory-safe-assembly
              assembly {
                  newImplementation := shr(96, shl(96, newImplementation)) // Clears upper 96 bits.
                  mstore(0x01, 0x52d1902d) // `proxiableUUID()`.
                  let s := _ERC1967_IMPLEMENTATION_SLOT
                  // Check if `newImplementation` implements `proxiableUUID` correctly.
                  if iszero(eq(mload(staticcall(gas(), newImplementation, 0x1d, 0x04, 0x01, 0x20)), s)) {
                      mstore(0x01, 0x55299b49) // `UpgradeFailed()`.
                      revert(0x1d, 0x04)
                  }
                  // Emit the {Upgraded} event.
                  log2(codesize(), 0x00, _UPGRADED_EVENT_SIGNATURE, newImplementation)
                  sstore(s, newImplementation) // Updates the implementation.
                  // Perform a delegatecall to `newImplementation` if `data` is non-empty.
                  if data.length {
                      // Forwards the `data` to `newImplementation` via delegatecall.
                      let m := mload(0x40)
                      calldatacopy(m, data.offset, data.length)
                      if iszero(delegatecall(gas(), newImplementation, m, data.length, codesize(), 0x00))
                      {
                          // Bubble up the revert if the call reverts.
                          returndatacopy(m, 0x00, returndatasize())
                          revert(m, returndatasize())
                      }
                  }
              }
          }
          /// @dev Requires that the execution is performed through a proxy.
          modifier onlyProxy() {
              uint256 s = __self;
              /// @solidity memory-safe-assembly
              assembly {
                  // To enable use cases with an immutable default implementation in the bytecode,
                  // (see: ERC6551Proxy), we don't require that the proxy address must match the
                  // value stored in the implementation slot, which may not be initialized.
                  if eq(s, address()) {
                      mstore(0x00, 0x9f03a026) // `UnauthorizedCallContext()`.
                      revert(0x1c, 0x04)
                  }
              }
              _;
          }
          /// @dev Requires that the execution is NOT performed via delegatecall.
          /// This is the opposite of `onlyProxy`.
          modifier notDelegated() {
              uint256 s = __self;
              /// @solidity memory-safe-assembly
              assembly {
                  if iszero(eq(s, address())) {
                      mstore(0x00, 0x9f03a026) // `UnauthorizedCallContext()`.
                      revert(0x1c, 0x04)
                  }
              }
              _;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.22;
      import {TokenStandard} from "../../common/Structs.sol";
      interface IMagicDropTokenImplRegistry {
          function registerImplementation(TokenStandard standard, address impl, bool isDefault, uint256 deploymentFee)
              external
              returns (uint32);
          function unregisterImplementation(TokenStandard standard, uint32 implId) external;
          function getImplementation(TokenStandard standard, uint32 implId) external view returns (address);
          function getDeploymentFee(TokenStandard standard, uint32 implId) external view returns (uint256);
          function setDeploymentFee(TokenStandard standard, uint32 implId, uint256 deploymentFee) external;
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
      pragma solidity ^0.8.0;
      /**
       * @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
      pragma solidity ^0.8.22;
      enum TokenStandard {
          ERC721,
          ERC1155,
          ERC20
      }
      struct MintStageInfo {
          uint80 price;
          uint80 mintFee;
          uint32 walletLimit; // 0 for unlimited
          bytes32 merkleRoot; // 0x0 for no presale enforced
          uint24 maxStageSupply; // 0 for unlimited
          uint256 startTimeUnixSeconds;
          uint256 endTimeUnixSeconds;
      }
      struct MintStageInfo1155 {
          uint80[] price;
          uint80[] mintFee;
          uint32[] walletLimit; // 0 for unlimited
          bytes32[] merkleRoot; // 0x0 for no presale enforced
          uint24[] maxStageSupply; // 0 for unlimited
          uint256 startTimeUnixSeconds;
          uint256 endTimeUnixSeconds;
      }