creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@intercoin/liquidity/contracts/interfaces/ILiquidityLib.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.0;\r\ninterface ILiquidityLib {\r\n    function calculateSellTradedAndLiquidity(uint256 reserve0, uint256 reserve1, uint256 incomingToken0) external view returns (uint256 traded2Swap, uint256 traded2Liq, uint256 reserved2Liq);\r\n    function uniswapSettings() external view returns(address, address);\r\n    function koefficients() external view returns(uint256, uint256, uint256, uint256, uint256, uint256);\r\n}"
      },
      "@intercoin/releasemanager/contracts/CostManagerBase.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./interfaces/ICostManager.sol\";\nimport \"./interfaces/ICostManagerFactoryHelper.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\nabstract contract CostManagerBase is Initializable {\n    using AddressUpgradeable for address;\n\n    address private costManager;\n    address private deployer;\n    bool private overrode;\n\n    error AlreadyOverrode();\n    error CanNotOverride();\n    error OverrideRequired();\n    error UnknownError();\n\n    /** \n    * @dev sets the costmanager token. calling only by factory owner\n    * @param costManager_ new address of costmanager token, or 0\n    */\n    function overrideCostManager(address costManager_) external {\n        // require factory owner or operator\n        // otherwise needed deployer(!!not contract owner)\n\n        if (overrode) {\n            revert AlreadyOverrode();\n        }\n\n        if (\n            deployer != _sender() ||\n            !ICostManagerFactoryHelper(deployer).canOverrideCostManager(address(this))\n        ) {\n            revert CanNotOverride();\n        }\n        \n        overrode = true;\n        _setCostManager(costManager_);\n    }\n\n    /** \n    * @dev viewer the costmanager token\n    * @return address of costmanager token\n    */\n    function getCostManager() public view returns(address) {\n        return costManager;\n    }\n\n    function __CostManagerHelper_init(address deployer_, address costManager_) internal onlyInitializing\n    {\n        deployer = deployer_;\n        costManager = costManager_;\n        overrode = false;\n    }\n\n     /**\n     * @dev Private function that tells contract to account for an operation\n     * @param info uint256 The operation ID (first 8 bits). in other bits any else info\n     * @param param1 uint256 Some more information, if any\n     * @param param2 uint256 Some more information, if any\n     */\n    function _accountForOperation(uint256 info, uint256 param1, uint256 param2) internal {\n        if (costManager != address(0)) {\n            try ICostManager(costManager).accountForOperation(\n                _sender(), info, param1, param2\n            )\n            returns (uint256 /*spent*/, uint256 /*remaining*/) {\n                // if error is not thrown, we are fine\n            } catch Error(string memory reason) {\n                // This is executed in case revert() was called with a reason\n                revert(reason);\n            } catch {\n                revert UnknownError();\n            }\n        }\n    }\n    \n    function _setCostManager(address costManager_) internal {\n        if (!overrode) {\n            revert OverrideRequired();\n        }\n        \n        costManager = costManager_;\n    }\n    \n    function _sender() internal virtual returns(address);\n}"
      },
      "@intercoin/releasemanager/contracts/CostManagerHelperERC2771Support.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./CostManagerBase.sol\";\nimport \"@intercoin/trustedforwarder/contracts/TrustedForwarder.sol\";\n\n/**\n* used for instances that have created(cloned) by factory with ERC2771 supports\n*/\nabstract contract CostManagerHelperERC2771Support is CostManagerBase, TrustedForwarder {\n    function _sender() internal override view returns(address){\n        return _msgSender();\n    }\n}"
      },
      "@intercoin/releasemanager/contracts/interfaces/ICostManager.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n//import \"@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol\";\n\ninterface ICostManager/* is IERC165Upgradeable*/ {\n    function accountForOperation(\n        address sender, \n        uint256 info, \n        uint256 param1, \n        uint256 param2\n    ) \n        external \n        returns(uint256, uint256);\n}"
      },
      "@intercoin/releasemanager/contracts/interfaces/ICostManagerFactoryHelper.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ICostManagerFactoryHelper {\n    \n    function canOverrideCostManager(address instance) external view returns (bool);\n}\n"
      },
      "@intercoin/trustedforwarder/contracts/TrustedForwarder.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.11;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\nabstract contract TrustedForwarder is Initializable {\n\n    address private _trustedForwarder;\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __TrustedForwarder_init() internal onlyInitializing {\n        _trustedForwarder = address(0);\n    }\n\n\n    /**\n    * @dev setup trusted forwarder address\n    * @param forwarder trustedforwarder's address to set\n    * @custom:shortd setup trusted forwarder\n    * @custom:calledby owner\n    */\n    function _setTrustedForwarder(\n        address forwarder\n    ) \n        internal \n      //  onlyOwner \n        //excludeTrustedForwarder \n    {\n        //require(owner() != forwarder, \"FORWARDER_CAN_NOT_BE_OWNER\");\n        _trustedForwarder = forwarder;\n    }\n    function setTrustedForwarder(address forwarder) public virtual;\n    /**\n    * @dev checking if forwarder is trusted\n    * @param forwarder trustedforwarder's address to check\n    * @custom:shortd checking if forwarder is trusted\n    */\n    function isTrustedForwarder(\n        address forwarder\n    ) \n        external\n        view \n        returns(bool) \n    {\n        return _isTrustedForwarder(forwarder);\n    }\n\n    /**\n    * @dev implemented EIP-2771\n    */\n    function _msgSender(\n    ) \n        internal \n        view \n        virtual\n        returns (address signer) \n    {\n        signer = msg.sender;\n        if (msg.data.length>=20 && _isTrustedForwarder(signer)) {\n            assembly {\n                signer := shr(96,calldataload(sub(calldatasize(),20)))\n            }\n        }    \n    }\n\n    // function transferOwnership(\n    //     address newOwner\n    // ) public \n    //     virtual \n    //     override \n    //     onlyOwner \n    // {\n    //     require(msg.sender != _trustedForwarder, \"DENIED_FOR_FORWARDER\");\n    //     if (newOwner == _trustedForwarder) {\n    //         _trustedForwarder = address(0);\n    //     }\n    //     super.transferOwnership(newOwner);\n        \n    // }\n\n    function _isTrustedForwarder(\n        address forwarder\n    ) \n        internal\n        view \n        returns(bool) \n    {\n        return forwarder == _trustedForwarder;\n    }\n\n\n  \n\n}\n"
      },
      "@intercoin/whitelist/contracts/interfaces/IWhitelist.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\ninterface IWhitelist {\n    struct WhitelistStruct\n\t{\n\t\taddress contractAddress; // 160\n\t\tbytes4 method; // 32\n\t\tuint8 role; // 8\n        bool useWhitelist;\n\t}\n    function whitelisted(address member) external view returns(bool);\n}\n"
      },
      "@intercoin/whitelist/contracts/Whitelist.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport \"./interfaces/IWhitelist.sol\";\n\nabstract contract Whitelist is IWhitelist {\n\n\tbytes4 public constant METHOD_HASROLE = 0x95a8c58d; // function hasRole(address member, uint8 role)\n\t\n\tWhitelistStruct public whitelist;\n\tmapping (address => bool) _whitelist;\n\t\n\tfunction whitelisted(address member) public view returns(bool) {\n\t\t// if will not useWhitelist then will always return true\n\t\tif (!whitelist.useWhitelist) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// using internal whitelist if whitelist.contractAddress == address(0)\n\t\tif (whitelist.useWhitelist && whitelist.contractAddress == address(0)) {\n\t\t\treturn _whitelist[member];\n\t\t}\n\n\t\t// else try to get external info\n\t\tbool success;\n\t\tbytes memory data;\n\t\tif (whitelist.role == 0) {\n\t\t\t(success, data) = whitelist.contractAddress.staticcall(abi.encodeWithSelector(whitelist.method, member));\n\t\t} else {\n\t\t\t(success, data) = whitelist.contractAddress.staticcall(abi.encodeWithSelector(METHOD_HASROLE, member, whitelist.role));\n\t\t}\n\t\tif (!success) {\n\t\t\treturn false;\n\t\t}\n\t\treturn abi.decode(data, (bool));\n\t}\n\n\tfunction whitelistInit(WhitelistStruct memory _whitelistStruct) internal {\n\t\twhitelist.contractAddress = _whitelistStruct.contractAddress;\n        whitelist.method = _whitelistStruct.method;\n        whitelist.role = _whitelistStruct.role;\n        whitelist.useWhitelist = _whitelistStruct.useWhitelist;\n\t}\n\n\tfunction _whitelistAdd(address account) internal {\n\t\t_whitelist[account] = true;\n\t}\n\n\tfunction _whitelistRemove(address account) internal {\n\t\tdelete _whitelist[account];\n\t}\n}\n"
      },
      "@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 {Initializable} from \"../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/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/security/ReentrancyGuardUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/token/ERC20/IERC20Upgradeable.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 IERC20Upgradeable {\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-upgradeable/token/ERC777/ERC777Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC777/ERC777.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC777Upgradeable.sol\";\nimport \"./IERC777RecipientUpgradeable.sol\";\nimport \"./IERC777SenderUpgradeable.sol\";\nimport \"../ERC20/IERC20Upgradeable.sol\";\nimport \"../../utils/AddressUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../utils/introspection/IERC1820RegistryUpgradeable.sol\";\nimport {Initializable} from \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC777} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n *\n * Support for ERC20 is included in this contract, as specified by the EIP: both\n * the ERC777 and ERC20 interfaces can be safely used when interacting with it.\n * Both {IERC777-Sent} and {IERC20-Transfer} events are emitted on token\n * movements.\n *\n * Additionally, the {IERC777-granularity} value is hard-coded to `1`, meaning that there\n * are no special restrictions in the amount of tokens that created, moved, or\n * destroyed. This makes integration with ERC20 applications seamless.\n *\n * CAUTION: This file is deprecated as of v4.9 and will be removed in the next major release.\n */\ncontract ERC777Upgradeable is Initializable, ContextUpgradeable, IERC777Upgradeable, IERC20Upgradeable {\n    using AddressUpgradeable for address;\n\n    IERC1820RegistryUpgradeable internal constant _ERC1820_REGISTRY = IERC1820RegistryUpgradeable(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);\n\n    mapping(address => uint256) private _balances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    bytes32 private constant _TOKENS_SENDER_INTERFACE_HASH = keccak256(\"ERC777TokensSender\");\n    bytes32 private constant _TOKENS_RECIPIENT_INTERFACE_HASH = keccak256(\"ERC777TokensRecipient\");\n\n    // This isn't ever read from - it's only used to respond to the defaultOperators query.\n    address[] private _defaultOperatorsArray;\n\n    // Immutable, but accounts may revoke them (tracked in __revokedDefaultOperators).\n    mapping(address => bool) private _defaultOperators;\n\n    // For each account, a mapping of its operators and revoked default operators.\n    mapping(address => mapping(address => bool)) private _operators;\n    mapping(address => mapping(address => bool)) private _revokedDefaultOperators;\n\n    // ERC20-allowances\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    /**\n     * @dev `defaultOperators` may be an empty array.\n     */\n    function __ERC777_init(string memory name_, string memory symbol_, address[] memory defaultOperators_) internal onlyInitializing {\n        __ERC777_init_unchained(name_, symbol_, defaultOperators_);\n    }\n\n    function __ERC777_init_unchained(string memory name_, string memory symbol_, address[] memory defaultOperators_) internal onlyInitializing {\n        _name = name_;\n        _symbol = symbol_;\n\n        _defaultOperatorsArray = defaultOperators_;\n        for (uint256 i = 0; i < defaultOperators_.length; i++) {\n            _defaultOperators[defaultOperators_[i]] = true;\n        }\n\n        // register interfaces\n        _ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256(\"ERC777Token\"), address(this));\n        _ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256(\"ERC20Token\"), address(this));\n    }\n\n    /**\n     * @dev See {IERC777-name}.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev See {IERC777-symbol}.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev See {ERC20-decimals}.\n     *\n     * Always returns 18, as per the\n     * [ERC777 EIP](https://eips.ethereum.org/EIPS/eip-777#backward-compatibility).\n     */\n    function decimals() public pure virtual returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC777-granularity}.\n     *\n     * This implementation always returns `1`.\n     */\n    function granularity() public view virtual override returns (uint256) {\n        return 1;\n    }\n\n    /**\n     * @dev See {IERC777-totalSupply}.\n     */\n    function totalSupply() public view virtual override(IERC20Upgradeable, IERC777Upgradeable) returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev Returns the amount of tokens owned by an account (`tokenHolder`).\n     */\n    function balanceOf(address tokenHolder) public view virtual override(IERC20Upgradeable, IERC777Upgradeable) returns (uint256) {\n        return _balances[tokenHolder];\n    }\n\n    /**\n     * @dev See {IERC777-send}.\n     *\n     * Also emits a {IERC20-Transfer} event for ERC20 compatibility.\n     */\n    function send(address recipient, uint256 amount, bytes memory data) public virtual override {\n        _send(_msgSender(), recipient, amount, data, \"\", true);\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Unlike `send`, `recipient` is _not_ required to implement the {IERC777Recipient}\n     * interface if it is a contract.\n     *\n     * Also emits a {Sent} event.\n     */\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n        _send(_msgSender(), recipient, amount, \"\", \"\", false);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC777-burn}.\n     *\n     * Also emits a {IERC20-Transfer} event for ERC20 compatibility.\n     */\n    function burn(uint256 amount, bytes memory data) public virtual override {\n        _burn(_msgSender(), amount, data, \"\");\n    }\n\n    /**\n     * @dev See {IERC777-isOperatorFor}.\n     */\n    function isOperatorFor(address operator, address tokenHolder) public view virtual override returns (bool) {\n        return\n            operator == tokenHolder ||\n            (_defaultOperators[operator] && !_revokedDefaultOperators[tokenHolder][operator]) ||\n            _operators[tokenHolder][operator];\n    }\n\n    /**\n     * @dev See {IERC777-authorizeOperator}.\n     */\n    function authorizeOperator(address operator) public virtual override {\n        require(_msgSender() != operator, \"ERC777: authorizing self as operator\");\n\n        if (_defaultOperators[operator]) {\n            delete _revokedDefaultOperators[_msgSender()][operator];\n        } else {\n            _operators[_msgSender()][operator] = true;\n        }\n\n        emit AuthorizedOperator(operator, _msgSender());\n    }\n\n    /**\n     * @dev See {IERC777-revokeOperator}.\n     */\n    function revokeOperator(address operator) public virtual override {\n        require(operator != _msgSender(), \"ERC777: revoking self as operator\");\n\n        if (_defaultOperators[operator]) {\n            _revokedDefaultOperators[_msgSender()][operator] = true;\n        } else {\n            delete _operators[_msgSender()][operator];\n        }\n\n        emit RevokedOperator(operator, _msgSender());\n    }\n\n    /**\n     * @dev See {IERC777-defaultOperators}.\n     */\n    function defaultOperators() public view virtual override returns (address[] memory) {\n        return _defaultOperatorsArray;\n    }\n\n    /**\n     * @dev See {IERC777-operatorSend}.\n     *\n     * Emits {Sent} and {IERC20-Transfer} events.\n     */\n    function operatorSend(\n        address sender,\n        address recipient,\n        uint256 amount,\n        bytes memory data,\n        bytes memory operatorData\n    ) public virtual override {\n        require(isOperatorFor(_msgSender(), sender), \"ERC777: caller is not an operator for holder\");\n        _send(sender, recipient, amount, data, operatorData, true);\n    }\n\n    /**\n     * @dev See {IERC777-operatorBurn}.\n     *\n     * Emits {Burned} and {IERC20-Transfer} events.\n     */\n    function operatorBurn(\n        address account,\n        uint256 amount,\n        bytes memory data,\n        bytes memory operatorData\n    ) public virtual override {\n        require(isOperatorFor(_msgSender(), account), \"ERC777: caller is not an operator for holder\");\n        _burn(account, amount, data, operatorData);\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     *\n     * Note that operator and allowance concepts are orthogonal: operators may\n     * not have allowance, and accounts with allowance may not be operators\n     * themselves.\n     */\n    function allowance(address holder, address spender) public view virtual override returns (uint256) {\n        return _allowances[holder][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Note that accounts cannot have allowance issued by their operators.\n     */\n    function approve(address spender, uint256 value) public virtual override returns (bool) {\n        address holder = _msgSender();\n        _approve(holder, spender, value);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Note that operator and allowance concepts are orthogonal: operators cannot\n     * call `transferFrom` (unless they have allowance), and accounts with\n     * allowance cannot call `operatorSend` (unless they are operators).\n     *\n     * Emits {Sent}, {IERC20-Transfer} and {IERC20-Approval} events.\n     */\n    function transferFrom(address holder, address recipient, uint256 amount) public virtual override returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(holder, spender, amount);\n        _send(holder, recipient, amount, \"\", \"\", false);\n        return true;\n    }\n\n    /**\n     * @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * If a send hook is registered for `account`, the corresponding function\n     * will be called with the caller address as the `operator` and with\n     * `userData` and `operatorData`.\n     *\n     * See {IERC777Sender} and {IERC777Recipient}.\n     *\n     * Emits {Minted} and {IERC20-Transfer} events.\n     *\n     * Requirements\n     *\n     * - `account` cannot be the zero address.\n     * - if `account` is a contract, it must implement the {IERC777Recipient}\n     * interface.\n     */\n    function _mint(address account, uint256 amount, bytes memory userData, bytes memory operatorData) internal virtual {\n        _mint(account, amount, userData, operatorData, true);\n    }\n\n    /**\n     * @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * If `requireReceptionAck` is set to true, and if a send hook is\n     * registered for `account`, the corresponding function will be called with\n     * `operator`, `data` and `operatorData`.\n     *\n     * See {IERC777Sender} and {IERC777Recipient}.\n     *\n     * Emits {Minted} and {IERC20-Transfer} events.\n     *\n     * Requirements\n     *\n     * - `account` cannot be the zero address.\n     * - if `account` is a contract, it must implement the {IERC777Recipient}\n     * interface.\n     */\n    function _mint(\n        address account,\n        uint256 amount,\n        bytes memory userData,\n        bytes memory operatorData,\n        bool requireReceptionAck\n    ) internal virtual {\n        require(account != address(0), \"ERC777: mint to the zero address\");\n\n        address operator = _msgSender();\n\n        _beforeTokenTransfer(operator, address(0), account, amount);\n\n        // Update state variables\n        _totalSupply += amount;\n        _balances[account] += amount;\n\n        _callTokensReceived(operator, address(0), account, amount, userData, operatorData, requireReceptionAck);\n\n        emit Minted(operator, account, amount, userData, operatorData);\n        emit Transfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Send tokens\n     * @param from address token holder address\n     * @param to address recipient address\n     * @param amount uint256 amount of tokens to transfer\n     * @param userData bytes extra information provided by the token holder (if any)\n     * @param operatorData bytes extra information provided by the operator (if any)\n     * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient\n     */\n    function _send(\n        address from,\n        address to,\n        uint256 amount,\n        bytes memory userData,\n        bytes memory operatorData,\n        bool requireReceptionAck\n    ) internal virtual {\n        require(from != address(0), \"ERC777: transfer from the zero address\");\n        require(to != address(0), \"ERC777: transfer to the zero address\");\n\n        address operator = _msgSender();\n\n        _callTokensToSend(operator, from, to, amount, userData, operatorData);\n\n        _move(operator, from, to, amount, userData, operatorData);\n\n        _callTokensReceived(operator, from, to, amount, userData, operatorData, requireReceptionAck);\n    }\n\n    /**\n     * @dev Burn tokens\n     * @param from address token holder address\n     * @param amount uint256 amount of tokens to burn\n     * @param data bytes extra information provided by the token holder\n     * @param operatorData bytes extra information provided by the operator (if any)\n     */\n    function _burn(address from, uint256 amount, bytes memory data, bytes memory operatorData) internal virtual {\n        require(from != address(0), \"ERC777: burn from the zero address\");\n\n        address operator = _msgSender();\n\n        _callTokensToSend(operator, from, address(0), amount, data, operatorData);\n\n        _beforeTokenTransfer(operator, from, address(0), amount);\n\n        // Update state variables\n        uint256 fromBalance = _balances[from];\n        require(fromBalance >= amount, \"ERC777: burn amount exceeds balance\");\n        unchecked {\n            _balances[from] = fromBalance - amount;\n        }\n        _totalSupply -= amount;\n\n        emit Burned(operator, from, amount, data, operatorData);\n        emit Transfer(from, address(0), amount);\n    }\n\n    function _move(\n        address operator,\n        address from,\n        address to,\n        uint256 amount,\n        bytes memory userData,\n        bytes memory operatorData\n    ) private {\n        _beforeTokenTransfer(operator, from, to, amount);\n\n        uint256 fromBalance = _balances[from];\n        require(fromBalance >= amount, \"ERC777: transfer amount exceeds balance\");\n        unchecked {\n            _balances[from] = fromBalance - amount;\n        }\n        _balances[to] += amount;\n\n        emit Sent(operator, from, to, amount, userData, operatorData);\n        emit Transfer(from, to, amount);\n    }\n\n    /**\n     * @dev See {ERC20-_approve}.\n     *\n     * Note that accounts cannot have allowance issued by their operators.\n     */\n    function _approve(address holder, address spender, uint256 value) internal virtual {\n        require(holder != address(0), \"ERC777: approve from the zero address\");\n        require(spender != address(0), \"ERC777: approve to the zero address\");\n\n        _allowances[holder][spender] = value;\n        emit Approval(holder, spender, value);\n    }\n\n    /**\n     * @dev Call from.tokensToSend() if the interface is registered\n     * @param operator address operator requesting the transfer\n     * @param from address token holder address\n     * @param to address recipient address\n     * @param amount uint256 amount of tokens to transfer\n     * @param userData bytes extra information provided by the token holder (if any)\n     * @param operatorData bytes extra information provided by the operator (if any)\n     */\n    function _callTokensToSend(\n        address operator,\n        address from,\n        address to,\n        uint256 amount,\n        bytes memory userData,\n        bytes memory operatorData\n    ) private {\n        address implementer = _ERC1820_REGISTRY.getInterfaceImplementer(from, _TOKENS_SENDER_INTERFACE_HASH);\n        if (implementer != address(0)) {\n            IERC777SenderUpgradeable(implementer).tokensToSend(operator, from, to, amount, userData, operatorData);\n        }\n    }\n\n    /**\n     * @dev Call to.tokensReceived() if the interface is registered. Reverts if the recipient is a contract but\n     * tokensReceived() was not registered for the recipient\n     * @param operator address operator requesting the transfer\n     * @param from address token holder address\n     * @param to address recipient address\n     * @param amount uint256 amount of tokens to transfer\n     * @param userData bytes extra information provided by the token holder (if any)\n     * @param operatorData bytes extra information provided by the operator (if any)\n     * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient\n     */\n    function _callTokensReceived(\n        address operator,\n        address from,\n        address to,\n        uint256 amount,\n        bytes memory userData,\n        bytes memory operatorData,\n        bool requireReceptionAck\n    ) private {\n        address implementer = _ERC1820_REGISTRY.getInterfaceImplementer(to, _TOKENS_RECIPIENT_INTERFACE_HASH);\n        if (implementer != address(0)) {\n            IERC777RecipientUpgradeable(implementer).tokensReceived(operator, from, to, amount, userData, operatorData);\n        } else if (requireReceptionAck) {\n            require(!to.isContract(), \"ERC777: token recipient contract has no implementer for ERC777TokensRecipient\");\n        }\n    }\n\n    /**\n     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n     *\n     * Does not update the allowance amount in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Might emit an {IERC20-Approval} event.\n     */\n    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance != type(uint256).max) {\n            require(currentAllowance >= amount, \"ERC777: insufficient allowance\");\n            unchecked {\n                _approve(owner, spender, currentAllowance - amount);\n            }\n        }\n    }\n\n    /**\n     * @dev Hook that is called before any token transfer. This includes\n     * calls to {send}, {transfer}, {operatorSend}, {transferFrom}, minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be to transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(address operator, address from, address to, uint256 amount) internal virtual {}\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[41] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC777/IERC777RecipientUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC777/IERC777Recipient.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC777TokensRecipient standard as defined in the EIP.\n *\n * Accounts can be notified of {IERC777} tokens being sent to them by having a\n * contract implement this interface (contract holders can be their own\n * implementer) and registering it on the\n * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].\n *\n * See {IERC1820Registry} and {ERC1820Implementer}.\n */\ninterface IERC777RecipientUpgradeable {\n    /**\n     * @dev Called by an {IERC777} token contract whenever tokens are being\n     * moved or created into a registered account (`to`). The type of operation\n     * is conveyed by `from` being the zero address or not.\n     *\n     * This call occurs _after_ the token contract's state is updated, so\n     * {IERC777-balanceOf}, etc., can be used to query the post-operation state.\n     *\n     * This function may revert to prevent the operation from being executed.\n     */\n    function tokensReceived(\n        address operator,\n        address from,\n        address to,\n        uint256 amount,\n        bytes calldata userData,\n        bytes calldata operatorData\n    ) external;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC777/IERC777SenderUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC777/IERC777Sender.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC777TokensSender standard as defined in the EIP.\n *\n * {IERC777} Token holders can be notified of operations performed on their\n * tokens by having a contract implement this interface (contract holders can be\n * their own implementer) and registering it on the\n * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].\n *\n * See {IERC1820Registry} and {ERC1820Implementer}.\n */\ninterface IERC777SenderUpgradeable {\n    /**\n     * @dev Called by an {IERC777} token contract whenever a registered holder's\n     * (`from`) tokens are about to be moved or destroyed. The type of operation\n     * is conveyed by `to` being the zero address or not.\n     *\n     * This call occurs _before_ the token contract's state is updated, so\n     * {IERC777-balanceOf}, etc., can be used to query the pre-operation state.\n     *\n     * This function may revert to prevent the operation from being executed.\n     */\n    function tokensToSend(\n        address operator,\n        address from,\n        address to,\n        uint256 amount,\n        bytes calldata userData,\n        bytes calldata operatorData\n    ) external;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC777/IERC777Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC777/IERC777.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC777Token standard as defined in the EIP.\n *\n * This contract uses the\n * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let\n * token holders and recipients react to token movements by using setting implementers\n * for the associated interfaces in said registry. See {IERC1820Registry} and\n * {ERC1820Implementer}.\n */\ninterface IERC777Upgradeable {\n    /**\n     * @dev Emitted when `amount` tokens are created by `operator` and assigned to `to`.\n     *\n     * Note that some additional user `data` and `operatorData` can be logged in the event.\n     */\n    event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);\n\n    /**\n     * @dev Emitted when `operator` destroys `amount` tokens from `account`.\n     *\n     * Note that some additional user `data` and `operatorData` can be logged in the event.\n     */\n    event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);\n\n    /**\n     * @dev Emitted when `operator` is made operator for `tokenHolder`.\n     */\n    event AuthorizedOperator(address indexed operator, address indexed tokenHolder);\n\n    /**\n     * @dev Emitted when `operator` is revoked its operator status for `tokenHolder`.\n     */\n    event RevokedOperator(address indexed operator, address indexed tokenHolder);\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the smallest part of the token that is not divisible. This\n     * means all token operations (creation, movement and destruction) must have\n     * amounts that are a multiple of this number.\n     *\n     * For most token contracts, this value will equal 1.\n     */\n    function granularity() external view returns (uint256);\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 an account (`owner`).\n     */\n    function balanceOf(address owner) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * If send or receive hooks are registered for the caller and `recipient`,\n     * the corresponding functions will be called with `data` and empty\n     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.\n     *\n     * Emits a {Sent} event.\n     *\n     * Requirements\n     *\n     * - the caller must have at least `amount` tokens.\n     * - `recipient` cannot be the zero address.\n     * - if `recipient` is a contract, it must implement the {IERC777Recipient}\n     * interface.\n     */\n    function send(address recipient, uint256 amount, bytes calldata data) external;\n\n    /**\n     * @dev Destroys `amount` tokens from the caller's account, reducing the\n     * total supply.\n     *\n     * If a send hook is registered for the caller, the corresponding function\n     * will be called with `data` and empty `operatorData`. See {IERC777Sender}.\n     *\n     * Emits a {Burned} event.\n     *\n     * Requirements\n     *\n     * - the caller must have at least `amount` tokens.\n     */\n    function burn(uint256 amount, bytes calldata data) external;\n\n    /**\n     * @dev Returns true if an account is an operator of `tokenHolder`.\n     * Operators can send and burn tokens on behalf of their owners. All\n     * accounts are their own operator.\n     *\n     * See {operatorSend} and {operatorBurn}.\n     */\n    function isOperatorFor(address operator, address tokenHolder) external view returns (bool);\n\n    /**\n     * @dev Make an account an operator of the caller.\n     *\n     * See {isOperatorFor}.\n     *\n     * Emits an {AuthorizedOperator} event.\n     *\n     * Requirements\n     *\n     * - `operator` cannot be calling address.\n     */\n    function authorizeOperator(address operator) external;\n\n    /**\n     * @dev Revoke an account's operator status for the caller.\n     *\n     * See {isOperatorFor} and {defaultOperators}.\n     *\n     * Emits a {RevokedOperator} event.\n     *\n     * Requirements\n     *\n     * - `operator` cannot be calling address.\n     */\n    function revokeOperator(address operator) external;\n\n    /**\n     * @dev Returns the list of default operators. These accounts are operators\n     * for all token holders, even if {authorizeOperator} was never called on\n     * them.\n     *\n     * This list is immutable, but individual holders may revoke these via\n     * {revokeOperator}, in which case {isOperatorFor} will return false.\n     */\n    function defaultOperators() external view returns (address[] memory);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must\n     * be an operator of `sender`.\n     *\n     * If send or receive hooks are registered for `sender` and `recipient`,\n     * the corresponding functions will be called with `data` and\n     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.\n     *\n     * Emits a {Sent} event.\n     *\n     * Requirements\n     *\n     * - `sender` cannot be the zero address.\n     * - `sender` must have at least `amount` tokens.\n     * - the caller must be an operator for `sender`.\n     * - `recipient` cannot be the zero address.\n     * - if `recipient` is a contract, it must implement the {IERC777Recipient}\n     * interface.\n     */\n    function operatorSend(\n        address sender,\n        address recipient,\n        uint256 amount,\n        bytes calldata data,\n        bytes calldata operatorData\n    ) external;\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the total supply.\n     * The caller must be an operator of `account`.\n     *\n     * If a send hook is registered for `account`, the corresponding function\n     * will be called with `data` and `operatorData`. See {IERC777Sender}.\n     *\n     * Emits a {Burned} event.\n     *\n     * Requirements\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     * - the caller must be an operator for `account`.\n     */\n    function operatorBurn(address account, uint256 amount, bytes calldata data, bytes calldata operatorData) external;\n\n    event Sent(\n        address indexed operator,\n        address indexed from,\n        address indexed to,\n        uint256 amount,\n        bytes data,\n        bytes operatorData\n    );\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 (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport {Initializable} from \"../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    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\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/IERC1820RegistryUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/introspection/IERC1820Registry.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the global ERC1820 Registry, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1820[EIP]. Accounts may register\n * implementers for interfaces in this registry, as well as query support.\n *\n * Implementers may be shared by multiple accounts, and can also implement more\n * than a single interface for each account. Contracts can implement interfaces\n * for themselves, but externally-owned accounts (EOA) must delegate this to a\n * contract.\n *\n * {IERC165} interfaces can also be queried via the registry.\n *\n * For an in-depth explanation and source code analysis, see the EIP text.\n */\ninterface IERC1820RegistryUpgradeable {\n    event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);\n\n    event ManagerChanged(address indexed account, address indexed newManager);\n\n    /**\n     * @dev Sets `newManager` as the manager for `account`. A manager of an\n     * account is able to set interface implementers for it.\n     *\n     * By default, each account is its own manager. Passing a value of `0x0` in\n     * `newManager` will reset the manager to this initial state.\n     *\n     * Emits a {ManagerChanged} event.\n     *\n     * Requirements:\n     *\n     * - the caller must be the current manager for `account`.\n     */\n    function setManager(address account, address newManager) external;\n\n    /**\n     * @dev Returns the manager for `account`.\n     *\n     * See {setManager}.\n     */\n    function getManager(address account) external view returns (address);\n\n    /**\n     * @dev Sets the `implementer` contract as ``account``'s implementer for\n     * `interfaceHash`.\n     *\n     * `account` being the zero address is an alias for the caller's address.\n     * The zero address can also be used in `implementer` to remove an old one.\n     *\n     * See {interfaceHash} to learn how these are created.\n     *\n     * Emits an {InterfaceImplementerSet} event.\n     *\n     * Requirements:\n     *\n     * - the caller must be the current manager for `account`.\n     * - `interfaceHash` must not be an {IERC165} interface id (i.e. it must not\n     * end in 28 zeroes).\n     * - `implementer` must implement {IERC1820Implementer} and return true when\n     * queried for support, unless `implementer` is the caller. See\n     * {IERC1820Implementer-canImplementInterfaceForAddress}.\n     */\n    function setInterfaceImplementer(address account, bytes32 _interfaceHash, address implementer) external;\n\n    /**\n     * @dev Returns the implementer of `interfaceHash` for `account`. If no such\n     * implementer is registered, returns the zero address.\n     *\n     * If `interfaceHash` is an {IERC165} interface id (i.e. it ends with 28\n     * zeroes), `account` will be queried for support of it.\n     *\n     * `account` being the zero address is an alias for the caller's address.\n     */\n    function getInterfaceImplementer(address account, bytes32 _interfaceHash) external view returns (address);\n\n    /**\n     * @dev Returns the interface hash for an `interfaceName`, as defined in the\n     * corresponding\n     * https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the EIP].\n     */\n    function interfaceHash(string calldata interfaceName) external pure returns (bytes32);\n\n    /**\n     * @notice Updates the cache with whether the contract implements an ERC165 interface or not.\n     * @param account Address of the contract for which to update the cache.\n     * @param interfaceId ERC165 interface for which to update the cache.\n     */\n    function updateERC165Cache(address account, bytes4 interfaceId) external;\n\n    /**\n     * @notice Checks whether a contract implements an ERC165 interface or not.\n     * If the result is not cached a direct lookup on the contract address is performed.\n     * If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling\n     * {updateERC165Cache} with the contract address.\n     * @param account Address of the contract to check.\n     * @param interfaceId ERC165 interface to check.\n     * @return True if `account` implements `interfaceId`, false otherwise.\n     */\n    function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool);\n\n    /**\n     * @notice Checks whether a contract implements an ERC165 interface or not without using or updating the cache.\n     * @param account Address of the contract to check.\n     * @param interfaceId ERC165 interface to check.\n     * @return True if `account` implements `interfaceId`, false otherwise.\n     */\n    function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol": {
        "content": "pragma solidity >=0.5.0;\n\ninterface IUniswapV2Factory {\n    event PairCreated(address indexed token0, address indexed token1, address pair, uint);\n\n    function feeTo() external view returns (address);\n    function feeToSetter() external view returns (address);\n\n    function getPair(address tokenA, address tokenB) external view returns (address pair);\n    function allPairs(uint) external view returns (address pair);\n    function allPairsLength() external view returns (uint);\n\n    function createPair(address tokenA, address tokenB) external returns (address pair);\n\n    function setFeeTo(address) external;\n    function setFeeToSetter(address) external;\n}\n"
      },
      "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol": {
        "content": "pragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n    event Approval(address indexed owner, address indexed spender, uint value);\n    event Transfer(address indexed from, address indexed to, uint value);\n\n    function name() external pure returns (string memory);\n    function symbol() external pure returns (string memory);\n    function decimals() external pure returns (uint8);\n    function totalSupply() external view returns (uint);\n    function balanceOf(address owner) external view returns (uint);\n    function allowance(address owner, address spender) external view returns (uint);\n\n    function approve(address spender, uint value) external returns (bool);\n    function transfer(address to, uint value) external returns (bool);\n    function transferFrom(address from, address to, uint value) external returns (bool);\n\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\n    function nonces(address owner) external view returns (uint);\n\n    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n    event Mint(address indexed sender, uint amount0, uint amount1);\n    event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n    event Swap(\n        address indexed sender,\n        uint amount0In,\n        uint amount1In,\n        uint amount0Out,\n        uint amount1Out,\n        address indexed to\n    );\n    event Sync(uint112 reserve0, uint112 reserve1);\n\n    function MINIMUM_LIQUIDITY() external pure returns (uint);\n    function factory() external view returns (address);\n    function token0() external view returns (address);\n    function token1() external view returns (address);\n    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n    function price0CumulativeLast() external view returns (uint);\n    function price1CumulativeLast() external view returns (uint);\n    function kLast() external view returns (uint);\n\n    function mint(address to) external returns (uint liquidity);\n    function burn(address to) external returns (uint amount0, uint amount1);\n    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n    function skim(address to) external;\n    function sync() external;\n\n    function initialize(address, address) external;\n}\n"
      },
      "abdk-libraries-solidity/ABDKMathQuad.sol": {
        "content": "// SPDX-License-Identifier: BSD-4-Clause\n/*\n * ABDK Math Quad Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\n */\npragma solidity ^0.8.0;\n\n/**\n * Smart contract library of mathematical functions operating with IEEE 754\n * quadruple-precision binary floating-point numbers (quadruple precision\n * numbers).  As long as quadruple precision numbers are 16-bytes long, they are\n * represented by bytes16 type.\n */\nlibrary ABDKMathQuad {\n  /*\n   * 0.\n   */\n  bytes16 private constant POSITIVE_ZERO = 0x00000000000000000000000000000000;\n\n  /*\n   * -0.\n   */\n  bytes16 private constant NEGATIVE_ZERO = 0x80000000000000000000000000000000;\n\n  /*\n   * +Infinity.\n   */\n  bytes16 private constant POSITIVE_INFINITY = 0x7FFF0000000000000000000000000000;\n\n  /*\n   * -Infinity.\n   */\n  bytes16 private constant NEGATIVE_INFINITY = 0xFFFF0000000000000000000000000000;\n\n  /*\n   * Canonical NaN value.\n   */\n  bytes16 private constant NaN = 0x7FFF8000000000000000000000000000;\n\n  /**\n   * Convert signed 256-bit integer number into quadruple precision number.\n   *\n   * @param x signed 256-bit integer number\n   * @return quadruple precision number\n   */\n  function fromInt (int256 x) internal pure returns (bytes16) {\n    unchecked {\n      if (x == 0) return bytes16 (0);\n      else {\n        // We rely on overflow behavior here\n        uint256 result = uint256 (x > 0 ? x : -x);\n\n        uint256 msb = mostSignificantBit (result);\n        if (msb < 112) result <<= 112 - msb;\n        else if (msb > 112) result >>= msb - 112;\n\n        result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16383 + msb << 112;\n        if (x < 0) result |= 0x80000000000000000000000000000000;\n\n        return bytes16 (uint128 (result));\n      }\n    }\n  }\n\n  /**\n   * Convert quadruple precision number into signed 256-bit integer number\n   * rounding towards zero.  Revert on overflow.\n   *\n   * @param x quadruple precision number\n   * @return signed 256-bit integer number\n   */\n  function toInt (bytes16 x) internal pure returns (int256) {\n    unchecked {\n      uint256 exponent = uint128 (x) >> 112 & 0x7FFF;\n\n      require (exponent <= 16638); // Overflow\n      if (exponent < 16383) return 0; // Underflow\n\n      uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF |\n        0x10000000000000000000000000000;\n\n      if (exponent < 16495) result >>= 16495 - exponent;\n      else if (exponent > 16495) result <<= exponent - 16495;\n\n      if (uint128 (x) >= 0x80000000000000000000000000000000) { // Negative\n        require (result <= 0x8000000000000000000000000000000000000000000000000000000000000000);\n        return -int256 (result); // We rely on overflow behavior here\n      } else {\n        require (result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\n        return int256 (result);\n      }\n    }\n  }\n\n  /**\n   * Convert unsigned 256-bit integer number into quadruple precision number.\n   *\n   * @param x unsigned 256-bit integer number\n   * @return quadruple precision number\n   */\n  function fromUInt (uint256 x) internal pure returns (bytes16) {\n    unchecked {\n      if (x == 0) return bytes16 (0);\n      else {\n        uint256 result = x;\n\n        uint256 msb = mostSignificantBit (result);\n        if (msb < 112) result <<= 112 - msb;\n        else if (msb > 112) result >>= msb - 112;\n\n        result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16383 + msb << 112;\n\n        return bytes16 (uint128 (result));\n      }\n    }\n  }\n\n  /**\n   * Convert quadruple precision number into unsigned 256-bit integer number\n   * rounding towards zero.  Revert on underflow.  Note, that negative floating\n   * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer\n   * without error, because they are rounded to zero.\n   *\n   * @param x quadruple precision number\n   * @return unsigned 256-bit integer number\n   */\n  function toUInt (bytes16 x) internal pure returns (uint256) {\n    unchecked {\n      uint256 exponent = uint128 (x) >> 112 & 0x7FFF;\n\n      if (exponent < 16383) return 0; // Underflow\n\n      require (uint128 (x) < 0x80000000000000000000000000000000); // Negative\n\n      require (exponent <= 16638); // Overflow\n      uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF |\n        0x10000000000000000000000000000;\n\n      if (exponent < 16495) result >>= 16495 - exponent;\n      else if (exponent > 16495) result <<= exponent - 16495;\n\n      return result;\n    }\n  }\n\n  /**\n   * Convert signed 128.128 bit fixed point number into quadruple precision\n   * number.\n   *\n   * @param x signed 128.128 bit fixed point number\n   * @return quadruple precision number\n   */\n  function from128x128 (int256 x) internal pure returns (bytes16) {\n    unchecked {\n      if (x == 0) return bytes16 (0);\n      else {\n        // We rely on overflow behavior here\n        uint256 result = uint256 (x > 0 ? x : -x);\n\n        uint256 msb = mostSignificantBit (result);\n        if (msb < 112) result <<= 112 - msb;\n        else if (msb > 112) result >>= msb - 112;\n\n        result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16255 + msb << 112;\n        if (x < 0) result |= 0x80000000000000000000000000000000;\n\n        return bytes16 (uint128 (result));\n      }\n    }\n  }\n\n  /**\n   * Convert quadruple precision number into signed 128.128 bit fixed point\n   * number.  Revert on overflow.\n   *\n   * @param x quadruple precision number\n   * @return signed 128.128 bit fixed point number\n   */\n  function to128x128 (bytes16 x) internal pure returns (int256) {\n    unchecked {\n      uint256 exponent = uint128 (x) >> 112 & 0x7FFF;\n\n      require (exponent <= 16510); // Overflow\n      if (exponent < 16255) return 0; // Underflow\n\n      uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF |\n        0x10000000000000000000000000000;\n\n      if (exponent < 16367) result >>= 16367 - exponent;\n      else if (exponent > 16367) result <<= exponent - 16367;\n\n      if (uint128 (x) >= 0x80000000000000000000000000000000) { // Negative\n        require (result <= 0x8000000000000000000000000000000000000000000000000000000000000000);\n        return -int256 (result); // We rely on overflow behavior here\n      } else {\n        require (result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\n        return int256 (result);\n      }\n    }\n  }\n\n  /**\n   * Convert signed 64.64 bit fixed point number into quadruple precision\n   * number.\n   *\n   * @param x signed 64.64 bit fixed point number\n   * @return quadruple precision number\n   */\n  function from64x64 (int128 x) internal pure returns (bytes16) {\n    unchecked {\n      if (x == 0) return bytes16 (0);\n      else {\n        // We rely on overflow behavior here\n        uint256 result = uint128 (x > 0 ? x : -x);\n\n        uint256 msb = mostSignificantBit (result);\n        if (msb < 112) result <<= 112 - msb;\n        else if (msb > 112) result >>= msb - 112;\n\n        result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16319 + msb << 112;\n        if (x < 0) result |= 0x80000000000000000000000000000000;\n\n        return bytes16 (uint128 (result));\n      }\n    }\n  }\n\n  /**\n   * Convert quadruple precision number into signed 64.64 bit fixed point\n   * number.  Revert on overflow.\n   *\n   * @param x quadruple precision number\n   * @return signed 64.64 bit fixed point number\n   */\n  function to64x64 (bytes16 x) internal pure returns (int128) {\n    unchecked {\n      uint256 exponent = uint128 (x) >> 112 & 0x7FFF;\n\n      require (exponent <= 16446); // Overflow\n      if (exponent < 16319) return 0; // Underflow\n\n      uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF |\n        0x10000000000000000000000000000;\n\n      if (exponent < 16431) result >>= 16431 - exponent;\n      else if (exponent > 16431) result <<= exponent - 16431;\n\n      if (uint128 (x) >= 0x80000000000000000000000000000000) { // Negative\n        require (result <= 0x80000000000000000000000000000000);\n        return -int128 (int256 (result)); // We rely on overflow behavior here\n      } else {\n        require (result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\n        return int128 (int256 (result));\n      }\n    }\n  }\n\n  /**\n   * Convert octuple precision number into quadruple precision number.\n   *\n   * @param x octuple precision number\n   * @return quadruple precision number\n   */\n  function fromOctuple (bytes32 x) internal pure returns (bytes16) {\n    unchecked {\n      bool negative = x & 0x8000000000000000000000000000000000000000000000000000000000000000 > 0;\n\n      uint256 exponent = uint256 (x) >> 236 & 0x7FFFF;\n      uint256 significand = uint256 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n      if (exponent == 0x7FFFF) {\n        if (significand > 0) return NaN;\n        else return negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY;\n      }\n\n      if (exponent > 278526)\n        return negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY;\n      else if (exponent < 245649)\n        return negative ? NEGATIVE_ZERO : POSITIVE_ZERO;\n      else if (exponent < 245761) {\n        significand = (significand | 0x100000000000000000000000000000000000000000000000000000000000) >> 245885 - exponent;\n        exponent = 0;\n      } else {\n        significand >>= 124;\n        exponent -= 245760;\n      }\n\n      uint128 result = uint128 (significand | exponent << 112);\n      if (negative) result |= 0x80000000000000000000000000000000;\n\n      return bytes16 (result);\n    }\n  }\n\n  /**\n   * Convert quadruple precision number into octuple precision number.\n   *\n   * @param x quadruple precision number\n   * @return octuple precision number\n   */\n  function toOctuple (bytes16 x) internal pure returns (bytes32) {\n    unchecked {\n      uint256 exponent = uint128 (x) >> 112 & 0x7FFF;\n\n      uint256 result = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n      if (exponent == 0x7FFF) exponent = 0x7FFFF; // Infinity or NaN\n      else if (exponent == 0) {\n        if (result > 0) {\n          uint256 msb = mostSignificantBit (result);\n          result = result << 236 - msb & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n          exponent = 245649 + msb;\n        }\n      } else {\n        result <<= 124;\n        exponent += 245760;\n      }\n\n      result |= exponent << 236;\n      if (uint128 (x) >= 0x80000000000000000000000000000000)\n        result |= 0x8000000000000000000000000000000000000000000000000000000000000000;\n\n      return bytes32 (result);\n    }\n  }\n\n  /**\n   * Convert double precision number into quadruple precision number.\n   *\n   * @param x double precision number\n   * @return quadruple precision number\n   */\n  function fromDouble (bytes8 x) internal pure returns (bytes16) {\n    unchecked {\n      uint256 exponent = uint64 (x) >> 52 & 0x7FF;\n\n      uint256 result = uint64 (x) & 0xFFFFFFFFFFFFF;\n\n      if (exponent == 0x7FF) exponent = 0x7FFF; // Infinity or NaN\n      else if (exponent == 0) {\n        if (result > 0) {\n          uint256 msb = mostSignificantBit (result);\n          result = result << 112 - msb & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n          exponent = 15309 + msb;\n        }\n      } else {\n        result <<= 60;\n        exponent += 15360;\n      }\n\n      result |= exponent << 112;\n      if (x & 0x8000000000000000 > 0)\n        result |= 0x80000000000000000000000000000000;\n\n      return bytes16 (uint128 (result));\n    }\n  }\n\n  /**\n   * Convert quadruple precision number into double precision number.\n   *\n   * @param x quadruple precision number\n   * @return double precision number\n   */\n  function toDouble (bytes16 x) internal pure returns (bytes8) {\n    unchecked {\n      bool negative = uint128 (x) >= 0x80000000000000000000000000000000;\n\n      uint256 exponent = uint128 (x) >> 112 & 0x7FFF;\n      uint256 significand = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n      if (exponent == 0x7FFF) {\n        if (significand > 0) return 0x7FF8000000000000; // NaN\n        else return negative ?\n            bytes8 (0xFFF0000000000000) : // -Infinity\n            bytes8 (0x7FF0000000000000); // Infinity\n      }\n\n      if (exponent > 17406)\n        return negative ?\n            bytes8 (0xFFF0000000000000) : // -Infinity\n            bytes8 (0x7FF0000000000000); // Infinity\n      else if (exponent < 15309)\n        return negative ?\n            bytes8 (0x8000000000000000) : // -0\n            bytes8 (0x0000000000000000); // 0\n      else if (exponent < 15361) {\n        significand = (significand | 0x10000000000000000000000000000) >> 15421 - exponent;\n        exponent = 0;\n      } else {\n        significand >>= 60;\n        exponent -= 15360;\n      }\n\n      uint64 result = uint64 (significand | exponent << 52);\n      if (negative) result |= 0x8000000000000000;\n\n      return bytes8 (result);\n    }\n  }\n\n  /**\n   * Test whether given quadruple precision number is NaN.\n   *\n   * @param x quadruple precision number\n   * @return true if x is NaN, false otherwise\n   */\n  function isNaN (bytes16 x) internal pure returns (bool) {\n    unchecked {\n      return uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF >\n        0x7FFF0000000000000000000000000000;\n    }\n  }\n\n  /**\n   * Test whether given quadruple precision number is positive or negative\n   * infinity.\n   *\n   * @param x quadruple precision number\n   * @return true if x is positive or negative infinity, false otherwise\n   */\n  function isInfinity (bytes16 x) internal pure returns (bool) {\n    unchecked {\n      return uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ==\n        0x7FFF0000000000000000000000000000;\n    }\n  }\n\n  /**\n   * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x\n   * is positive.  Note that sign (-0) is zero.  Revert if x is NaN. \n   *\n   * @param x quadruple precision number\n   * @return sign of x\n   */\n  function sign (bytes16 x) internal pure returns (int8) {\n    unchecked {\n      uint128 absoluteX = uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n      require (absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\n\n      if (absoluteX == 0) return 0;\n      else if (uint128 (x) >= 0x80000000000000000000000000000000) return -1;\n      else return 1;\n    }\n  }\n\n  /**\n   * Calculate sign (x - y).  Revert if either argument is NaN, or both\n   * arguments are infinities of the same sign. \n   *\n   * @param x quadruple precision number\n   * @param y quadruple precision number\n   * @return sign (x - y)\n   */\n  function cmp (bytes16 x, bytes16 y) internal pure returns (int8) {\n    unchecked {\n      uint128 absoluteX = uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n      require (absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\n\n      uint128 absoluteY = uint128 (y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n      require (absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN\n\n      // Not infinities of the same sign\n      require (x != y || absoluteX < 0x7FFF0000000000000000000000000000);\n\n      if (x == y) return 0;\n      else {\n        bool negativeX = uint128 (x) >= 0x80000000000000000000000000000000;\n        bool negativeY = uint128 (y) >= 0x80000000000000000000000000000000;\n\n        if (negativeX) {\n          if (negativeY) return absoluteX > absoluteY ? -1 : int8 (1);\n          else return -1; \n        } else {\n          if (negativeY) return 1;\n          else return absoluteX > absoluteY ? int8 (1) : -1;\n        }\n      }\n    }\n  }\n\n  /**\n   * Test whether x equals y.  NaN, infinity, and -infinity are not equal to\n   * anything. \n   *\n   * @param x quadruple precision number\n   * @param y quadruple precision number\n   * @return true if x equals to y, false otherwise\n   */\n  function eq (bytes16 x, bytes16 y) internal pure returns (bool) {\n    unchecked {\n      if (x == y) {\n        return uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF <\n          0x7FFF0000000000000000000000000000;\n      } else return false;\n    }\n  }\n\n  /**\n   * Calculate x + y.  Special values behave in the following way:\n   *\n   * NaN + x = NaN for any x.\n   * Infinity + x = Infinity for any finite x.\n   * -Infinity + x = -Infinity for any finite x.\n   * Infinity + Infinity = Infinity.\n   * -Infinity + -Infinity = -Infinity.\n   * Infinity + -Infinity = -Infinity + Infinity = NaN.\n   *\n   * @param x quadruple precision number\n   * @param y quadruple precision number\n   * @return quadruple precision number\n   */\n  function add (bytes16 x, bytes16 y) internal pure returns (bytes16) {\n    unchecked {\n      uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;\n      uint256 yExponent = uint128 (y) >> 112 & 0x7FFF;\n\n      if (xExponent == 0x7FFF) {\n        if (yExponent == 0x7FFF) { \n          if (x == y) return x;\n          else return NaN;\n        } else return x; \n      } else if (yExponent == 0x7FFF) return y;\n      else {\n        bool xSign = uint128 (x) >= 0x80000000000000000000000000000000;\n        uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n        if (xExponent == 0) xExponent = 1;\n        else xSignifier |= 0x10000000000000000000000000000;\n\n        bool ySign = uint128 (y) >= 0x80000000000000000000000000000000;\n        uint256 ySignifier = uint128 (y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n        if (yExponent == 0) yExponent = 1;\n        else ySignifier |= 0x10000000000000000000000000000;\n\n        if (xSignifier == 0) return y == NEGATIVE_ZERO ? POSITIVE_ZERO : y;\n        else if (ySignifier == 0) return x == NEGATIVE_ZERO ? POSITIVE_ZERO : x;\n        else {\n          int256 delta = int256 (xExponent) - int256 (yExponent);\n  \n          if (xSign == ySign) {\n            if (delta > 112) return x;\n            else if (delta > 0) ySignifier >>= uint256 (delta);\n            else if (delta < -112) return y;\n            else if (delta < 0) {\n              xSignifier >>= uint256 (-delta);\n              xExponent = yExponent;\n            }\n  \n            xSignifier += ySignifier;\n  \n            if (xSignifier >= 0x20000000000000000000000000000) {\n              xSignifier >>= 1;\n              xExponent += 1;\n            }\n  \n            if (xExponent == 0x7FFF)\n              return xSign ? NEGATIVE_INFINITY : POSITIVE_INFINITY;\n            else {\n              if (xSignifier < 0x10000000000000000000000000000) xExponent = 0;\n              else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n  \n              return bytes16 (uint128 (\n                  (xSign ? 0x80000000000000000000000000000000 : 0) |\n                  (xExponent << 112) |\n                  xSignifier)); \n            }\n          } else {\n            if (delta > 0) {\n              xSignifier <<= 1;\n              xExponent -= 1;\n            } else if (delta < 0) {\n              ySignifier <<= 1;\n              xExponent = yExponent - 1;\n            }\n\n            if (delta > 112) ySignifier = 1;\n            else if (delta > 1) ySignifier = (ySignifier - 1 >> uint256 (delta - 1)) + 1;\n            else if (delta < -112) xSignifier = 1;\n            else if (delta < -1) xSignifier = (xSignifier - 1 >> uint256 (-delta - 1)) + 1;\n\n            if (xSignifier >= ySignifier) xSignifier -= ySignifier;\n            else {\n              xSignifier = ySignifier - xSignifier;\n              xSign = ySign;\n            }\n\n            if (xSignifier == 0)\n              return POSITIVE_ZERO;\n\n            uint256 msb = mostSignificantBit (xSignifier);\n\n            if (msb == 113) {\n              xSignifier = xSignifier >> 1 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n              xExponent += 1;\n            } else if (msb < 112) {\n              uint256 shift = 112 - msb;\n              if (xExponent > shift) {\n                xSignifier = xSignifier << shift & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n                xExponent -= shift;\n              } else {\n                xSignifier <<= xExponent - 1;\n                xExponent = 0;\n              }\n            } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n            if (xExponent == 0x7FFF)\n              return xSign ? NEGATIVE_INFINITY : POSITIVE_INFINITY;\n            else return bytes16 (uint128 (\n                (xSign ? 0x80000000000000000000000000000000 : 0) |\n                (xExponent << 112) |\n                xSignifier));\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Calculate x - y.  Special values behave in the following way:\n   *\n   * NaN - x = NaN for any x.\n   * Infinity - x = Infinity for any finite x.\n   * -Infinity - x = -Infinity for any finite x.\n   * Infinity - -Infinity = Infinity.\n   * -Infinity - Infinity = -Infinity.\n   * Infinity - Infinity = -Infinity - -Infinity = NaN.\n   *\n   * @param x quadruple precision number\n   * @param y quadruple precision number\n   * @return quadruple precision number\n   */\n  function sub (bytes16 x, bytes16 y) internal pure returns (bytes16) {\n    unchecked {\n      return add (x, y ^ 0x80000000000000000000000000000000);\n    }\n  }\n\n  /**\n   * Calculate x * y.  Special values behave in the following way:\n   *\n   * NaN * x = NaN for any x.\n   * Infinity * x = Infinity for any finite positive x.\n   * Infinity * x = -Infinity for any finite negative x.\n   * -Infinity * x = -Infinity for any finite positive x.\n   * -Infinity * x = Infinity for any finite negative x.\n   * Infinity * 0 = NaN.\n   * -Infinity * 0 = NaN.\n   * Infinity * Infinity = Infinity.\n   * Infinity * -Infinity = -Infinity.\n   * -Infinity * Infinity = -Infinity.\n   * -Infinity * -Infinity = Infinity.\n   *\n   * @param x quadruple precision number\n   * @param y quadruple precision number\n   * @return quadruple precision number\n   */\n  function mul (bytes16 x, bytes16 y) internal pure returns (bytes16) {\n    unchecked {\n      uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;\n      uint256 yExponent = uint128 (y) >> 112 & 0x7FFF;\n\n      if (xExponent == 0x7FFF) {\n        if (yExponent == 0x7FFF) {\n          if (x == y) return x ^ y & 0x80000000000000000000000000000000;\n          else if (x ^ y == 0x80000000000000000000000000000000) return x | y;\n          else return NaN;\n        } else {\n          if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\n          else return x ^ y & 0x80000000000000000000000000000000;\n        }\n      } else if (yExponent == 0x7FFF) {\n          if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\n          else return y ^ x & 0x80000000000000000000000000000000;\n      } else {\n        uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n        if (xExponent == 0) xExponent = 1;\n        else xSignifier |= 0x10000000000000000000000000000;\n\n        uint256 ySignifier = uint128 (y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n        if (yExponent == 0) yExponent = 1;\n        else ySignifier |= 0x10000000000000000000000000000;\n\n        xSignifier *= ySignifier;\n        if (xSignifier == 0)\n          return (x ^ y) & 0x80000000000000000000000000000000 > 0 ?\n              NEGATIVE_ZERO : POSITIVE_ZERO;\n\n        xExponent += yExponent;\n\n        uint256 msb =\n          xSignifier >= 0x200000000000000000000000000000000000000000000000000000000 ? 225 :\n          xSignifier >= 0x100000000000000000000000000000000000000000000000000000000 ? 224 :\n          mostSignificantBit (xSignifier);\n\n        if (xExponent + msb < 16496) { // Underflow\n          xExponent = 0;\n          xSignifier = 0;\n        } else if (xExponent + msb < 16608) { // Subnormal\n          if (xExponent < 16496)\n            xSignifier >>= 16496 - xExponent;\n          else if (xExponent > 16496)\n            xSignifier <<= xExponent - 16496;\n          xExponent = 0;\n        } else if (xExponent + msb > 49373) {\n          xExponent = 0x7FFF;\n          xSignifier = 0;\n        } else {\n          if (msb > 112)\n            xSignifier >>= msb - 112;\n          else if (msb < 112)\n            xSignifier <<= 112 - msb;\n\n          xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n          xExponent = xExponent + msb - 16607;\n        }\n\n        return bytes16 (uint128 (uint128 ((x ^ y) & 0x80000000000000000000000000000000) |\n            xExponent << 112 | xSignifier));\n      }\n    }\n  }\n\n  /**\n   * Calculate x / y.  Special values behave in the following way:\n   *\n   * NaN / x = NaN for any x.\n   * x / NaN = NaN for any x.\n   * Infinity / x = Infinity for any finite non-negative x.\n   * Infinity / x = -Infinity for any finite negative x including -0.\n   * -Infinity / x = -Infinity for any finite non-negative x.\n   * -Infinity / x = Infinity for any finite negative x including -0.\n   * x / Infinity = 0 for any finite non-negative x.\n   * x / -Infinity = -0 for any finite non-negative x.\n   * x / Infinity = -0 for any finite non-negative x including -0.\n   * x / -Infinity = 0 for any finite non-negative x including -0.\n   * \n   * Infinity / Infinity = NaN.\n   * Infinity / -Infinity = -NaN.\n   * -Infinity / Infinity = -NaN.\n   * -Infinity / -Infinity = NaN.\n   *\n   * Division by zero behaves in the following way:\n   *\n   * x / 0 = Infinity for any finite positive x.\n   * x / -0 = -Infinity for any finite positive x.\n   * x / 0 = -Infinity for any finite negative x.\n   * x / -0 = Infinity for any finite negative x.\n   * 0 / 0 = NaN.\n   * 0 / -0 = NaN.\n   * -0 / 0 = NaN.\n   * -0 / -0 = NaN.\n   *\n   * @param x quadruple precision number\n   * @param y quadruple precision number\n   * @return quadruple precision number\n   */\n  function div (bytes16 x, bytes16 y) internal pure returns (bytes16) {\n    unchecked {\n      uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;\n      uint256 yExponent = uint128 (y) >> 112 & 0x7FFF;\n\n      if (xExponent == 0x7FFF) {\n        if (yExponent == 0x7FFF) return NaN;\n        else return x ^ y & 0x80000000000000000000000000000000;\n      } else if (yExponent == 0x7FFF) {\n        if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN;\n        else return POSITIVE_ZERO | (x ^ y) & 0x80000000000000000000000000000000;\n      } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) {\n        if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\n        else return POSITIVE_INFINITY | (x ^ y) & 0x80000000000000000000000000000000;\n      } else {\n        uint256 ySignifier = uint128 (y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n        if (yExponent == 0) yExponent = 1;\n        else ySignifier |= 0x10000000000000000000000000000;\n\n        uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n        if (xExponent == 0) {\n          if (xSignifier != 0) {\n            uint shift = 226 - mostSignificantBit (xSignifier);\n\n            xSignifier <<= shift;\n\n            xExponent = 1;\n            yExponent += shift - 114;\n          }\n        }\n        else {\n          xSignifier = (xSignifier | 0x10000000000000000000000000000) << 114;\n        }\n\n        xSignifier = xSignifier / ySignifier;\n        if (xSignifier == 0)\n          return (x ^ y) & 0x80000000000000000000000000000000 > 0 ?\n              NEGATIVE_ZERO : POSITIVE_ZERO;\n\n        assert (xSignifier >= 0x1000000000000000000000000000);\n\n        uint256 msb =\n          xSignifier >= 0x80000000000000000000000000000 ? mostSignificantBit (xSignifier) :\n          xSignifier >= 0x40000000000000000000000000000 ? 114 :\n          xSignifier >= 0x20000000000000000000000000000 ? 113 : 112;\n\n        if (xExponent + msb > yExponent + 16497) { // Overflow\n          xExponent = 0x7FFF;\n          xSignifier = 0;\n        } else if (xExponent + msb + 16380  < yExponent) { // Underflow\n          xExponent = 0;\n          xSignifier = 0;\n        } else if (xExponent + msb + 16268  < yExponent) { // Subnormal\n          if (xExponent + 16380 > yExponent)\n            xSignifier <<= xExponent + 16380 - yExponent;\n          else if (xExponent + 16380 < yExponent)\n            xSignifier >>= yExponent - xExponent - 16380;\n\n          xExponent = 0;\n        } else { // Normal\n          if (msb > 112)\n            xSignifier >>= msb - 112;\n\n          xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n          xExponent = xExponent + msb + 16269 - yExponent;\n        }\n\n        return bytes16 (uint128 (uint128 ((x ^ y) & 0x80000000000000000000000000000000) |\n            xExponent << 112 | xSignifier));\n      }\n    }\n  }\n\n  /**\n   * Calculate -x.\n   *\n   * @param x quadruple precision number\n   * @return quadruple precision number\n   */\n  function neg (bytes16 x) internal pure returns (bytes16) {\n    unchecked {\n      return x ^ 0x80000000000000000000000000000000;\n    }\n  }\n\n  /**\n   * Calculate |x|.\n   *\n   * @param x quadruple precision number\n   * @return quadruple precision number\n   */\n  function abs (bytes16 x) internal pure returns (bytes16) {\n    unchecked {\n      return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n    }\n  }\n\n  /**\n   * Calculate square root of x.  Return NaN on negative x excluding -0.\n   *\n   * @param x quadruple precision number\n   * @return quadruple precision number\n   */\n  function sqrt (bytes16 x) internal pure returns (bytes16) {\n    unchecked {\n      if (uint128 (x) >  0x80000000000000000000000000000000) return NaN;\n      else {\n        uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;\n        if (xExponent == 0x7FFF) return x;\n        else {\n          uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n          if (xExponent == 0) xExponent = 1;\n          else xSignifier |= 0x10000000000000000000000000000;\n\n          if (xSignifier == 0) return POSITIVE_ZERO;\n\n          bool oddExponent = xExponent & 0x1 == 0;\n          xExponent = xExponent + 16383 >> 1;\n\n          if (oddExponent) {\n            if (xSignifier >= 0x10000000000000000000000000000)\n              xSignifier <<= 113;\n            else {\n              uint256 msb = mostSignificantBit (xSignifier);\n              uint256 shift = (226 - msb) & 0xFE;\n              xSignifier <<= shift;\n              xExponent -= shift - 112 >> 1;\n            }\n          } else {\n            if (xSignifier >= 0x10000000000000000000000000000)\n              xSignifier <<= 112;\n            else {\n              uint256 msb = mostSignificantBit (xSignifier);\n              uint256 shift = (225 - msb) & 0xFE;\n              xSignifier <<= shift;\n              xExponent -= shift - 112 >> 1;\n            }\n          }\n\n          uint256 r = 0x10000000000000000000000000000;\n          r = (r + xSignifier / r) >> 1;\n          r = (r + xSignifier / r) >> 1;\n          r = (r + xSignifier / r) >> 1;\n          r = (r + xSignifier / r) >> 1;\n          r = (r + xSignifier / r) >> 1;\n          r = (r + xSignifier / r) >> 1;\n          r = (r + xSignifier / r) >> 1; // Seven iterations should be enough\n          uint256 r1 = xSignifier / r;\n          if (r1 < r) r = r1;\n\n          return bytes16 (uint128 (xExponent << 112 | r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF));\n        }\n      }\n    }\n  }\n\n  /**\n   * Calculate binary logarithm of x.  Return NaN on negative x excluding -0.\n   *\n   * @param x quadruple precision number\n   * @return quadruple precision number\n   */\n  function log_2 (bytes16 x) internal pure returns (bytes16) {\n    unchecked {\n      if (uint128 (x) > 0x80000000000000000000000000000000) return NaN;\n      else if (x == 0x3FFF0000000000000000000000000000) return POSITIVE_ZERO; \n      else {\n        uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;\n        if (xExponent == 0x7FFF) return x;\n        else {\n          uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n          if (xExponent == 0) xExponent = 1;\n          else xSignifier |= 0x10000000000000000000000000000;\n\n          if (xSignifier == 0) return NEGATIVE_INFINITY;\n\n          bool resultNegative;\n          uint256 resultExponent = 16495;\n          uint256 resultSignifier;\n\n          if (xExponent >= 0x3FFF) {\n            resultNegative = false;\n            resultSignifier = xExponent - 0x3FFF;\n            xSignifier <<= 15;\n          } else {\n            resultNegative = true;\n            if (xSignifier >= 0x10000000000000000000000000000) {\n              resultSignifier = 0x3FFE - xExponent;\n              xSignifier <<= 15;\n            } else {\n              uint256 msb = mostSignificantBit (xSignifier);\n              resultSignifier = 16493 - msb;\n              xSignifier <<= 127 - msb;\n            }\n          }\n\n          if (xSignifier == 0x80000000000000000000000000000000) {\n            if (resultNegative) resultSignifier += 1;\n            uint256 shift = 112 - mostSignificantBit (resultSignifier);\n            resultSignifier <<= shift;\n            resultExponent -= shift;\n          } else {\n            uint256 bb = resultNegative ? 1 : 0;\n            while (resultSignifier < 0x10000000000000000000000000000) {\n              resultSignifier <<= 1;\n              resultExponent -= 1;\n  \n              xSignifier *= xSignifier;\n              uint256 b = xSignifier >> 255;\n              resultSignifier += b ^ bb;\n              xSignifier >>= 127 + b;\n            }\n          }\n\n          return bytes16 (uint128 ((resultNegative ? 0x80000000000000000000000000000000 : 0) |\n              resultExponent << 112 | resultSignifier & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF));\n        }\n      }\n    }\n  }\n\n  /**\n   * Calculate natural logarithm of x.  Return NaN on negative x excluding -0.\n   *\n   * @param x quadruple precision number\n   * @return quadruple precision number\n   */\n  function ln (bytes16 x) internal pure returns (bytes16) {\n    unchecked {\n      return mul (log_2 (x), 0x3FFE62E42FEFA39EF35793C7673007E5);\n    }\n  }\n\n  /**\n   * Calculate 2^x.\n   *\n   * @param x quadruple precision number\n   * @return quadruple precision number\n   */\n  function pow_2 (bytes16 x) internal pure returns (bytes16) {\n    unchecked {\n      bool xNegative = uint128 (x) > 0x80000000000000000000000000000000;\n      uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;\n      uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n      if (xExponent == 0x7FFF && xSignifier != 0) return NaN;\n      else if (xExponent > 16397)\n        return xNegative ? POSITIVE_ZERO : POSITIVE_INFINITY;\n      else if (xExponent < 16255)\n        return 0x3FFF0000000000000000000000000000;\n      else {\n        if (xExponent == 0) xExponent = 1;\n        else xSignifier |= 0x10000000000000000000000000000;\n\n        if (xExponent > 16367)\n          xSignifier <<= xExponent - 16367;\n        else if (xExponent < 16367)\n          xSignifier >>= 16367 - xExponent;\n\n        if (xNegative && xSignifier > 0x406E00000000000000000000000000000000)\n          return POSITIVE_ZERO;\n\n        if (!xNegative && xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\n          return POSITIVE_INFINITY;\n\n        uint256 resultExponent = xSignifier >> 128;\n        xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n        if (xNegative && xSignifier != 0) {\n          xSignifier = ~xSignifier;\n          resultExponent += 1;\n        }\n\n        uint256 resultSignifier = 0x80000000000000000000000000000000;\n        if (xSignifier & 0x80000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128;\n        if (xSignifier & 0x40000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128;\n        if (xSignifier & 0x20000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128;\n        if (xSignifier & 0x10000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10B5586CF9890F6298B92B71842A98363 >> 128;\n        if (xSignifier & 0x8000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1059B0D31585743AE7C548EB68CA417FD >> 128;\n        if (xSignifier & 0x4000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128;\n        if (xSignifier & 0x2000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128;\n        if (xSignifier & 0x1000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128;\n        if (xSignifier & 0x800000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128;\n        if (xSignifier & 0x400000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128;\n        if (xSignifier & 0x200000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100162F3904051FA128BCA9C55C31E5DF >> 128;\n        if (xSignifier & 0x100000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000B175EFFDC76BA38E31671CA939725 >> 128;\n        if (xSignifier & 0x80000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128;\n        if (xSignifier & 0x40000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128;\n        if (xSignifier & 0x20000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000162E525EE054754457D5995292026 >> 128;\n        if (xSignifier & 0x10000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000B17255775C040618BF4A4ADE83FC >> 128;\n        if (xSignifier & 0x8000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128;\n        if (xSignifier & 0x4000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128;\n        if (xSignifier & 0x2000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000162E43F4F831060E02D839A9D16D >> 128;\n        if (xSignifier & 0x1000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000B1721BCFC99D9F890EA06911763 >> 128;\n        if (xSignifier & 0x800000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128;\n        if (xSignifier & 0x400000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128;\n        if (xSignifier & 0x200000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000162E430E5A18F6119E3C02282A5 >> 128;\n        if (xSignifier & 0x100000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000B1721835514B86E6D96EFD1BFE >> 128;\n        if (xSignifier & 0x80000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128;\n        if (xSignifier & 0x40000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000002C5C8601CC6B9E94213C72737A >> 128;\n        if (xSignifier & 0x20000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000162E42FFF037DF38AA2B219F06 >> 128;\n        if (xSignifier & 0x10000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000B17217FBA9C739AA5819F44F9 >> 128;\n        if (xSignifier & 0x8000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128;\n        if (xSignifier & 0x4000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128;\n        if (xSignifier & 0x2000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000162E42FF0999CE3541B9FFFCF >> 128;\n        if (xSignifier & 0x1000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000B17217F80F4EF5AADDA45554 >> 128;\n        if (xSignifier & 0x800000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000058B90BFBF8479BD5A81B51AD >> 128;\n        if (xSignifier & 0x400000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128;\n        if (xSignifier & 0x200000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000162E42FEFB2FED257559BDAA >> 128;\n        if (xSignifier & 0x100000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128;\n        if (xSignifier & 0x80000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128;\n        if (xSignifier & 0x40000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128;\n        if (xSignifier & 0x20000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000162E42FEFA494F1478FDE05 >> 128;\n        if (xSignifier & 0x10000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000B17217F7D20CF927C8E94C >> 128;\n        if (xSignifier & 0x8000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128;\n        if (xSignifier & 0x4000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000002C5C85FDF477B662B26945 >> 128;\n        if (xSignifier & 0x2000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000162E42FEFA3AE53369388C >> 128;\n        if (xSignifier & 0x1000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000B17217F7D1D351A389D40 >> 128;\n        if (xSignifier & 0x800000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128;\n        if (xSignifier & 0x400000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000002C5C85FDF4741BEA6E77E >> 128;\n        if (xSignifier & 0x200000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000162E42FEFA39FE95583C2 >> 128;\n        if (xSignifier & 0x100000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000B17217F7D1CFB72B45E1 >> 128;\n        if (xSignifier & 0x80000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128;\n        if (xSignifier & 0x40000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000002C5C85FDF473E242EA38 >> 128;\n        if (xSignifier & 0x20000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000162E42FEFA39F02B772C >> 128;\n        if (xSignifier & 0x10000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000B17217F7D1CF7D83C1A >> 128;\n        if (xSignifier & 0x8000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128;\n        if (xSignifier & 0x4000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000002C5C85FDF473DEA871F >> 128;\n        if (xSignifier & 0x2000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000162E42FEFA39EF44D91 >> 128;\n        if (xSignifier & 0x1000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000B17217F7D1CF79E949 >> 128;\n        if (xSignifier & 0x800000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000058B90BFBE8E7BCE544 >> 128;\n        if (xSignifier & 0x400000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000002C5C85FDF473DE6ECA >> 128;\n        if (xSignifier & 0x200000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000162E42FEFA39EF366F >> 128;\n        if (xSignifier & 0x100000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000B17217F7D1CF79AFA >> 128;\n        if (xSignifier & 0x80000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000058B90BFBE8E7BCD6D >> 128;\n        if (xSignifier & 0x40000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000002C5C85FDF473DE6B2 >> 128;\n        if (xSignifier & 0x20000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000162E42FEFA39EF358 >> 128;\n        if (xSignifier & 0x10000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000B17217F7D1CF79AB >> 128;\n        if (xSignifier & 0x8000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000058B90BFBE8E7BCD5 >> 128;\n        if (xSignifier & 0x4000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000002C5C85FDF473DE6A >> 128;\n        if (xSignifier & 0x2000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000162E42FEFA39EF34 >> 128;\n        if (xSignifier & 0x1000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000B17217F7D1CF799 >> 128;\n        if (xSignifier & 0x800000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000058B90BFBE8E7BCC >> 128;\n        if (xSignifier & 0x400000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000002C5C85FDF473DE5 >> 128;\n        if (xSignifier & 0x200000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000162E42FEFA39EF2 >> 128;\n        if (xSignifier & 0x100000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000B17217F7D1CF78 >> 128;\n        if (xSignifier & 0x80000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000058B90BFBE8E7BB >> 128;\n        if (xSignifier & 0x40000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000002C5C85FDF473DD >> 128;\n        if (xSignifier & 0x20000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000162E42FEFA39EE >> 128;\n        if (xSignifier & 0x10000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000B17217F7D1CF6 >> 128;\n        if (xSignifier & 0x8000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000058B90BFBE8E7A >> 128;\n        if (xSignifier & 0x4000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000002C5C85FDF473C >> 128;\n        if (xSignifier & 0x2000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000162E42FEFA39D >> 128;\n        if (xSignifier & 0x1000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000B17217F7D1CE >> 128;\n        if (xSignifier & 0x800000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000058B90BFBE8E6 >> 128;\n        if (xSignifier & 0x400000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000002C5C85FDF472 >> 128;\n        if (xSignifier & 0x200000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000162E42FEFA38 >> 128;\n        if (xSignifier & 0x100000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000B17217F7D1B >> 128;\n        if (xSignifier & 0x80000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000058B90BFBE8D >> 128;\n        if (xSignifier & 0x40000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000002C5C85FDF46 >> 128;\n        if (xSignifier & 0x20000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000162E42FEFA2 >> 128;\n        if (xSignifier & 0x10000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000B17217F7D0 >> 128;\n        if (xSignifier & 0x8000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000058B90BFBE7 >> 128;\n        if (xSignifier & 0x4000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000002C5C85FDF3 >> 128;\n        if (xSignifier & 0x2000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000162E42FEF9 >> 128;\n        if (xSignifier & 0x1000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000B17217F7C >> 128;\n        if (xSignifier & 0x800000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000058B90BFBD >> 128;\n        if (xSignifier & 0x400000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000002C5C85FDE >> 128;\n        if (xSignifier & 0x200000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000162E42FEE >> 128;\n        if (xSignifier & 0x100000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000B17217F6 >> 128;\n        if (xSignifier & 0x80000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000058B90BFA >> 128;\n        if (xSignifier & 0x40000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000002C5C85FC >> 128;\n        if (xSignifier & 0x20000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000162E42FD >> 128;\n        if (xSignifier & 0x10000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000B17217E >> 128;\n        if (xSignifier & 0x8000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000058B90BE >> 128;\n        if (xSignifier & 0x4000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000002C5C85E >> 128;\n        if (xSignifier & 0x2000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000162E42E >> 128;\n        if (xSignifier & 0x1000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000B17216 >> 128;\n        if (xSignifier & 0x800000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000058B90A >> 128;\n        if (xSignifier & 0x400000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000002C5C84 >> 128;\n        if (xSignifier & 0x200000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000162E41 >> 128;\n        if (xSignifier & 0x100000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000B1720 >> 128;\n        if (xSignifier & 0x80000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000058B8F >> 128;\n        if (xSignifier & 0x40000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000002C5C7 >> 128;\n        if (xSignifier & 0x20000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000162E3 >> 128;\n        if (xSignifier & 0x10000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000B171 >> 128;\n        if (xSignifier & 0x8000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000058B8 >> 128;\n        if (xSignifier & 0x4000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000002C5B >> 128;\n        if (xSignifier & 0x2000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000162D >> 128;\n        if (xSignifier & 0x1000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000B16 >> 128;\n        if (xSignifier & 0x800 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000058A >> 128;\n        if (xSignifier & 0x400 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000002C4 >> 128;\n        if (xSignifier & 0x200 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000161 >> 128;\n        if (xSignifier & 0x100 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000000B0 >> 128;\n        if (xSignifier & 0x80 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000057 >> 128;\n        if (xSignifier & 0x40 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000002B >> 128;\n        if (xSignifier & 0x20 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000015 >> 128;\n        if (xSignifier & 0x10 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000000A >> 128;\n        if (xSignifier & 0x8 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000004 >> 128;\n        if (xSignifier & 0x4 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000001 >> 128;\n\n        if (!xNegative) {\n          resultSignifier = resultSignifier >> 15 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n          resultExponent += 0x3FFF;\n        } else if (resultExponent <= 0x3FFE) {\n          resultSignifier = resultSignifier >> 15 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n          resultExponent = 0x3FFF - resultExponent;\n        } else {\n          resultSignifier = resultSignifier >> resultExponent - 16367;\n          resultExponent = 0;\n        }\n\n        return bytes16 (uint128 (resultExponent << 112 | resultSignifier));\n      }\n    }\n  }\n\n  /**\n   * Calculate e^x.\n   *\n   * @param x quadruple precision number\n   * @return quadruple precision number\n   */\n  function exp (bytes16 x) internal pure returns (bytes16) {\n    unchecked {\n      return pow_2 (mul (x, 0x3FFF71547652B82FE1777D0FFDA0D23A));\n    }\n  }\n\n  /**\n   * Get index of the most significant non-zero bit in binary representation of\n   * x.  Reverts if x is zero.\n   *\n   * @return index of the most significant non-zero bit in binary representation\n   *         of x\n   */\n  function mostSignificantBit (uint256 x) private pure returns (uint256) {\n    unchecked {\n      require (x > 0);\n\n      uint256 result = 0;\n\n      if (x >= 0x100000000000000000000000000000000) { x >>= 128; result += 128; }\n      if (x >= 0x10000000000000000) { x >>= 64; result += 64; }\n      if (x >= 0x100000000) { x >>= 32; result += 32; }\n      if (x >= 0x10000) { x >>= 16; result += 16; }\n      if (x >= 0x100) { x >>= 8; result += 8; }\n      if (x >= 0x10) { x >>= 4; result += 4; }\n      if (x >= 0x4) { x >>= 2; result += 2; }\n      if (x >= 0x2) result += 1; // No need to shift x anymore\n\n      return result;\n    }\n  }\n}\n"
      },
      "contracts/interfaces/IERC20Burnable.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IERC20Burnable {\n    function burn(uint256 amount) external returns(bool success);\n}\n"
      },
      "contracts/interfaces/IPresale.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IPresale {\n    function endTime() external view returns (uint64);\n    function owner() external view returns (address);\n}\n"
      },
      "contracts/interfaces/ISalesStructs.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ISalesStructs {\n    enum EnumWithdraw {\n        never,\n        afterEndTime,\n        anytime\n    }\n\n    struct CommonSettings {\n        address sellingToken;\n        address token0;\n        address token1;\n        address liquidityLib;\n        uint64 endTime;\n        uint64 compensationEndTime;\n    }\n    \n    struct PriceSettings {\n        uint64 timestamp;\n        uint256 price;\n        uint256 amountRaised;\n    }\n\n    struct ThresholdBonuses {\n        uint256 threshold;\n        uint256 bonus;\n    }\n\n    struct LockedInPrice {\n        uint256 minimumLockedInAmount;\n        uint256 maximumLockedInAmount;\n    }\n\n}"
      },
      "contracts/interfaces/ISalesToken.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./ISalesStructs.sol\";\nimport \"@intercoin/whitelist/contracts/interfaces/IWhitelist.sol\";\n\ninterface ISalesToken is ISalesStructs {\n    /**\n     * @param _payToken address of token's pay\n     * @param _commonSettings CommonSettings data struct\n     *  address sellingToken address of ITR token\n     *  address token0 USD Coin\n     *  address token1 Wrapped token (WETH,WBNB,...)\n     *  address liquidityLib liquidityLib address(see intercoin/liquidity pkg)\n     *  address endTime after this time exchange stop\n     *  address compensationEndTime after this time receiving compensation tokens will be disabled\n     * @param _priceSettings PriceSettings struct's array\n     *  uint64 timestamp timestamp\n     *  uint256 price price exchange\n     *  uint256 amountRaised raised amount\n     * @param _bonusSettings ThresholdBonuses struct's array\n     *  uint256 threshold thresholds\n     *  uint256 bonus bonuses\n     * @param _ownerCanWithdraw enum option where:\n     *  0 -owner can not withdraw tokens\n     *  1 -owner can withdraw tokens only after endTimePassed\n     *  2 -owner can withdraw tokens anytime\n     * @param _whitelistData whitelist data struct\n     *  address contractAddress;\n\t *\tbytes4 method;\n\t *\tuint8 role;\n     *  bool useWhitelist;\n     * @param _lockedInPrice lockedInPrice struct\n     *  uint256 minimumLockedInAmount Minimum amount required to buy and hold the price.\n     *  uint256 maximumLockedInAmount Maximum amount available to buy at the held price.\n     * @param _costManager costmanager address\n     */\n     function init(\n        address _payToken,\n        CommonSettings memory _commonSettings,\n        PriceSettings[] memory _priceSettings,\n        ThresholdBonuses[] memory _bonusSettings,\n        EnumWithdraw _ownerCanWithdraw,\n        IWhitelist.WhitelistStruct memory _whitelistData,\n        LockedInPrice memory _lockedInPrice,\n        address _costManager,\n        address _producedBy\n    ) external;\n\n    function owner() external view returns (address);   \n}\n"
      },
      "contracts/SalesBase.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC777/ERC777Upgradeable.sol\"; // interface does not contain transfer method needed for erc20 compatible\nimport \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@intercoin/releasemanager/contracts/CostManagerHelperERC2771Support.sol\";\nimport \"@intercoin/whitelist/contracts/Whitelist.sol\";\nimport \"./interfaces/IPresale.sol\";\nimport \"./interfaces/ISalesStructs.sol\";\nimport \"./interfaces/IERC20Burnable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/introspection/IERC1820RegistryUpgradeable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC777/IERC777RecipientUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC777/IERC777SenderUpgradeable.sol\";\n\nimport \"@intercoin/liquidity/contracts/interfaces/ILiquidityLib.sol\";\nimport \"@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol\";\nimport \"@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol\";\nimport \"abdk-libraries-solidity/ABDKMathQuad.sol\";\n\nabstract contract SalesBase is OwnableUpgradeable, CostManagerHelperERC2771Support, ReentrancyGuardUpgradeable, Whitelist, IPresale, ISalesStructs, IERC777RecipientUpgradeable, IERC777SenderUpgradeable {\n    using ABDKMathQuad for *;\n\n    address public sellingToken;\n    uint64[] public timestamps;\n    uint256[] public prices;\n    uint256[] public amountRaised;\n\n    uint256[] public commissionFractions;\n    address[] public commissionAddresses;\n    uint256 public holdTotalFraction;\n\n    /// total income tokens\n    uint256 public totalIncome;\n\n    /// total income tokens payed by sendCommission\n    uint256 public holdTotalAlreadyPayed;\n    /// total income tokens payed by claim\n    uint256 public totalIncomeAlreadyClaimed;\n\n    uint64 public _endTime;\n    uint64 public _compensationEndTime;\n\n    uint256 public totalAmountRaised;\n    \n    // true if token0 == uniswapPair.token0()\n    bool internal token00; \n    address uniswapV2Pair;\n    \n    uint256 internal constant maxGasPrice = 1*10**18; \n\n    uint256 internal constant priceDenom = 100000000;//1*10**8;\n\n    uint256 internal constant FRACTION = 10000;\n\n    uint8 internal constant OPERATION_SHIFT_BITS = 240;  // 256 - 16\n    // Constants representing operations\n    uint8 internal constant OPERATION_INITIALIZE = 0x0;\n    uint8 internal constant OPERATION_BUY = 0x1;\n    uint8 internal constant OPERATION_WITHDRAW = 0x1;\n    uint8 internal constant OPERATION_WITHDRAW_ALL = 0x2;\n    uint8 internal constant OPERATION_CLAIM = 0x3;\n    uint8 internal constant OPERATION_CLAIM_ALL = 0x4;\n    uint8 internal constant OPERATION_SETGROUP = 0x5;\n    uint8 internal constant OPERATION_SET_TRUSTED_FORWARDER = 0x6;\n    uint8 internal constant OPERATION_TRANSFER_OWNERSHIP = 0x7;\n\n    IERC1820RegistryUpgradeable internal constant _ERC1820_REGISTRY = IERC1820RegistryUpgradeable(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);\n    bytes32 private constant _TOKENS_SENDER_INTERFACE_HASH = keccak256(\"ERC777TokensSender\");\n    bytes32 private constant _TOKENS_RECIPIENT_INTERFACE_HASH = keccak256(\"ERC777TokensRecipient\");\n\n    struct Participant {\n        string groupName;\n        uint256 totalAmount;\n        uint256 contributed;\n        bool exists;\n    }\n    \n    struct Group {\n        string name;\n        uint256 totalAmount;\n        address[] participants;\n        bool exists;\n    }\n\n    uint256 minimumLockedInAmount;\n    uint256 maximumLockedInAmount;\n    struct LockedPrice {\n        uint256 price;\n        uint256 boughtAmount; // bought by locked price\n        uint256 totalAmount; // total bought even if not in locked \n        bool exists;\n    }\n    mapping(address => LockedPrice) lockedPrice;\n    \n    mapping(string => Group) groups;\n    mapping(address => Participant) participants;\n    mapping(address => uint256) totalInvestedGroupOutside;\n    \n    uint256[] thresholds; // count in ETH\n    uint256[] bonuses;// percents mul by 100\n\n    struct Compensation{\n        uint256 nextCounter;\n        uint256[] sent;\n        bytes16 [] price; // ABDKMathQuad value\n        uint256 claimedCounter;\n    }\n    mapping(address => Compensation) compensations;\n\n    EnumWithdraw public withdrawOption;\n\n    event Exchange(address indexed account, uint256 amountIn, uint256 amountOut);\n    event GroupBonusAdded(string indexed groupName, uint256 ethAmount, uint256 tokenPrice);\n    event Claimed(uint256 amount, address addr);\n    event Withdrawn(uint256 amount, address addr);\n    event CommissionsWasSent(uint256 amount, address[] addrs);\n\n    error ForwarderCanNotBeOwner();\n    error DeniedForForwarder();\n    error NotSupported();\n    error WithdrawDisabled();\n    error WhitelistError();\n    error InvalidInput();\n    error AddressInvalid();\n    error GroupNameInvalid();\n    error InsufficientAmount();\n    error TransferError();\n    error MaxGasPriceExceeded();\n    error ExchangeTimeIsOver();\n    error ExchangeTimeShouldBePassed();\n    error CompensationTimeShouldBePassed();\n    error CompensationTimeExpired();\n    error CompensationNotFound();\n    error CantCalculateAmountOfTokens();\n\n    modifier validGasPrice() {\n        //require(tx.gasprice <= maxGasPrice, \"Transaction gas price cannot exceed maximum gas price.\");\n        if (tx.gasprice > maxGasPrice) {\n            revert MaxGasPriceExceeded();\n        }\n        _;\n    } \n\n    modifier validateWithdraw() {\n        _checkOwner();\n        if (\n            (withdrawOption == EnumWithdraw.never) ||\n            (withdrawOption == EnumWithdraw.afterEndTime && block.timestamp <= _endTime)\n        ) {\n            revert WithdrawDisabled();\n        }\n\n        // (withdrawOption == EnumWithdraw.anytime)\n\n        _;\n    }\n\n    function __SalesBase__init(\n        CommonSettings memory _commonSettings,\n        PriceSettings[] memory _priceSettings,\n        ThresholdBonuses[] memory _bonusSettings,\n        EnumWithdraw _ownerCanWithdraw,\n        WhitelistStruct memory _whitelistData,\n        LockedInPrice memory _lockedInPrice,\n        address _costManager\n    ) \n        internal \n        onlyInitializing\n    {\n        \n        __CostManagerHelper_init(_msgSender(), _costManager);\n\n        __Ownable_init();\n        __ReentrancyGuard_init();\n        \n        if (_commonSettings.sellingToken == address(0)) {\n            revert InvalidInput();\n        }\n        \n        sellingToken = _commonSettings.sellingToken;\n\n        // setup swap addresses\n        address uniswapRouterFactory;\n        (, uniswapRouterFactory) = ILiquidityLib(_commonSettings.liquidityLib).uniswapSettings();\n        uniswapV2Pair = IUniswapV2Factory(uniswapRouterFactory).getPair(_commonSettings.token0, _commonSettings.token1);\n\n        if (_commonSettings.token0 == IUniswapV2Pair(uniswapV2Pair).token0()) {\n            token00 = true;\n        } else {\n            token00 = false;\n        }\n\n        timestamps = new uint64[](_priceSettings.length);\n        prices = new uint256[](_priceSettings.length);\n        amountRaised = new uint256[](_priceSettings.length);\n        for (uint256 i = 0; i<_priceSettings.length; i++) {\n            timestamps[i] = _priceSettings[i].timestamp;\n            prices[i] = _priceSettings[i].price;\n            amountRaised[i] = _priceSettings[i].amountRaised;\n        }\n        // timestamps = _timestamps;\n        // prices = _prices;\n        // amountRaised = _amountRaised;\n        _endTime = _commonSettings.endTime;\n        _compensationEndTime = _commonSettings.compensationEndTime;\n\n        thresholds = new uint256[](_bonusSettings.length);\n        bonuses = new uint256[](_bonusSettings.length);\n        for (uint256 i = 0; i < _bonusSettings.length; i++) {\n            thresholds[i] = _bonusSettings[i].threshold;\n            bonuses[i] = _bonusSettings[i].bonus;\n        }\n        // thresholds = _thresholds;\n        // bonuses = _bonuses;\n        \n        withdrawOption = _ownerCanWithdraw;\n\n        whitelistInit(_whitelistData);\n\n        minimumLockedInAmount = _lockedInPrice.minimumLockedInAmount;\n        maximumLockedInAmount = _lockedInPrice.maximumLockedInAmount;\n\n        // register interfaces\n        _ERC1820_REGISTRY.setInterfaceImplementer(address(this), _TOKENS_SENDER_INTERFACE_HASH, address(this));\n        _ERC1820_REGISTRY.setInterfaceImplementer(address(this), _TOKENS_RECIPIENT_INTERFACE_HASH, address(this));\n    }\n\n    function tokensToSend(\n        address operator,\n        address from,\n        address to,\n        uint256 amount,\n        bytes calldata userData,\n        bytes calldata operatorData\n    ) external {\n        \n    }\n\n    function tokensReceived(\n        address operator,\n        address from,\n        address to,\n        uint256 amount,\n        bytes calldata userData,\n        bytes calldata operatorData\n    ) external {\n        \n    }\n    \n    /**\n     * data which contract was initialized\n     */\n    function getConfig(\n    ) \n        public \n        view \n        returns ( \n            address _sellingToken, \n            uint64[] memory _timestamps,\n            uint256[] memory _prices,\n            uint256[] memory _amountRaised, \n            uint64 _endTs,\n            uint256[] memory _thresholds,\n            uint256[] memory _bonuses\n        ) \n    {\n        _sellingToken = sellingToken;\n        _timestamps = timestamps;\n        _prices = prices;\n        _amountRaised = amountRaised;\n        _endTs = _endTime;\n        _thresholds = thresholds;\n        _bonuses = bonuses;\n    }\n\n    function endTime() external view returns (uint64) {\n        return _endTime;\n    }\n\n    function addCommission(uint256 fraction, address account) public onlyOwner {\n        if (fraction == 0 || fraction > FRACTION || account == address(0)) {\n            revert InvalidInput();\n        }\n        commissionFractions.push(fraction);\n        commissionAddresses.push(account);\n\n        holdTotalFraction += fraction;\n    }\n\n    function _exchange(uint256 inputAmount) internal virtual returns(uint256) {\n        address sender = _msgSender();\n\n        if (!whitelisted(sender)) { \n            revert WhitelistError(); \n        }\n\n        if (_endTime <= block.timestamp) {\n            revert ExchangeTimeIsOver();\n        }\n    \n        // uint256 tokenPrice = getTokenPrice();\n        // uint256 amount2send = _getTokenAmount(inputAmount, tokenPrice);\n\n        uint256 totalAmount2Send;\n        uint256[2] memory inputAmounts;\n        uint256[2] memory tokenPrices;\n        uint256[2] memory tokens2Send;\n\n        (totalAmount2Send, inputAmounts, tokenPrices, tokens2Send) = getTokenAmount(sender, inputAmount);\n\n        if (totalAmount2Send == 0) {\n            revert CantCalculateAmountOfTokens();\n        }\n\n        totalIncome += inputAmount;\n        totalAmountRaised += totalAmount2Send;\n\n        uint256 tokenBalance = IERC777Upgradeable(sellingToken).balanceOf(address(this));\n        if (tokenBalance < totalAmount2Send) {\n            revert InsufficientAmount();\n        }\n\n        bool success = ERC777Upgradeable(sellingToken).transfer(sender, totalAmount2Send);\n        if (!success) {\n            revert TransferError();\n        }\n        \n        emit Exchange(sender, inputAmount, totalAmount2Send);\n\n        // bonus calculation\n        // _addBonus(\n        //     sender, \n        //     inputAmount,\n        //     tokenPrice,\n        //     true\n        // );\n\n        //compensations\n        Compensation storage compensationData = compensations[sender];\n        compensationData.nextCounter +=1;\n        compensationData.sent.push(totalAmount2Send);\n        compensationData.price.push(getPrice());\n        //----------\n\n        if (inputAmounts[1] != 0 && tokenPrices[1] != 0) {\n            if (!lockedPrice[sender].exists) {\n                lockedPrice[sender].exists = true;\n\n                lockedPrice[sender].price = tokenPrices[1];\n            }\n            lockedPrice[sender].boughtAmount += tokens2Send[1];\n            \n            // we can't exceed maximumLockedInAmount. we calculated it in getTokenAmount\n        }\n        lockedPrice[sender].totalAmount += totalAmount2Send;\n\n        for(uint256 i = 0; i < inputAmounts.length;  i++) {\n            if (inputAmounts[i] != 0 && tokenPrices[i] != 0) {\n                _addBonus(\n                    sender, \n                    inputAmounts[i],\n                    tokenPrices[i],\n                    true\n                );\n            }\n        }\n\n        return totalAmount2Send;\n    }\n\n    function compensation() public {\n        \n        if (_endTime > block.timestamp) {\n            revert CompensationTimeShouldBePassed();\n        }\n        if (_compensationEndTime < block.timestamp) {\n            revert CompensationTimeExpired();        \n        }\n\n        address sender = msg.sender;\n        Compensation storage compensationData = compensations[sender];\n\n        if (compensationData.nextCounter <= compensationData.claimedCounter) {\n            revert CompensationNotFound();\n        }\n\n\n        bytes16 currentPrice = getPrice(); // ABDKMathQuad memory\n        uint256 compensationAmount = 0;\n        for(uint256 i = compensationData.claimedCounter; i < compensationData.nextCounter; ++i) {\n            // compensate =  [was sent] / ([oldPrice]/[newPrice]), where newPrice > oldPrice\n\n            if (ABDKMathQuad.toUInt(compensationData.price[i]) < ABDKMathQuad.toUInt(currentPrice)) {\n\n                compensationAmount += (\n                    ABDKMathQuad.toUInt(\n                        ABDKMathQuad.div(\n                            ABDKMathQuad.fromUInt(compensationData.sent[i]), // not more than 1e15 tokens\n                            ABDKMathQuad.div(\n                                compensationData.price[i],\n                                currentPrice\n                            )\n                        )\n                    )\n                );\n            }\n        }\n\n        compensationData.claimedCounter = compensationData.nextCounter;\n\n        if (compensationAmount > 0) {\n            bool success = ERC777Upgradeable(sellingToken).transfer(sender, compensationAmount);\n            if (!success) {\n                revert TransferError();\n            }\n        }\n\n    }\n    \n    /**\n     * withdraw some tokens to address\n     * @param amount amount of tokens\n     * @param addr address to send\n     */\n    function withdraw(uint256 amount, address addr) public validateWithdraw {\n        _sendTokens(amount, addr, true);\n\n        emit Withdrawn(amount, addr);\n        _accountForOperation(\n            OPERATION_WITHDRAW << OPERATION_SHIFT_BITS,\n            uint256(uint160(addr)),\n            amount\n        );\n    }\n    \n    /**\n     * withdraw all tokens to owner\n     */\n    function withdrawAll() public validateWithdraw {\n        uint256 amount = IERC777Upgradeable(sellingToken).balanceOf(address(this));\n\n        emit Withdrawn(amount, _msgSender());\n        _sendTokens(amount, _msgSender(), true);\n\n        _accountForOperation(\n            OPERATION_WITHDRAW_ALL << OPERATION_SHIFT_BITS,\n            uint256(uint160(_msgSender())),\n            amount\n        );\n    }\n\n    /**\n     * @notice adding account into a internal whitelist.  worked only if instance initialized with internal whitelist\n     */\n    function whitelistAdd(address account) public onlyOwner {\n        _validateWhitelistForInternalUse();\n        _whitelistAdd(account);\n    }\n\n    /**\n     * @notice removing account from a internal whitelist.  worked only if instance initialized with internal whitelist\n     */\n    function whitelistRemove(address account) public onlyOwner {\n        _validateWhitelistForInternalUse();\n        _whitelistRemove(account);\n    }\n    \n    /**\n     * @param amount amount of eth\n     * @param addr address to send\n     */\n    function claim(uint256 amount, address addr) public onlyOwner {\n        uint256 amountAvailableToClaim = availableToClaim();\n        if (amountAvailableToClaim < amount) {\n            revert InsufficientAmount();\n        }\n        totalIncomeAlreadyClaimed += amount;\n\n        _claim(amount, addr);\n        emit Claimed(amount, addr);\n        _accountForOperation(\n            OPERATION_CLAIM << OPERATION_SHIFT_BITS,\n            uint256(uint160(addr)),\n            amount\n        );\n    }\n\n    /**\n     * @notice send commission to the addresses `commissionAddresses`\n     */\n    function sendCommissions() public nonReentrant {\n        if (_endTime >= block.timestamp) {\n            revert ExchangeTimeShouldBePassed();\n        }\n\n        uint256 totalIncomeLeftToPaid = totalIncome - holdTotalAlreadyPayed;\n        holdTotalAlreadyPayed += totalIncome;\n\n        uint256 amount2send = (totalIncomeLeftToPaid*holdTotalFraction/FRACTION);\n\n        if (amount2send == 0) {\n            revert InsufficientAmount();\n        }\n        \n        for (uint256 i = 0; i<commissionAddresses.length; i++) {\n            _claim(\n                totalIncomeLeftToPaid * commissionFractions[i] / FRACTION, \n                commissionAddresses[i]\n            );\n        }\n\n        emit CommissionsWasSent(amount2send, commissionAddresses);\n    }\n    \n    /**\n     * @param addresses array of addresses which need to link with group\n     * @param groupName group name. if does not exists it will be created\n     */\n    function setGroup(address[] memory addresses, string memory groupName) public onlyOwner {\n        for (uint256 i = 0; i < addresses.length; i++) {\n            _setGroup(addresses[i], groupName);\n        }\n        \n        _accountForOperation(\n            OPERATION_SETGROUP << OPERATION_SHIFT_BITS,\n            0,\n            0\n        );\n    }\n    \n    /**\n     * claim all eth to owner(sender)\n     */\n    function claimAll() public onlyOwner {\n        uint256 amount = availableToClaim();\n        totalIncomeAlreadyClaimed += amount;\n        _claim(amount, _msgSender());\n        emit Claimed(amount, _msgSender());\n\n        _accountForOperation(\n            OPERATION_CLAIM_ALL << OPERATION_SHIFT_BITS,\n            uint256(uint160(_msgSender())),\n            amount\n        );\n    }\n\n    /**\n     * burn all unsold tokens. used only if initialised with (withdrawOption == EnumWithdraw.never)\n     */\n    function burnAllUnsoldTokens() public {\n        if (withdrawOption != EnumWithdraw.never) {\n            revert NotSupported();\n        }\n        if (_endTime >= block.timestamp) {\n            revert ExchangeTimeShouldBePassed();\n        }\n        \n        uint256 tokenBalance = IERC777Upgradeable(sellingToken).balanceOf(address(this));\n        if (tokenBalance > 0) {\n\n             // create a low level call to the token\n            (bool lowLevelSuccess, bytes memory returnData) =\n                address(sellingToken).call(\n                    abi.encodePacked(\n                        IERC20Burnable.burn.selector,\n                        abi.encode(tokenBalance)\n                    )\n                );\n            bool returnedBool;\n            if (lowLevelSuccess) { // transferFrom completed successfully (did not revert)\n                (returnedBool) = abi.decode(returnData, (bool));\n            }\n            if (!returnedBool) {\n                revert TransferError();\n            }\n        }\n    }\n\n    function continueSale(\n        uint64[] memory _timestamps,\n        uint256[] memory _prices,\n        uint256[] memory _amountRaised,\n        uint64 _endTs\n    ) \n        public \n        onlyOwner \n    {\n        if (withdrawOption != EnumWithdraw.never) {\n            revert NotSupported();\n        }\n\n        if (_endTs <= block.timestamp || _endTs <= _endTime) {\n            revert ExchangeTimeShouldBePassed();\n        }\n        \n        for(uint256 i = 0; i < _timestamps.length; i++) {\n            if (_timestamps[i] < _endTime) {\n                revert InvalidInput();\n            }\n        }\n        timestamps = _timestamps;\n        prices = _prices;\n        amountRaised = _amountRaised;\n        _endTime = _endTs;\n\n    }\n    \n    /**\n     * get exchange rate ETH -> sellingToken\n     */\n    function getTokenPrice() public view returns (uint256 price) {\n        uint256 raised = amountRaised[0];\n        uint256 ts = timestamps[0];\n        price = prices[0];\n        for (uint256 i = 0; i < timestamps.length; i++) {\n            if (block.timestamp >= timestamps[i] && timestamps[i] >= ts) {\n                ts = timestamps[i];\n                price = prices[i];\n            }\n\n            if (totalAmountRaised >= amountRaised[i] && amountRaised[i] >= raised) {\n                raised = amountRaised[i];\n                price = prices[i];\n            }\n\n        }\n        \n    }\n\n    function getPrice() internal view virtual returns(bytes16 price_) {\n        uint112 reserve0;\n        uint112 reserve1;\n        \n        (reserve0, reserve1, ) = IUniswapV2Pair(uniswapV2Pair).getReserves();\n        if (reserve0 == 0 || reserve1 == 0) {\n            // Exclude case when reserves are empty\n        } else {\n            \n            if (token00) {\n                //price_ = FixedPoint.fraction(reserve0,reserve1);\n                price_ = ABDKMathQuad.div(\n                    ABDKMathQuad.fromUInt(reserve0),\n                    ABDKMathQuad.fromUInt(reserve1)\n                );\n            } else {\n                //price_ = FixedPoint.fraction(reserve1,reserve0);\n                price_ = ABDKMathQuad.div(\n                    ABDKMathQuad.fromUInt(reserve1),\n                    ABDKMathQuad.fromUInt(reserve0)\n                );\n            }\n        \n        }\n\n    }\n    \n    \n/*\n    struct LockedPrice {\n        uint256 price;\n        uint256 boughtAmount;\n        bool exists;\n    }\n    mapping(address => LockedPrice) lockedPrice;\n*/\n\n        // uint256 totalAmount2Send;\n        // uint256[2] inputAmounts;\n        // uint256[2] tokenPrices;\n                // uint256 tokenPrice = getTokenPrice();\n        // uint256 amount2send = _getTokenAmount(inputAmount, tokenPrice);\n\n//(totalAmount2Send, inputAmounts, tokenPrices) = \n    function getTokenAmount(\n        address sender,\n        uint256 inputAmount\n    ) internal view returns (\n        uint256 totalAmount2Send,\n        uint256[2] memory inputAmounts,\n        uint256[2] memory tokenPrices,\n        uint256[2] memory tokens2Send\n    ) {\n        // 0 - main\n        // 1 - lockedprice\n        uint256 defaultTokenPrice = getTokenPrice();\n        uint256 defaultAmount2send = _getTokenAmount(inputAmount, defaultTokenPrice);\n\n        \n        if (\n            minimumLockedInAmount == 0 || \n            maximumLockedInAmount == 0 ||\n            lockedPrice[sender].totalAmount > maximumLockedInAmount\n        ) {\n            // \"minimum locked in price\" are off\n\n            totalAmount2Send = defaultAmount2send;\n            tokens2Send[0] = defaultAmount2send;\n            inputAmounts[0] = inputAmount;\n            tokenPrices[0] = defaultTokenPrice;\n        } else {\n            // \"minimum locked in price\" are on\n\n            //need to calculate how much user should get by usual price and how much by special\n            uint256 leftByLockedPrice;\n\n            if (lockedPrice[sender].exists) {\n                    leftByLockedPrice = maximumLockedInAmount - lockedPrice[sender].boughtAmount;\n            } else {\n                if (\n                    //    -----++.+++----------------\n                    (lockedPrice[sender].totalAmount + defaultAmount2send) > minimumLockedInAmount &&\n                    (lockedPrice[sender].totalAmount + defaultAmount2send) < maximumLockedInAmount\n                ) {\n                    leftByLockedPrice = (lockedPrice[sender].totalAmount + defaultAmount2send) - minimumLockedInAmount  - lockedPrice[sender].boughtAmount;\n                } else if (\n                    //    -----+++++---.-------------\n                    (lockedPrice[sender].totalAmount + defaultAmount2send) > maximumLockedInAmount\n                ) {\n                    leftByLockedPrice = maximumLockedInAmount - minimumLockedInAmount  - lockedPrice[sender].boughtAmount;\n                }\n            }\n\n            if (leftByLockedPrice > 0) { // then available to get tokens with locked price\n                //try to calcualte how much available with current price\n                uint256 currentLockedPrice;\n                if (lockedPrice[sender].exists) {\n                    currentLockedPrice = lockedPrice[sender].price;\n\n                } else {\n                    currentLockedPrice = defaultTokenPrice;\n                }\n\n                if (lockedPrice[sender].exists) {\n\n                    // buy as possible\n                    uint256 howMuchUselWillBuyByLockedPrice = _getTokenAmount(inputAmount, currentLockedPrice);\n\n                    if (maximumLockedInAmount < lockedPrice[sender].boughtAmount + howMuchUselWillBuyByLockedPrice) {\n                        tokens2Send[1] = maximumLockedInAmount-lockedPrice[sender].boughtAmount;\n                        inputAmounts[1] = _getInputAmount(tokens2Send[1], currentLockedPrice);\n                        tokenPrices[1] = currentLockedPrice;\n\n                        inputAmounts[0] = inputAmount - inputAmounts[1];\n                        tokens2Send[0] = _getTokenAmount(inputAmounts[0], defaultTokenPrice);\n                        tokenPrices[0] = defaultTokenPrice;\n                    } else {\n                        tokens2Send[1] = howMuchUselWillBuyByLockedPrice;\n                        inputAmounts[1] = inputAmount;\n                        tokenPrices[1] = leftByLockedPrice;\n\n                        tokens2Send[0] = 0;\n                        inputAmounts[0] = 0;\n                        tokenPrices[0] = 0;\n                    }\n                } else {\n                    tokens2Send[1] = leftByLockedPrice;\n                    inputAmounts[1] = _getInputAmount(leftByLockedPrice, currentLockedPrice);\n                    tokenPrices[1] = currentLockedPrice;\n                    \n                    inputAmounts[0] = inputAmount - inputAmounts[1];\n                    tokenPrices[0] = defaultTokenPrice;\n                    tokens2Send[0] = _getTokenAmount(inputAmounts[0], defaultTokenPrice);\n                }\n\n                totalAmount2Send = tokens2Send[0] + tokens2Send[1];\n            } else {\n                tokens2Send[0] = defaultAmount2send;\n                inputAmounts[0] = inputAmount;\n                tokenPrices[0] = defaultTokenPrice;\n                totalAmount2Send = tokens2Send[0] + tokens2Send[1];\n            }\n        }\n    }\n    \n    /**\n     * @param groupName group name\n     */\n    function getGroupBonus(string memory groupName) public view returns(uint256 bonus) {\n        return _getGroupBonus(groupName);\n    }\n    \n    function setTrustedForwarder(\n        address forwarder\n    ) \n        public \n        virtual\n        override\n        onlyOwner \n    {\n        if (owner() == forwarder) {\n            revert ForwarderCanNotBeOwner();\n        }\n        _setTrustedForwarder(forwarder);\n\n        _accountForOperation(\n            OPERATION_SET_TRUSTED_FORWARDER << OPERATION_SHIFT_BITS,\n            uint256(uint160(_msgSender())),\n            uint256(uint160(forwarder))\n        );\n    }\n\n    function transferOwnership(\n        address newOwner\n    ) public \n        virtual \n        override \n        onlyOwner \n    {\n        if (_isTrustedForwarder(msg.sender)) {\n            revert DeniedForForwarder();\n        }\n        if (_isTrustedForwarder(newOwner)) {\n            _setTrustedForwarder(address(0));\n        }\n        super.transferOwnership(newOwner);\n        _accountForOperation(\n            OPERATION_TRANSFER_OWNERSHIP << OPERATION_SHIFT_BITS,\n            uint256(uint160(_msgSender())),\n            uint256(uint160(newOwner))\n        );\n    }\n    \n    function owner(\n    ) \n        public \n        view \n        virtual\n        override(IPresale,OwnableUpgradeable)\n        returns (address) \n    {\n        return super.owner();\n    }\n\n\n    function availableToClaim() internal view returns(uint256) {\n        return (totalIncome - totalIncome*holdTotalFraction/FRACTION) - totalIncomeAlreadyClaimed;\n    }\n    \n    function _msgSender(\n    ) \n        internal \n        view \n        virtual\n        override(TrustedForwarder, ContextUpgradeable)\n        returns (address signer) \n    {\n        return TrustedForwarder._msgSender();\n    }\n\n    function _getGroupBonus(string memory groupName) internal view returns(uint256 bonus) {\n        bonus = 0;\n        \n        if (groups[groupName].exists == true) {\n            uint256 groupTotalAmount = groups[groupName].totalAmount;\n            uint256 tmp = 0;\n            for (uint256 i = 0; i < thresholds.length; i++) {\n                if (groupTotalAmount >= thresholds[i] && thresholds[i] >= tmp) {\n                    tmp = thresholds[i];\n                    bonus = bonuses[i];\n                }\n            }\n        }\n    }\n    /**\n     * calculate token's amount\n     * @param inputAmount amount in eth that should be converted in tokenAmount\n     * @param price token price\n     */\n    function _getTokenAmount(uint256 inputAmount, uint256 price) internal pure returns (uint256) {\n        return inputAmount * priceDenom / price;\n    }\n    \n    /**\n     * calculate eth's amount\n     * @param tokenAmount amount in token that should be converted in tokenAmount\n     * @param price token price\n     */\n    function _getInputAmount(uint256 tokenAmount, uint256 price) internal pure returns (uint256) {\n        return tokenAmount * price / priceDenom;\n    }\n\n    /**\n     * @param amount amount of eth\n     * @param addr address to send\n     */\n    function _claim(uint256 amount, address addr) internal virtual;\n    // function _claim(uint256 amount, address addr) internal {\n        \n    //     require(address(this).balance >= amount, \"Amount exceeds allowed balance\");\n    //     require(addr != address(0), \"address can not be empty\");\n        \n    //     address payable addr1 = payable(addr); // correct since Solidity >= 0.6.0\n    //     bool success = addr1.send(amount);\n    //     require(success == true, \"Transfer ether was failed\"); \n    // }\n    \n    /**\n     * @param amount amount of tokens\n     * @param addr address to send\n     */\n    // function _sendTokens(uint256 amount, address addr) internal {\n        \n    //     require(amount>0, \"Amount can not be zero\");\n    //     require(addr != address(0), \"address can not be empty\");\n        \n    //     uint256 tokenBalance = IERC20Upgradeable(sellingToken).balanceOf(address(this));\n    //     require(tokenBalance >= amount, \"Amount exceeds allowed balance\");\n        \n    //     bool success = IERC20Upgradeable(sellingToken).transfer(addr, amount);\n    //     require(success == true, \"Transfer tokens were failed\"); \n    // }\n\n    /**\n     * @param amount amount of tokens\n     * @param addr address to send\n     * @param revertWhenError if true - tx will revert if error happens\n     * @return success true if all ok. and false - if revertWhenError == false and tx have exceptions\n     */\n    function _sendTokens(uint256 amount, address addr, bool revertWhenError) internal returns(bool success) {\n        //\n        success = true;\n\n        //require(amount>0, \"Amount can not be zero\");\n        if (amount == 0) {\n            if (revertWhenError) { \n                revert InvalidInput();\n            } else {\n                success = false;\n            }\n        }\n\n        //require(addr != address(0), \"address can not be empty\");\n        if (success && addr == address(0)) {\n            if (revertWhenError) { \n                revert AddressInvalid();\n            } else {\n                success = false;\n            }\n        }\n\n        if (success) {\n            uint256 tokenBalance = IERC777Upgradeable(sellingToken).balanceOf(address(this));\n            if (tokenBalance < amount) {\n                if (revertWhenError) { \n                    revert InsufficientAmount();\n                } else {\n                    success = false;\n                }\n            }\n        }\n\n        bool lowLevelSuccess;\n        bytes memory returnData;\n        bool returnedBool;\n        if (success) {\n            // create a low level call to the token\n            //lowLevelSuccess\n            (lowLevelSuccess, returnData) =\n                address(sellingToken).call(\n                    abi.encodePacked(\n                        ERC777Upgradeable.transfer.selector,\n                        abi.encode(addr, amount)\n                    )\n                );\n            success = lowLevelSuccess;\n        }\n        if (success) {\n            //returnedBool\n            (returnedBool) = abi.decode(returnData, (bool));\n            success = returnedBool;\n        }\n        \n        // if lowLevelSuccess == false  - it's tx revert\n        // if returnedBool == false - tx is ok but method return false\n        // but in our case - See {IERC20-transfer}, method will always return true or tx will revert ;)\n        if (revertWhenError && !success) {\n            revert TransferError();    \n        }\n\n    }\n \n    /**\n     * @param addr address which need to link with group\n     * @param groupName group name. if does not exists it will be created\n     */\n    function _setGroup(address addr, string memory groupName) internal {\n        if (addr == address(0)) {\n            revert AddressInvalid();\n        }\n        if (bytes(groupName).length == 0) {\n            revert GroupNameInvalid();\n        }\n        \n        uint256 tokenPrice = getTokenPrice();\n        \n        if (participants[addr].exists == false) {\n            participants[addr].exists = true;\n            participants[addr].contributed = 0;\n            participants[addr].groupName = groupName;\n            \n            if (groups[groupName].exists == false) {\n                groups[groupName].exists = true;\n                groups[groupName].name = groupName;\n                groups[groupName].totalAmount = 0;\n            } \n            \n            groups[groupName].participants.push(addr);\n            \n            if (totalInvestedGroupOutside[addr] > 0) {\n                _addBonus(\n                    addr,\n                    totalInvestedGroupOutside[addr],\n                    tokenPrice,\n                    true\n                );\n            }\n            \n        }\n    }\n    \n    /**\n     * calculate user bonus tokens and send it to him\n     * @param addr Address of participant\n     * @param ethAmount amount\n     * @param tokenPrice price ratio ETH -> token\n     * @param revertIfCantSendTokens revert if tokens are not enough when  contract will try to send bonuses to users\n     */\n    function _addBonus(\n        address addr, \n        uint256 ethAmount,\n        uint256 tokenPrice,\n        bool revertIfCantSendTokens\n    ) \n        internal \n        virtual\n    {\n\n        if (participants[addr].exists == true) {\n            \n            string memory groupName = participants[addr].groupName;\n            \n            groups[groupName].totalAmount +=  ethAmount;\n            participants[addr].totalAmount += ethAmount;    \n            \n            //// send tokens\n            uint256 groupBonus = _getGroupBonus(groupName);\n            address participantAddr;\n            uint256 participantTotalBonusTokens;\n            for (uint256 i = 0; i < groups[groupName].participants.length; i++) {\n                participantAddr = groups[groupName].participants[i];\n\n                participantTotalBonusTokens = _getTokenAmount(\n                                                                participants[participantAddr].totalAmount, \n                                                                tokenPrice\n                                                            ) * groupBonus / 1e2;\n\n                if (participantTotalBonusTokens > participants[participantAddr].contributed) {\n                    uint256 amount2Send = participantTotalBonusTokens - participants[participantAddr].contributed;\n                    participants[participantAddr].contributed = participantTotalBonusTokens;\n                  \n                    _sendTokens(amount2Send, participantAddr, revertIfCantSendTokens);\n                    \n                }\n            }\n\n            emit GroupBonusAdded(groupName, ethAmount, tokenPrice);\n               \n        } else {\n            totalInvestedGroupOutside[addr] += ethAmount;    \n        }\n    }\n\n    function _validateWhitelistForInternalUse() internal view {\n        if ((!whitelist.useWhitelist) || (whitelist.useWhitelist && (whitelist.contractAddress != address(0)))) {\n           revert WhitelistError(); \n        }\n    }\n    \n    function getContractTotalAmount() internal view virtual returns(uint256);\n}\n"
      },
      "contracts/SalesToken.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\npragma experimental ABIEncoderV2;\n\nimport \"./interfaces/ISalesToken.sol\";\nimport \"./SalesBase.sol\";\n/**\n*****************\nTEMPLATE CONTRACT\n*****************\n\nAlthough this code is available for viewing on GitHub and here, the general public is NOT given a license to freely deploy smart contracts based on this code, on any blockchains.\n\nTo prevent confusion and increase trust in the audited code bases of smart contracts we produce, we intend for there to be only ONE official Factory address on the blockchain producing the corresponding smart contracts, and we are going to point a blockchain domain name at it.\n\nCopyright (c) Intercoin Inc. All rights reserved.\n\nALLOWED USAGE.\n\nProvided they agree to all the conditions of this Agreement listed below, anyone is welcome to interact with the official Factory Contract at the this address to produce smart contract instances, or to interact with instances produced in this manner by others.\n\nAny user of software powered by this code MUST agree to the following, in order to use it. If you do not agree, refrain from using the software:\n\nDISCLAIMERS AND DISCLOSURES.\n\nCustomer expressly recognizes that nearly any software may contain unforeseen bugs or other defects, due to the nature of software development. Moreover, because of the immutable nature of smart contracts, any such defects will persist in the software once it is deployed onto the blockchain. Customer therefore expressly acknowledges that any responsibility to obtain outside audits and analysis of any software produced by Developer rests solely with Customer.\n\nCustomer understands and acknowledges that the Software is being delivered as-is, and may contain potential defects. While Developer and its staff and partners have exercised care and best efforts in an attempt to produce solid, working software products, Developer EXPRESSLY DISCLAIMS MAKING ANY GUARANTEES, REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, ABOUT THE FITNESS OF THE SOFTWARE, INCLUDING LACK OF DEFECTS, MERCHANTABILITY OR SUITABILITY FOR A PARTICULAR PURPOSE.\n\nCustomer agrees that neither Developer nor any other party has made any representations or warranties, nor has the Customer relied on any representations or warranties, express or implied, including any implied warranty of merchantability or fitness for any particular purpose with respect to the Software. Customer acknowledges that no affirmation of fact or statement (whether written or oral) made by Developer, its representatives, or any other party outside of this Agreement with respect to the Software shall be deemed to create any express or implied warranty on the part of Developer or its representatives.\n\nINDEMNIFICATION.\n\nCustomer agrees to indemnify, defend and hold Developer and its officers, directors, employees, agents and contractors harmless from any loss, cost, expense (including attorney’s fees and expenses), associated with or related to any demand, claim, liability, damages or cause of action of any kind or character (collectively referred to as “claim”), in any manner arising out of or relating to any third party demand, dispute, mediation, arbitration, litigation, or any violation or breach of any provision of this Agreement by Customer.\n\nNO WARRANTY.\n\nTHE SOFTWARE IS PROVIDED “AS IS” WITHOUT WARRANTY. DEVELOPER SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL, OR EXEMPLARY DAMAGES FOR BREACH OF THE LIMITED WARRANTY. TO THE MAXIMUM EXTENT PERMITTED BY LAW, DEVELOPER EXPRESSLY DISCLAIMS, AND CUSTOMER EXPRESSLY WAIVES, ALL OTHER WARRANTIES, WHETHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR USE, OR ANY WARRANTY ARISING OUT OF ANY PROPOSAL, SPECIFICATION, OR SAMPLE, AS WELL AS ANY WARRANTIES THAT THE SOFTWARE (OR ANY ELEMENTS THEREOF) WILL ACHIEVE A PARTICULAR RESULT, OR WILL BE UNINTERRUPTED OR ERROR-FREE. THE TERM OF ANY IMPLIED WARRANTIES THAT CANNOT BE DISCLAIMED UNDER APPLICABLE LAW SHALL BE LIMITED TO THE DURATION OF THE FOREGOING EXPRESS WARRANTY PERIOD. SOME STATES DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES AND/OR DO NOT ALLOW LIMITATIONS ON THE AMOUNT OF TIME AN IMPLIED WARRANTY LASTS, SO THE ABOVE LIMITATIONS MAY NOT APPLY TO CUSTOMER. THIS LIMITED WARRANTY GIVES CUSTOMER SPECIFIC LEGAL RIGHTS. CUSTOMER MAY HAVE OTHER RIGHTS WHICH VARY FROM STATE TO STATE. \n\nLIMITATION OF LIABILITY. \n\nTO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL DEVELOPER BE LIABLE UNDER ANY THEORY OF LIABILITY FOR ANY CONSEQUENTIAL, INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE OR EXEMPLARY DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, DAMAGES ARISING FROM LOSS OF PROFITS, REVENUE, DATA OR USE, OR FROM INTERRUPTED COMMUNICATIONS OR DAMAGED DATA, OR FROM ANY DEFECT OR ERROR OR IN CONNECTION WITH CUSTOMER'S ACQUISITION OF SUBSTITUTE GOODS OR SERVICES OR MALFUNCTION OF THE SOFTWARE, OR ANY SUCH DAMAGES ARISING FROM BREACH OF CONTRACT OR WARRANTY OR FROM NEGLIGENCE OR STRICT LIABILITY, EVEN IF DEVELOPER OR ANY OTHER PERSON HAS BEEN ADVISED OR SHOULD KNOW OF THE POSSIBILITY OF SUCH DAMAGES, AND NOTWITHSTANDING THE FAILURE OF ANY REMEDY TO ACHIEVE ITS INTENDED PURPOSE. WITHOUT LIMITING THE FOREGOING OR ANY OTHER LIMITATION OF LIABILITY HEREIN, REGARDLESS OF THE FORM OF ACTION, WHETHER FOR BREACH OF CONTRACT, WARRANTY, NEGLIGENCE, STRICT LIABILITY IN TORT OR OTHERWISE, CUSTOMER'S EXCLUSIVE REMEDY AND THE TOTAL LIABILITY OF DEVELOPER OR ANY SUPPLIER OF SERVICES TO DEVELOPER FOR ANY CLAIMS ARISING IN ANY WAY IN CONNECTION WITH OR RELATED TO THIS AGREEMENT, THE SOFTWARE, FOR ANY CAUSE WHATSOEVER, SHALL NOT EXCEED 1,000 USD.\n\nTRADEMARKS.\n\nThis Agreement does not grant you any right in any trademark or logo of Developer or its affiliates.\n\nLINK REQUIREMENTS.\n\nOperators of any Websites and Apps which make use of smart contracts based on this code must conspicuously include the following phrase in their website, featuring a clickable link that takes users to intercoin.app:\n\n\"Visit https://intercoin.app to launch your own NFTs, DAOs and other Web3 solutions.\"\n\nSTAKING OR SPENDING REQUIREMENTS.\n\nIn the future, Developer may begin requiring staking or spending of Intercoin tokens in order to take further actions (such as producing series and minting tokens). Any staking or spending requirements will first be announced on Developer's website (intercoin.org) four weeks in advance. Staking requirements will not apply to any actions already taken before they are put in place.\n\nCUSTOM ARRANGEMENTS.\n\nReach out to us at intercoin.org if you are looking to obtain Intercoin tokens in bulk, remove link requirements forever, remove staking requirements forever, or get custom work done with your Web3 projects.\n\nENTIRE AGREEMENT\n\nThis Agreement contains the entire agreement and understanding among the parties hereto with respect to the subject matter hereof, and supersedes all prior and contemporaneous agreements, understandings, inducements and conditions, express or implied, oral or written, of any nature whatsoever with respect to the subject matter hereof. The express terms hereof control and supersede any course of performance and/or usage of the trade inconsistent with any of the terms hereof. Provisions from previous Agreements executed between Customer and Developer., which are not expressly dealt with in this Agreement, will remain in effect.\n\nSUCCESSORS AND ASSIGNS\n\nThis Agreement shall continue to apply to any successors or assigns of either party, or any corporation or other entity acquiring all or substantially all the assets and business of either party whether by operation of law or otherwise.\n\nARBITRATION\n\nAll disputes related to this agreement shall be governed by and interpreted in accordance with the laws of New York, without regard to principles of conflict of laws. The parties to this agreement will submit all disputes arising under this agreement to arbitration in New York City, New York before a single arbitrator of the American Arbitration Association (“AAA”). The arbitrator shall be selected by application of the rules of the AAA, or by mutual agreement of the parties, except that such arbitrator shall be an attorney admitted to practice law New York. No party to this agreement will challenge the jurisdiction or venue provisions as provided in this section. No party to this agreement will challenge the jurisdiction or venue provisions as provided in this section.\n**/\ncontract SalesToken is SalesBase, ISalesToken {\n    address internal payToken;\n    \n    /**\n     * exchange eth to token via ratios ETH/<token>\n     */\n    receive() external payable  {\n        revert NotSupported();\n       //_exchange(msg.value);\n    }\n    \n\n    /**\n     * @param _commonSettings CommonSettings struct's array\n     *  address sellingToken address of ITR token\n     *  address token0 USD Coin\n     *  address token1 Wrapped token (WETH,WBNB,...)\n     *  address liquidityLib liquidityLib address(see intercoin/liquidity pkg)\n     *  address endTime after this time exchange stop\n     *  address compensationEndTime after this time receiving compensation tokens will be disabled\n     * @param _priceSettings PriceSettings struct's array\n     *  uint64 timestamp timestamp\n     *  uint256 price price exchange\n     *  uint256 amountRaised raised amount\n     * @param _bonusSettings ThresholdBonuses struct's array\n     *  uint256 threshold thresholds\n     *  uint256 bonus bonuses\n     * @param _ownerCanWithdraw enum option where:\n     *  0 -owner can not withdraw tokens\n     *  1 -owner can withdraw tokens only after endTimePassed\n     *  2 -owner can withdraw tokens anytime\n     * @param _whitelistData whitelist data struct\n     *  address contractAddress;\n\t *\tbytes4 method;\n\t *\tuint8 role;\n     *  bool useWhitelist;\n     * @param _lockedInPrice lockedInPrice struct\n     *  uint256 minimumLockedInAmount Minimum amount required to buy and hold the price.\n     *  uint256 maximumLockedInAmount Maximum amount available to buy at the held price.\n     * @param _costManager costmanager address\n     */\n     function init(\n        address _payToken,\n        CommonSettings memory _commonSettings,\n        PriceSettings[] memory _priceSettings,\n        ThresholdBonuses[] memory _bonusSettings,\n        EnumWithdraw _ownerCanWithdraw,\n        WhitelistStruct memory _whitelistData,\n        LockedInPrice memory _lockedInPrice,\n        address _costManager,\n        address _producedBy\n    ) \n        public\n        initializer\n        override\n    {\n        __SalesBase__init(\n            _commonSettings, \n            _priceSettings,\n            _bonusSettings,\n            _ownerCanWithdraw,\n            _whitelistData,\n            _lockedInPrice,\n            _costManager\n        );\n\n        _accountForOperation(\n            OPERATION_INITIALIZE << OPERATION_SHIFT_BITS,\n            uint256(uint160(_producedBy)),\n            2 // type\n        );\n        \n        // __SalesToken__init(_payToken);\n        if (_payToken == address(0)) {\n            revert AddressInvalid();\n        }\n        payToken = _payToken;\n    }\n    \n    function buy(uint256 amount) public {\n        \n        bool success = IERC20Upgradeable(payToken).transferFrom(_msgSender(), address(this), amount); \n        if (!success) {\n            revert TransferError();\n        }\n        \n        _exchange(amount); \n\n        _accountForOperation(\n            OPERATION_BUY << OPERATION_SHIFT_BITS,\n            uint256(uint160(_msgSender())),\n            amount\n        );\n    }\n\n    function owner() public view override(ISalesToken, SalesBase) returns (address) {\n        return super.owner();\n    }\n\n    /**\n     * @param amount amount of eth\n     * @param addr address to send\n     */\n    function _claim(uint256 amount, address addr) internal override {\n        if (IERC20Upgradeable(payToken).balanceOf(address(this)) < amount) {\n            revert InsufficientAmount();\n        }\n\n        if (addr == address(0)) {\n            revert AddressInvalid();\n        }\n        \n        bool success = IERC20Upgradeable(payToken).transfer(addr, amount); \n        if (!success) {\n            revert TransferError();   \n        }\n        \n    }\n    \n    function getContractTotalAmount() internal view virtual override returns(uint256) {\n        return IERC20Upgradeable(payToken).balanceOf(address(this));\n    }\n    \n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 100
      },
      "metadata": {
        "bytecodeHash": "none"
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}