contract UpgradeableCustomProxy 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() public payable {
        assert(_IMPLEMENTATION_STORAGE_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation_storage")) - 1));
    }

    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementationStorage);

    /**
     * @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_STORAGE_SLOT = 0x32966ed17b28d3117e87cb2c15a847a3829937667aa3286f41cf85a257e10460;

    /**
     * @dev Returns the current implementation address.
     */
    function _implementation() internal virtual override returns (address impl) {
        bytes32 slot = _IMPLEMENTATION_STORAGE_SLOT;
        address storage_address;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            storage_address := sload(slot)
        }
        impl = ImplementationGetter(storage_address).getImplementationAddress();
    }

    /**
     * @dev Upgrades the proxy to a new implementation.
     * 
     * Emits an {Upgraded} event.
     */
    function _upgradeStorageTo(address newImplementationStorage) virtual internal {
        _setImplementationStorage(newImplementationStorage);
        emit Upgraded(newImplementationStorage);
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementationStorage(address newImplementationStorage) private {
        bytes32 slot = _IMPLEMENTATION_STORAGE_SLOT;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            sstore(slot, newImplementationStorage)
        }
    }
}
/**
 * @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}.
 */
function _setImplementationStorage(address newImplementationStorage) private {
    bytes32 slot = _IMPLEMENTATION_STORAGE_SLOT;

    // solhint-disable-next-line no-inline-assembly
    assembly {
        sstore(slot, newImplementationStorage)
    }
}

/**
 * @dev Stores a new address in the EIP1967 implementation slot.
 */