// File: contracts/dlx.sol



// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @title: Back To The Future
/// @author: manifold.xyz

import "./manifold/ERC721Creator.sol";

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                                //
//                                                                                                                                //
//    8X8X888X8@888X888X8X8X8X8X8X8X8X8X8X888X888X888X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X888X888X888X888X    //
//    8S8888X888S88X888@@@@@@@@@@@@@@@@@@@888@888@888@8X8X@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@888@888@888@888X    //
//    888888888X@8XX8S888X888X888X888X888X8S88@@8@X8SX8@8XXXXX@XXX@XXX@XXX@XXX@XXX@XXX@XXX@XXX@XXX@XXX@XXX@XXX888@X8SX888@X8:S    //
//    888888@S888@8888888888888888888888888@8@8@@8888888@8888888888888888888888888888888888888888888888888888888@88888X8@88888    //
//    8S88X@8@8888@:@8XS@8@8@XXX@8@8@XXX@8@8888@SX@8@8@888888X888@:@8@888X888@:@8@888X888@:@8@888X888@:@8@888X88:S88@XX@8@8888    //
//    8888X88@88888%X@888@X@8@88888@8@8888888@88@88888888X88@88888888@88S88X88%8X888S88X88%8X888S88X88%8X888S888%8X88888888S@8    //
//    8S@88S8888888888@X88888888@8X8X88@@8888X@8@88888X@8888@888@X8S888X8@XS888@88@8:X8888S88X8@.X8888S88X8@88S88X8888;@X@888@    //
//    88@88@8@S888888888@888888@8@8@X@@88@888@8S88888@8@88X888888@@S88888X@8:88888S8XS8@S88@8888888888X88X@888888888S88888X888    //
//    8@8@S88@8@@X8@888;X88S888S8888X@88@8@8@8@888@88S888888888888@888@888888S@88X8S888888X888S8X888S8@8@8SX88@8@X888888888888    //
//    8888@@88888@888S88X@8X88@X8@XX88@88@8@88X@@88888@8S888888@8@8@8888X888X888@S888888X@S888X8@888@888S888@8XS888:X8X88@S8X8    //
//    888888@8S8888S888888XX@88@8888@88888@888@8@:@@@888@S8888S888S8:@888888@8888@8888@@S88.X8888S8888S88.X888888@@8@8XX88X88X    //
//    8X@8888888888@88888888888888:8888888S88X8@8@@888X@@8.@8888888@88X88888888X8@888X8888@8X@S888@888@8@88888@8XS@888888888@8    //
//    8888888888888888X8888:@X888888:X88@88@%88S88X88@8:X@@X8888888S888S@8S8X888888@8S8:@@8S88X88@@8X@@8888X88S@888888888888S8    //
//    88@S888888888S88X@@8X88888888888@888888888.8X888X8S888888S88X8S88888888S8888X8S888S8888888S8888888@88X888S@8888888888X88    //
//    88888888888;X8888;X@8:X888@8@X@8X8888@888888888X888S8@8888@X88X888888888.88888@888888888@88;88888888@X@8888@88@88888X88X    //
//    888S888888888X8;%8S88S8X8@8888@888@888X8888 888:S88@8XS888S888888888;X888S@8S88888X8888S888888@@S888@88888888;8XX:888SX8    //
//    888SS88@8S88@8X8X8X88888X8888XX8888888S@8888;8X88888@8S8888888888888SX8S@@8@8:@S88@8X8888888@8888.8X888@88@8@@S88X888888    //
//    8S@8@@888@88@8S888888@X88X8X8@888S8888t%t:;88@t88.@8888;X88S888@X888S888888S8888888@8@88@8888888888888@8@888S88@8888X888    //
//    88888@@S@S@88@8S8@8888X8888888888@@8SX@8SSX.8@88t888%8888@S@888888X8@@8@888X8@S@8@8@88888X8X8888X8X8888S88888X@X88@S8888    //
//    8S88@88888888S88.tX8888@88@S88S88@;:888SSXtSS8@8@8X8%8XX;:8X8888@S888SX8X8S@888@@S8888888X88.XS8888X88@@88.%88@8888@8888    //
//    8888@@:X8@8S8888S88888@8XX8:8S88@:8 8@SS888@  St88888 t:X88X8@XX@888S8;:@@@88X88888888X8S8.tX8888888888888S8@888@8888888    //
//    8X88888S@888888XS88@t88888S8S@X8X8St8@X@8t.@%X8888X8@888XX8 X@8@8@@;tS88888XX88@88@888@888XS88X8X88X@S8.@888888X8S8@888S    //
//    8888.@8888888@8S@;t@8S88@88X@X@@8SS88888.88 t 8.88%88S S8 @XX SSS8XSXXX@8X@888@88X888@@S88XX88@@88888@88@@88888X88.@X88@    //
//    8X@88S888888S8888@@8888S;8tSSSSXX8X8t8@88X.: @@88888;X@@@888S@88@X888S8S8@SXX88888888888@XX88888@S8888SX88XS8888888888@8    //
//    8888X888888888XX8S%%SS8%888888;8;XXS88@888@SXXX@;@;X8 .8@8t%8.8%t8;S8X888S888@@S@888888888888X888888@88S8@8@@888888;X888    //
//    8X8S8.@X88X88@@;X@%:88888@X88888888:88S8@@88S88SS@88 88%8%888X8888888888;8X88SS88888X8X88888X@88888888X888S8888S888S888X    //
//    888@@8X@X88@88X88StS8SXS8S888 8@8888:8.SXS@S8@88@X8;:888S88@8 @8888XSS@88Xt8S888S8S;888S8888X88@@88X88S888S8X8S888X8888S    //
//    8S88888S@S8X8SX888X8 S88888888S@;888S8;8t88888888%S@t8XX@t888888888888%8X888%:8@88X8S8%8X8S8X@8X8888888@8S8S8X88888888@8    //
//    88S8888888S@888X8S;X8 88888888%88S;;88S8%;@;8%8@@X@@tS@SXtXSS888888X88888SX88 8%8t;t88X88X8%XSX@8S8888888@8@X8X8S8888@8@    //
//    8@88@8888888888XXS8X8S888X88S@S88t%X@@8888888@888XXXS@@X@88888%8 8 @ @8 8888X 88 @ 8.8 8;88S8XX88S8888S8S@88888S@8888@88    //
//    888@@8X888@@8XX@%. :8888888tXXX88888888S8888@88S88@8@S888XStX@S@88@X888  @88888X88888 @ @.8;8X%88X@88X8X8888@888X8888S8@    //
//    8X88X88@888@888X8 8@ 88;%@t88SS88@88888 .888@8@8@8@@8@888X8@88@8;88.8X@@8@8888X888S8X88888 @ 8 .;;8S88XS888SX8@888@S888X    //
//    888888S@S:%8SX8 S%88%:S@8S8@8t8888@88X8t@88888@888888X88@8888@X@8SSt888@XS 8:;X8X88X@S@8888@88888.8;8%88888888X888@@X88@    //
//    88S88X8S88S8:8888X;;X.S@%@@8%8888@@tSS8XX8@88X8@8@%8XXXX8@8X@8S88S@8X88888t8888.:X8X;%@88 @ 8S888888 X 8:8X.8S@@8@@@8X8X    //
//    88888@88@X8  8%  ; %88@888%8;;;@8888@888@S ;88888t88 .8.8tS8X8;88888% :%%: t  .X;  S:% 8888888 8S8X@888  X%@8@:S@X88@@8X    //
//    8@8@888888SX888 ;%8X88%8888888888 8@ S8S@888:8:8@;;@ 888888 S88888X8888;::;;;:;t%X8XS8888888S8888888X8888SX88:88%@X88888    //
//    888S@88X888 888:8@S88@;8 888S8@888 88@S@@888XX:8.8%@.88@@88888%X 88S88888SSSXXXXSXXXXX888@8888X88XSS8@88888SX8t 8888S888    //
//    88S8X8@8 @X888:@888@.%8@888888X8888 88S@S8888@ .8@S888X88%X8@888S8S8 8 8888888888888888888 88888888888 88888X88@t8S88@X@    //
//    88@S888 @ S8%%.%;S88@8888888888888 8.X888X88%8 8888X88X@88X888%X% S88S.88X888888S88888888@S88888t%. 88  :%X8X 8S:@S888@S    //
//    @8X88888 8 888@8:88 88888X8tS8@@XS:% 8tX88@X888888X8SX%88S8XX8@St;:8Xt::t:888@8888X ;. ;S888X888%   %8;.;%8888 8::8@%S@8    //
//    888X8@; X X88@888%8 8888SS888888t8t8;8X8.88888S88@ 88888 %.%888@8888 88X:88888@8888@8@88XS@88@88X:@88;8@88X%8@8 8%;8X@88    //
//    888888;888888 :X.: %;8X888 888 8%@S8S88  8@X.8XX@XS88S 8;88@888888888888@88@888888888888888888888@88888888%;S8@8.8 8t.St    //
//    888@88S88;888S@XX8@X888;X88 888X@S8S 8888@S8 8SS%S888S888XSX@8SSXSS88XSX@88888S 88888@XXX@S8@%%t;XSXS%X888S8.@ 8;8:@.@S8    //
//    8888@SSX%8.@88@8   :8tS8@88888 8888X 888S8%:t :t8@.8888@@8@X@@@88888888888888Xt8@88S;8S8@:%@8S88@8888S88@88. 88;8@:S88X8    //
//    @888X888@88 88888@tSt88@8:t:88888S8%%X@8%88@:8;S8@t%@8@8888X@8@8@8X8X8X88XS8S88S8:8;:8X8S.@88@8@8X8@888S888XX8888888@8X@    //
//    8888X88S88t. 8@888%t88X@X8.: 8 8t8SS8S;88@St:X@S8S88  8% S@@@S88@XX@8@XXX8XX8@8@SX@S@X@88X8@88X@88XX88.88S8S8@8:88:8@8@8    //
//    @XX8@8X8888X8 @888  X8SSX88SS8@8t8@;8S8S8  t%X@X8X%@;88X8@XX@S8888888888@@88@888X8X@8@88@8@@X888888888t888888888:S8:8@88    //
//    @8S88@888 @8888@888S8%SX@S%%8X8X::. 8 8:.88@S;:888S%8SX8888@8888888@8XX8X88888888:8888@8888888:@;88X8:St 8888@8;88.88X@8    //
//    8X88@8S88t8 88X%8888@8888@888888:X. :888888%S@@X8XX@XS8:@S8888X8;;8;8;XSt:;;;t%%t8S%8.8888888X@8X8888X8S  888@8%8%@@8888    //
//    888@X88@%;t8@8888888.:@8888@888%8.St:8@8888: %8@XX@SS%@888@@8;8@@8@X8S88@888@888SXX8t%t@88X88X8S@SS8@XtS888888%@.@88@X88    //
//    888X8X8@@SX888X888888. 888X888;8:S  8 8X888S S8XSS8X@SS88@888@888@8@@8X88888.8S888888888SS88888@X888888888@@88%@88888888    //
//    88X8S8X8XX:8888X88 8t88S88@@S@X%St88:8 8SX8@8888888888@XS8S8888888888@888%8;8 8 8X 88888XX8888888@8 S8888SX8.X8@88888@88    //
//    88888888XX;8;SX8XX8S8t X8t8:8X8;8 888;X 8X888t:8888@888888X8X88X88888@ tS:;@X8XtS8XS8@@S@@@88888XX88X888@8888;8888@8XX@@    //
//    8X88X8888@X.@888@8 :8 88 SS  8@88:8X8X8 888888SX8X888888888S8X8X@888@@ ;@S88888@t%SX8X8SSXS88S@8@88%;.88888%t88888888@S8    //
//    88S88@88888Xt 88.88:%@@%8 X8@888@S8@;888 ;X8%8tX88@8888888888888X8888888@8X@@8X8888X88X88888@@888888@@% %%;%%8888@88888X    //
//    888888888@X@X;t8%8%8@@8X:8t888;@;8.X888%88888%@X@@8888S88X8@88S@8@X8888@8888X888@88@S@S88@888S88888888Xt  ;%XS88@8S8S888    //
//    8S8X@8888@888X@@8888888@@t;%%;.:.8S888t.88XSX8XX888@8X8S888S888@@S8@X8Xt@8S888S888S8@;88888888888@888S8S%X8S8@8@8888XS88    //
//    8888888@8@88@8S8S88@8888S@%%SXSSttSSStXttXX@8S8X888;t8@8@88@88X88@X8@8X888@88;@;8:8@X8888@8@S888S88888@888888@88XX@88@8X    //
//    88@88888S88888.X8@X8X888888888@X@X@@XXXX@X@@88S88S88X@8@88X8S8888888S8X8S88888@8S888:8888888:8888:X8888888@X8888S@88X888    //
//    8888888888@8@8S8@888888SX8X8XX@8@8@8X88S88@.XX8S88@@8X@88S8888X8@8@8@888888888888%8888888;@8@;@888S8S8S8S88@888X88X8888X    //
//    88X888X8@S888S8S8888@88@888888888888888888@888S888S8X8888@888888S@88S888:8S8.@88888888;X8X8@S88@888@88888@88888;8X8888S@    //
//    888X88X8X888S88@888888X@8888S8:XX888X88@S@8@888888@88888888:X888@88S88@X88@888X8888888888888@888XX8888S8888@88S8@@88@888    //
//    8S@8888S888888@8888:@888XX888@8X8888888X888S888X8@@8X88@888888;888@@;88@8@88@88@888S88@8@88888S8@X888@88X8@@88X888@X8:@8    //
//    88888X888888888X8888S88@S88@@888@S88@@X8888S8888888S888X88@8888S@88X8888888S8888@8X88@8888888888888X@88888X88888888888S8    //
//    8888@S888S888888888S888S888S888@XX8888@@XS888888888@88888888888@8X@8@8S888S@88888@8888S@888888X8888S8888@88@888:XX@:X888    //
//    888@8X8888@88888@8S8888@888888X888@888@8888X88.%88888@888888@88X@S88888S@88888@8888888@@8@@8X888888X888S8.@888888888S8S@    //
//    888XS8@88@@X@88X8@X8@888888X@8@888S8888XS8@8@88888X888@8XX888X@S88:@S88S88:888S88888888@8888888X88S8888888X8888:X888888     //
//    88888888888888S888@8888S@8888888S8888@S888X888S888S8888@888@888X888888888@88888@@888@88888@88888888@888@@@88888%8888@@8@    //
//    8888888888888888@88S888@S888@X@@8;888SX88XXX888.@888@8888X88888@S8888@8888@888S@X8@@888888888888888@888@888888888@X8@888    //
//    888X888S88888888X@@888S88888X8888%@@8888888.S.t8888@S8888888@88888@888@S@8888888X8888S888@X8888888SS8888:X88S8X@888X88:%    //
//    88@8888@888S8@S88;88888@88X88888@8@S88@888X88@X8@8S88:@888X888888888888@88S8S888X88X888888@8S@88X@8@X8X888:S888S888@S@8X    //
//    8888@888888888X88@S8.@@X8X8888888888@888@88888@@@888XX8888888S88S888@XX88888@8888888;X8S88X88.tX88@88888:t8S888@888@88@8    //
//                                                                                                                                //
//                                                                                                                                //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


