creation_sourcecode: // SPDX-License-Identifier: MIT
  
  pragma solidity ^0.7.0;
  
  /**
   * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
   * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
   * be specified by overriding the virtual {_implementation} function.
   *
   * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
   * different contract through the {_delegate} function.
   *
   * The success and return data of the delegated call will be returned back to the caller of the proxy.
   */
  abstract contract Proxy {
      /**
       * @dev Delegates the current call to `implementation`.
       *
       * This function does not return to its internall call site, it will return directly to the external caller.
       */
      function _delegate(address implementation) internal virtual {
          // solhint-disable-next-line no-inline-assembly
          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(0, 0, calldatasize())
  
              // Call the implementation.
              // out and outsize are 0 because we don't know the size yet.
              let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
  
              // Copy the returned data.
              returndatacopy(0, 0, returndatasize())
  
              switch result
              // delegatecall returns 0 on error.
              case 0 { revert(0, returndatasize()) }
              default { return(0, returndatasize()) }
          }
      }
  
      /**
       * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
       * and {_fallback} should delegate.
       */
      function _implementation() internal view virtual returns (address);
  
      /**
       * @dev Delegates the current call to the address returned by `_implementation()`.
       *
       * This function does not return to its internall call site, it will return directly to the external caller.
       */
      function _fallback() internal virtual {
          _beforeFallback();
          _delegate(_implementation());
      }
  
      /**
       * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
       * function in the contract matches the call data.
       */
      fallback () external payable virtual {
          _fallback();
      }
  
      /**
       * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
       * is empty.
       */
      receive () external payable virtual {
          _fallback();
      }
  
      /**
       * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
       * call, or as part of the Solidity `fallback` or `receive` functions.
       *
       * If overriden should call `super._beforeFallback()`.
       */
      function _beforeFallback() internal virtual {
      }
  }
  
  
  
  /**
   * @dev Collection of functions related to the address type
   */
  library Address {
      /**
       * @dev Returns true if `account` is a contract.
       *
       * [IMPORTANT]
       * ====
       * It is unsafe to assume that an address for which this function returns
       * false is an externally-owned account (EOA) and not a contract.
       *
       * Among others, `isContract` will return false for the following
       * types of addresses:
       *
       *  - an externally-owned account
       *  - a contract in construction
       *  - an address where a contract will be created
       *  - an address where a contract lived, but was destroyed
       * ====
       */
      function isContract(address account) internal view returns (bool) {
          // This method relies on extcodesize, which returns 0 for contracts in
          // construction, since the code is only stored at the end of the
          // constructor execution.
  
          uint256 size;
          // solhint-disable-next-line no-inline-assembly
          assembly { size := extcodesize(account) }
          return size > 0;
      }
  
      /**
       * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
       * `recipient`, forwarding all available gas and reverting on errors.
       *
       * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
       * of certain opcodes, possibly making contracts go over the 2300 gas limit
       * imposed by `transfer`, making them unable to receive funds via
       * `transfer`. {sendValue} removes this limitation.
       *
       * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
       *
       * IMPORTANT: because control is transferred to `recipient`, care must be
       * taken to not create reentrancy vulnerabilities. Consider using
       * {ReentrancyGuard} or the
       * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
       */
      function sendValue(address payable recipient, uint256 amount) internal {
          require(address(this).balance >= amount, "Address: insufficient balance");
  
          // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
          (bool success, ) = recipient.call{ value: amount }("");
          require(success, "Address: unable to send value, recipient may have reverted");
      }
  
      /**
       * @dev Performs a Solidity function call using a low level `call`. A
       * plain`call` is an unsafe replacement for a function call: use this
       * function instead.
       *
       * If `target` reverts with a revert reason, it is bubbled up by this
       * function (like regular Solidity function calls).
       *
       * Returns the raw returned data. To convert to the expected return value,
       * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
       *
       * Requirements:
       *
       * - `target` must be a contract.
       * - calling `target` with `data` must not revert.
       *
       * _Available since v3.1._
       */
      function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
      }
  
      /**
       * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
       * `errorMessage` as a fallback revert reason when `target` reverts.
       *
       * _Available since v3.1._
       */
      function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
          return functionCallWithValue(target, data, 0, errorMessage);
      }
  
      /**
       * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
       * but also transferring `value` wei to `target`.
       *
       * Requirements:
       *
       * - the calling contract must have an ETH balance of at least `value`.
       * - the called Solidity function must be `payable`.
       *
       * _Available since v3.1._
       */
      function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
          return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
      }
  
      /**
       * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
       * with `errorMessage` as a fallback revert reason when `target` reverts.
       *
       * _Available since v3.1._
       */
      function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
          require(address(this).balance >= value, "Address: insufficient balance for call");
          require(isContract(target), "Address: call to non-contract");
  
          // solhint-disable-next-line avoid-low-level-calls
          (bool success, bytes memory returndata) = target.call{ value: value }(data);
          return _verifyCallResult(success, returndata, errorMessage);
      }
  
      /**
       * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
       * but performing a static call.
       *
       * _Available since v3.3._
       */
      function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
          return functionStaticCall(target, data, "Address: low-level static call failed");
      }
  
      /**
       * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
       * but performing a static call.
       *
       * _Available since v3.3._
       */
      function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
          require(isContract(target), "Address: static call to non-contract");
  
          // solhint-disable-next-line avoid-low-level-calls
          (bool success, bytes memory returndata) = target.staticcall(data);
          return _verifyCallResult(success, returndata, errorMessage);
      }
  
      /**
       * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
       * but performing a delegate call.
       *
       * _Available since v3.4._
       */
      function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
          return functionDelegateCall(target, data, "Address: low-level delegate call failed");
      }
  
      /**
       * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
       * but performing a delegate call.
       *
       * _Available since v3.4._
       */
      function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
          require(isContract(target), "Address: delegate call to non-contract");
  
          // solhint-disable-next-line avoid-low-level-calls
          (bool success, bytes memory returndata) = target.delegatecall(data);
          return _verifyCallResult(success, returndata, errorMessage);
      }
  
      function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
          if (success) {
              return returndata;
          } else {
              // Look for revert reason and bubble it up if present
              if (returndata.length > 0) {
                  // The easiest way to bubble the revert reason is using memory via assembly
  
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      let returndata_size := mload(returndata)
                      revert(add(32, returndata), returndata_size)
                  }
              } else {
                  revert(errorMessage);
              }
          }
      }
  }
  
  
  /**
   * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
   * implementation address that can be changed. This address is stored in storage in the location specified by
   * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
   * implementation behind the proxy.
   *
   * Upgradeability is only provided internally through {_upgradeTo}. For an externally upgradeable proxy see
   * {TransparentUpgradeableProxy}.
   */
  contract UpgradeableProxy is Proxy {
      /**
       * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
       *
       * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
       * function call, and allows initializating the storage of the proxy like a Solidity constructor.
       */
      constructor(address _logic, bytes memory _data) payable {
          assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
          _setImplementation(_logic);
          if(_data.length > 0) {
              Address.functionDelegateCall(_logic, _data);
          }
      }
  
      /**
       * @dev Emitted when the implementation is upgraded.
       */
      event Upgraded(address indexed implementation);
  
      /**
       * @dev Storage slot with the address of the current implementation.
       * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
       * validated in the constructor.
       */
      bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
  
      /**
       * @dev Returns the current implementation address.
       */
      function _implementation() internal view virtual override returns (address impl) {
          bytes32 slot = _IMPLEMENTATION_SLOT;
          // solhint-disable-next-line no-inline-assembly
          assembly {
              impl := sload(slot)
          }
      }
  
      /**
       * @dev Upgrades the proxy to a new implementation.
       *
       * Emits an {Upgraded} event.
       */
      function _upgradeTo(address newImplementation) internal virtual {
          _setImplementation(newImplementation);
          emit Upgraded(newImplementation);
      }
  
      /**
       * @dev Stores a new address in the EIP1967 implementation slot.
       */
      function _setImplementation(address newImplementation) private {
          require(Address.isContract(newImplementation), "UpgradeableProxy: new implementation is not a contract");
  
          bytes32 slot = _IMPLEMENTATION_SLOT;
  
          // solhint-disable-next-line no-inline-assembly
          assembly {
              sstore(slot, newImplementation)
          }
      }
  }
  
  
  
  /**
   * @dev This contract implements a proxy that is upgradeable by an admin.
   *
   * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
   * clashing], which can potentially be used in an attack, this contract uses the
   * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
   * things that go hand in hand:
   *
   * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
   * that call matches one of the admin functions exposed by the proxy itself.
   * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
   * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
   * "admin cannot fallback to proxy target".
   *
   * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
   * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
   * to sudden errors when trying to call a function from the proxy implementation.
   *
   * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
   * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.
   */
  contract TransparentUpgradeableProxy is UpgradeableProxy {
      /**
       * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
       * optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.
       */
      constructor(address _logic, address admin_, bytes memory _data) payable UpgradeableProxy(_logic, _data) {
          assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
          _setAdmin(admin_);
      }
  
      /**
       * @dev Emitted when the admin account has changed.
       */
      event AdminChanged(address previousAdmin, address newAdmin);
  
      /**
       * @dev Storage slot with the admin of the contract.
       * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
       * validated in the constructor.
       */
      bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
  
      /**
       * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
       */
      modifier ifAdmin() {
          if (msg.sender == _admin()) {
              _;
          } else {
              _fallback();
          }
      }
  
      /**
       * @dev Returns the current admin.
       *
       * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.
       *
       * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
       * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
       * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
       */
      function admin() external ifAdmin returns (address admin_) {
          admin_ = _admin();
      }
  
      /**
       * @dev Returns the current implementation.
       *
       * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.
       *
       * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
       * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
       * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
       */
      function implementation() external ifAdmin returns (address implementation_) {
          implementation_ = _implementation();
      }
  
      /**
       * @dev Changes the admin of the proxy.
       *
       * Emits an {AdminChanged} event.
       *
       * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.
       */
      function changeAdmin(address newAdmin) external virtual ifAdmin {
          require(newAdmin != address(0), "TransparentUpgradeableProxy: new admin is the zero address");
          emit AdminChanged(_admin(), newAdmin);
          _setAdmin(newAdmin);
      }
  
      /**
       * @dev Upgrade the implementation of the proxy.
       *
       * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
       */
      function upgradeTo(address newImplementation) external virtual ifAdmin {
          _upgradeTo(newImplementation);
      }
  
      /**
       * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
       * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
       * proxied contract.
       *
       * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.
       */
      function upgradeToAndCall(address newImplementation, bytes calldata data) external payable virtual ifAdmin {
          _upgradeTo(newImplementation);
          Address.functionDelegateCall(newImplementation, data);
      }
  
      /**
       * @dev Returns the current admin.
       */
      function _admin() internal view virtual returns (address adm) {
          bytes32 slot = _ADMIN_SLOT;
          // solhint-disable-next-line no-inline-assembly
          assembly {
              adm := sload(slot)
          }
      }
  
      /**
       * @dev Stores a new address in the EIP1967 admin slot.
       */
      function _setAdmin(address newAdmin) private {
          bytes32 slot = _ADMIN_SLOT;
  
          // solhint-disable-next-line no-inline-assembly
          assembly {
              sstore(slot, newAdmin)
          }
      }
  
      /**
       * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.
       */
      function _beforeFallback() internal virtual override {
          require(msg.sender != _admin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target");
          super._beforeFallback();
      }
  }