creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/interfaces/IERC2981Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC2981.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Interface for the NFT Royalty Standard.\n *\n * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal\n * support for royalty payments across all NFT marketplaces and ecosystem participants.\n *\n * _Available since v4.5._\n */\ninterface IERC2981Upgradeable is IERC165Upgradeable {\n    /**\n     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of\n     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.\n     */\n    function royaltyInfo(\n        uint256 tokenId,\n        uint256 salePrice\n    ) external view returns (address receiver, uint256 royaltyAmount);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/metatx/ERC2771ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (metatx/ERC2771Context.sol)\n\npragma solidity ^0.8.9;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Context variant with ERC2771 support.\n */\nabstract contract ERC2771ContextUpgradeable is Initializable, ContextUpgradeable {\n    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n    address private immutable _trustedForwarder;\n\n    /// @custom:oz-upgrades-unsafe-allow constructor\n    constructor(address trustedForwarder) {\n        _trustedForwarder = trustedForwarder;\n    }\n\n    function isTrustedForwarder(address forwarder) public view virtual returns (bool) {\n        return forwarder == _trustedForwarder;\n    }\n\n    function _msgSender() internal view virtual override returns (address sender) {\n        if (isTrustedForwarder(msg.sender) && msg.data.length >= 20) {\n            // The assembly code is more direct than the Solidity version using `abi.decode`.\n            /// @solidity memory-safe-assembly\n            assembly {\n                sender := shr(96, calldataload(sub(calldatasize(), 20)))\n            }\n        } else {\n            return super._msgSender();\n        }\n    }\n\n    function _msgData() internal view virtual override returns (bytes calldata) {\n        if (isTrustedForwarder(msg.sender) && msg.data.length >= 20) {\n            return msg.data[:msg.data.length - 20];\n        } else {\n            return super._msgData();\n        }\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721Upgradeable.sol\";\nimport \"./IERC721ReceiverUpgradeable.sol\";\nimport \"./extensions/IERC721MetadataUpgradeable.sol\";\nimport \"../../utils/AddressUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../utils/StringsUpgradeable.sol\";\nimport \"../../utils/introspection/ERC165Upgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable {\n    using AddressUpgradeable for address;\n    using StringsUpgradeable for uint256;\n\n    // Token name\n    string private _name;\n\n    // Token symbol\n    string private _symbol;\n\n    // Mapping from token ID to owner address\n    mapping(uint256 => address) private _owners;\n\n    // Mapping owner address to token count\n    mapping(address => uint256) private _balances;\n\n    // Mapping from token ID to approved address\n    mapping(uint256 => address) private _tokenApprovals;\n\n    // Mapping from owner to operator approvals\n    mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n    /**\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n     */\n    function __ERC721_init(string memory name_, string memory symbol_) internal onlyInitializing {\n        __ERC721_init_unchained(name_, symbol_);\n    }\n\n    function __ERC721_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {\n        return\n            interfaceId == type(IERC721Upgradeable).interfaceId ||\n            interfaceId == type(IERC721MetadataUpgradeable).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev See {IERC721-balanceOf}.\n     */\n    function balanceOf(address owner) public view virtual override returns (uint256) {\n        require(owner != address(0), \"ERC721: address zero is not a valid owner\");\n        return _balances[owner];\n    }\n\n    /**\n     * @dev See {IERC721-ownerOf}.\n     */\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n        address owner = _ownerOf(tokenId);\n        require(owner != address(0), \"ERC721: invalid token ID\");\n        return owner;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-name}.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-symbol}.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-tokenURI}.\n     */\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n        _requireMinted(tokenId);\n\n        string memory baseURI = _baseURI();\n        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n    }\n\n    /**\n     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n     * by default, can be overridden in child contracts.\n     */\n    function _baseURI() internal view virtual returns (string memory) {\n        return \"\";\n    }\n\n    /**\n     * @dev See {IERC721-approve}.\n     */\n    function approve(address to, uint256 tokenId) public virtual override {\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\n        require(to != owner, \"ERC721: approval to current owner\");\n\n        require(\n            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n            \"ERC721: approve caller is not token owner or approved for all\"\n        );\n\n        _approve(to, tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-getApproved}.\n     */\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\n        _requireMinted(tokenId);\n\n        return _tokenApprovals[tokenId];\n    }\n\n    /**\n     * @dev See {IERC721-setApprovalForAll}.\n     */\n    function setApprovalForAll(address operator, bool approved) public virtual override {\n        _setApprovalForAll(_msgSender(), operator, approved);\n    }\n\n    /**\n     * @dev See {IERC721-isApprovedForAll}.\n     */\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n        return _operatorApprovals[owner][operator];\n    }\n\n    /**\n     * @dev See {IERC721-transferFrom}.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\n        //solhint-disable-next-line max-line-length\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n\n        _transfer(from, to, tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\n        safeTransferFrom(from, to, tokenId, \"\");\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override {\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n        _safeTransfer(from, to, tokenId, data);\n    }\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * `data` is additional data, it has no specified format and it is sent in call to `to`.\n     *\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {\n        _transfer(from, to, tokenId);\n        require(_checkOnERC721Received(from, to, tokenId, data), \"ERC721: transfer to non ERC721Receiver implementer\");\n    }\n\n    /**\n     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\n     */\n    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n        return _owners[tokenId];\n    }\n\n    /**\n     * @dev Returns whether `tokenId` exists.\n     *\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n     *\n     * Tokens start existing when they are minted (`_mint`),\n     * and stop existing when they are burned (`_burn`).\n     */\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\n        return _ownerOf(tokenId) != address(0);\n    }\n\n    /**\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\n        return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n    }\n\n    /**\n     * @dev Safely mints `tokenId` and transfers it to `to`.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeMint(address to, uint256 tokenId) internal virtual {\n        _safeMint(to, tokenId, \"\");\n    }\n\n    /**\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n     */\n    function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {\n        _mint(to, tokenId);\n        require(\n            _checkOnERC721Received(address(0), to, tokenId, data),\n            \"ERC721: transfer to non ERC721Receiver implementer\"\n        );\n    }\n\n    /**\n     * @dev Mints `tokenId` and transfers it to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - `to` cannot be the zero address.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _mint(address to, uint256 tokenId) internal virtual {\n        require(to != address(0), \"ERC721: mint to the zero address\");\n        require(!_exists(tokenId), \"ERC721: token already minted\");\n\n        _beforeTokenTransfer(address(0), to, tokenId, 1);\n\n        // Check that tokenId was not minted by `_beforeTokenTransfer` hook\n        require(!_exists(tokenId), \"ERC721: token already minted\");\n\n        unchecked {\n            // Will not overflow unless all 2**256 token ids are minted to the same owner.\n            // Given that tokens are minted one by one, it is impossible in practice that\n            // this ever happens. Might change if we allow batch minting.\n            // The ERC fails to describe this case.\n            _balances[to] += 1;\n        }\n\n        _owners[tokenId] = to;\n\n        emit Transfer(address(0), to, tokenId);\n\n        _afterTokenTransfer(address(0), to, tokenId, 1);\n    }\n\n    /**\n     * @dev Destroys `tokenId`.\n     * The approval is cleared when the token is burned.\n     * This is an internal function that does not check if the sender is authorized to operate on the token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _burn(uint256 tokenId) internal virtual {\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\n\n        _beforeTokenTransfer(owner, address(0), tokenId, 1);\n\n        // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook\n        owner = ERC721Upgradeable.ownerOf(tokenId);\n\n        // Clear approvals\n        delete _tokenApprovals[tokenId];\n\n        unchecked {\n            // Cannot overflow, as that would require more tokens to be burned/transferred\n            // out than the owner initially received through minting and transferring in.\n            _balances[owner] -= 1;\n        }\n        delete _owners[tokenId];\n\n        emit Transfer(owner, address(0), tokenId);\n\n        _afterTokenTransfer(owner, address(0), tokenId, 1);\n    }\n\n    /**\n     * @dev Transfers `tokenId` from `from` to `to`.\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\n        require(ERC721Upgradeable.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n        require(to != address(0), \"ERC721: transfer to the zero address\");\n\n        _beforeTokenTransfer(from, to, tokenId, 1);\n\n        // Check that tokenId was not transferred by `_beforeTokenTransfer` hook\n        require(ERC721Upgradeable.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n\n        // Clear approvals from the previous owner\n        delete _tokenApprovals[tokenId];\n\n        unchecked {\n            // `_balances[from]` cannot overflow for the same reason as described in `_burn`:\n            // `from`'s balance is the number of token held, which is at least one before the current\n            // transfer.\n            // `_balances[to]` could overflow in the conditions described in `_mint`. That would require\n            // all 2**256 token ids to be minted, which in practice is impossible.\n            _balances[from] -= 1;\n            _balances[to] += 1;\n        }\n        _owners[tokenId] = to;\n\n        emit Transfer(from, to, tokenId);\n\n        _afterTokenTransfer(from, to, tokenId, 1);\n    }\n\n    /**\n     * @dev Approve `to` to operate on `tokenId`\n     *\n     * Emits an {Approval} event.\n     */\n    function _approve(address to, uint256 tokenId) internal virtual {\n        _tokenApprovals[tokenId] = to;\n        emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId);\n    }\n\n    /**\n     * @dev Approve `operator` to operate on all of `owner` tokens\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\n        require(owner != operator, \"ERC721: approve to caller\");\n        _operatorApprovals[owner][operator] = approved;\n        emit ApprovalForAll(owner, operator, approved);\n    }\n\n    /**\n     * @dev Reverts if the `tokenId` has not been minted yet.\n     */\n    function _requireMinted(uint256 tokenId) internal view virtual {\n        require(_exists(tokenId), \"ERC721: invalid token ID\");\n    }\n\n    /**\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n     * The call is not executed if the target address is not a contract.\n     *\n     * @param from address representing the previous owner of the given token ID\n     * @param to target address that will receive the tokens\n     * @param tokenId uint256 ID of the token to be transferred\n     * @param data bytes optional data to send along with the call\n     * @return bool whether the call correctly returned the expected magic value\n     */\n    function _checkOnERC721Received(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) private returns (bool) {\n        if (to.isContract()) {\n            try IERC721ReceiverUpgradeable(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\n                return retval == IERC721ReceiverUpgradeable.onERC721Received.selector;\n            } catch (bytes memory reason) {\n                if (reason.length == 0) {\n                    revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n                } else {\n                    /// @solidity memory-safe-assembly\n                    assembly {\n                        revert(add(32, reason), mload(reason))\n                    }\n                }\n            }\n        } else {\n            return true;\n        }\n    }\n\n    /**\n     * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n     *\n     * Calling conditions:\n     *\n     * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.\n     * - When `from` is zero, the tokens will be minted for `to`.\n     * - When `to` is zero, ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     * - `batchSize` is non-zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n     *\n     * Calling conditions:\n     *\n     * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.\n     * - When `from` is zero, the tokens were minted for `to`.\n     * - When `to` is zero, ``from``'s tokens were burned.\n     * - `from` and `to` are never both zero.\n     * - `batchSize` is non-zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}\n\n    /**\n     * @dev Unsafe write access to the balances, used by extensions that \"mint\" tokens using an {ownerOf} override.\n     *\n     * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant\n     * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such\n     * that `ownerOf(tokenId)` is `a`.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function __unsafe_increaseBalance(address account, uint256 amount) internal {\n        _balances[account] += amount;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[44] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721Upgradeable.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721MetadataUpgradeable is IERC721Upgradeable {\n    /**\n     * @dev Returns the token collection name.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the token collection symbol.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n     */\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721ReceiverUpgradeable {\n    /**\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n     * by `operator` from `from`, this function is called.\n     *\n     * It must return its Solidity selector to confirm the token transfer.\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n     *\n     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n     */\n    function onERC721Received(\n        address operator,\n        address from,\n        uint256 tokenId,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721Upgradeable is IERC165Upgradeable {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n     * understand this adds an external call which potentially creates a reentrancy vulnerability.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the caller.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165Upgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\n    function __ERC165_init() internal onlyInitializing {\n    }\n\n    function __ERC165_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165Upgradeable).interfaceId;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165Upgradeable {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary MathUpgradeable {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, \"Math: mulDiv overflow\");\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMathUpgradeable {\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // must be unchecked in order to support `n = type(int256).min`\n            return uint256(n >= 0 ? n : -n);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/MathUpgradeable.sol\";\nimport \"./math/SignedMathUpgradeable.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary StringsUpgradeable {\n    bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n    uint8 private constant _ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = MathUpgradeable.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toString(int256 value) internal pure returns (string memory) {\n        return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMathUpgradeable.abs(value))));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, MathUpgradeable.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(IERC20 token, address spender, uint256 value) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n     * Revert on invalid signature.\n     */\n    function safePermit(\n        IERC20Permit token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return\n            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, \"Math: mulDiv overflow\");\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/math/SignedMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // must be unchecked in order to support `n = type(int256).min`\n            return uint256(n >= 0 ? n : -n);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Strings.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n    uint8 private constant _ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toString(int256 value) internal pure returns (string memory) {\n        return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n}\n"
      },
      "contracts/domain/BosonConstants.sol": {
        "content": "import \"./BosonTypes.sol\";\n\n// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\n// Access Control Roles\nbytes32 constant ADMIN = keccak256(\"ADMIN\"); // Role Admin\nbytes32 constant PAUSER = keccak256(\"PAUSER\"); // Role for pausing the protocol\nbytes32 constant PROTOCOL = keccak256(\"PROTOCOL\"); // Role for facets of the ProtocolDiamond\nbytes32 constant CLIENT = keccak256(\"CLIENT\"); // Role for clients of the ProtocolDiamond\nbytes32 constant UPGRADER = keccak256(\"UPGRADER\"); // Role for performing contract and config upgrades\nbytes32 constant FEE_COLLECTOR = keccak256(\"FEE_COLLECTOR\"); // Role for collecting fees from the protocol\n\n// Generic\nuint256 constant HUNDRED_PERCENT = 10000; // 100% in basis points\n\n// Pause Handler\nuint256 constant ALL_REGIONS_MASK = (1 << (uint256(type(BosonTypes.PausableRegion).max) + 1)) - 1;\n\n// Reentrancy guard\nuint256 constant NOT_ENTERED = 1;\nuint256 constant ENTERED = 2;\n\n// Twin handler\nuint256 constant SINGLE_TWIN_RESERVED_GAS = 160000;\nuint256 constant MINIMAL_RESIDUAL_GAS = 230000;\n\n// Config related\nbytes32 constant VOUCHER_PROXY_SALT = keccak256(abi.encodePacked(\"BosonVoucherProxy\"));\n\n// Funds related\nstring constant NATIVE_CURRENCY = \"Native currency\";\nstring constant TOKEN_NAME_UNSPECIFIED = \"Token name unavailable\";\n\n// EIP712Lib\nstring constant PROTOCOL_NAME = \"Boson Protocol\";\nstring constant PROTOCOL_VERSION = \"V2\";\nbytes32 constant EIP712_DOMAIN_TYPEHASH = keccak256(\n    bytes(\"EIP712Domain(string name,string version,address verifyingContract,bytes32 salt)\")\n);\n\n// BosonVoucher\nstring constant VOUCHER_NAME = \"Boson Voucher (rNFT)\";\nstring constant VOUCHER_SYMBOL = \"BOSON_VOUCHER_RNFT\";\n\n// Meta Transactions - Error\nstring constant FUNCTION_CALL_NOT_SUCCESSFUL = \"Function call not successful\";\n\n// External contracts errors\nstring constant OWNABLE_ZERO_ADDRESS = \"Ownable: new owner is the zero address\"; // exception message from OpenZeppelin Ownable\nstring constant ERC721_INVALID_TOKEN_ID = \"ERC721: invalid token ID\"; // exception message from OpenZeppelin ERC721\n\n// Meta Transactions - Structs\nbytes32 constant META_TRANSACTION_TYPEHASH = keccak256(\n    bytes(\n        \"MetaTransaction(uint256 nonce,address from,address contractAddress,string functionName,bytes functionSignature)\"\n    )\n);\nbytes32 constant OFFER_DETAILS_TYPEHASH = keccak256(\"MetaTxOfferDetails(address buyer,uint256 offerId)\");\nbytes32 constant META_TX_COMMIT_TO_OFFER_TYPEHASH = keccak256(\n    \"MetaTxCommitToOffer(uint256 nonce,address from,address contractAddress,string functionName,MetaTxOfferDetails offerDetails)MetaTxOfferDetails(address buyer,uint256 offerId)\"\n);\nbytes32 constant CONDITIONAL_OFFER_DETAILS_TYPEHASH = keccak256(\n    \"MetaTxConditionalOfferDetails(address buyer,uint256 offerId,uint256 tokenId)\"\n);\nbytes32 constant META_TX_COMMIT_TO_CONDITIONAL_OFFER_TYPEHASH = keccak256(\n    \"MetaTxCommitToConditionalOffer(uint256 nonce,address from,address contractAddress,string functionName,MetaTxConditionalOfferDetails offerDetails)MetaTxConditionalOfferDetails(address buyer,uint256 offerId,uint256 tokenId)\"\n);\nbytes32 constant EXCHANGE_DETAILS_TYPEHASH = keccak256(\"MetaTxExchangeDetails(uint256 exchangeId)\");\nbytes32 constant META_TX_EXCHANGE_TYPEHASH = keccak256(\n    \"MetaTxExchange(uint256 nonce,address from,address contractAddress,string functionName,MetaTxExchangeDetails exchangeDetails)MetaTxExchangeDetails(uint256 exchangeId)\"\n);\nbytes32 constant FUND_DETAILS_TYPEHASH = keccak256(\n    \"MetaTxFundDetails(uint256 entityId,address[] tokenList,uint256[] tokenAmounts)\"\n);\nbytes32 constant META_TX_FUNDS_TYPEHASH = keccak256(\n    \"MetaTxFund(uint256 nonce,address from,address contractAddress,string functionName,MetaTxFundDetails fundDetails)MetaTxFundDetails(uint256 entityId,address[] tokenList,uint256[] tokenAmounts)\"\n);\nbytes32 constant DISPUTE_RESOLUTION_DETAILS_TYPEHASH = keccak256(\n    \"MetaTxDisputeResolutionDetails(uint256 exchangeId,uint256 buyerPercentBasisPoints,bytes32 sigR,bytes32 sigS,uint8 sigV)\"\n);\nbytes32 constant META_TX_DISPUTE_RESOLUTIONS_TYPEHASH = keccak256(\n    \"MetaTxDisputeResolution(uint256 nonce,address from,address contractAddress,string functionName,MetaTxDisputeResolutionDetails disputeResolutionDetails)MetaTxDisputeResolutionDetails(uint256 exchangeId,uint256 buyerPercentBasisPoints,bytes32 sigR,bytes32 sigS,uint8 sigV)\"\n);\n\n// Function names\nstring constant COMMIT_TO_OFFER = \"commitToOffer(address,uint256)\";\nstring constant COMMIT_TO_CONDITIONAL_OFFER = \"commitToConditionalOffer(address,uint256,uint256)\";\nstring constant CANCEL_VOUCHER = \"cancelVoucher(uint256)\";\nstring constant REDEEM_VOUCHER = \"redeemVoucher(uint256)\";\nstring constant COMPLETE_EXCHANGE = \"completeExchange(uint256)\";\nstring constant WITHDRAW_FUNDS = \"withdrawFunds(uint256,address[],uint256[])\";\nstring constant RETRACT_DISPUTE = \"retractDispute(uint256)\";\nstring constant RAISE_DISPUTE = \"raiseDispute(uint256)\";\nstring constant ESCALATE_DISPUTE = \"escalateDispute(uint256)\";\nstring constant RESOLVE_DISPUTE = \"resolveDispute(uint256,uint256,bytes32,bytes32,uint8)\";\n"
      },
      "contracts/domain/BosonErrors.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport { BosonTypes } from \"./BosonTypes.sol\";\n\ninterface BosonErrors {\n    // Pause related\n    // Trying to unpause a protocol when it's not paused\n    error NotPaused();\n    // Whenever a region is paused, and a method from that region is called\n    error RegionPaused(BosonTypes.PausableRegion region);\n\n    // General\n    // Input parameter of type address is zero address\n    error InvalidAddress();\n    // Exchange or dispute is in different state than expected when certain action is called\n    error InvalidState();\n    // Two or more array parameters with different lengths\n    error ArrayLengthMismatch();\n\n    // Reentrancy guard\n    // Reentrancy guard is active and second call to protocol is made\n    error ReentrancyGuard();\n\n    // Protocol initialization related\n    // Trying to initialize the facet when it's already initialized\n    error AlreadyInitialized(); // ToDo consider adding the facet to the error message\n    // Initialization of some facet failed\n    error ProtocolInitializationFailed(); // ToDo consider adding the facet to the error message\n    // Trying to initialize the protocol with empty version\n    error VersionMustBeSet();\n    // Length of _addresses and _calldata arrays do not match\n    error AddressesAndCalldataLengthMismatch(); // ToDo consider reusing ArrayLengthMismatch\n    // The new protocol version is not subsequent to the current one\n    error WrongCurrentVersion();\n    // Initialization can be done only through proxy\n    error DirectInitializationNotAllowed();\n    // Initialization of v2.3.0 can be done only if not twin exists\n    error TwinsAlreadyExist();\n\n    // Access related\n    // ToDo consider having a single error, with a parameter for the role\n    // Caller is not authorized to call the method\n    error AccessDenied();\n    // Caller is not entitiy's assistant\n    error NotAssistant();\n    // Caller is not entitiy's admin\n    error NotAdmin();\n    // Caller is not entitiy's admin and assistant\n    error NotAdminAndAssistant();\n    // Caller is neither the buyer or the seller involved in the exchange\n    error NotBuyerOrSeller();\n    // Caller is not the owner of the voucher\n    error NotVoucherHolder();\n    // Caller is not the buyer\n    error NotBuyerWallet();\n    // Caller is not the agent\n    error NotAgentWallet();\n    // Caller is not dispute resolver assistant\n    error NotDisputeResolverAssistant();\n    // Supplied clerk is not zero address\n    error ClerkDeprecated();\n\n    // Account-related\n    // Entity must be active\n    error MustBeActive();\n    // Seller's address cannot be already used in another seller\n    error SellerAddressMustBeUnique();\n    // Buyer's address cannot be already used in another buyer\n    error BuyerAddressMustBeUnique();\n    // DR's address cannot be already used in another DR\n    error DisputeResolverAddressMustBeUnique();\n    // Agent's address cannot be already used in another agent\n    error AgentAddressMustBeUnique();\n    // Seller does not exist\n    error NoSuchSeller();\n    // Buyer does not exist\n    error NoSuchBuyer();\n    // Dispute resolver does not exist\n    error NoSuchDisputeResolver();\n    // Agent does not exist\n    error NoSuchAgent();\n    // Buyer is involved in an non-finalized exchange\n    error WalletOwnsVouchers();\n    // Escalation period is not greater than zero or is more than the max allowed\n    error InvalidEscalationPeriod();\n    // Action would remove the last supported fee from the DR (must always have at least one)\n    error InexistentDisputeResolverFees();\n    // Trying to add a fee that already exists\n    error DuplicateDisputeResolverFees();\n    // Trying to add a fee with non-zero amount\n    error FeeAmountNotYetSupported();\n    // Trying to remove a fee that does not exist\n    error DisputeResolverFeeNotFound();\n    // Trying to approve a seller that is already approved (list of sellers that DR will handle disputes for)\n    error SellerAlreadyApproved();\n    // Trying to assing a DR that had not approved the seller\n    error SellerNotApproved();\n    // Trying to add or removed 0 sellers\n    error InexistentAllowedSellersList();\n    // Custom auth token is not yet supported\n    error InvalidAuthTokenType();\n    // Seller must use either and address or auth token for authentication, but not both\n    error AdminOrAuthToken();\n    // A single auth token can only be used by one seller\n    error AuthTokenMustBeUnique();\n    // Sum of protocol and agent fee exceed the max allowed fee\n    error InvalidAgentFeePercentage();\n    // Trying to finalize the update, while it's not even started\n    error NoPendingUpdateForAccount();\n    // Only the account itself can finalize the update\n    error UnauthorizedCallerUpdate();\n    // Trying to update the account with the same values\n    error NoUpdateApplied();\n    // Creating a seller's collection failed\n    error CloneCreationFailed();\n    // Seller's salt is already used by another seller\n    error SellerSaltNotUnique();\n\n    // Offer related\n    // Offer does not exist\n    error NoSuchOffer();\n    // Offer finishes in the past or it starts after it finishes\n    error InvalidOfferPeriod();\n    // Buyer cancellation penalty is higher than the item price\n    error InvalidOfferPenalty();\n    // New offer must be actiove\n    error OfferMustBeActive();\n    // Offer can be added to same group only once\n    error OfferMustBeUnique();\n    // Offer has been voided\n    error OfferHasBeenVoided();\n    // Current timestamp is higher than offer's expiry timestamp\n    error OfferHasExpired();\n    // Current timestamp is lower than offer's start timestamp\n    error OfferNotAvailable();\n    // Offer's quantity available is zero\n    error OfferSoldOut();\n    // Buyer is not allowed to commit to the offer (does not meet the token gating requirements)\n    error CannotCommit();\n    // Bundle cannot be created since exchganes for offer exist already\n    error ExchangeForOfferExists();\n    // Voucher must have either a fixed expiry or a fixed redeemable period, not both\n    error AmbiguousVoucherExpiry();\n    // Redemption period starts after it ends or it ends before offer itself expires\n    error InvalidRedemptionPeriod();\n    // Dispute period is less than minimal dispute period allowed\n    error InvalidDisputePeriod();\n    // Resolution period is not within the allowed range or it's being misconfigured (minimal > maximal)\n    error InvalidResolutionPeriod();\n    // Dispute resolver does not exist or is not active\n    error InvalidDisputeResolver();\n    // Quantity available is zero\n    error InvalidQuantityAvailable();\n    // Chose DR does not support the fees in the chosen exchange token\n    error DRUnsupportedFee();\n    // Sum of protocol and agent fee exceeds the max allowed fee\n    error AgentFeeAmountTooHigh();\n    // Sum of protocol and agent fee exceeds the seller defined max fee\n    error TotalFeeExceedsLimit();\n    // Collection does not exist\n    error NoSuchCollection();\n    // Royalty recipient is not allow listed for the seller\n    error InvalidRoyaltyRecipient();\n    // Total royality fee exceeds the max allowed\n    error InvalidRoyaltyPercentage();\n    // Specified royalty recipient already added\n    error RecipientNotUnique();\n    // Trying to access an out of bounds royalty recipient\n    error InvalidRoyaltyRecipientId();\n    // Array of royalty recipients is not sorted by id\n    error RoyaltyRecipientIdsNotSorted();\n    // Trying to remove the default recipient (treasury)\n    error CannotRemoveDefaultRecipient();\n    // Supplying too many Royalty info structs\n    error InvalidRoyaltyInfo();\n    // Trying to change the default recipient address (treasury)\n    error WrongDefaultRecipient();\n    // Price discovery offer has non zero price\n    error InvalidPriceDiscoveryPrice();\n\n    // Group related\n    // Group does not exist\n    error NoSuchGroup();\n    // Offer is not in a group\n    error OfferNotInGroup();\n    // Group remains the same\n    error NothingUpdated();\n    // There is a logical error in the group's condition parameters or it's not supported yet\n    error InvalidConditionParameters();\n    // Group does not have a condition\n    error GroupHasNoCondition();\n    // Group has a condition\n    error GroupHasCondition();\n    // User exhaused the number of commits allowed for the group\n    error MaxCommitsReached();\n    // The supplied token id is outside the condition's range\n    error TokenIdNotInConditionRange();\n    // ERC20 and ERC721 require zero token id\n    error InvalidTokenId();\n\n    // Exchange related\n    // Exchange does not exist\n    error NoSuchExchange();\n    // Exchange cannot be completed yet\n    error DisputePeriodNotElapsed();\n    // Current timestamp is outside the voucher's redeemable period\n    error VoucherNotRedeemable();\n    // New expiration date is earlier than existing expiration date\n    error VoucherExtensionNotValid();\n    // Voucher cannot be expired yet\n    error VoucherStillValid();\n    // Voucher has expired and cannot be transferred anymore\n    error VoucherHasExpired();\n    // Exchange has not been finalized yet\n    error ExchangeIsNotInAFinalState();\n    // Exchange with the same id already exists\n    error ExchangeAlreadyExists();\n    // Range length is 0, is more than quantity available or it would cause an overflow\n    error InvalidRangeLength();\n    // Exchange is being finalized into an invalid state\n    error InvalidTargeExchangeState();\n\n    // Twin related\n    // Twin does not exist\n    error NoSuchTwin();\n    // Seller did not approve the twin transfer\n    error NoTransferApproved();\n    // Twin transfer failed\n    error TwinTransferUnsuccessful();\n    // Token address is 0 or it does not implement the required interface\n    error UnsupportedToken();\n    // Twin cannot be removed if it's in a bundle\n    error BundleForTwinExists();\n    // Supply available is zero\n    error InvalidSupplyAvailable();\n    // Twin is Fungible or Multitoken and amount was set\n    error InvalidAmount();\n    // Twin is NonFungible and amount was not set\n    error InvalidTwinProperty(); // ToDo consider replacing with InvalidAmount\n    // Token range overlap with another, starting token id is too high or end of range would overflow\n    error InvalidTwinTokenRange();\n    // Token does not support IERC721 interface\n    error InvalidTokenAddress();\n\n    // Bundle related\n    // Bundle does not exist\n    error NoSuchBundle();\n    // Twin is not in a bundle\n    error TwinNotInBundle();\n    // Offer is not in a bundle\n    error OfferNotInBundle();\n    // Offer can appear in a bundle only once\n    error BundleOfferMustBeUnique();\n    // Twin can appear in a bundle only once\n    error BundleTwinMustBeUnique();\n    // Twin supply does not covver all offers in the bundle\n    error InsufficientTwinSupplyToCoverBundleOffers();\n    // Bundle cannot be created without an offer or a twin\n    error BundleRequiresAtLeastOneTwinAndOneOffer();\n\n    // Funds related\n    // Native token must be represented with zero address\n    error NativeWrongAddress();\n    // Amount sent along (msg.value) does not match the expected amount\n    error NativeWrongAmount();\n    // Token list lenght does not match the amount list length\n    error TokenAmountMismatch(); // ToDo consider replacing with ArrayLengthMismatch\n    // Token list is empty\n    error NothingToWithdraw();\n    // Call is not allowed to transfer the funds\n    error NotAuthorized();\n    // Token transfer failed\n    error TokenTransferFailed();\n    // Received amount does not match the expected amount\n    error InsufficientValueReceived();\n    // Seller's pool does not have enough funds to encumber\n    error InsufficientAvailableFunds();\n    // Native token was sent when ERC20 was expected\n    error NativeNotAllowed();\n    // Trying to deposit zero amount\n    error ZeroDepositNotAllowed();\n\n    // Meta-Transactions related\n    // Meta-transaction nonce is invalid\n    error NonceUsedAlready();\n    // Signature does not match the signer\n    error SignerAndSignatureDoNotMatch();\n    // Function signature does not match it's name\n    error InvalidFunctionName();\n    // Signature has invalid parameters\n    error InvalidSignature();\n    // Function is not allowed to be executed as a meta-transaction\n    error FunctionNotAllowlisted();\n\n    // Dispute related\n    // Dispute cannot be raised since the period to do it has elapsed\n    error DisputePeriodHasElapsed();\n    // Dispute cannot be resolved anymore and must be finalized with expireDispute\n    error DisputeHasExpired();\n    // Buyer gets more than 100% of the total pot\n    error InvalidBuyerPercent();\n    // Dispute is still valid and cannot be expired yet\n    error DisputeStillValid();\n    // New dispute timeout is earlier than existing dispute timeout\n    error InvalidDisputeTimeout();\n    // Absolute zero offers cannot be escalated\n    error EscalationNotAllowed();\n    // Dispute is being finalized into an invalid state\n    error InvalidTargeDisputeState();\n\n    // Config related\n    // Percentage exceeds 100%\n    error InvalidFeePercentage();\n    // Zero config value is not allowed\n    error ValueZeroNotAllowed();\n\n    // BosonVoucher\n    // Trying to issue an voucher that is in a reseverd range\n    error ExchangeIdInReservedRange();\n    // Trying to premint vouchers for an offer that does not have a reserved range\n    error NoReservedRangeForOffer();\n    // Trying to reserve a range that is already reserved\n    error OfferRangeAlreadyReserved();\n    // Range start at 0 is not allowed\n    error InvalidRangeStart();\n    // Amount to premint exceeds the range length\n    error InvalidAmountToMint();\n    // Trying to silent mint vouchers not belonging to the range owner\n    error NoSilentMintAllowed();\n    // Trying to premint the voucher of already expired offer\n    error OfferExpiredOrVoided();\n    // Trying to burn preminted vouchers of still valid offer\n    error OfferStillValid();\n    // Trying to burn more vouchers than available\n    error AmountExceedsRangeOrNothingToBurn();\n    // Royalty fee exceeds the max allowed\n    error InvalidRoyaltyFee();\n    // Trying to assign the premined vouchers to the address that is neither the contract owner nor the contract itself\n    error InvalidToAddress();\n    // Call to an external contract was not successful\n    error ExternalCallFailed();\n    // Trying to interact with external contract in a way that could result in transferring assets from the contract\n    error InteractionNotAllowed();\n\n    // Price discovery related\n    // Price discovery returned a price that does not match the expected one\n    error PriceMismatch();\n    // Token id is mandatory for bid orders and wrappers\n    error TokenIdMandatory();\n    // Incoming token id does not match the expected one\n    error TokenIdMismatch();\n    // Using price discovery for non-price discovery offer or using ordinary commit for price discovery offer\n    error InvalidPriceType();\n    // Missing price discovery contract address or data\n    error InvalidPriceDiscovery();\n    // Trying to set incoming voucher when it's already set, indicating reentrancy\n    error IncomingVoucherAlreadySet();\n    // Conduit address must be zero ()\n    error InvalidConduitAddress();\n    // Protocol does not know what token id to use\n    error TokenIdNotSet();\n    // Transferring a preminted voucher to wrong recipient\n    error VoucherTransferNotAllowed();\n    // Price discovery contract returned a negative price\n    error NegativePriceNotAllowed();\n    // Price discovery did not send the voucher to the protocol\n    error VoucherNotReceived();\n    // Price discovery did not send the voucher from the protocol\n    error VoucherNotTransferred();\n    // Either token with wrong id received or wrong voucher contract made the transfer\n    error UnexpectedERC721Received();\n    // Royalty fee exceeds the price\n    error FeeAmountTooHigh();\n    // Price does not cover the cancellation penalty\n    error PriceDoesNotCoverPenalty();\n}\n"
      },
      "contracts/domain/BosonTypes.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\n/**\n * @title BosonTypes\n *\n * @notice Enums and structs used by the Boson Protocol contract ecosystem.\n */\n\ncontract BosonTypes {\n    enum PausableRegion {\n        Offers,\n        Twins,\n        Bundles,\n        Groups,\n        Sellers,\n        Buyers,\n        DisputeResolvers,\n        Agents,\n        Exchanges,\n        Disputes,\n        Funds,\n        Orchestration,\n        MetaTransaction,\n        PriceDiscovery,\n        SequentialCommit\n    }\n\n    enum EvaluationMethod {\n        None, // None should always be at index 0. Never change this value.\n        Threshold,\n        SpecificToken\n    }\n\n    enum GatingType {\n        PerAddress,\n        PerTokenId\n    }\n\n    enum ExchangeState {\n        Committed,\n        Revoked,\n        Canceled,\n        Redeemed,\n        Completed,\n        Disputed\n    }\n\n    enum DisputeState {\n        Resolving,\n        Retracted,\n        Resolved,\n        Escalated,\n        Decided,\n        Refused\n    }\n\n    enum TokenType {\n        FungibleToken,\n        NonFungibleToken,\n        MultiToken\n    } // ERC20, ERC721, ERC1155\n\n    enum MetaTxInputType {\n        Generic,\n        CommitToOffer,\n        Exchange,\n        Funds,\n        CommitToConditionalOffer,\n        ResolveDispute\n    }\n\n    enum AuthTokenType {\n        None,\n        Custom, // For future use\n        Lens,\n        ENS\n    }\n\n    enum SellerUpdateFields {\n        Admin,\n        Assistant,\n        Clerk, // Deprecated.\n        AuthToken\n    }\n\n    enum DisputeResolverUpdateFields {\n        Admin,\n        Assistant,\n        Clerk // Deprecated.\n    }\n\n    enum PriceType {\n        Static, // Default should always be at index 0. Never change this value.\n        Discovery\n    }\n\n    struct AuthToken {\n        uint256 tokenId;\n        AuthTokenType tokenType;\n    }\n\n    struct Seller {\n        uint256 id;\n        address assistant;\n        address admin;\n        address clerk; // Deprecated. Kept for backwards compatibility.\n        address payable treasury;\n        bool active;\n        string metadataUri;\n    }\n\n    struct Buyer {\n        uint256 id;\n        address payable wallet;\n        bool active;\n    }\n\n    struct RoyaltyRecipient {\n        uint256 id;\n        address payable wallet;\n    }\n\n    struct DisputeResolver {\n        uint256 id;\n        uint256 escalationResponsePeriod;\n        address assistant;\n        address admin;\n        address clerk; // Deprecated. Kept for backwards compatibility.\n        address payable treasury;\n        string metadataUri;\n        bool active;\n    }\n\n    struct DisputeResolverFee {\n        address tokenAddress;\n        string tokenName;\n        uint256 feeAmount;\n    }\n\n    struct Agent {\n        uint256 id;\n        uint256 feePercentage;\n        address payable wallet;\n        bool active;\n    }\n\n    struct DisputeResolutionTerms {\n        uint256 disputeResolverId;\n        uint256 escalationResponsePeriod;\n        uint256 feeAmount;\n        uint256 buyerEscalationDeposit;\n    }\n\n    struct Offer {\n        uint256 id;\n        uint256 sellerId;\n        uint256 price;\n        uint256 sellerDeposit;\n        uint256 buyerCancelPenalty;\n        uint256 quantityAvailable;\n        address exchangeToken;\n        PriceType priceType;\n        string metadataUri;\n        string metadataHash;\n        bool voided;\n        uint256 collectionIndex;\n        RoyaltyInfo[] royaltyInfo;\n    }\n\n    struct OfferDates {\n        uint256 validFrom;\n        uint256 validUntil;\n        uint256 voucherRedeemableFrom;\n        uint256 voucherRedeemableUntil;\n    }\n\n    struct OfferDurations {\n        uint256 disputePeriod;\n        uint256 voucherValid;\n        uint256 resolutionPeriod;\n    }\n\n    struct Group {\n        uint256 id;\n        uint256 sellerId;\n        uint256[] offerIds;\n    }\n\n    struct Condition {\n        EvaluationMethod method;\n        TokenType tokenType;\n        address tokenAddress;\n        GatingType gating; // added in v2.3.0. All conditions created before that have a default value of \"PerAddress\"\n        uint256 minTokenId;\n        uint256 threshold;\n        uint256 maxCommits;\n        uint256 maxTokenId;\n    }\n\n    struct Exchange {\n        uint256 id;\n        uint256 offerId;\n        uint256 buyerId;\n        uint256 finalizedDate;\n        ExchangeState state;\n    }\n\n    struct ExchangeCosts {\n        uint256 resellerId;\n        uint256 price;\n        uint256 protocolFeeAmount;\n        uint256 royaltyAmount;\n        uint256 royaltyInfoIndex;\n    }\n\n    struct Voucher {\n        uint256 committedDate;\n        uint256 validUntilDate;\n        uint256 redeemedDate;\n        bool expired;\n    }\n\n    struct Dispute {\n        uint256 exchangeId;\n        uint256 buyerPercent;\n        DisputeState state;\n    }\n\n    struct DisputeDates {\n        uint256 disputed;\n        uint256 escalated;\n        uint256 finalized;\n        uint256 timeout;\n    }\n\n    struct Receipt {\n        uint256 exchangeId;\n        uint256 offerId;\n        uint256 buyerId;\n        uint256 sellerId;\n        uint256 price;\n        uint256 sellerDeposit;\n        uint256 buyerCancelPenalty;\n        OfferFees offerFees;\n        uint256 agentId;\n        address exchangeToken;\n        uint256 finalizedDate;\n        Condition condition;\n        uint256 committedDate;\n        uint256 redeemedDate;\n        bool voucherExpired;\n        uint256 disputeResolverId;\n        uint256 disputedDate;\n        uint256 escalatedDate;\n        DisputeState disputeState;\n        TwinReceipt[] twinReceipts;\n    }\n\n    struct TokenRange {\n        uint256 start;\n        uint256 end;\n        uint256 twinId;\n    }\n\n    struct Twin {\n        uint256 id;\n        uint256 sellerId;\n        uint256 amount; // ERC1155 / ERC20 (amount to be transferred to each buyer on redemption)\n        uint256 supplyAvailable; // all\n        uint256 tokenId; // ERC1155 / ERC721 (must be initialized with the initial pointer position of the ERC721 ids available range)\n        address tokenAddress; // all\n        TokenType tokenType;\n    }\n\n    struct TwinReceipt {\n        uint256 twinId;\n        uint256 tokenId; // only for ERC721 and ERC1155\n        uint256 amount; // only for ERC1155 and ERC20\n        address tokenAddress;\n        TokenType tokenType;\n    }\n\n    struct Bundle {\n        uint256 id;\n        uint256 sellerId;\n        uint256[] offerIds;\n        uint256[] twinIds;\n    }\n\n    struct Funds {\n        address tokenAddress;\n        string tokenName;\n        uint256 availableAmount;\n    }\n\n    struct MetaTransaction {\n        uint256 nonce;\n        address from;\n        address contractAddress;\n        string functionName;\n        bytes functionSignature;\n    }\n\n    struct HashInfo {\n        bytes32 typeHash;\n        function(bytes memory) internal pure returns (bytes32) hashFunction;\n    }\n\n    struct OfferFees {\n        uint256 protocolFee;\n        uint256 agentFee;\n    }\n\n    struct VoucherInitValues {\n        string contractURI;\n        uint256 royaltyPercentage;\n        bytes32 collectionSalt;\n    }\n\n    struct Collection {\n        address collectionAddress;\n        string externalId;\n    }\n\n    struct PriceDiscovery {\n        uint256 price;\n        Side side;\n        address priceDiscoveryContract;\n        address conduit;\n        bytes priceDiscoveryData;\n    }\n\n    enum Side {\n        Ask,\n        Bid,\n        Wrapper // Side is not relevant from the protocol perspective\n    }\n\n    struct RoyaltyInfo {\n        address payable[] recipients;\n        uint256[] bps;\n    }\n\n    struct RoyaltyRecipientInfo {\n        address payable wallet;\n        uint256 minRoyaltyPercentage;\n    }\n\n    struct PremintParameters {\n        uint256 reservedRangeLength;\n        address to;\n    }\n\n    struct Payoff {\n        uint256 seller;\n        uint256 buyer;\n        uint256 protocol;\n        uint256 agent;\n    }\n}\n"
      },
      "contracts/interfaces/clients/IBosonVoucher.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport { IERC721Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\";\nimport { IERC721MetadataUpgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol\";\nimport { IERC721ReceiverUpgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol\";\n\n/**\n * @title IBosonVoucher\n *\n * @notice This is the interface for the Boson Protocol ERC-721 Voucher contract.\n *\n * The ERC-165 identifier for this interface is: 0x6a474d2c\n */\ninterface IBosonVoucher is IERC721Upgradeable, IERC721MetadataUpgradeable, IERC721ReceiverUpgradeable {\n    event ContractURIChanged(string contractURI);\n    event VoucherInitialized(uint256 indexed sellerId, string indexed contractURI);\n    event RangeReserved(uint256 indexed offerId, Range range);\n    event VouchersPreMinted(uint256 indexed offerId, uint256 startId, uint256 endId);\n\n    // Describe a reserved range of token ids\n    struct Range {\n        uint256 start; // First token id of range\n        uint256 length; // Length of range\n        uint256 minted; // Amount pre-minted so far\n        uint256 lastBurnedTokenId; // Last burned token id\n        address owner; // The range owner\n    }\n\n    /**\n     * @notice Issues a voucher to a buyer.\n     *\n     * Minted voucher supply is sent to the buyer.\n     * Caller must have PROTOCOL role.\n     *\n     * @param _tokenId - voucher token id corresponds to <<uint128(offerId)>>.<<uint128(exchangeId)>>\n     * @param _buyer - the buyer address\n     */\n    function issueVoucher(uint256 _tokenId, address _buyer) external;\n\n    /**\n     * @notice Burns a voucher.\n     *\n     * Caller must have PROTOCOL role.\n     *\n     * @param _tokenId - voucher token id corresponds to <<uint128(offerId)>>.<<uint128(exchangeId)>>\n     */\n    function burnVoucher(uint256 _tokenId) external;\n\n    /**\n     * @notice Gets the seller id.\n     *\n     * @return the id for the Voucher seller\n     */\n    function getSellerId() external view returns (uint256);\n\n    /**\n     * @notice Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the protocol. Change is done by calling `updateSeller` on the protocol.\n     *\n     * @param newOwner - the address to which ownership of the voucher contract will be transferred\n     */\n    function transferOwnership(address newOwner) external;\n\n    /**\n     * @notice Returns storefront-level metadata used by OpenSea.\n     *\n     * @return Contract metadata URI\n     */\n    function contractURI() external view returns (string memory);\n\n    /**\n     * @notice Sets new contract URI.\n     * Can only be called by the owner or during the initialization.\n     *\n     * @param _newContractURI - new contract metadata URI\n     */\n    function setContractURI(string calldata _newContractURI) external;\n\n    /**\n     * @notice Provides royalty info.\n     * Called with the sale price to determine how much royalty is owed and to whom.\n     *\n     * @param _tokenId - the voucher queried for royalty information\n     * @param _salePrice - the sale price of the voucher specified by _tokenId\n     *\n     * @return receiver - address of who should be sent the royalty payment\n     * @return royaltyAmount - the royalty payment amount for the given sale price\n     */\n    function royaltyInfo(\n        uint256 _tokenId,\n        uint256 _salePrice\n    ) external view returns (address receiver, uint256 royaltyAmount);\n\n    /**\n     * @notice Reserves a range of vouchers to be associated with an offer\n     *\n     * Must happen prior to calling preMint\n     * Caller must have PROTOCOL role.\n     *\n     * Reverts if:\n     * - Start id is not greater than zero for the first range\n     * - Start id is not greater than the end id of the previous range for subsequent ranges\n     * - Range length is zero\n     * - Range length is too large, i.e., would cause an overflow\n     * - Offer id is already associated with a range\n     * - _to is not the contract address or the contract owner\n     *\n     * @param _offerId - the id of the offer\n     * @param _start - the first id of the token range\n     * @param _length - the length of the range\n     * @param _to - the address to send the pre-minted vouchers to (contract address or contract owner)\n     */\n    function reserveRange(uint256 _offerId, uint256 _start, uint256 _length, address _to) external;\n\n    /**\n     * @notice Pre-mints all or part of an offer's reserved vouchers.\n     *\n     * For small offer quantities, this method may only need to be\n     * called once.\n     *\n     * But, if the range is large, e.g., 10k vouchers, block gas limit\n     * could cause the transaction to fail. Thus, in order to support\n     * a batched approach to pre-minting an offer's vouchers,\n     * this method can be called multiple times, until the whole\n     * range is minted.\n     *\n     * A benefit to the batched approach is that the entire reserved\n     * range for an offer need not be pre-minted at one time. A seller\n     * could just mint batches periodically, controlling the amount\n     * that are available on the market at any given time, e.g.,\n     * creating a pre-minted offer with a validity period of one year,\n     * causing the token range to be reserved, but only pre-minting\n     * a certain amount monthly.\n     *\n     * Caller must be contract owner (seller assistant address).\n     *\n     * Reverts if:\n     * - Offer id is not associated with a range\n     * - Amount to mint is more than remaining un-minted in range\n     * - Too many to mint in a single transaction, given current block gas limit\n     *\n     * @param _offerId - the id of the offer\n     * @param _amount - the amount to mint\n     */\n    function preMint(uint256 _offerId, uint256 _amount) external;\n\n    /**\n     * @notice Burn all or part of an offer's preminted vouchers.\n     * If offer expires or it's voided, the seller can burn the preminted vouchers that were not transferred yet.\n     * This way they will not show in seller's wallet and marketplaces anymore.\n     *\n     * For small offer quantities, this method may only need to be\n     * called once.\n     *\n     * But, if the range is large, e.g., 10k vouchers, block gas limit\n     * could cause the transaction to fail. Thus, in order to support\n     * a batched approach to pre-minting an offer's vouchers,\n     * this method can be called multiple times, until the whole\n     * range is burned.\n     *\n     * Caller must be contract owner (seller assistant address).\n     *\n     * Reverts if:\n     * - Offer id is not associated with a range\n     * - Offer is not expired or voided\n     * - There is nothing to burn\n     *\n     * @param _offerId - the id of the offer\n     * @param _amount - amount to burn\n     */\n    function burnPremintedVouchers(uint256 _offerId, uint256 _amount) external;\n\n    /**\n     * @notice Gets the number of vouchers available to be pre-minted for an offer.\n     *\n     * @param _offerId - the id of the offer\n     * @return count - the count of vouchers in reserved range available to be pre-minted\n     */\n    function getAvailablePreMints(uint256 _offerId) external view returns (uint256 count);\n\n    /**\n     * @notice Gets the range for an offer.\n     *\n     * @param _offerId - the id of the offer\n     * @return range - range struct with information about range start, length and already minted tokens\n     */\n    function getRangeByOfferId(uint256 _offerId) external view returns (Range memory range);\n\n    /**\n     * @notice Make a call to an external contract.\n     *\n     * Reverts if:\n     * - _to is zero address\n     * - call to external contract fails\n     * - caller is not the owner\n     * - _to is a contract that represents some assets (all contracts that implement `balanceOf` method, including ERC20 and ERC721)\n     *\n     * @param _to - address of the contract to call\n     * @param _data - data to pass to the external contract\n     * @return result - result of the call\n     */\n    function callExternalContract(address _to, bytes memory _data) external payable returns (bytes memory);\n\n    /** @notice Set approval for all to the vouchers owned by this contract\n     *\n     * Reverts if:\n     * - _operator is zero address\n     * - caller is not the owner\n     * - _operator is this contract\n     *\n     * @param _operator - address of the operator to set approval for\n     * @param _approved - true to approve the operator in question, false to revoke approval\n     */\n    function setApprovalForAllToContract(address _operator, bool _approved) external;\n\n    /**\n     * @notice Withdraw funds from the contract to the protocol seller pool\n     *\n     * @param _tokenList - list of tokens to withdraw, including native token (address(0))\n     */\n    function withdrawToProtocol(address[] calldata _tokenList) external;\n}\n"
      },
      "contracts/interfaces/clients/IClientExternalAddresses.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport { IAccessControl } from \"../IAccessControl.sol\";\nimport { IClientExternalAddressesEvents } from \"../events/IClientExternalAddressesEvents.sol\";\n\n/**\n * @title IClientExternalAddresses\n *\n * @notice ClientExternalAddresses is used to set and get addresses used either by proxies or\n * by protocol clients.\n *\n *\n * The ERC-165 identifier for this interface is: 0x344552b3\n */\ninterface IClientExternalAddresses is IClientExternalAddressesEvents {\n    /**\n     * @notice Sets the implementation address.\n     *\n     * @param _implementation - the implementation address\n     */\n    function setImplementation(address _implementation) external;\n\n    /**\n     * @notice Gets the implementation address.\n     *\n     * @return the implementation address\n     */\n    function getImplementation() external view returns (address);\n\n    /**\n     * @notice Gets the address of the Boson Protocol AccessController contract.\n     *\n     * @return the address of the AccessController contract\n     */\n    function getAccessController() external view returns (IAccessControl);\n\n    /**\n     * @notice Set the ProtocolDiamond address.\n     *\n     * Emits a ProtocolAddressChanged event.\n     *\n     * @param _protocolAddress - the ProtocolDiamond address\n     */\n    function setProtocolAddress(address _protocolAddress) external;\n\n    /**\n     * @notice Gets the address of the ProtocolDiamond contract.\n     *\n     * @return the ProtocolDiamond address\n     */\n    function getProtocolAddress() external view returns (address);\n}\n"
      },
      "contracts/interfaces/events/IBosonAccountEvents.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport { BosonTypes } from \"../../domain/BosonTypes.sol\";\n\n/**\n * @title IBosonAccountEvents\n *\n * @notice Defines events related to management of accounts within the protocol.\n */\ninterface IBosonAccountEvents {\n    event SellerCreated(\n        uint256 indexed sellerId,\n        BosonTypes.Seller seller,\n        address voucherCloneAddress,\n        BosonTypes.AuthToken authToken,\n        address indexed executedBy\n    );\n    event SellerUpdatePending(\n        uint256 indexed sellerId,\n        BosonTypes.Seller pendingSeller,\n        BosonTypes.AuthToken pendingAuthToken,\n        address indexed executedBy\n    );\n    event SellerUpdateApplied(\n        uint256 indexed sellerId,\n        BosonTypes.Seller seller,\n        BosonTypes.Seller pendingSeller,\n        BosonTypes.AuthToken authToken,\n        BosonTypes.AuthToken pendingAuthToken,\n        address indexed executedBy\n    );\n    event RoyaltyRecipientsChanged(\n        uint256 indexed sellerId,\n        BosonTypes.RoyaltyRecipientInfo[] royaltyRecipients,\n        address indexed executedBy\n    );\n    event BuyerCreated(uint256 indexed buyerId, BosonTypes.Buyer buyer, address indexed executedBy);\n    event BuyerUpdated(uint256 indexed buyerId, BosonTypes.Buyer buyer, address indexed executedBy);\n    event AgentUpdated(uint256 indexed agentId, BosonTypes.Agent agent, address indexed executedBy);\n    event DisputeResolverCreated(\n        uint256 indexed disputeResolverId,\n        BosonTypes.DisputeResolver disputeResolver,\n        BosonTypes.DisputeResolverFee[] disputeResolverFees,\n        uint256[] sellerAllowList,\n        address indexed executedBy\n    );\n    event DisputeResolverUpdatePending(\n        uint256 indexed disputeResolverId,\n        BosonTypes.DisputeResolver pendingDisputeResolver,\n        address indexed executedBy\n    );\n    event DisputeResolverUpdateApplied(\n        uint256 indexed disputeResolverId,\n        BosonTypes.DisputeResolver disputeResolver,\n        BosonTypes.DisputeResolver pendingDisputeResolver,\n        address indexed executedBy\n    );\n    event DisputeResolverFeesAdded(\n        uint256 indexed disputeResolverId,\n        BosonTypes.DisputeResolverFee[] disputeResolverFees,\n        address indexed executedBy\n    );\n    event DisputeResolverFeesRemoved(\n        uint256 indexed disputeResolverId,\n        address[] feeTokensRemoved,\n        address indexed executedBy\n    );\n    event AllowedSellersAdded(uint256 indexed disputeResolverId, uint256[] addedSellers, address indexed executedBy);\n    event AllowedSellersRemoved(\n        uint256 indexed disputeResolverId,\n        uint256[] removedSellers,\n        address indexed executedBy\n    );\n    event AgentCreated(uint256 indexed agentId, BosonTypes.Agent agent, address indexed executedBy);\n    event CollectionCreated(\n        uint256 indexed sellerId,\n        uint256 collectionIndex,\n        address collectionAddress,\n        string indexed externalId,\n        address indexed executedBy\n    );\n}\n"
      },
      "contracts/interfaces/events/IBosonExchangeEvents.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport { BosonTypes } from \"../../domain/BosonTypes.sol\";\n\n/**\n * @title IBosonExchangeEvents\n *\n * @notice Defines events related to exchanges within the protocol.\n */\ninterface IBosonExchangeEvents {\n    event BuyerCommitted(\n        uint256 indexed offerId,\n        uint256 indexed buyerId,\n        uint256 indexed exchangeId,\n        BosonTypes.Exchange exchange,\n        BosonTypes.Voucher voucher,\n        address executedBy\n    );\n    event ExchangeCompleted(\n        uint256 indexed offerId,\n        uint256 indexed buyerId,\n        uint256 indexed exchangeId,\n        address executedBy\n    );\n    event VoucherCanceled(uint256 indexed offerId, uint256 indexed exchangeId, address indexed executedBy);\n    event VoucherExpired(uint256 indexed offerId, uint256 indexed exchangeId, address indexed executedBy);\n    event VoucherExtended(\n        uint256 indexed offerId,\n        uint256 indexed exchangeId,\n        uint256 validUntil,\n        address indexed executedBy\n    );\n    event VoucherRedeemed(uint256 indexed offerId, uint256 indexed exchangeId, address indexed executedBy);\n    event VoucherRevoked(uint256 indexed offerId, uint256 indexed exchangeId, address indexed executedBy);\n    event VoucherTransferred(\n        uint256 indexed offerId,\n        uint256 indexed exchangeId,\n        uint256 indexed newBuyerId,\n        address executedBy\n    );\n    event ConditionalCommitAuthorized(\n        uint256 indexed offerId,\n        BosonTypes.GatingType gating,\n        address indexed buyerAddress,\n        uint256 indexed tokenId,\n        uint256 commitCount,\n        uint256 maxCommits\n    );\n}\n"
      },
      "contracts/interfaces/events/IBosonFundsEvents.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport { BosonTypes } from \"../../domain/BosonTypes.sol\";\n\n/**\n * @title IBosonFundsEvents\n *\n * @notice Defines events related to management of funds within the protocol.\n */\ninterface IBosonFundsEvents {\n    event FundsDeposited(\n        uint256 indexed sellerId,\n        address indexed executedBy,\n        address indexed tokenAddress,\n        uint256 amount\n    );\n}\n\ninterface IBosonFundsLibEvents {\n    event FundsEncumbered(\n        uint256 indexed entityId,\n        address indexed exchangeToken,\n        uint256 amount,\n        address indexed executedBy\n    );\n    event FundsReleased(\n        uint256 indexed exchangeId,\n        uint256 indexed entityId,\n        address indexed exchangeToken,\n        uint256 amount,\n        address executedBy\n    );\n    event ProtocolFeeCollected(\n        uint256 indexed exchangeId,\n        address indexed exchangeToken,\n        uint256 amount,\n        address indexed executedBy\n    );\n    event FundsWithdrawn(\n        uint256 indexed sellerId,\n        address indexed withdrawnTo,\n        address indexed tokenAddress,\n        uint256 amount,\n        address executedBy\n    );\n}\n"
      },
      "contracts/interfaces/events/IBosonOfferEvents.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport { BosonTypes } from \"../../domain/BosonTypes.sol\";\n\n/**\n * @title IBosonOfferEvents\n *\n * @notice Defines events related to management of offers within the protocol.\n */\ninterface IBosonOfferEvents {\n    event OfferCreated(\n        uint256 indexed offerId,\n        uint256 indexed sellerId,\n        BosonTypes.Offer offer,\n        BosonTypes.OfferDates offerDates,\n        BosonTypes.OfferDurations offerDurations,\n        BosonTypes.DisputeResolutionTerms disputeResolutionTerms,\n        BosonTypes.OfferFees offerFees,\n        uint256 indexed agentId,\n        address executedBy\n    );\n    event OfferExtended(\n        uint256 indexed offerId,\n        uint256 indexed sellerId,\n        uint256 validUntilDate,\n        address indexed executedBy\n    );\n    event OfferVoided(uint256 indexed offerId, uint256 indexed sellerId, address indexed executedBy);\n    event RangeReserved(\n        uint256 indexed offerId,\n        uint256 indexed sellerId,\n        uint256 startExchangeId,\n        uint256 endExchangeId,\n        address owner,\n        address indexed executedBy\n    );\n    event OfferRoyaltyInfoUpdated(\n        uint256 indexed offerId,\n        uint256 indexed sellerId,\n        BosonTypes.RoyaltyInfo royaltyInfo,\n        address indexed executedBy\n    );\n}\n"
      },
      "contracts/interfaces/events/IBosonTwinEvents.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport { BosonTypes } from \"../../domain/BosonTypes.sol\";\n\n/**\n * @title IBosonTwinEvents\n *\n * @notice Defines events related to management of twins within the protocol.\n */\ninterface IBosonTwinEvents {\n    event TwinCreated(\n        uint256 indexed twinId,\n        uint256 indexed sellerId,\n        BosonTypes.Twin twin,\n        address indexed executedBy\n    );\n    event TwinDeleted(uint256 indexed twinId, uint256 indexed sellerId, address indexed executedBy);\n    // Amount must be 0 if token type is TokenType.NonFungible\n    // tokenId must be 0 if token type is TokenType.Fungible\n    event TwinTransferred(\n        uint256 indexed twinId,\n        address indexed tokenAddress,\n        uint256 indexed exchangeId,\n        uint256 tokenId,\n        uint256 amount,\n        address executedBy\n    );\n    event TwinTransferFailed(\n        uint256 indexed twinId,\n        address indexed tokenAddress,\n        uint256 indexed exchangeId,\n        uint256 tokenId,\n        uint256 amount,\n        address executedBy\n    );\n    event TwinTransferSkipped(uint256 indexed exchangeId, uint256 twinCount, address indexed executedBy);\n}\n"
      },
      "contracts/interfaces/events/IClientExternalAddressesEvents.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\n/**\n * @title IClientExternalAddressesEvents\n *\n * @notice Defines events related to management of Boson Protocol clients.\n */\ninterface IClientExternalAddressesEvents {\n    event Upgraded(address indexed implementation, address indexed executedBy);\n    event ProtocolAddressChanged(address indexed protocol, address indexed executedBy);\n}\n"
      },
      "contracts/interfaces/handlers/IBosonAccountHandler.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport { BosonErrors } from \"../../domain/BosonErrors.sol\";\nimport { IBosonAccountEvents } from \"../events/IBosonAccountEvents.sol\";\nimport { IBosonAgentHandler } from \"./IBosonAgentHandler.sol\";\nimport { IBosonBuyerHandler } from \"./IBosonBuyerHandler.sol\";\nimport { IBosonDisputeResolverHandler } from \"./IBosonDisputeResolverHandler.sol\";\nimport { IBosonSellerHandler } from \"./IBosonSellerHandler.sol\";\n\n/**\n * @title IBosonAccountHandler\n *\n * @notice Handles creation, update, retrieval of accounts within the protocol.\n *\n * The ERC-165 identifier for this interface is: 0x0757010c\n */\ninterface IBosonAccountHandler is\n    IBosonAgentHandler,\n    IBosonBuyerHandler,\n    IBosonDisputeResolverHandler,\n    IBosonSellerHandler,\n    IBosonAccountEvents,\n    BosonErrors\n{\n    /**\n     * @notice Gets the next account id that can be assigned to an account.\n     *\n     * @dev Does not increment the counter.\n     *\n     * @return nextAccountId - the account id\n     */\n    function getNextAccountId() external view returns (uint256 nextAccountId);\n}\n"
      },
      "contracts/interfaces/handlers/IBosonAgentHandler.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport { BosonTypes } from \"../../domain/BosonTypes.sol\";\n\n/**\n * @title IBosonAgentHandler\n *\n * @notice Handles creation, update, retrieval of agents within the protocol.\n *\n * The ERC-165 identifier for this interface is: 0xf94031f7\n */\ninterface IBosonAgentHandler {\n    /**\n     * @notice Creates a marketplace agent.\n     *\n     * Emits an AgentCreated event if successful.\n     *\n     * Reverts if:\n     * - The agents region of protocol is paused\n     * - Wallet address is zero address\n     * - Active is not true\n     * - Wallet address is not unique to this agent\n     * - Fee percentage + protocol fee percentage is greater than the max allowable fee percentage for an offer\n     *\n     * @param _agent - the fully populated struct with agent id set to 0x0\n     */\n    function createAgent(BosonTypes.Agent memory _agent) external;\n\n    /**\n     * @notice Updates an agent, with the exception of the active flag.\n     *         All other fields should be filled, even those staying the same.\n     * @dev    Active flag passed in by caller will be ignored. The value from storage will be used.\n     *\n     * Emits an AgentUpdated event if successful.\n     *\n     * Reverts if:\n     * - The agents region of protocol is paused\n     * - Caller is not the wallet address associated with the agent account\n     * - Wallet address is zero address\n     * - Wallet address is not unique to this agent\n     * - Agent does not exist\n     * - Fee percentage + protocol fee percentage is greater than the max allowable fee percentage for an offer\n     *\n     * @param _agent - the fully populated agent struct\n     */\n    function updateAgent(BosonTypes.Agent memory _agent) external;\n\n    /**\n     * @notice Gets the details about an agent.\n     *\n     * @param _agentId - the id of the agent to check\n     * @return exists - whether the agent was found\n     * @return agent - the agent details. See {BosonTypes.Agent}\n     */\n    function getAgent(uint256 _agentId) external view returns (bool exists, BosonTypes.Agent memory agent);\n}\n"
      },
      "contracts/interfaces/handlers/IBosonBuyerHandler.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport { BosonTypes } from \"../../domain/BosonTypes.sol\";\n\n/**\n * @title IBosonBuyerHandler\n *\n * @notice Handles creation, update, retrieval of buyers within the protocol.\n *\n * The ERC-165 identifier for this interface is: 0x3bcf1749\n */\ninterface IBosonBuyerHandler {\n    /**\n     * @notice Creates a buyer.\n     *\n     * Emits an BuyerCreated event if successful.\n     *\n     * Reverts if:\n     * - The buyers region of protocol is paused\n     * - Wallet address is zero address\n     * - Active is not true\n     * - Wallet address is not unique to this buyer\n     *\n     * @param _buyer - the fully populated struct with buyer id set to 0x0\n     */\n    function createBuyer(BosonTypes.Buyer memory _buyer) external;\n\n    /**\n     * @notice Updates a buyer, with the exception of the active flag.\n     *         All other fields should be filled, even those staying the same.\n     * @dev    Active flag passed in by caller will be ignored. The value from storage will be used.\n     *\n     * Emits a BuyerUpdated event if successful.\n     *\n     * Reverts if:\n     * - The buyers region of protocol is paused\n     * - Caller is not the wallet address of the stored buyer\n     * - Wallet address is zero address\n     * - Address is not unique to this buyer\n     * - Buyer does not exist\n     * - Current wallet address has outstanding vouchers\n     *\n     * @param _buyer - the fully populated buyer struct\n     */\n    function updateBuyer(BosonTypes.Buyer memory _buyer) external;\n\n    /**\n     * @notice Gets the details about a buyer.\n     *\n     * @param _buyerId - the id of the buyer to check\n     * @return exists - whether the buyer was found\n     * @return buyer - the buyer details. See {BosonTypes.Buyer}\n     */\n    function getBuyer(uint256 _buyerId) external view returns (bool exists, BosonTypes.Buyer memory buyer);\n}\n"
      },
      "contracts/interfaces/handlers/IBosonDisputeResolverHandler.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport { BosonTypes } from \"../../domain/BosonTypes.sol\";\n\n/**\n * @title IBosonDisputeResolverHandler\n *\n * @notice Handles creation, update, retrieval of dispute resolvers within the protocol.\n *\n * The ERC-165 identifier for this interface is: 0x50564987\n */\ninterface IBosonDisputeResolverHandler {\n    /**\n     * @notice Creates a dispute resolver.\n     *\n     * Emits a DisputeResolverCreated event if successful.\n     *\n     * Reverts if:\n     * - Caller is not the supplied admin and assistant\n     * - Supplied clerk is not a zero address\n     * - The dispute resolvers region of protocol is paused\n     * - Any address is zero address\n     * - Any address is not unique to this dispute resolver\n     * - EscalationResponsePeriod is invalid\n     * - Some seller does not exist\n     * - Some seller id is duplicated\n     * - DisputeResolver is not active (if active == false)\n     * - Fee amount is a non-zero value. Protocol doesn't yet support fees for dispute resolvers\n     *\n     * @param _disputeResolver - the fully populated struct with dispute resolver id set to 0x0\n     * @param _disputeResolverFees - list of fees dispute resolver charges per token type. Zero address is native currency. See {BosonTypes.DisputeResolverFee}\n     *                               feeAmount will be ignored because protocol doesn't yet support fees yet but DR still needs to provide array of fees to choose supported tokens\n     * @param _sellerAllowList - list of ids of sellers that can choose this dispute resolver. If empty, there are no restrictions on which seller can chose it.\n     */\n    function createDisputeResolver(\n        BosonTypes.DisputeResolver memory _disputeResolver,\n        BosonTypes.DisputeResolverFee[] calldata _disputeResolverFees,\n        uint256[] calldata _sellerAllowList\n    ) external;\n\n    /**\n     * @notice Updates treasury address, escalationResponsePeriod or metadataUri if changed. Puts admin and assistant in pending queue, if changed.\n     *         Pending updates can be completed by calling the optInToDisputeResolverUpdate function.\n     *\n     *         Update doesn't include DisputeResolverFees, allowed seller list or active flag.\n     *         All DisputeResolver fields should be filled, even those staying the same.\n     *         Use removeFeesFromDisputeResolver and addFeesToDisputeResolver to add and remove fees.\n     *         Use addSellersToAllowList and removeSellersFromAllowList to add and remove allowed sellers.\n     *\n     * @dev    Active flag passed in by caller will be ignored. The value from storage will be used.\n     *\n     * Emits a DisputeResolverUpdated event if successful.\n     * Emits a DisputeResolverUpdatePending event if the dispute resolver has requested an update for admin or assistant.\n     * Owner(s) of new addresses for admin, assistant must opt-in to the update.\n     *\n     * Reverts if:\n     * - The dispute resolvers region of protocol is paused\n     * - Caller is not the admin address of the stored dispute resolver\n     * - Any address is not unique to this dispute resolver\n     * - Supplied clerk is not a zero address\n     * - Dispute resolver does not exist\n     * - EscalationResponsePeriod is invalid\n     * - No field has been updated or requested to be updated\n     *\n     * @param _disputeResolver - the fully populated dispute resolver struct\n     */\n    function updateDisputeResolver(BosonTypes.DisputeResolver memory _disputeResolver) external;\n\n    /**\n     * @notice Opt-in to a pending dispute resolver update\n     *\n     * Emits a DisputeResolverUpdateApplied event if successful.\n     *\n     * Reverts if:\n     * - The dispute resolver region of protocol is paused\n     * - Addresses are not unique to this dispute resolver\n     * - Caller address is not pending update for the field being updated\n     * - No pending update exists for this dispute resolver\n     * - Dispute resolver tries to update the clerk\n     *\n     * @param _disputeResolverId - disputeResolver id\n     * @param _fieldsToUpdate - fields to update, see DisputeResolverUpdateFields enum\n     */\n    function optInToDisputeResolverUpdate(\n        uint256 _disputeResolverId,\n        BosonTypes.DisputeResolverUpdateFields[] calldata _fieldsToUpdate\n    ) external;\n\n    /**\n     * @notice Adds DisputeResolverFees to an existing dispute resolver.\n     *\n     * Emits a DisputeResolverFeesAdded event if successful.\n     *\n     * Reverts if:\n     * - The dispute resolvers region of protocol is paused\n     * - Caller is not the admin address associated with the dispute resolver account\n     * - Dispute resolver does not exist\n     * - Number of DisputeResolverFee structs in array is zero\n     * - DisputeResolverFee array contains duplicates\n     * - Fee amount is a non-zero value. Protocol doesn't yet support fees for dispute resolvers\n     *\n     * @param _disputeResolverId - id of the dispute resolver\n     * @param _disputeResolverFees - list of fees dispute resolver charges per token type. Zero address is native currency. See {BosonTypes.DisputeResolverFee}\n     *                               feeAmount will be ignored because protocol doesn't yet support fees yet but DR still needs to provide array of fees to choose supported tokens\n     */\n    function addFeesToDisputeResolver(\n        uint256 _disputeResolverId,\n        BosonTypes.DisputeResolverFee[] calldata _disputeResolverFees\n    ) external;\n\n    /**\n     * @notice Removes DisputeResolverFees from  an existing dispute resolver.\n     *\n     * Emits a DisputeResolverFeesRemoved event if successful.\n     *\n     * Reverts if:\n     * - The dispute resolvers region of protocol is paused\n     * - Caller is not the admin address associated with the dispute resolver account\n     * - Dispute resolver does not exist\n     * - Number of DisputeResolverFee structs in array is zero\n     * - DisputeResolverFee does not exist for the dispute resolver\n     *\n     * @param _disputeResolverId - id of the dispute resolver\n     * @param _feeTokenAddresses - list of addresses of dispute resolver fee tokens to remove\n     */\n    function removeFeesFromDisputeResolver(uint256 _disputeResolverId, address[] calldata _feeTokenAddresses) external;\n\n    /**\n     * @notice Adds seller ids to set of ids allowed to choose the given dispute resolver for an offer.\n     *\n     * Emits an AllowedSellersAdded event if successful.\n     *\n     * Reverts if:\n     * - The dispute resolvers region of protocol is paused\n     * - Caller is not the admin address associated with the dispute resolver account\n     * - Dispute resolver does not exist\n     * - Number of seller ids in array is zero\n     * - Some seller does not exist\n     * - Seller id is already approved\n     *\n     * @param _disputeResolverId - id of the dispute resolver\n     * @param _sellerAllowList - List of seller ids to add to allowed list\n     */\n    function addSellersToAllowList(uint256 _disputeResolverId, uint256[] calldata _sellerAllowList) external;\n\n    /**\n     * @notice Removes seller ids from set of ids allowed to choose the given dispute resolver for an offer.\n     *\n     * Emits an AllowedSellersRemoved event if successful.\n     *\n     * Reverts if:\n     * - The dispute resolvers region of protocol is paused\n     * - Caller is not the admin address associated with the dispute resolver account\n     * - Dispute resolver does not exist\n     * - Number of seller ids structs in array is zero\n     * - Seller id is not approved\n     *\n     * @param _disputeResolverId - id of the dispute resolver\n     * @param _sellerAllowList - list of seller ids to remove from allowed list\n     */\n    function removeSellersFromAllowList(uint256 _disputeResolverId, uint256[] calldata _sellerAllowList) external;\n\n    /**\n     * @notice Gets the details about a dispute resolver.\n     *\n     * @param _disputeResolverId - the id of the dispute resolver to check\n     * @return exists - the dispute resolver was found\n     * @return disputeResolver - the dispute resolver details. See {BosonTypes.DisputeResolver}\n     * @return disputeResolverFees - list of fees dispute resolver charges per token type. Zero address is native currency. See {BosonTypes.DisputeResolverFee}\n     * @return sellerAllowList - list of sellers that are allowed to choose this dispute resolver\n     */\n    function getDisputeResolver(\n        uint256 _disputeResolverId\n    )\n        external\n        view\n        returns (\n            bool exists,\n            BosonTypes.DisputeResolver memory disputeResolver,\n            BosonTypes.DisputeResolverFee[] memory disputeResolverFees,\n            uint256[] memory sellerAllowList\n        );\n\n    /**\n     * @notice Gets the details about a dispute resolver by an address associated with that dispute resolver: assistant, or admin address.\n     *\n     * @param _associatedAddress - the address associated with the dispute resolver. Must be an assistant, or admin address.\n     * @return exists - the dispute resolver was found\n     * @return disputeResolver - the dispute resolver details. See {BosonTypes.DisputeResolver}\n     * @return disputeResolverFees - list of fees dispute resolver charges per token type. Zero address is native currency. See {BosonTypes.DisputeResolverFee}\n     * @return sellerAllowList - list of sellers that are allowed to chose this dispute resolver\n     */\n    function getDisputeResolverByAddress(\n        address _associatedAddress\n    )\n        external\n        view\n        returns (\n            bool exists,\n            BosonTypes.DisputeResolver memory disputeResolver,\n            BosonTypes.DisputeResolverFee[] memory disputeResolverFees,\n            uint256[] memory sellerAllowList\n        );\n\n    /**\n     * @notice Checks whether given sellers are allowed to choose the given dispute resolver.\n     *\n     * @param _disputeResolverId - id of dispute resolver to check\n     * @param _sellerIds - list of seller ids to check\n     * @return sellerAllowed - array with indicator (true/false) if seller is allowed to choose the dispute resolver. Index in this array corresponds to indices of the incoming _sellerIds\n     */\n    function areSellersAllowed(\n        uint256 _disputeResolverId,\n        uint256[] calldata _sellerIds\n    ) external view returns (bool[] memory sellerAllowed);\n}\n"
      },
      "contracts/interfaces/handlers/IBosonExchangeHandler.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport { BosonTypes } from \"../../domain/BosonTypes.sol\";\nimport { BosonErrors } from \"../../domain/BosonErrors.sol\";\nimport { IBosonExchangeEvents } from \"../events/IBosonExchangeEvents.sol\";\nimport { IBosonTwinEvents } from \"../events/IBosonTwinEvents.sol\";\nimport { IBosonFundsLibEvents } from \"../events/IBosonFundsEvents.sol\";\n\n/**\n * @title IBosonExchangeHandler\n *\n * @notice Handles exchanges associated with offers within the protocol.\n *\n * The ERC-165 identifier for this interface is: 0x66e9075a\n */\ninterface IBosonExchangeHandler is BosonErrors, IBosonExchangeEvents, IBosonFundsLibEvents, IBosonTwinEvents {\n    /**\n     * @notice Commits to a static offer (first step of an exchange).\n     *\n     * Emits a BuyerCommitted event if successful.\n     * Issues a voucher to the buyer address.\n     *\n     * Reverts if:\n     * - The exchanges region of protocol is paused\n     * - The buyers region of protocol is paused\n     * - OfferId is invalid\n     * - Offer has been voided\n     * - Offer has expired\n     * - Offer is not yet available for commits\n     * - Offer's quantity available is zero\n     * - Buyer address is zero\n     * - Buyer account is inactive\n     * - Buyer is token-gated (conditional commit requirements not met or already used)\n     * - Offer price is in native token and caller does not send enough\n     * - Offer price is in some ERC20 token and caller also sends native currency\n     * - Contract at token address does not support ERC20 function transferFrom\n     * - Calling transferFrom on token fails for some reason (e.g. protocol is not approved to transfer)\n     * - Received ERC20 token amount differs from the expected value\n     * - Seller has less funds available than sellerDeposit\n     *\n     * @param _buyer - the buyer's address (caller can commit on behalf of a buyer)\n     * @param _offerId - the id of the offer to commit to\n     */\n    function commitToOffer(address payable _buyer, uint256 _offerId) external payable;\n\n    /**\n     * @notice Commits to an conditional offer (first step of an exchange).\n     *\n     * Emits a BuyerCommitted event if successful.\n     * Issues a voucher to the buyer address.\n     *\n     * Reverts if:\n     * - The exchanges region of protocol is paused\n     * - The buyers region of protocol is paused\n     * - OfferId is invalid\n     * - Offer has been voided\n     * - Offer has expired\n     * - Offer is not yet available for commits\n     * - Offer's quantity available is zero\n     * - Buyer address is zero\n     * - Buyer account is inactive\n     * - Conditional commit requirements not met or already used\n     * - Offer price is in native token and caller does not send enough\n     * - Offer price is in some ERC20 token and caller also sends native currency\n     * - Contract at token address does not support ERC20 function transferFrom\n     * - Calling transferFrom on token fails for some reason (e.g. protocol is not approved to transfer)\n     * - Received ERC20 token amount differs from the expected value\n     * - Seller has less funds available than sellerDeposit\n     * - Condition has a range and the token id is not within the range\n     *\n     * @param _buyer - the buyer's address (caller can commit on behalf of a buyer)\n     * @param _offerId - the id of the offer to commit to\n     * @param _tokenId - the id of the token to use for the conditional commit\n     */\n    function commitToConditionalOffer(address payable _buyer, uint256 _offerId, uint256 _tokenId) external payable;\n\n    /**\n     * @notice Completes an exchange.\n     *\n     * Emits an ExchangeCompleted event if successful.\n     *\n     * Reverts if\n     * - The exchanges region of protocol is paused\n     * - Exchange does not exist\n     * - Exchange is not in Redeemed state\n     * - Caller is not buyer and offer dispute period has not elapsed\n     *\n     * @param _exchangeId - the id of the exchange to complete\n     */\n    function completeExchange(uint256 _exchangeId) external;\n\n    /**\n     * @notice Completes a batch of exchanges.\n     *\n     * Emits an ExchangeCompleted event for every exchange if finalized to the Complete state.\n     *\n     * Reverts if:\n     * - The exchanges region of protocol is paused\n     * - For any exchange:\n     *   - Exchange does not exist\n     *   - Exchange is not in Redeemed state\n     *   - Caller is not buyer and offer dispute period has not elapsed\n     *\n     * @param _exchangeIds - the array of exchanges ids\n     */\n    function completeExchangeBatch(uint256[] calldata _exchangeIds) external;\n\n    /**\n     * @notice Revokes a voucher.\n     *\n     * Emits a VoucherRevoked event if successful.\n     *\n     * Reverts if\n     * - The exchanges region of protocol is paused\n     * - Exchange does not exist\n     * - Exchange is not in Committed state\n     * - Caller is not seller's assistant\n     *\n     * @param _exchangeId - the id of the exchange\n     */\n    function revokeVoucher(uint256 _exchangeId) external;\n\n    /**\n     * @notice Cancels a voucher.\n     *\n     * Emits a VoucherCanceled event if successful.\n     *\n     * Reverts if\n     * - The exchanges region of protocol is paused\n     * - Exchange does not exist\n     * - Exchange is not in Committed state\n     * - Caller does not own voucher\n     *\n     * @param _exchangeId - the id of the exchange\n     */\n    function cancelVoucher(uint256 _exchangeId) external;\n\n    /**\n     * @notice Expires a voucher.\n     *\n     * Emits a VoucherExpired event if successful.\n     *\n     * Reverts if\n     * - The exchanges region of protocol is paused\n     * - Exchange does not exist\n     * - Exchange is not in Committed state\n     * - Redemption period has not yet elapsed\n     *\n     * @param _exchangeId - the id of the exchange\n     */\n    function expireVoucher(uint256 _exchangeId) external;\n\n    /**\n     * @notice Extends a Voucher's validity period.\n     *\n     * Emits a VoucherExtended event if successful.\n     *\n     * Reverts if\n     * - The exchanges region of protocol is paused\n     * - Exchange does not exist\n     * - Exchange is not in Committed state\n     * - Caller is not seller's assistant\n     * - New date is not later than the current one\n     *\n     * @param _exchangeId - the id of the exchange\n     * @param _validUntilDate - the new voucher expiry date\n     */\n    function extendVoucher(uint256 _exchangeId, uint256 _validUntilDate) external;\n\n    /**\n     * @notice Redeems a voucher.\n     *\n     * Emits a VoucherRedeemed event if successful.\n     * Emits TwinTransferred if twin transfer was successfull\n     * Emits TwinTransferFailed if twin transfer failed\n     * Emits TwinTransferSkipped if twin transfer was skipped when the number of twins is too high\n     *\n     * Reverts if\n     * - The exchanges region of protocol is paused\n     * - Exchange does not exist\n     * - Exchange is not in committed state\n     * - Caller does not own voucher\n     * - Current time is prior to offer.voucherRedeemableFromDate\n     * - Current time is after voucher.validUntilDate\n     *\n     * @param _exchangeId - the id of the exchange\n     */\n    function redeemVoucher(uint256 _exchangeId) external;\n\n    /**\n     * @notice Informs protocol of new buyer associated with an exchange.\n     *\n     * Emits a VoucherTransferred event if successful.\n     *\n     * Reverts if\n     * - The exchanges region of protocol is paused\n     * - The buyers region of protocol is paused\n     * - Caller is not a clone address associated with the seller\n     * - Exchange does not exist\n     * - Exchange is not in Committed state\n     * - Voucher has expired\n     * - New buyer's existing account is deactivated\n     *\n     * @param _tokenId - the voucher id\n     * @param _newBuyer - the address of the new buyer\n     */\n    function onVoucherTransferred(uint256 _tokenId, address payable _newBuyer) external;\n\n    /**\n     * @notice Handle pre-minted voucher transfer\n     *\n     * Reverts if:\n     * - The exchanges region of protocol is paused\n     * - The buyers region of protocol is paused\n     * - Caller is not a clone address associated with the seller\n     * - Incoming voucher clone address is not the caller\n     * - Offer price is discovery, transaction is not starting from protocol nor seller is _from address\n     * - Any reason that ExchangeHandler commitToOfferInternal reverts. See ExchangeHandler.commitToOfferInternal\n     *\n     * @param _tokenId - the voucher id\n     * @param _to - the receiver address\n     * @param _from - the address of current owner\n     * @param _rangeOwner - the address of the preminted range owner\n     * @return committed - true if the voucher was committed\n     */\n    function onPremintedVoucherTransferred(\n        uint256 _tokenId,\n        address payable _to,\n        address _from,\n        address _rangeOwner\n    ) external returns (bool committed);\n\n    /**\n     * @notice Checks if the given exchange in a finalized state.\n     *\n     * Returns true if\n     * - Exchange state is Revoked, Canceled, or Completed\n     * - Exchange is disputed and dispute state is Retracted, Resolved, Decided or Refused\n     *\n     * @param _exchangeId - the id of the exchange to check\n     * @return exists - true if the exchange exists\n     * @return isFinalized - true if the exchange is finalized\n     */\n    function isExchangeFinalized(uint256 _exchangeId) external view returns (bool exists, bool isFinalized);\n\n    /**\n     * @notice Gets the details about a given exchange.\n     *\n     * @param _exchangeId - the id of the exchange to check\n     * @return exists - true if the exchange exists\n     * @return exchange - the exchange details. See {BosonTypes.Exchange}\n     * @return voucher - the voucher details. See {BosonTypes.Voucher}\n     */\n    function getExchange(\n        uint256 _exchangeId\n    ) external view returns (bool exists, BosonTypes.Exchange memory exchange, BosonTypes.Voucher memory voucher);\n\n    /**\n     * @notice Gets the state of a given exchange.\n     *\n     * @param _exchangeId - the id of the exchange to check\n     * @return exists - true if the exchange exists\n     * @return state - the exchange state. See {BosonTypes.ExchangeStates}\n     */\n    function getExchangeState(uint256 _exchangeId) external view returns (bool exists, BosonTypes.ExchangeState state);\n\n    /**\n     * @notice Gets the id that will be assigned to the next exchange.\n     *\n     * @dev Does not increment the counter.\n     *\n     * @return nextExchangeId - the next exchange id\n     */\n    function getNextExchangeId() external view returns (uint256 nextExchangeId);\n\n    /**\n     * @notice Gets EIP2981 style royalty information for a chosen offer or exchange.\n     *\n     * EIP2981 supports only 1 recipient, therefore this method defaults to treasury address.\n     * This method is not exactly compliant with EIP2981, since it does not accept `salePrice` and does not return `royaltyAmount,\n     * but it rather returns `royaltyPercentage` which is the sum of all bps (an exchange can have multiple royalty recipients).\n     *\n     * This function is meant to be primarly used by boson voucher client, which implements EIP2981.\n     *\n     * Reverts if exchange does not exist.\n     *\n     * @param _queryId - offer id or exchange id\n     * @param _isExchangeId - indicates if the query represents the exchange id\n     * @return receiver - the address of the royalty receiver (seller's treasury address)\n     * @return royaltyPercentage - the royalty percentage in bps\n     */\n    function getEIP2981Royalties(\n        uint256 _queryId,\n        bool _isExchangeId\n    ) external view returns (address receiver, uint256 royaltyPercentage);\n\n    /**\n     * @notice Gets royalty information for a chosen offer or exchange.\n     *\n     * Returns a list of royalty recipients and corresponding bps. Format is compatible with Manifold and Foundation royalties\n     * and can be directly used by royalty registry.\n     *\n     * Reverts if exchange does not exist.\n     *\n     * @param _tokenId - tokenId\n     * @return recipients - list of royalty recipients\n     * @return bps - list of corresponding bps\n     */\n    function getRoyalties(\n        uint256 _tokenId\n    ) external view returns (address payable[] memory recipients, uint256[] memory bps);\n\n    /**\n     * @notice Gets exchange receipt.\n     *\n     * Reverts if:\n     * - Exchange is not in a final state\n     * - Exchange id is invalid\n     *\n     * @param _exchangeId - the exchange id\n     * @return receipt - the receipt for the exchange. See {BosonTypes.Receipt}\n     */\n    function getReceipt(uint256 _exchangeId) external view returns (BosonTypes.Receipt memory receipt);\n\n    /**\n     * @notice Tells if buyer is elligible to commit to conditional\n     * Returns the eligibility status, the number of used commits and the maximal number of commits to the conditional offer.\n     *\n     * Unconditional offers do not have maximal number of commits, so the returned value will always be 0.\n     *\n     * This method does not check if the timestamp is within the offer's validity period or if the quantity available is greater than 0.\n     *\n     * N.B. Unmined transaction might affect the eligibility status.\n     *\n     * Reverts if:\n     * - The offer does not exist\n     * - The offer is voided\n     * - The external call to condition contract reverts\n     *\n     * @param _buyer buyer address\n     * @param _offerId - the id of the offer\n     * @param _tokenId - the id of conditional token\n     * @return isEligible - true if buyer is eligible to commit\n     * @return commitCount - the current number of commits to the conditional offer\n     * @return maxCommits - the maximal number of commits to the conditional offer\n     */\n    function isEligibleToCommit(\n        address _buyer,\n        uint256 _offerId,\n        uint256 _tokenId\n    ) external view returns (bool isEligible, uint256 commitCount, uint256 maxCommits);\n}\n"
      },
      "contracts/interfaces/handlers/IBosonFundsHandler.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport { BosonTypes } from \"../../domain/BosonTypes.sol\";\nimport { BosonErrors } from \"../../domain/BosonErrors.sol\";\nimport { IBosonFundsEvents } from \"../events/IBosonFundsEvents.sol\";\nimport { IBosonFundsLibEvents } from \"../events/IBosonFundsEvents.sol\";\n\n/**\n * @title IBosonFundsHandler\n *\n * @notice Handles custody and withdrawal of buyer and seller funds within the protocol.\n *\n * The ERC-165 identifier for this interface is: 0x2f4a64d7\n */\ninterface IBosonFundsHandler is IBosonFundsEvents, IBosonFundsLibEvents, BosonErrors {\n    /**\n     * @notice Receives funds from the caller, maps funds to the seller id and stores them so they can be used during the commitToOffer.\n     *\n     * Emits FundsDeposited event if successful.\n     *\n     * Reverts if:\n     * - The funds region of protocol is paused\n     * - Amount to deposit is zero\n     * - Seller id does not exist\n     * - It receives some native currency (e.g. ETH), but token address is not zero\n     * - It receives some native currency (e.g. ETH), and the amount does not match msg.value\n     * - It receives no native currency, but token address is zero\n     * - Contract at token address does not support ERC20 function transferFrom\n     * - Calling transferFrom on token fails for some reason (e.g. protocol is not approved to transfer)\n     * - Received ERC20 token amount differs from the expected value\n     *\n     * @param _sellerId - id of the seller that will be credited\n     * @param _tokenAddress - contract address of token that is being deposited (0 for native currency)\n     * @param _amount - amount to be credited\n     */\n    function depositFunds(uint256 _sellerId, address _tokenAddress, uint256 _amount) external payable;\n\n    /**\n     * @notice Withdraws the specified funds. Can be called for seller, buyer or agent.\n     *\n     * Emits FundsWithdrawn event if successful.\n     *\n     * Reverts if:\n     * - The funds region of protocol is paused\n     * - Caller is not associated with the entity id\n     * - Token list length does not match amount list length\n     * - Caller tries to withdraw more that they have in available funds\n     * - There is nothing to withdraw\n     * - Transfer of funds is not successful\n     *\n     * @param _entityId - id of entity for which funds should be withdrawn\n     * @param _tokenList - list of contract addresses of tokens that are being withdrawn\n     * @param _tokenAmounts - list of amounts to be withdrawn, corresponding to tokens in tokenList\n     */\n    function withdrawFunds(uint256 _entityId, address[] calldata _tokenList, uint256[] calldata _tokenAmounts) external;\n\n    /**\n     * @notice Withdraws the protocol fees.\n     *\n     * @dev Can only be called by the FEE_COLLECTOR role.\n     *\n     * Emits FundsWithdrawn event if successful.\n     *\n     * Reverts if:\n     * - The funds region of protocol is paused\n     * - Caller does not have the FEE_COLLECTOR role\n     * - Token list length does not match amount list length\n     * - Caller tries to withdraw more that they have in available funds\n     * - There is nothing to withdraw\n     * - Transfer of funds is not successful\n     *\n     * @param _tokenList - list of contract addresses of tokens that are being withdrawn\n     * @param _tokenAmounts - list of amounts to be withdrawn, corresponding to tokens in tokenList\n     */\n    function withdrawProtocolFees(address[] calldata _tokenList, uint256[] calldata _tokenAmounts) external;\n\n    /**\n     * @notice Returns list of addresses for which the entity has funds available.\n     * If the list is too long, it can be retrieved in chunks by using `getTokenListPaginated` and specifying _limit and _offset.\n     *\n     * @param _entityId - id of entity for which availability of funds should be checked\n     * @return tokenList - list of token addresses\n     */\n    function getTokenList(uint256 _entityId) external view returns (address[] memory tokenList);\n\n    /**\n     * @notice Returns list of addresses for which the entity has funds available.\n     *\n     * @param _entityId - id of entity for which availability of funds should be checked\n     * @param _limit - the maximum number of token addresses that should be returned starting from the index defined by `_offset`. If `_offset` + `_limit` exceeds total tokens, `_limit` is adjusted to return all remaining tokens.\n     * @param _offset - the starting index from which to return token addresses. If `_offset` is greater than or equal to total tokens, an empty list is returned.\n     * @return tokenList - list of token addresses\n     */\n    function getTokenListPaginated(\n        uint256 _entityId,\n        uint256 _limit,\n        uint256 _offset\n    ) external view returns (address[] memory tokenList);\n\n    /**\n     * @notice Returns the information about the funds that an entity can use as a sellerDeposit and/or withdraw from the protocol.\n     * It tries to get information about all tokens that the entity has in availableFunds storage.\n     * If the token list is too long, this call may run out of gas. In this case, the caller should use the function `getAvailableFunds` and pass the token list.\n     *\n     * @param _entityId - id of entity for which availability of funds should be checked\n     * @return availableFunds - list of token addresses, token names and amount that can be used as a seller deposit or be withdrawn\n     */\n    function getAllAvailableFunds(uint256 _entityId) external view returns (BosonTypes.Funds[] memory availableFunds);\n\n    /**\n     * @notice Returns the information about the funds that an entity can use as a sellerDeposit and/or withdraw from the protocol.\n     * To get a list of tokens that the entity has in availableFunds storage, use the function `getTokenList`.\n     *\n     * @param _entityId - id of entity for which availability of funds should be checked\n     * @param _tokenList - list of tokens addresses to get available funds\n     * @return availableFunds - list of token addresses, token names and amount that can be used as a seller deposit or be withdrawn\n     */\n    function getAvailableFunds(\n        uint256 _entityId,\n        address[] calldata _tokenList\n    ) external view returns (BosonTypes.Funds[] memory availableFunds);\n}\n"
      },
      "contracts/interfaces/handlers/IBosonOfferHandler.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport { BosonTypes } from \"../../domain/BosonTypes.sol\";\nimport { BosonErrors } from \"../../domain/BosonErrors.sol\";\nimport { IBosonOfferEvents } from \"../events/IBosonOfferEvents.sol\";\n\n/**\n * @title IBosonOfferHandler\n *\n * @notice Handles creation, voiding, and querying of offers within the protocol.\n *\n * The ERC-165 identifier for this interface is: 0x91b54fdc\n */\ninterface IBosonOfferHandler is BosonErrors, IBosonOfferEvents {\n    /**\n     * @notice Creates an offer.\n     *\n     * Emits an OfferCreated event if successful.\n     *\n     * Reverts if:\n     * - The offers region of protocol is paused\n     * - Caller is not an assistant\n     * - Valid from date is greater than valid until date\n     * - Valid until date is not in the future\n     * - Both voucher expiration date and voucher expiration period are defined\n     * - Neither of voucher expiration date and voucher expiration period are defined\n     * - Voucher redeemable period is fixed, but it ends before it starts\n     * - Voucher redeemable period is fixed, but it ends before offer expires\n     * - Dispute period is less than minimum dispute period\n     * - Resolution period is not between the minimum and the maximum resolution period\n     * - Voided is set to true\n     * - Available quantity is set to zero\n     * - Offer type is discovery and the price is not set to zero\n     * - Dispute resolver wallet is not registered, except for absolute zero offers with unspecified dispute resolver\n     * - Dispute resolver is not active, except for absolute zero offers with unspecified dispute resolver\n     * - Seller is not on dispute resolver's seller allow list\n     * - Dispute resolver does not accept fees in the exchange token\n     * - Buyer cancel penalty is greater than price\n     * - Collection does not exist\n     * - When agent id is non zero:\n     *   - If Agent does not exist\n     * - If the sum of agent fee amount and protocol fee amount is greater than the offer fee limit determined by the protocol\n     * - If the sum of agent fee amount and protocol fee amount is greater than fee limit set by seller\n     * - Royalty recipient is not on seller's allow list\n     * - Royalty percentage is less than the value decided by the admin\n     * - Total royalty percentage is more than max royalty percentage\n     *\n     * @param _offer - the fully populated struct with offer id set to 0x0 and voided set to false\n     * @param _offerDates - the fully populated offer dates struct\n     * @param _offerDurations - the fully populated offer durations struct\n     * @param _disputeResolverId - the id of chosen dispute resolver (can be 0)\n     * @param _agentId - the id of agent\n     * @param _feeLimit - the maximum fee that seller is willing to pay per exchange (for static offers)\n     */\n    function createOffer(\n        BosonTypes.Offer memory _offer,\n        BosonTypes.OfferDates calldata _offerDates,\n        BosonTypes.OfferDurations calldata _offerDurations,\n        uint256 _disputeResolverId,\n        uint256 _agentId,\n        uint256 _feeLimit\n    ) external;\n\n    /**\n     * @notice Creates a batch of offers.\n     *\n     * Emits an OfferCreated event for every offer if successful.\n     *\n     * Reverts if:\n     * - The offers region of protocol is paused\n     * - Number of elements in offers, offerDates, offerDurations, disputeResolverIds, agentIds and feeLimits do not match\n     * - For any offer:\n     *   - Caller is not an assistant\n     *   - Valid from date is greater than valid until date\n     *   - Valid until date is not in the future\n     *   - Both voucher expiration date and voucher expiration period are defined\n     *   - Neither of voucher expiration date and voucher expiration period are defined\n     *   - Voucher redeemable period is fixed, but it ends before it starts\n     *   - Voucher redeemable period is fixed, but it ends before offer expires\n     *   - Dispute period is less than minimum dispute period\n     *   - Resolution period is not between the minimum and the maximum resolution period\n     *   - Voided is set to true\n     *   - Available quantity is set to zero\n     *   - Offer type is discovery and the price is not set to zero\n     *   - Dispute resolver wallet is not registered, except for absolute zero offers with unspecified dispute resolver\n     *   - Dispute resolver is not active, except for absolute zero offers with unspecified dispute resolver\n     *   - Seller is not on dispute resolver's seller allow list\n     *   - Dispute resolver does not accept fees in the exchange token\n     *   - Buyer cancel penalty is greater than price\n     *   - Collection does not exist\n     *   - Royalty recipient is not on seller's allow list\n     *   - Royalty percentage is less than the value decided by the admin\n     *   - Total royalty percentage is more than max royalty percentage\n     * - When agent ids are non zero:\n     *   - If Agent does not exist\n     *   - If the sum of agent fee amount and protocol fee amount is greater than the offer fee limit\n     *\n     * @param _offers - the array of fully populated Offer structs with offer id set to 0x0 and voided set to false\n     * @param _offerDates - the array of fully populated offer dates structs\n     * @param _offerDurations - the array of fully populated offer durations structs\n     * @param _disputeResolverIds - the array of ids of chosen dispute resolvers (can be 0)\n     * @param _agentIds - the array of ids of agents\n     * @param _feeLimits - the array of maximum fees that seller is willing to pay per exchange (for static offers)\n     */\n    function createOfferBatch(\n        BosonTypes.Offer[] calldata _offers,\n        BosonTypes.OfferDates[] calldata _offerDates,\n        BosonTypes.OfferDurations[] calldata _offerDurations,\n        uint256[] calldata _disputeResolverIds,\n        uint256[] calldata _agentIds,\n        uint256[] calldata _feeLimits\n    ) external;\n\n    /**\n     * @notice Reserves a range of vouchers to be associated with an offer\n     *\n     *\n     * Reverts if:\n     * - The offers region of protocol is paused\n     * - The exchanges region of protocol is paused\n     * - Offer does not exist\n     * - Offer already voided\n     * - Caller is not the seller\n     * - Range length is zero\n     * - Range length is greater than quantity available\n     * - Range length is greater than maximum allowed range length\n     * - Call to BosonVoucher.reserveRange() reverts\n     * - _to is not the BosonVoucher contract address or the BosonVoucher contract owner\n     *\n     * @param _offerId - the id of the offer\n     * @param _length - the length of the range\n     * @param _to - the address to send the pre-minted vouchers to (contract address or contract owner)\n     */\n    function reserveRange(uint256 _offerId, uint256 _length, address _to) external;\n\n    /**\n     * @notice Voids a given offer.\n     * Existing exchanges are not affected.\n     * No further vouchers can be issued against a voided offer.\n     *\n     * Emits an OfferVoided event if successful.\n     *\n     * Reverts if:\n     * - The offers region of protocol is paused\n     * - Offer id is invalid\n     * - Caller is not the assistant of the offer\n     * - Offer has already been voided\n     *\n     * @param _offerId - the id of the offer to void\n     */\n    function voidOffer(uint256 _offerId) external;\n\n    /**\n     * @notice  Voids a batch of offers.\n     * Existing exchanges are not affected.\n     * No further vouchers can be issued against a voided offer.\n     *\n     * Emits an OfferVoided event for every offer if successful.\n     *\n     * Reverts if, for any offer:\n     * - The offers region of protocol is paused\n     * - Offer id is invalid\n     * - Caller is not the assistant of the offer\n     * - Offer has already been voided\n     *\n     * @param _offerIds - list of ids of offers to void\n     */\n    function voidOfferBatch(uint256[] calldata _offerIds) external;\n\n    /**\n     * @notice Sets new valid until date.\n     *\n     * Emits an OfferExtended event if successful.\n     *\n     * Reverts if:\n     * - The offers region of protocol is paused\n     * - Offer does not exist\n     * - Caller is not the assistant of the offer\n     * - New valid until date is before existing valid until dates\n     * - Offer has voucherRedeemableUntil set and new valid until date is greater than that\n     *\n     *  @param _offerId - the id of the offer to extend\n     *  @param _validUntilDate - new valid until date\n     */\n    function extendOffer(uint256 _offerId, uint256 _validUntilDate) external;\n\n    /**\n     * @notice Sets new valid until date for a batch of offers.\n     *\n     * Emits an OfferExtended event for every offer if successful.\n     *\n     * Reverts if:\n     * - The offers region of protocol is paused\n     * - For any of the offers:\n     *   - Offer does not exist\n     *   - Caller is not the assistant of the offer\n     *   - New valid until date is before existing valid until dates\n     *   - Offer has voucherRedeemableUntil set and new valid until date is greater than that\n     *\n     *  @param _offerIds - list of ids of the offers to extend\n     *  @param _validUntilDate - new valid until date\n     */\n    function extendOfferBatch(uint256[] calldata _offerIds, uint256 _validUntilDate) external;\n\n    /**\n     * @notice Sets new valid royalty info.\n     *\n     * Emits an OfferRoyaltyInfoUpdated event if successful.\n     *\n     * Reverts if:\n     * - The offers region of protocol is paused\n     * - Offer does not exist\n     * - Caller is not the assistant of the offer\n     * - New royalty info is invalid\n     *\n     *  @param _offerId - the id of the offer to be updated\n     *  @param _royaltyInfo - new royalty info\n     */\n    function updateOfferRoyaltyRecipients(uint256 _offerId, BosonTypes.RoyaltyInfo calldata _royaltyInfo) external;\n\n    /**\n     * @notice Sets new valid until date for a batch of offers.\n     *\n     * Emits an OfferExtended event for every offer if successful.\n     *\n     * Reverts if:\n     * - The offers region of protocol is paused\n     * - For any of the offers:\n     *   - Offer does not exist\n     *   - Caller is not the assistant of the offer\n     *   - New royalty info is invalid\n     *\n     *  @param _offerIds - list of ids of the offers to extend\n     *  @param _royaltyInfo - new royalty info\n     */\n    function updateOfferRoyaltyRecipientsBatch(\n        uint256[] calldata _offerIds,\n        BosonTypes.RoyaltyInfo calldata _royaltyInfo\n    ) external;\n\n    /**\n     * @notice Gets the details about a given offer.\n     *\n     * @param _offerId - the id of the offer to retrieve\n     * @return exists - the offer was found\n     * @return offer - the offer details. See {BosonTypes.Offer}\n     * @return offerDates - the offer dates details. See {BosonTypes.OfferDates}\n     * @return offerDurations - the offer durations details. See {BosonTypes.OfferDurations}\n     * @return disputeResolutionTerms - the details about the dispute resolution terms. See {BosonTypes.DisputeResolutionTerms}\n     * @return offerFees - the offer fees details. See {BosonTypes.OfferFees}\n     */\n    function getOffer(\n        uint256 _offerId\n    )\n        external\n        view\n        returns (\n            bool exists,\n            BosonTypes.Offer memory offer,\n            BosonTypes.OfferDates memory offerDates,\n            BosonTypes.OfferDurations memory offerDurations,\n            BosonTypes.DisputeResolutionTerms memory disputeResolutionTerms,\n            BosonTypes.OfferFees memory offerFees\n        );\n\n    /**\n     * @notice Gets the next offer id.\n     *\n     * @dev Does not increment the counter.\n     *\n     * @return nextOfferId - the next offer id\n     */\n    function getNextOfferId() external view returns (uint256 nextOfferId);\n\n    /**\n     * @notice Checks if offer is voided or not.\n     *\n     * @param _offerId - the id of the offer to check\n     * @return exists - the offer was found\n     * @return offerVoided - true if voided, false otherwise\n     */\n    function isOfferVoided(uint256 _offerId) external view returns (bool exists, bool offerVoided);\n\n    /**\n     * @notice Gets the agent id for a given offer id.\n     *\n     * @param _offerId - the offer id\n     * @return exists - whether the agent id exists\n     * @return agentId - the agent id\n     */\n    function getAgentIdByOffer(uint256 _offerId) external view returns (bool exists, uint256 agentId);\n}\n"
      },
      "contracts/interfaces/handlers/IBosonSellerHandler.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport { BosonTypes } from \"../../domain/BosonTypes.sol\";\n\n/**\n * @title IBosonSellerHandler\n *\n * @notice Handles creation, update, retrieval of sellers within the protocol.\n *\n * The ERC-165 identifier for this interface is: 0x3e8eaeef\n */\ninterface IBosonSellerHandler {\n    /**\n     * @notice Creates a seller.\n     *\n     * Emits a SellerCreated event if successful.\n     *\n     * Reverts if:\n     * - Caller is not the supplied admin or does not own supplied auth token\n     * - Caller is not the supplied assistant\n     * - Supplied clerk is not a zero address\n     * - The sellers region of protocol is paused\n     * - Address values are zero address\n     * - Addresses are not unique to this seller\n     * - Seller is not active (if active == false)\n     * - Admin address is zero address and AuthTokenType == None\n     * - AuthTokenType is not unique to this seller\n     * - AuthTokenType is Custom\n     * - Seller salt is not unique\n     * - Clone creation fails\n     *\n     * @param _seller - the fully populated struct with seller id set to 0x0\n     * @param _authToken - optional AuthToken struct that specifies an AuthToken type and tokenId that the seller can use to do admin functions\n     * @param _voucherInitValues - the fully populated BosonTypes.VoucherInitValues struct\n     */\n    function createSeller(\n        BosonTypes.Seller memory _seller,\n        BosonTypes.AuthToken calldata _authToken,\n        BosonTypes.VoucherInitValues calldata _voucherInitValues\n    ) external;\n\n    /**\n     * @notice Updates treasury address, if changed. Puts admin, assistant and AuthToken in pending queue, if changed.\n     *         Pending updates can be completed by calling the optInToSellerUpdate function.\n     * @dev    Active flag passed in by caller will be ignored. The value from storage will be used.\n     *\n     * Emits a SellerUpdateApplied event if the seller has changed the treasury.\n     * Emits a SellerUpdatePending event if the seller has requested an update for admin, assistant, or auth token.\n     * Holder of new auth token and/or owner(s) of new addresses for admin, assistant must opt-in to the update.\n     *\n     * Reverts if:\n     * - The sellers region of protocol is paused\n     * - Address values are zero address\n     * - Addresses are not unique to this seller\n     * - Supplied clerk is not a zero address\n     * - Caller address is not the admin address of the stored seller with no AuthToken\n     * - Caller is not the owner of the seller's stored AuthToken\n     * - Seller does not exist\n     * - Admin address is zero address and AuthTokenType == None\n     * - AuthTokenType is not unique to this seller\n     * - AuthTokenType is Custom\n     * - No field has been updated or requested to be updated\n     *\n     * @param _seller - the fully populated seller struct\n     * @param _authToken - optional AuthToken struct that specifies an AuthToken type and tokenId that the seller can use to do admin functions\n     */\n    function updateSeller(BosonTypes.Seller memory _seller, BosonTypes.AuthToken calldata _authToken) external;\n\n    /**\n     * @notice Opt-in to a pending seller update\n     *\n     * Emits a SellerUpdateApplied event if successful.\n     *\n     * Reverts if:\n     * - The sellers region of protocol is paused\n     * - Addresses are not unique to this seller\n     * - Caller address is not pending update for the field being updated\n     * - Caller is not the owner of the pending AuthToken being updated\n     * - No pending update exists for this seller\n     * - AuthTokenType is not unique to this seller\n     * - Seller tries to update the clerk\n     *\n     * @param _sellerId - seller id\n     * @param _fieldsToUpdate - fields to update, see SellerUpdateFields enum\n     */\n    function optInToSellerUpdate(uint256 _sellerId, BosonTypes.SellerUpdateFields[] calldata _fieldsToUpdate) external;\n\n    /**\n     * @notice Adds royalty recipients to a seller.\n     *\n     * Emits a RoyalRecipientsUpdated event if successful.\n     *\n     *  Reverts if:\n     *  - The sellers region of protocol is paused\n     *  - Seller does not exist\n     *  - Caller is not the seller admin\n     *  - Caller does not own auth token\n     *  - Some recipient is not unique\n     *  - some royalty percentage is above the limit\n     *\n     * @param _sellerId - seller id\n     * @param _royaltyRecipients - list of royalty recipients to add\n     */\n    function addRoyaltyRecipients(\n        uint256 _sellerId,\n        BosonTypes.RoyaltyRecipientInfo[] calldata _royaltyRecipients\n    ) external;\n\n    /**\n     * @notice Updates seller's royalty recipients.\n     *\n     * Emits a RoyalRecipientsUpdated event if successful.\n     *\n     *  Reverts if:\n     *  - The sellers region of protocol is paused\n     *  - Seller does not exist\n     *  - Caller is not the seller admin\n     *  - Caller does not own auth token\n     *  - Length of ids to change does not match length of new values\n     *  - Id to update does not exist\n     *  - Seller tries to update the address of default recipient\n     *  - Some recipient is not unique\n     *  - Some royalty percentage is above the limit\n     *\n     * @param _sellerId - seller id\n     * @param _royaltyRecipientIds - list of royalty recipient ids to update. Ids are zero based and corresponds to ids returned by `getRoyaltyRecipients`.\n     * @param _royaltyRecipients - list of new royalty recipients corresponding to ids\n     */\n    function updateRoyaltyRecipients(\n        uint256 _sellerId,\n        uint256[] calldata _royaltyRecipientIds,\n        BosonTypes.RoyaltyRecipientInfo[] calldata _royaltyRecipients\n    ) external;\n\n    /**\n     * @notice Removes seller's royalty recipients.\n     *\n     * Emits a RoyalRecipientsUpdated event if successful.\n     *\n     *  Reverts if:\n     *  - The sellers region of protocol is paused\n     *  - Seller does not exist\n     *  - Caller is not the seller admin\n     *  - Caller does not own auth token\n     *  - List of ids to remove is not sorted in ascending order\n     *  - Id to remove does not exist\n     *  - Seller tries to remove the default recipient\n     *\n     * @param _sellerId - seller id\n     * @param _royaltyRecipientIds - list of royalty recipient ids to remove. Ids are zero based and corresponds to ids returned by `getRoyaltyRecipients`.\n     */\n    function removeRoyaltyRecipients(uint256 _sellerId, uint256[] calldata _royaltyRecipientIds) external;\n\n    /**\n     * @notice Creates a new seller collection.\n     *\n     * Emits a CollectionCreated event if successful.\n     *\n     * Reverts if:\n     * - The sellers region of protocol is paused\n     * - Caller is not the seller assistant\n     *\n     * @param _externalId - external collection id\n     * @param _voucherInitValues - the fully populated BosonTypes.VoucherInitValues struct\n     */\n    function createNewCollection(\n        string calldata _externalId,\n        BosonTypes.VoucherInitValues calldata _voucherInitValues\n    ) external;\n\n    /**\n     * @notice Updates a salt.\n     * Use this if the admin address is updated and there exists a possibility that the old admin will try to create the vouchers\n     * with matching addresses on other chains.\n     *\n     * Reverts if:\n     * - The sellers region of protocol is paused\n     * - Caller is not the admin of any seller\n     * - Seller salt is not unique\n     *\n     * @param _sellerId - the id of the seller\n     * @param _newSalt - new salt\n     */\n    function updateSellerSalt(uint256 _sellerId, bytes32 _newSalt) external;\n\n    /**\n     * @notice Gets the details about a seller.\n     *\n     * @param _sellerId - the id of the seller to check\n     * @return exists - the seller was found\n     * @return seller - the seller details. See {BosonTypes.Seller}\n     * @return authToken - optional AuthToken struct that specifies an AuthToken type and tokenId that the seller can use to do admin functions\n     *                     See {BosonTypes.AuthToken}\n     */\n    function getSeller(\n        uint256 _sellerId\n    ) external view returns (bool exists, BosonTypes.Seller memory seller, BosonTypes.AuthToken memory authToken);\n\n    /**\n     * @notice Gets the details about a seller by an address associated with that seller: assistant, or admin address.\n     * A seller will have either an admin address or an auth token.\n     * If seller's admin uses NFT Auth the seller should call `getSellerByAuthToken` instead.\n     *\n     * @param _associatedAddress - the address associated with the seller. Must be an assistant, or admin  address.\n     * @return exists - the seller was found\n     * @return seller - the seller details. See {BosonTypes.Seller}\n     * @return authToken - optional AuthToken struct that specifies an AuthToken type and tokenId that the seller can use to do admin functions\n     *                     See {BosonTypes.AuthToken}\n     */\n    function getSellerByAddress(\n        address _associatedAddress\n    ) external view returns (bool exists, BosonTypes.Seller memory seller, BosonTypes.AuthToken memory authToken);\n\n    /**\n     * @notice Gets the details about a seller by an auth token associated with that seller.\n     * A seller will have either an admin address or an auth token.\n     * If seller's admin uses an admin address, the seller should call `getSellerByAddress` instead.\n     *\n     *\n     * @param _associatedAuthToken - the auth token that may be associated with the seller.\n     * @return exists - the seller was found\n     * @return seller - the seller details. See {BosonTypes.Seller}\n     * @return authToken - optional AuthToken struct that specifies an AuthToken type and tokenId that the seller can use to do admin functions\n     *                     See {BosonTypes.AuthToken}\n     */\n    function getSellerByAuthToken(\n        BosonTypes.AuthToken calldata _associatedAuthToken\n    ) external view returns (bool exists, BosonTypes.Seller memory seller, BosonTypes.AuthToken memory authToken);\n\n    /**\n     * @notice Gets the details about all seller's collections.\n     * In case seller has too many collections and this runs out of gas, please use getSellersCollectionsPaginated.\n     *\n     * @param _sellerId - the id of the seller to check\n     * @return defaultVoucherAddress - the address of the default voucher contract for the seller\n     * @return additionalCollections - an array of additional collections that the seller has created\n     */\n    function getSellersCollections(\n        uint256 _sellerId\n    ) external view returns (address defaultVoucherAddress, BosonTypes.Collection[] memory additionalCollections);\n\n    /**\n     * @notice Gets the details about all seller's collections.\n     * Use getSellersCollectionCount to get the total number of collections.\n     *\n     * @param _sellerId - the id of the seller to check\n     * @param _limit - the maximum number of Collections that should be returned starting from the index defined by `_offset`. If `_offset` + `_limit` exceeds total number of collections, `_limit` is adjusted to return all remaining collections.\n     * @param _offset - the starting index from which to return collections. If `_offset` is greater than or equal to total number of collections, an empty list is returned.\n     * @return defaultVoucherAddress - the address of the default voucher contract for the seller\n     * @return additionalCollections - an array of additional collections that the seller has created\n     */\n    function getSellersCollectionsPaginated(\n        uint256 _sellerId,\n        uint256 _limit,\n        uint256 _offset\n    ) external view returns (address defaultVoucherAddress, BosonTypes.Collection[] memory additionalCollections);\n\n    /**\n     * @notice Returns the number of additional collections for a seller.\n     * Use this in conjunction with getSellersCollectionsPaginated to get all collections.\n     *\n     * @param _sellerId - the id of the seller to check\n     */\n    function getSellersCollectionCount(uint256 _sellerId) external view returns (uint256 collectionCount);\n\n    /**\n     * @notice Returns the availability of salt for a seller.\n     *\n     * @param _adminAddres - the admin address to check\n     * @param _salt - the salt to check (corresponds to `collectionSalt` when `createSeler` or `createNewCollection` is called or `newSalt` when `updateSellerSalt` is called)\n     * @return isAvailable - salt can be used\n     */\n    function isSellerSaltAvailable(address _adminAddres, bytes32 _salt) external view returns (bool isAvailable);\n\n    /**\n     * @notice Calculates the expected collection address and tells if it's still avaialble.\n     *\n     * @param _sellerId - the seller id\n     * @param _collectionSalt - the collection specific salt\n     * @return collectionAddress - the collection address\n     * @return isAvailable - whether the collection address is available\n     */\n    function calculateCollectionAddress(\n        uint256 _sellerId,\n        bytes32 _collectionSalt\n    ) external view returns (address collectionAddress, bool isAvailable);\n\n    /**\n     * @notice Gets seller's royalty recipients.\n     *\n     * @param _sellerId - seller id\n     * @return royaltyRecipients - list of royalty recipients\n     */\n    function getRoyaltyRecipients(\n        uint256 _sellerId\n    ) external view returns (BosonTypes.RoyaltyRecipientInfo[] memory royaltyRecipients);\n}\n"
      },
      "contracts/interfaces/IAccessControl.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity 0.8.22;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted signaling this.\n     *\n     * _Available since v3.1._\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call, an admin role\n     * bearer except when using {AccessControl-_setupRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     */\n    function renounceRole(bytes32 role, address account) external;\n}\n"
      },
      "contracts/protocol/bases/BeaconClientBase.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport \"../../domain/BosonConstants.sol\";\nimport { BosonErrors } from \"../../domain/BosonErrors.sol\";\nimport { IBosonOfferHandler } from \"../../interfaces/handlers/IBosonOfferHandler.sol\";\nimport { IBosonExchangeHandler } from \"../../interfaces/handlers/IBosonExchangeHandler.sol\";\nimport { IBosonAccountHandler } from \"../../interfaces/handlers/IBosonAccountHandler.sol\";\nimport { BosonTypes } from \"../../domain/BosonTypes.sol\";\nimport { BeaconClientLib } from \"../libs/BeaconClientLib.sol\";\nimport { IClientExternalAddresses } from \"../../interfaces/clients/IClientExternalAddresses.sol\";\n\n/**\n * @title BeaconClientBase\n *\n * @notice Extended by Boson Protocol contracts that need to communicate with the ProtocolDiamond\n * but are NOT facets of the ProtocolDiamond. This is used where it's expected that multiple clients\n * will use the same implementation. If it's expected that only one client will use it, it's recommended to use `ClientBase` instead\n *\n * Boson client contracts include BosonVoucher\n */\nabstract contract BeaconClientBase is BosonTypes, BosonErrors {\n    /**\n     * @dev Modifier that checks that the caller has a specific role.\n     *\n     * Reverts if:\n     * - Caller doesn't have role\n     *\n     * See: {AccessController.hasRole}\n     *\n     * @param _role - the role to check\n     */\n    modifier onlyRole(bytes32 _role) {\n        if (!BeaconClientLib.hasRole(_role)) revert AccessDenied();\n        _;\n    }\n\n    /**\n     * @notice Gets the info about the offer associated with a voucher's exchange\n     *\n     * @param _exchangeId - the id of the exchange\n     * @return exists - the offer was found\n     * @return offer - the offer associated with the _exchangeId\n     */\n    function getBosonOfferByExchangeId(uint256 _exchangeId) internal view returns (bool exists, Offer memory offer) {\n        address protocolDiamond = IClientExternalAddresses(BeaconClientLib._beacon()).getProtocolAddress();\n        (, Exchange memory exchange, ) = IBosonExchangeHandler(protocolDiamond).getExchange(_exchangeId);\n        (exists, offer, , , , ) = IBosonOfferHandler(protocolDiamond).getOffer(exchange.offerId);\n    }\n\n    /**\n     * @notice Gets the royalty information for a chosen offer or exchange from the protocol.\n     *\n     * @param _queryId - offer id or exchange id\n     * @param _isExchangeId - indicates if the query represents the exchange id\n     * @return receiver - the address of the royalty receiver (seller's treasury address)\n     * @return royaltyPercentage - the royalty percentage in bps\n     */\n    function getEIP2981RoyaltiesFromProtocol(\n        uint256 _queryId,\n        bool _isExchangeId\n    ) internal view returns (address receiver, uint256 royaltyPercentage) {\n        address protocolDiamond = IClientExternalAddresses(BeaconClientLib._beacon()).getProtocolAddress();\n        return IBosonExchangeHandler(protocolDiamond).getEIP2981Royalties(_queryId, _isExchangeId);\n    }\n\n    /**\n     * @notice Gets the info about the offer associated with a voucher's exchange\n     *\n     * @param _offerId - the offer id\n     * @return offer - the offer associated with the _offerId\n     * @return offerDates - the offer dates associated with the _offerId\n     */\n    function getBosonOffer(uint256 _offerId) internal view returns (Offer memory offer, OfferDates memory offerDates) {\n        address protocolDiamond = IClientExternalAddresses(BeaconClientLib._beacon()).getProtocolAddress();\n        (, offer, offerDates, , , ) = IBosonOfferHandler(protocolDiamond).getOffer(_offerId);\n    }\n\n    /**\n     * @notice Informs protocol of new buyer associated with an exchange\n     *\n     * @param _tokenId - the voucher id\n     * @param _newBuyer - the address of the new buyer\n     */\n    function onVoucherTransferred(uint256 _tokenId, address payable _newBuyer) internal {\n        address protocolDiamond = IClientExternalAddresses(BeaconClientLib._beacon()).getProtocolAddress();\n        IBosonExchangeHandler(protocolDiamond).onVoucherTransferred(_tokenId, _newBuyer);\n    }\n\n    /**\n     * @notice Informs protocol of a pre-minted voucher transfer\n     *\n     * @param _tokenId - the voucher id\n     * @param _to - the address of the new buyer\n     * @param _from - the address of current owner\n     * @param _rangeOwner - the address of the preminted range owner\n     */\n    function onPremintedVoucherTransferred(\n        uint256 _tokenId,\n        address payable _to,\n        address _from,\n        address _rangeOwner\n    ) internal returns (bool) {\n        address protocolDiamond = IClientExternalAddresses(BeaconClientLib._beacon()).getProtocolAddress();\n        return IBosonExchangeHandler(protocolDiamond).onPremintedVoucherTransferred(_tokenId, _to, _from, _rangeOwner);\n    }\n\n    /**\n     * @notice Gets the info about the seller associated with the address.\n     *\n     * @param _sellerAddress - the address of the seller\n     * @return exists - the seller was found\n     * @return seller - the seller associated with the _sellerAddress\n     */\n    function getBosonSellerByAddress(address _sellerAddress) internal view returns (bool exists, Seller memory seller) {\n        address protocolDiamond = IClientExternalAddresses(BeaconClientLib._beacon()).getProtocolAddress();\n\n        (exists, seller, ) = IBosonAccountHandler(protocolDiamond).getSellerByAddress(_sellerAddress);\n    }\n}\n"
      },
      "contracts/protocol/clients/voucher/BosonVoucher.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.22;\n\nimport \"../../../domain/BosonConstants.sol\";\nimport { ERC721Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\";\nimport { IERC721Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\";\nimport { IERC721MetadataUpgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol\";\nimport { IERC2981Upgradeable } from \"@openzeppelin/contracts-upgradeable/interfaces/IERC2981Upgradeable.sol\";\nimport { IERC165Upgradeable } from \"@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol\";\nimport { OwnableUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { IERC721ReceiverUpgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol\";\nimport { ContextUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\nimport { ERC2771ContextUpgradeable } from \"@openzeppelin/contracts-upgradeable/metatx/ERC2771ContextUpgradeable.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IBosonVoucher } from \"../../../interfaces/clients/IBosonVoucher.sol\";\nimport { BeaconClientBase } from \"../../bases/BeaconClientBase.sol\";\nimport { BeaconClientLib } from \"../../libs/BeaconClientLib.sol\";\nimport { IClientExternalAddresses } from \"../../../interfaces/clients/IClientExternalAddresses.sol\";\nimport { IBosonFundsHandler } from \"../../../interfaces/handlers/IBosonFundsHandler.sol\";\n\n/**\n * @title BosonVoucherBase\n * @notice This is the Boson Protocol ERC-721 Voucher contract.\n *\n * N.B. Although this contract extends OwnableUpgradeable and ERC721Upgradeable,\n *      that is only for convenience, to avoid conflicts with mixed imports.\n */\ncontract BosonVoucherBase is IBosonVoucher, BeaconClientBase, OwnableUpgradeable, ERC721Upgradeable {\n    using Address for address;\n    using SafeERC20 for IERC20;\n\n    // Struct that is used to manipulate private variables from ERC721UpgradeableStorage\n    struct ERC721UpgradeableStorage {\n        // Mapping from token ID to owner address\n        mapping(uint256 => address) _owners;\n        // Mapping owner address to token count\n        mapping(address => uint256) _balances;\n    }\n\n    // Opensea collection config\n    string private _contractURI;\n\n    // Royalty percentage requested by seller (for all offers)\n    // Not used anymore. Need to stay to avoid storage shift.\n    uint256 private _royaltyPercentageUnused;\n\n    // Map an offerId to a Range for pre-minted offers\n    mapping(uint256 => Range) private _rangeByOfferId;\n\n    // Used only temporarly in transfers\n    bool private _isCommittable;\n\n    // Tell if voucher has already been _committed\n    mapping(uint256 => bool) private _committed;\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[45] private __gap;\n\n    /**\n     * @notice Initializes the voucher.\n     * This function is callable only once.\n     */\n    function initializeVoucher(\n        uint256 _sellerId,\n        uint256 _collectionIndex,\n        address _newOwner,\n        VoucherInitValues calldata voucherInitValues\n    ) public initializer {\n        string memory sellerId = string.concat(\n            \"S\",\n            Strings.toString(_sellerId),\n            \"_C\",\n            Strings.toString(_collectionIndex)\n        );\n        string memory voucherName = string.concat(VOUCHER_NAME, \" \", sellerId);\n        string memory voucherSymbol = string.concat(VOUCHER_SYMBOL, \"_\", sellerId);\n\n        __ERC721_init_unchained(voucherName, voucherSymbol);\n\n        // we don't call init on ownable, but rather just set the ownership to correct owner\n        _transferOwnership(_newOwner);\n\n        _setContractURI(voucherInitValues.contractURI);\n\n        emit VoucherInitialized(_sellerId, _contractURI);\n    }\n\n    /**\n     * @notice Issues a voucher to a buyer.\n     *\n     * Minted voucher supply is sent to the buyer.\n     * Caller must have PROTOCOL role.\n     *\n     * Reverts if:\n     * - Exchange id falls within a reserved range\n     *\n     * @param _tokenId - voucher token id corresponds to <<uint128(offerId)>>.<<uint128(exchangeId)>>\n     * @param _buyer - the buyer address\n     */\n    function issueVoucher(uint256 _tokenId, address _buyer) external override onlyRole(PROTOCOL) {\n        // Derive offerId\n        uint256 offerId = _tokenId >> 128;\n\n        // See if the offer id is associated with a range\n        Range storage range = _rangeByOfferId[offerId];\n\n        // Revert if exchange id falls within a reserved range\n        uint256 rangeStart = range.start;\n        if (_tokenId >= rangeStart && _tokenId < rangeStart + range.length) revert ExchangeIdInReservedRange();\n\n        // Issue voucher is called only during commitToOffer (in protocol), so token can be set as committed\n        _committed[_tokenId] = true;\n\n        // Mint the voucher, sending it to the buyer address\n        _mint(_buyer, _tokenId);\n    }\n\n    /**\n     * @notice Burns a voucher.\n     *\n     * Caller must have PROTOCOL role.\n     *\n     * @param _tokenId - voucher token id corresponds to <<uint128(offerId)>>.<<uint128(exchangeId)>>\n     */\n    function burnVoucher(uint256 _tokenId) external override onlyRole(PROTOCOL) {\n        _burn(_tokenId);\n    }\n\n    /**\n     * @notice Reserves a range of vouchers to be associated with an offer\n     *\n     * Must happen prior to calling preMint\n     * Caller must have PROTOCOL role.\n     *\n     * Reverts if:\n     * - Start id is not greater than zero for the first range\n     * - Start id is not greater than the end id of the previous range for subsequent ranges\n     * - Range length is zero\n     * - Range length is too large, i.e., would cause an overflow\n     * - Offer id is already associated with a range\n     * - _to is not the contract address or the contract owner\n     *\n     * @param _offerId - the id of the offer\n     * @param _start - the first id of the token range\n     * @param _length - the length of the range\n     * @param _to - the address to send the pre-minted vouchers to (contract address or contract owner)\n     */\n    function reserveRange(uint256 _offerId, uint256 _start, uint256 _length, address _to) external onlyRole(PROTOCOL) {\n        // _to must be the contract address or the contract owner (operator)\n        if (_to != address(this) && _to != owner()) revert InvalidToAddress();\n\n        // Prevent reservation of an empty range\n        if (_length == 0) revert InvalidRangeLength();\n\n        // Adjust start id to include offer id\n        if (_start == 0) revert InvalidRangeStart();\n        _start += (_offerId << 128);\n\n        // Prevent overflow in issueVoucher and preMint\n        if (_start > type(uint256).max - _length) revert InvalidRangeLength();\n\n        // Get storage slot for the range\n        Range storage range = _rangeByOfferId[_offerId];\n\n        // Revert if the offer id is already associated with a range\n        if (range.length != 0) revert OfferRangeAlreadyReserved();\n\n        // Store the reserved range\n        range.start = _start;\n        range.length = _length;\n        range.owner = _to;\n\n        emit RangeReserved(_offerId, range);\n    }\n\n    /**\n     * @notice Pre-mints all or part of an offer's reserved vouchers.\n     *\n     * For small offer quantities, this method may only need to be\n     * called once.\n     *\n     * But, if the range is large, e.g., 10k vouchers, block gas limit\n     * could cause the transaction to fail. Thus, in order to support\n     * a batched approach to pre-minting an offer's vouchers,\n     * this method can be called multiple times, until the whole\n     * range is minted.\n     *\n     * A benefit to the batched approach is that the entire reserved\n     * range for an offer need not be pre-minted at one time. A seller\n     * could just mint batches periodically, controlling the amount\n     * that are available on the market at any given time, e.g.,\n     * creating a pre-minted offer with a validity period of one year,\n     * causing the token range to be reserved, but only pre-minting\n     * a certain amount monthly.\n     *\n     * Caller must be contract owner (seller assistant address).\n     *\n     * Reverts if:\n     * - Offer id is not associated with a range\n     * - Amount to mint is more than remaining un-minted in range\n     * - Offer already expired\n     * - Offer is voided\n     *\n     * @param _offerId - the id of the offer\n     * @param _amount - the amount to mint\n     */\n    function preMint(uint256 _offerId, uint256 _amount) external onlyOwner {\n        // Get the offer's range\n        Range storage range = _rangeByOfferId[_offerId];\n\n        // Revert if id not associated with a range\n        if (range.length == 0) revert NoReservedRangeForOffer();\n\n        // Revert if no more to mint in range\n        if (range.length < range.minted + _amount) revert InvalidAmountToMint();\n\n        // Make sure that offer is not expired or voided\n        (Offer memory offer, OfferDates memory offerDates) = getBosonOffer(_offerId);\n        if (offer.voided || block.timestamp > offerDates.validUntil) revert OfferExpiredOrVoided();\n\n        // Get the first token to mint\n        uint256 start = range.start + range.minted;\n        address to = range.owner;\n\n        // Pre-mint the range\n        uint256 tokenId;\n        for (uint256 i = 0; i < _amount; ) {\n            tokenId = start + i;\n\n            emit Transfer(address(0), to, tokenId);\n\n            unchecked {\n                i++;\n            }\n        }\n\n        // Bump the minted count\n        range.minted += _amount;\n\n        // Update to total balance\n        getERC721UpgradeableStorage()._balances[to] += _amount;\n\n        emit VouchersPreMinted(_offerId, start, tokenId);\n    }\n\n    /**\n     * @notice Burn all or part of an offer's preminted vouchers.\n     * If offer expires or it's voided, the seller can burn the preminted vouchers that were not transferred yet.\n     * This way they will not show in seller's wallet and marketplaces anymore.\n     *\n     * For small offer quantities, this method may only need to be\n     * called once.\n     *\n     * But, if the range is large, e.g., 10k vouchers, block gas limit\n     * could cause the transaction to fail. Thus, in order to support\n     * a batched approach to pre-minting an offer's vouchers,\n     * this method can be called multiple times, until the whole\n     * range is burned.\n     *\n     * Caller must be contract owner (seller assistant address).\n     *\n     * Reverts if:\n     * - Offer id is not associated with a range\n     * - Offer is not expired or voided\n     * - There is nothing to burn\n     *\n     * @param _offerId - the id of the offer\n     * @param _amount - amount to burn\n     */\n    function burnPremintedVouchers(uint256 _offerId, uint256 _amount) external override onlyOwner {\n        // Get the offer's range\n        Range storage range = _rangeByOfferId[_offerId];\n\n        // Revert if id not associated with a range\n        if (range.length == 0) revert NoReservedRangeForOffer();\n\n        // Make sure that offer is either expired or voided\n        (Offer memory offer, OfferDates memory offerDates) = getBosonOffer(_offerId);\n        if (!offer.voided && block.timestamp <= offerDates.validUntil) revert OfferStillValid();\n\n        // Get the first token to burn\n        uint256 start = range.lastBurnedTokenId == 0 ? range.start : range.lastBurnedTokenId + 1;\n\n        // Get the last token to burn\n        uint256 end = start + _amount;\n\n        // End should be greater than start\n        if (end <= start || end > range.start + range.minted) revert AmountExceedsRangeOrNothingToBurn();\n\n        // Burn the range\n        address rangeOwner = range.owner;\n        uint256 burned;\n        for (uint256 tokenId = start; tokenId < end; tokenId++) {\n            // Burn only if not already _committed\n            if (!_committed[tokenId]) {\n                emit Transfer(rangeOwner, address(0), tokenId);\n                burned++;\n            }\n        }\n\n        // Update last burned token id\n        range.lastBurnedTokenId = end - 1;\n\n        // Update owner's total balance\n        getERC721UpgradeableStorage()._balances[rangeOwner] -= burned;\n    }\n\n    /**\n     * @notice Gets the number of vouchers available to be pre-minted for an offer.\n     *\n     * @param _offerId - the id of the offer\n     * @return count - the count of vouchers in reserved range available to be pre-minted\n     */\n    function getAvailablePreMints(uint256 _offerId) external view returns (uint256 count) {\n        // If offer is expired or voided, return 0\n        (Offer memory offer, OfferDates memory offerDates) = getBosonOffer(_offerId);\n        if (offer.voided || block.timestamp > offerDates.validUntil) {\n            return 0;\n        }\n\n        // Get the offer's range\n        Range storage range = _rangeByOfferId[_offerId];\n\n        // Count the number left to be minted\n        count = range.length - range.minted;\n    }\n\n    /**\n     * @notice Gets the range for an offer.\n     *\n     * @param _offerId - the id of the offer\n     * @return range - the range struct with information about range start, length and already minted tokens\n     */\n    function getRangeByOfferId(uint256 _offerId) external view returns (Range memory range) {\n        // Get the offer's range\n        range = _rangeByOfferId[_offerId];\n    }\n\n    /**\n     * @dev Returns the owner of the specified token.\n     *\n     * If the token IS a pre-mint, then the actual owner address hasn't been set,\n     * but will be reported as the owner of this contract (the seller assistant).\n     *\n     * If the token IS NOT a pre-mint, then the actual owner will be reported.\n     *\n     * Reverts if:\n     * - Token is not a pre-mint and does not have a stored owner, i.e., invalid token id\n     *\n     * @param _tokenId - the id of the token to check\n     * @return owner - the address of the owner\n     */\n    function ownerOf(\n        uint256 _tokenId\n    ) public view virtual override(ERC721Upgradeable, IERC721Upgradeable) returns (address owner) {\n        if (_exists(_tokenId)) {\n            // If _tokenId exists, it does not matter if vouchers were preminted or not\n            return super.ownerOf(_tokenId);\n        } else {\n            // If _tokenId does not exist, but offer is committable, report contract owner as token owner\n            bool committable = isTokenCommittable(_tokenId);\n\n            if (committable) {\n                owner = _rangeByOfferId[_tokenId >> 128].owner;\n                return owner;\n            }\n\n            // Otherwise revert\n            revert(ERC721_INVALID_TOKEN_ID);\n        }\n    }\n\n    /**\n     * @dev See {IERC721-transferFrom}.\n     */\n    function transferFrom(\n        address _from,\n        address _to,\n        uint256 _tokenId\n    ) public virtual override(ERC721Upgradeable, IERC721Upgradeable) {\n        bool committable = isTokenCommittable(_tokenId);\n\n        if (committable) {\n            silentMint(_from, _tokenId);\n        }\n\n        super.transferFrom(_from, _to, _tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(\n        address _from,\n        address _to,\n        uint256 _tokenId,\n        bytes memory _data\n    ) public virtual override(ERC721Upgradeable, IERC721Upgradeable) {\n        bool committable = isTokenCommittable(_tokenId);\n\n        if (committable) {\n            silentMint(_from, _tokenId);\n        }\n\n        super.safeTransferFrom(_from, _to, _tokenId, _data);\n    }\n\n    /**\n     * @notice Implements the {IERC165} interface.\n     *\n     * N.B. This method is inherited from several parents and\n     * the compiler cannot decide which to use. Thus, they must\n     * be overridden here.\n     *\n     * If you just call super.supportsInterface, it chooses\n     * 'the most derived contract'. But that's not good for this\n     * particular function because you may inherit from several\n     * IERC165 contracts, and all concrete ones need to be allowed\n     * to respond.\n     *\n     * 0x2a55205a represents ERC2981 interface id\n     */\n    function supportsInterface(\n        bytes4 _interfaceId\n    ) public view override(ERC721Upgradeable, IERC165Upgradeable) returns (bool) {\n        return (_interfaceId == type(IBosonVoucher).interfaceId ||\n            _interfaceId == type(IERC2981Upgradeable).interfaceId ||\n            super.supportsInterface(_interfaceId));\n    }\n\n    /**\n     * @notice Gets the Voucher metadata URI.\n     *\n     * This method overrides the Open Zeppelin version, returning\n     * a unique stored metadata URI for each token rather than a\n     * replaceable baseURI template, since the latter is not compatible\n     * with IPFS hashes.\n     *\n     * Reverts if token id is not associated with any exchange or pre-minted offer.\n     *\n     * @param _tokenId - id of the voucher's associated exchange or pre-minted token id\n     * @return the uri for the associated offer's off-chain metadata (blank if not found)\n     */\n    function tokenURI(\n        uint256 _tokenId\n    ) public view override(ERC721Upgradeable, IERC721MetadataUpgradeable) returns (string memory) {\n        uint256 exchangeId = _tokenId & type(uint128).max;\n        (bool exists, Offer memory offer) = getBosonOfferByExchangeId(exchangeId);\n\n        if (!exists) {\n            bool committable = isTokenCommittable(_tokenId);\n\n            if (committable) {\n                uint256 offerId = _tokenId >> 128;\n                exists = true;\n                (offer, ) = getBosonOffer(offerId);\n            }\n        }\n\n        require(exists, ERC721_INVALID_TOKEN_ID);\n        return offer.metadataUri;\n    }\n\n    /**\n     * @notice Gets the seller id.\n     *\n     * @return the id for the Voucher seller\n     */\n    function getSellerId() public view override returns (uint256) {\n        (bool exists, Seller memory seller) = getBosonSellerByAddress(owner());\n\n        return exists ? seller.id : 0;\n    }\n\n    /**\n     * @notice Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the protocol. Change is done by calling `updateSeller` on the protocol.\n     *\n     * Reverts if:\n     * - Caller is not the protocol\n     * - New owner is the zero address\n     *\n     * @param _newOwner - the address to which ownership of the voucher contract will be transferred\n     */\n    function transferOwnership(\n        address _newOwner\n    ) public override(IBosonVoucher, OwnableUpgradeable) onlyRole(PROTOCOL) {\n        require(_newOwner != address(0), OWNABLE_ZERO_ADDRESS);\n\n        _transferOwnership(_newOwner);\n    }\n\n    /**\n     * @notice Overriding renounceOwnership() from OwnableUpgradeable, so it's not possible to renounce ownership.\n     *\n     * N.B. In the future it might be possible to renounce ownership via seller deactivation in the protocol.\n     */\n    function renounceOwnership() public pure override {\n        revert AccessDenied();\n    }\n\n    /**\n     * @notice Returns storefront-level metadata used by OpenSea.\n     *\n     * @return Contract metadata URI\n     */\n    function contractURI() external view override returns (string memory) {\n        return _contractURI;\n    }\n\n    /**\n     * @notice Sets new contract URI.\n     * Can only be called by the owner or during the initialization.\n     *\n     * @param _newContractURI - new contract metadata URI\n     */\n    function setContractURI(string calldata _newContractURI) external override onlyOwner {\n        _setContractURI(_newContractURI);\n    }\n\n    /** @notice Make a call to an external contract.\n     *\n     * Reverts if:\n     * - _to is zero address\n     * - call to external contract fails\n     * - caller is not the owner\n     * - _to is a contract that represents some assets (all contracts that implement `balanceOf` method, including ERC20 and ERC721)\n     *\n     *\n     * @param _to - address of the contract to call\n     * @param _data - data to pass to the external contract\n     * @return result - result of the call\n     */\n    function callExternalContract(address _to, bytes calldata _data) external payable onlyOwner returns (bytes memory) {\n        if (_to == address(0)) revert InvalidAddress();\n\n        // Check if _to supports `balanceOf` method and revert if it does\n        // This works with all contracts that implement this method even if they don't necessary implement ERC20 interface\n        try IERC20(_to).balanceOf(address(this)) returns (uint256) {\n            revert InteractionNotAllowed();\n        } catch {}\n\n        return _to.functionCallWithValue(_data, msg.value, FUNCTION_CALL_NOT_SUCCESSFUL);\n    }\n\n    /** @notice Set approval for all to the vouchers owned by this contract\n     *\n     * Reverts if:\n     * - _operator is zero address\n     * - caller is not the owner\n     * - _operator is this contract\n     *\n     * @param _operator - address of the operator to set approval for\n     * @param _approved - true to approve the operator in question, false to revoke approval\n     */\n    function setApprovalForAllToContract(address _operator, bool _approved) external onlyOwner {\n        if (_operator == address(0)) revert InvalidAddress();\n\n        _setApprovalForAll(address(this), _operator, _approved);\n    }\n\n    // @dev Contract must be allowed to receive native token as it can be used as voucher's owner\n    receive() external payable {}\n\n    /**\n     * @dev See {IERC721Receiver-onERC721Received}.\n     *\n     * Always returns `IERC721Receiver.onERC721Received.selector`.\n     */\n    function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {\n        return this.onERC721Received.selector;\n    }\n\n    /**\n     * @notice Sets new contract URI.\n     * Can only be called by the owner or during the initialization.\n     *\n     * @param _newContractURI new contract metadata URI\n     */\n    function _setContractURI(string calldata _newContractURI) internal {\n        _contractURI = _newContractURI;\n\n        emit ContractURIChanged(_newContractURI);\n    }\n\n    /**\n     * @notice Provides royalty info.\n     * Called with the sale price to determine how much royalty is owed and to whom.\n     *\n     * @param _tokenId - the voucher queried for royalty information\n     * @param _salePrice - the sale price of the voucher specified by _tokenId\n     *\n     * @return receiver - address of who should be sent the royalty payment\n     * @return royaltyAmount - the royalty payment amount for the given sale price\n     */\n    function royaltyInfo(\n        uint256 _tokenId,\n        uint256 _salePrice\n    ) external view override returns (address receiver, uint256 royaltyAmount) {\n        uint256 offerId;\n        bool isPreminted;\n        if (!_exists(_tokenId)) {\n            // might not exists or is preminted\n            isPreminted = isTokenCommittable(_tokenId);\n            if (!isPreminted) {\n                return (address(0), 0);\n            }\n            offerId = _tokenId >> 128;\n        }\n\n        uint256 royaltyPercentage;\n        (receiver, royaltyPercentage) = getEIP2981RoyaltiesFromProtocol(\n            isPreminted ? offerId : (_tokenId & type(uint128).max),\n            !isPreminted\n        );\n\n        royaltyAmount = (_salePrice * royaltyPercentage) / HUNDRED_PERCENT;\n    }\n\n    /**\n     * @notice Performs special case transfer hooks.\n     *\n     * - Commits to pre-minted offers on first transfer.\n     *\n     * When a voucher is pre-minted, the owner is not stored\n     * but the seller is reported as the transferee and owner,\n     * so that it can be found by marketplaces and listed by\n     * the seller for their asking price.\n     *\n     * On the first transfer after pre-minting, this method\n     * will commit to the associated offer on behalf of the\n     * new owner.\n     *\n     * - Updates buyer on subsequent transfers.\n     *\n     * When a voucher with an associated exchange is transferred\n     * either on the secondary market or just between wallets,\n     * the protocol needs to be alerted to the change of buyer\n     * address.\n     *\n     * The buyer account associated with the exchange will be\n     * replaced. If the new voucher holder already has a\n     * Boson Protocol buyer account, it will be used. Otherwise,\n     * a new buyer account will be created and associated with\n     * the exchange.\n     *\n     * @param _from - the address from which the voucher is being transferred\n     * @param _to - the address to which the voucher is being transferred\n     * @param _tokenId - the first token id of the batch\n     * @param - this parameter is ignored, but required to match the signature of the parent method\n     */\n    function _beforeTokenTransfer(address _from, address _to, uint256 _tokenId, uint256) internal override {\n        // If is committable, invoke onPremintedVoucherTransferred on the protocol\n        if (_isCommittable) {\n            // Set _isCommitable to false\n            _isCommittable = false;\n\n            address rangeOwner = _rangeByOfferId[_tokenId >> 128].owner;\n\n            // Call protocol onPremintedVoucherTransferred\n            bool committed = onPremintedVoucherTransferred(_tokenId, payable(_to), _from, rangeOwner);\n\n            // Set committed status\n            _committed[_tokenId] = committed;\n        } else if (_from != address(0) && _to != address(0) && _from != _to) {\n            // Update the buyer associated with the voucher in the protocol\n            // Only when transferring, not when minting or burning\n            onVoucherTransferred(_tokenId, payable(_to));\n        }\n    }\n\n    /**\n     * @notice Verify if token is committable.\n     *\n     * @param _tokenId - the tokenId of the voucher that is being transferred\n     *\n     * @return committable - true if the voucher is committable\n     */\n    function isTokenCommittable(uint256 _tokenId) public view returns (bool committable) {\n        if (_committed[_tokenId]) {\n            return false;\n        } else {\n            // it might be a pre-minted token. Preminted tokens have offerId in the upper 128 bits\n            uint256 offerId = _tokenId >> 128;\n\n            if (offerId > 0) {\n                // Get the range stored at the midpoint\n                Range storage range = _rangeByOfferId[offerId];\n\n                // Get the beginning of the range once for reference\n                uint256 start = range.start;\n\n                // Start is 0 if the range does not exist\n                // Token is committable if is within the range and has not been burned already\n                if (\n                    start > 0 &&\n                    start <= _tokenId &&\n                    start + range.minted - 1 >= _tokenId &&\n                    _tokenId > range.lastBurnedTokenId\n                ) {\n                    // Has it been pre-minted, not burned yet\n                    committable = true;\n                }\n            }\n        }\n    }\n\n    /**\n     * @notice Withdraw funds from the contract to the protocol seller pool\n     *\n     * @param _tokenList - list of tokens to withdraw, including native token (address(0))\n     */\n    function withdrawToProtocol(address[] calldata _tokenList) external {\n        address protocolDiamond = IClientExternalAddresses(BeaconClientLib._beacon()).getProtocolAddress();\n        uint256 sellerId = getSellerId();\n\n        for (uint256 i = 0; i < _tokenList.length; ) {\n            address token = _tokenList[i];\n            if (token == address(0)) {\n                uint256 balance = address(this).balance;\n\n                if (balance > 0) {\n                    IBosonFundsHandler(protocolDiamond).depositFunds{ value: balance }(sellerId, token, balance);\n                }\n            } else {\n                uint256 balance = IERC20(token).balanceOf(address(this));\n                if (balance > 0) {\n                    // get current allowance\n                    uint256 allowance = IERC20(token).allowance(address(this), protocolDiamond);\n                    if (allowance < balance) {\n                        IERC20(token).forceApprove(protocolDiamond, balance);\n                    }\n                    IBosonFundsHandler(protocolDiamond).depositFunds(sellerId, token, balance);\n                }\n            }\n\n            unchecked {\n                i++;\n            }\n        }\n    }\n\n    /*\n     * Returns storage pointer to location of private variables\n     * 0x99 is location of _owners\n     * 0x9a is location of _balances\n     *\n     * Since ERC721UpgradeableStorage slot is 0x99\n     * _owners slot is ERC721UpgradeableStorage + 0\n     * _balances slot is ERC721UpgradeableStorage + 1\n     */\n    function getERC721UpgradeableStorage() internal pure returns (ERC721UpgradeableStorage storage ps) {\n        assembly {\n            ps.slot := 0x99\n        }\n    }\n\n    /*\n     * Updates owners, but do not emit Transfer event. Event was already emited during pre-mint.\n     */\n    function silentMint(address _from, uint256 _tokenId) internal {\n        if (!_exists(_tokenId) && (_from == address(this) || _from == owner())) {\n            // update data, so transfer will succeed\n            getERC721UpgradeableStorage()._owners[_tokenId] = _from;\n        }\n\n        _isCommittable = true;\n    }\n\n    /*\n     * Override ERC721Upgradeable._isApprovedOrOwner to check for pre-minted tokens\n     */\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view override returns (bool) {\n        address owner = ownerOf(tokenId);\n        return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n    }\n\n    /*\n     **\n     * @dev Reverts if the `_tokenId` has not been minted yet and is not a pre-minted token.\n     */\n    function _requireMinted(uint256 _tokenId) internal view override {\n        // If token is committable, it is a pre-minted token\n        bool committable = isTokenCommittable(_tokenId);\n\n        require(_exists(_tokenId) || committable, \"ERC721: invalid token ID\");\n    }\n}\n\n/**\n * @title BosonVoucher\n * @notice This is the Boson Protocol ERC-721 Voucher contract.\n *\n * N.B. This is only a logic contract, delegated to by BeaconClientProxy. Thus,\n *      this contract will never be \"upgraded\". Rather it will be redeployed\n *      with changes and the BosonClientBeacon will be advised of the new address.\n *      Individual seller collections are clones of BeaconClientProxy, which\n *      asks the BosonClientBeacon for the address of the BosonVoucher contract\n *      on each call. This allows us to upgrade all voucher collections cheaply,\n *      and at once.\n *\n * Key features:\n * - Only PROTOCOL-roled addresses can issue vouchers, i.e., the ProtocolDiamond or an EOA for testing\n * - Minted to the buyer when the buyer commits to an offer\n * - Burned when the buyer redeems the voucher\n * - Support for pre-minted voucher id ranges\n *\n * @dev This contract inherit BosonVoucherBase because we have added support to meta transaction\n *      and split into two contracts doesn't mess up the storage layout when importing ERC2771ContextUpgradeable\n */\ncontract BosonVoucher is BosonVoucherBase, ERC2771ContextUpgradeable {\n    constructor(address forwarder) ERC2771ContextUpgradeable(forwarder) {}\n\n    /**\n     * @notice This function returns the calldata of the current message.\n     * @dev It is an override of the ERC2771ContextUpgradeable._msgData() function which allows meta transactions.\n     */\n    function _msgData() internal view override(ContextUpgradeable, ERC2771ContextUpgradeable) returns (bytes calldata) {\n        return ERC2771ContextUpgradeable._msgData();\n    }\n\n    /**\n     * @notice This function returns the sender of the current message.\n     * @dev It is an override of the ERC2771ContextUpgradeable._msgSender() function which allows meta transactions.\n     */\n    function _msgSender()\n        internal\n        view\n        override(ContextUpgradeable, ERC2771ContextUpgradeable)\n        returns (address sender)\n    {\n        return ERC2771ContextUpgradeable._msgSender();\n    }\n}\n"
      },
      "contracts/protocol/libs/BeaconClientLib.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport { IAccessControl } from \"../../interfaces/IAccessControl.sol\";\nimport { IClientExternalAddresses } from \"../../interfaces/clients/IClientExternalAddresses.sol\";\n\n/**\n * @title BeaconClientLib\n *\n * @notice\n * - Defines BeaconSlot position\n * - Provides BeaconSlot accessor\n * - Defines hasRole function\n */\nlibrary BeaconClientLib {\n    /**\n     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n     */\n    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n    struct BeaconSlot {\n        address value;\n        bool initialized;\n    }\n\n    /**\n     * @notice Returns a `BeaconSlot` with member `value`.\n     *\n     * @return r - the BeaconSlot storage slot cast to BeaconSlot\n     */\n    function getBeaconSlot() internal pure returns (BeaconSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := _BEACON_SLOT\n        }\n    }\n\n    /**\n     * @notice Returns the address of the Beacon\n     *\n     * @return the Beacon address\n     */\n    function _beacon() internal view returns (address) {\n        return getBeaconSlot().value;\n    }\n\n    /**\n     * @notice Checks that the caller has a specific role.\n     *\n     * Reverts if caller doesn't have role.\n     *\n     * See: {AccessController.hasRole}\n     *\n     * @param _role - the role to check\n     * @return whether caller has role\n     */\n    function hasRole(bytes32 _role) internal view returns (bool) {\n        // retrieve accessController from Beacon\n        IAccessControl accessController = IClientExternalAddresses(_beacon()).getAccessController();\n\n        // forward the check to accessController\n        return accessController.hasRole(_role, msg.sender);\n    }\n}\n"
      }
    },
    "settings": {
      "viaIR": false,
      "optimizer": {
        "enabled": true,
        "runs": 200,
        "details": {
          "yul": true
        }
      },
      "evmVersion": "london",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}