contract dlx is ERC721Creator {
    constructor() ERC721Creator("Back To The Future", "dlx") {}
}

// File: contracts/manifold/ERC721Creator.sol



// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "@openzeppelin/contracts/proxy/Proxy.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/StorageSlot.sol";

contract ERC721Creator is Proxy {
    
    constructor(string memory name, string memory symbol) {
        assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = 0x5133522ea5A0494EcB83F26311A095DDD7a9D4b6;
        (bool success, ) = 0x5133522ea5A0494EcB83F26311A095DDD7a9D4b6.delegatecall(abi.encodeWithSignature("initialize(string,string)", name, symbol));
        require(success, "Initialization failed");
    }
        
    /**
     * @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 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @dev Returns the current implementation address.
     */
     function implementation() public view returns (address) {
        return _implementation();
    }

    function _implementation() internal override view returns (address) {
        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }    

}

// File: node_modules/@openzeppelin/contracts/proxy/Proxy.sol



// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)

pragma solidity ^0.8.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 internal call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        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 overridden 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 internal 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 overridden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {}
}

// File: node_modules/@openzeppelin/contracts/utils/Address.sol



// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @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
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 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://consensys.net/diligence/blog/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.8.0/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");

        (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 functionCallWithValue(target, data, 0, "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");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, 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) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, 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) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // 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
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

// File: node_modules/@openzeppelin/contracts/utils/StorageSlot.sol



// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
 * _Available since v4.9 for `string`, `bytes`._
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }
}