creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "node_modules/@gearbox-protocol/core-v3/contracts/pool/PoolQuotaKeeperV3.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Foundation, 2023.\npragma solidity ^0.8.17;\npragma abicoder v1;\n\nimport {EnumerableSet} from \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\n\n/// LIBS & TRAITS\nimport {ACLNonReentrantTrait} from \"../traits/ACLNonReentrantTrait.sol\";\nimport {ContractsRegisterTrait} from \"../traits/ContractsRegisterTrait.sol\";\nimport {QuotasLogic} from \"../libraries/QuotasLogic.sol\";\n\nimport {IPoolV3} from \"../interfaces/IPoolV3.sol\";\nimport {IPoolQuotaKeeperV3, TokenQuotaParams, AccountQuota} from \"../interfaces/IPoolQuotaKeeperV3.sol\";\nimport {IGaugeV3} from \"../interfaces/IGaugeV3.sol\";\nimport {ICreditManagerV3} from \"../interfaces/ICreditManagerV3.sol\";\n\nimport {PERCENTAGE_FACTOR, RAY} from \"@gearbox-protocol/core-v2/contracts/libraries/Constants.sol\";\n\n// EXCEPTIONS\nimport \"../interfaces/IExceptions.sol\";\n\n/// @title Pool quota keeper V3\n/// @notice In Gearbox V3, quotas are used to limit the system exposure to risky assets.\n///         In order for a risky token to be counted towards credit account's collateral, account owner must \"purchase\"\n///         a quota for this token, which entails two kinds of payments:\n///         * interest that accrues over time with rates determined by the gauge (more suited to leveraged farming), and\n///         * increase fee that is charged when additional quota is purchased (more suited to leveraged trading).\n///         Quota keeper stores information about quotas of accounts in all credit managers connected to the pool, and\n///         performs calculations that help to keep pool's expected liquidity and credit managers' debt consistent.\ncontract PoolQuotaKeeperV3 is IPoolQuotaKeeperV3, ACLNonReentrantTrait, ContractsRegisterTrait {\n    using EnumerableSet for EnumerableSet.AddressSet;\n    using QuotasLogic for TokenQuotaParams;\n\n    /// @notice Contract version\n    uint256 public constant override version = 3_00;\n\n    /// @notice Address of the underlying token\n    address public immutable override underlying;\n\n    /// @notice Address of the pool\n    address public immutable override pool;\n\n    /// @dev The list of all allowed credit managers\n    EnumerableSet.AddressSet internal creditManagerSet;\n\n    /// @dev The list of all quoted tokens\n    EnumerableSet.AddressSet internal quotaTokensSet;\n\n    /// @notice Mapping from token to global token quota params\n    mapping(address => TokenQuotaParams) internal totalQuotaParams;\n\n    /// @dev Mapping from (creditAccount, token) to account's token quota params\n    mapping(address => mapping(address => AccountQuota)) internal accountQuotas;\n\n    /// @notice Address of the gauge\n    address public override gauge;\n\n    /// @notice Timestamp of the last quota rates update\n    uint40 public override lastQuotaRateUpdate;\n\n    /// @dev Ensures that function caller is gauge\n    modifier gaugeOnly() {\n        _revertIfCallerNotGauge();\n        _;\n    }\n\n    /// @dev Ensures that function caller is an allowed credit manager\n    modifier creditManagerOnly() {\n        _revertIfCallerNotCreditManager();\n        _;\n    }\n\n    /// @notice Constructor\n    /// @param _pool Pool address\n    constructor(address _pool)\n        ACLNonReentrantTrait(IPoolV3(_pool).addressProvider())\n        ContractsRegisterTrait(IPoolV3(_pool).addressProvider())\n    {\n        pool = _pool; // U:[PQK-1]\n        underlying = IPoolV3(_pool).asset(); // U:[PQK-1]\n    }\n\n    // ----------------- //\n    // QUOTAS MANAGEMENT //\n    // ----------------- //\n\n    /// @notice Updates credit account's quota for a token\n    ///         - Updates account's interest index\n    ///         - Updates account's quota by requested delta subject to the total quota limit (which is considered\n    ///           to be zero for tokens added to the quota keeper but not yet activated via `updateRates`)\n    ///         - Checks that the resulting quota is no less than the user-specified min desired value\n    ///           and no more than system-specified max allowed value\n    ///         - Updates pool's quota revenue\n    /// @param creditAccount Credit account to update the quota for\n    /// @param token Token to update the quota for\n    /// @param requestedChange Requested quota change in pool's underlying asset units\n    /// @param minQuota Minimum deisred quota amount\n    /// @param maxQuota Maximum allowed quota amount\n    /// @return caQuotaInterestChange Token quota interest accrued by account since the last update\n    /// @return fees Quota increase fees, if any\n    /// @return enableToken Whether the token needs to be enabled as collateral\n    /// @return disableToken Whether the token needs to be disabled as collateral\n    function updateQuota(address creditAccount, address token, int96 requestedChange, uint96 minQuota, uint96 maxQuota)\n        external\n        override\n        creditManagerOnly // U:[PQK-4]\n        returns (uint128 caQuotaInterestChange, uint128 fees, bool enableToken, bool disableToken)\n    {\n        int96 quotaChange;\n        (caQuotaInterestChange, fees, quotaChange, enableToken, disableToken) =\n            _updateQuota(creditAccount, token, requestedChange, minQuota, maxQuota);\n\n        if (quotaChange != 0) {\n            emit UpdateQuota({creditAccount: creditAccount, token: token, quotaChange: quotaChange});\n        }\n    }\n\n    /// @dev Implementation of `updateQuota`\n    function _updateQuota(address creditAccount, address token, int96 requestedChange, uint96 minQuota, uint96 maxQuota)\n        internal\n        returns (uint128 caQuotaInterestChange, uint128 fees, int96 quotaChange, bool enableToken, bool disableToken)\n    {\n        AccountQuota storage accountQuota = accountQuotas[creditAccount][token];\n        TokenQuotaParams storage tokenQuotaParams = totalQuotaParams[token];\n\n        uint96 quoted = accountQuota.quota;\n\n        (uint16 rate, uint192 tqCumulativeIndexLU, uint16 quotaIncreaseFee) =\n            _getTokenQuotaParamsOrRevert(tokenQuotaParams);\n\n        uint192 cumulativeIndexNow = QuotasLogic.cumulativeIndexSince(tqCumulativeIndexLU, rate, lastQuotaRateUpdate);\n\n        // Accrued quota interest depends on the quota and thus must be computed before updating it\n        caQuotaInterestChange =\n            QuotasLogic.calcAccruedQuotaInterest(quoted, cumulativeIndexNow, accountQuota.cumulativeIndexLU); // U:[PQK-15]\n\n        uint96 newQuoted;\n        quotaChange = requestedChange;\n        if (quotaChange > 0) {\n            (uint96 totalQuoted, uint96 limit) = _getTokenQuotaTotalAndLimit(tokenQuotaParams);\n            quotaChange = (rate == 0) ? int96(0) : QuotasLogic.calcActualQuotaChange(totalQuoted, limit, quotaChange); // U:[PQK-15]\n\n            fees = uint128(uint256(uint96(quotaChange)) * quotaIncreaseFee / PERCENTAGE_FACTOR); // U:[PQK-15]\n\n            newQuoted = quoted + uint96(quotaChange);\n            if (quoted == 0 && newQuoted != 0) {\n                enableToken = true; // U:[PQK-15]\n            }\n\n            tokenQuotaParams.totalQuoted = totalQuoted + uint96(quotaChange); // U:[PQK-15]\n        } else {\n            if (quotaChange == type(int96).min) {\n                quotaChange = -int96(quoted);\n            }\n\n            uint96 absoluteChange = uint96(-quotaChange);\n            newQuoted = quoted - absoluteChange;\n            tokenQuotaParams.totalQuoted -= absoluteChange; // U:[PQK-15]\n\n            if (quoted != 0 && newQuoted == 0) {\n                disableToken = true; // U:[PQK-15]\n            }\n        }\n\n        if (newQuoted < minQuota || newQuoted > maxQuota) revert QuotaIsOutOfBoundsException(); // U:[PQK-15]\n\n        accountQuota.quota = newQuoted; // U:[PQK-15]\n        accountQuota.cumulativeIndexLU = cumulativeIndexNow; // U:[PQK-15]\n\n        int256 quotaRevenueChange = QuotasLogic.calcQuotaRevenueChange(rate, int256(quotaChange)); // U:[PQK-15]\n        if (quotaRevenueChange != 0) {\n            IPoolV3(pool).updateQuotaRevenue(quotaRevenueChange); // U:[PQK-15]\n        }\n    }\n\n    /// @notice Removes credit account's quotas for provided tokens\n    ///         - Sets account's tokens quotas to zero\n    ///         - Optionally sets quota limits for tokens to zero, effectively preventing further exposure\n    ///           to them in extreme cases (e.g., liquidations with loss)\n    ///         - Does not update account's interest indexes (can be skipped since quotas are zero)\n    ///         - Decreases pool's quota revenue\n    /// @param creditAccount Credit account to remove quotas for\n    /// @param tokens Array of tokens to remove quotas for\n    /// @param setLimitsToZero Whether tokens quota limits should be set to zero\n    function removeQuotas(address creditAccount, address[] calldata tokens, bool setLimitsToZero)\n        external\n        override\n        creditManagerOnly // U:[PQK-4]\n    {\n        int256 quotaRevenueChange;\n\n        uint256 len = tokens.length;\n        for (uint256 i; i < len;) {\n            address token = tokens[i];\n\n            AccountQuota storage accountQuota = accountQuotas[creditAccount][token];\n            TokenQuotaParams storage tokenQuotaParams = totalQuotaParams[token];\n\n            uint96 quoted = accountQuota.quota;\n            if (quoted != 0) {\n                uint16 rate = tokenQuotaParams.rate;\n                quotaRevenueChange += QuotasLogic.calcQuotaRevenueChange(rate, -int256(uint256(quoted))); // U:[PQK-16]\n                tokenQuotaParams.totalQuoted -= quoted; // U:[PQK-16]\n                accountQuota.quota = 0; // U:[PQK-16]\n                emit UpdateQuota({creditAccount: creditAccount, token: token, quotaChange: -int96(quoted)});\n            }\n\n            if (setLimitsToZero) {\n                _setTokenLimit({tokenQuotaParams: tokenQuotaParams, token: token, limit: 0}); // U:[PQK-16]\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n\n        if (quotaRevenueChange != 0) {\n            IPoolV3(pool).updateQuotaRevenue(quotaRevenueChange); // U:[PQK-16]\n        }\n    }\n\n    /// @notice Updates credit account's interest indexes for provided tokens\n    /// @param creditAccount Credit account to accrue interest for\n    /// @param tokens Array tokens to accrue interest for\n    function accrueQuotaInterest(address creditAccount, address[] calldata tokens)\n        external\n        override\n        creditManagerOnly // U:[PQK-4]\n    {\n        uint256 len = tokens.length;\n        uint40 lastQuotaRateUpdate_ = lastQuotaRateUpdate;\n\n        unchecked {\n            for (uint256 i; i < len; ++i) {\n                address token = tokens[i];\n\n                AccountQuota storage accountQuota = accountQuotas[creditAccount][token];\n                TokenQuotaParams storage tokenQuotaParams = totalQuotaParams[token];\n\n                (uint16 rate, uint192 tqCumulativeIndexLU,) = _getTokenQuotaParamsOrRevert(tokenQuotaParams); // U:[PQK-17]\n\n                accountQuota.cumulativeIndexLU =\n                    QuotasLogic.cumulativeIndexSince(tqCumulativeIndexLU, rate, lastQuotaRateUpdate_); // U:[PQK-17]\n            }\n        }\n    }\n\n    /// @notice Returns credit account's token quota and interest accrued since the last update\n    /// @param creditAccount Account to compute the values for\n    /// @param token Token to compute the values for\n    /// @return quoted Account's token quota\n    /// @return outstandingInterest Quota interest accrued since the last update\n    function getQuotaAndOutstandingInterest(address creditAccount, address token)\n        external\n        view\n        override\n        returns (uint96 quoted, uint128 outstandingInterest)\n    {\n        AccountQuota storage accountQuota = accountQuotas[creditAccount][token];\n\n        uint192 cumulativeIndexNow = cumulativeIndex(token);\n\n        quoted = accountQuota.quota;\n        uint192 aqCumulativeIndexLU = accountQuota.cumulativeIndexLU;\n\n        outstandingInterest = QuotasLogic.calcAccruedQuotaInterest(quoted, cumulativeIndexNow, aqCumulativeIndexLU); // U:[PQK-15]\n    }\n\n    /// @notice Returns current quota interest index for a token in ray\n    function cumulativeIndex(address token) public view override returns (uint192) {\n        TokenQuotaParams storage tokenQuotaParams = totalQuotaParams[token];\n        (uint16 rate, uint192 tqCumulativeIndexLU,) = _getTokenQuotaParamsOrRevert(tokenQuotaParams);\n\n        return QuotasLogic.cumulativeIndexSince(tqCumulativeIndexLU, rate, lastQuotaRateUpdate);\n    }\n\n    /// @notice Returns quota interest rate for a token in bps\n    function getQuotaRate(address token) external view override returns (uint16) {\n        return totalQuotaParams[token].rate;\n    }\n\n    /// @notice Returns an array of all quoted tokens\n    function quotedTokens() external view override returns (address[] memory) {\n        return quotaTokensSet.values();\n    }\n\n    /// @notice Whether a token is quoted\n    function isQuotedToken(address token) external view override returns (bool) {\n        return quotaTokensSet.contains(token);\n    }\n\n    /// @notice Returns account's quota params for a token\n    function getQuota(address creditAccount, address token)\n        external\n        view\n        override\n        returns (uint96 quota, uint192 cumulativeIndexLU)\n    {\n        AccountQuota storage aq = accountQuotas[creditAccount][token];\n        return (aq.quota, aq.cumulativeIndexLU);\n    }\n\n    /// @notice Returns global quota params for a token\n    function getTokenQuotaParams(address token)\n        external\n        view\n        override\n        returns (\n            uint16 rate,\n            uint192 cumulativeIndexLU,\n            uint16 quotaIncreaseFee,\n            uint96 totalQuoted,\n            uint96 limit,\n            bool isActive\n        )\n    {\n        TokenQuotaParams memory tq = totalQuotaParams[token];\n        rate = tq.rate;\n        cumulativeIndexLU = tq.cumulativeIndexLU;\n        quotaIncreaseFee = tq.quotaIncreaseFee;\n        totalQuoted = tq.totalQuoted;\n        limit = tq.limit;\n        isActive = rate != 0;\n    }\n\n    /// @notice Returns the pool's quota revenue (in units of underlying per year)\n    function poolQuotaRevenue() external view virtual override returns (uint256 quotaRevenue) {\n        address[] memory tokens = quotaTokensSet.values();\n\n        uint256 len = tokens.length;\n\n        for (uint256 i; i < len;) {\n            address token = tokens[i];\n\n            TokenQuotaParams storage tokenQuotaParams = totalQuotaParams[token];\n            (uint16 rate,,) = _getTokenQuotaParamsOrRevert(tokenQuotaParams);\n            (uint256 totalQuoted,) = _getTokenQuotaTotalAndLimit(tokenQuotaParams);\n\n            quotaRevenue += totalQuoted * rate / PERCENTAGE_FACTOR;\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /// @notice Returns the list of allowed credit managers\n    function creditManagers() external view override returns (address[] memory) {\n        return creditManagerSet.values(); // U:[PQK-10]\n    }\n\n    // ------------- //\n    // CONFIGURATION //\n    // ------------- //\n\n    /// @notice Adds a new quota token\n    /// @param token Address of the token\n    function addQuotaToken(address token)\n        external\n        override\n        gaugeOnly // U:[PQK-3]\n    {\n        if (quotaTokensSet.contains(token)) {\n            revert TokenAlreadyAddedException(); // U:[PQK-6]\n        }\n\n        // The rate will be set during a general epoch update in the gauge\n        quotaTokensSet.add(token); // U:[PQK-5]\n        totalQuotaParams[token].cumulativeIndexLU = 1; // U:[PQK-5]\n\n        emit AddQuotaToken(token); // U:[PQK-5]\n    }\n\n    /// @notice Updates quota rates\n    ///         - Updates global token cumulative indexes before changing rates\n    ///         - Queries new rates for all quoted tokens from the gauge\n    ///         - Sets new pool quota revenue\n    function updateRates()\n        external\n        override\n        gaugeOnly // U:[PQK-3]\n    {\n        address[] memory tokens = quotaTokensSet.values();\n        uint16[] memory rates = IGaugeV3(gauge).getRates(tokens); // U:[PQK-7]\n\n        uint256 quotaRevenue;\n        uint256 timestampLU = lastQuotaRateUpdate;\n        uint256 len = tokens.length;\n\n        for (uint256 i; i < len;) {\n            address token = tokens[i];\n            uint16 rate = rates[i];\n\n            TokenQuotaParams storage tokenQuotaParams = totalQuotaParams[token]; // U:[PQK-7]\n            (uint16 prevRate, uint192 tqCumulativeIndexLU,) = _getTokenQuotaParamsOrRevert(tokenQuotaParams);\n\n            tokenQuotaParams.cumulativeIndexLU =\n                QuotasLogic.cumulativeIndexSince(tqCumulativeIndexLU, prevRate, timestampLU); // U:[PQK-7]\n\n            tokenQuotaParams.rate = rate; // U:[PQK-7]\n\n            quotaRevenue += uint256(tokenQuotaParams.totalQuoted) * rate / PERCENTAGE_FACTOR; // U:[PQK-7]\n\n            emit UpdateTokenQuotaRate(token, rate); // U:[PQK-7]\n\n            unchecked {\n                ++i;\n            }\n        }\n\n        IPoolV3(pool).setQuotaRevenue(quotaRevenue); // U:[PQK-7]\n        lastQuotaRateUpdate = uint40(block.timestamp); // U:[PQK-7]\n    }\n\n    /// @notice Sets a new gauge contract to compute quota rates\n    /// @param _gauge Address of the new gauge contract\n    function setGauge(address _gauge)\n        external\n        override\n        configuratorOnly // U:[PQK-2]\n    {\n        if (gauge != _gauge) {\n            gauge = _gauge; // U:[PQK-8]\n            emit SetGauge(_gauge); // U:[PQK-8]\n        }\n    }\n\n    /// @notice Adds an address to the set of allowed credit managers\n    /// @param _creditManager Address of the new credit manager\n    function addCreditManager(address _creditManager)\n        external\n        override\n        configuratorOnly // U:[PQK-2]\n        nonZeroAddress(_creditManager)\n        registeredCreditManagerOnly(_creditManager) // U:[PQK-9]\n    {\n        if (ICreditManagerV3(_creditManager).pool() != pool) {\n            revert IncompatibleCreditManagerException(); // U:[PQK-9]\n        }\n\n        if (!creditManagerSet.contains(_creditManager)) {\n            creditManagerSet.add(_creditManager); // U:[PQK-10]\n            emit AddCreditManager(_creditManager); // U:[PQK-10]\n        }\n    }\n\n    /// @notice Sets the total quota limit for a token\n    /// @param token Address of token to set the limit for\n    /// @param limit The limit to set\n    function setTokenLimit(address token, uint96 limit)\n        external\n        override\n        controllerOnly // U:[PQK-2]\n    {\n        TokenQuotaParams storage tokenQuotaParams = totalQuotaParams[token];\n        _setTokenLimit(tokenQuotaParams, token, limit);\n    }\n\n    /// @dev Implementation of `setTokenLimit`\n    function _setTokenLimit(TokenQuotaParams storage tokenQuotaParams, address token, uint96 limit) internal {\n        if (!isInitialised(tokenQuotaParams)) {\n            revert TokenIsNotQuotedException(); // U:[PQK-11]\n        }\n\n        if (tokenQuotaParams.limit != limit) {\n            tokenQuotaParams.limit = limit; // U:[PQK-12]\n            emit SetTokenLimit(token, limit); // U:[PQK-12]\n        }\n    }\n\n    /// @notice Sets the one-time quota increase fee for a token\n    /// @param token Token to set the fee for\n    /// @param fee The new fee value in bps\n    function setTokenQuotaIncreaseFee(address token, uint16 fee)\n        external\n        override\n        controllerOnly // U:[PQK-2]\n    {\n        if (fee > PERCENTAGE_FACTOR) {\n            revert IncorrectParameterException();\n        }\n\n        TokenQuotaParams storage tokenQuotaParams = totalQuotaParams[token]; // U:[PQK-13]\n\n        if (!isInitialised(tokenQuotaParams)) {\n            revert TokenIsNotQuotedException();\n        }\n\n        if (tokenQuotaParams.quotaIncreaseFee != fee) {\n            tokenQuotaParams.quotaIncreaseFee = fee; // U:[PQK-13]\n            emit SetQuotaIncreaseFee(token, fee); // U:[PQK-13]\n        }\n    }\n\n    // --------- //\n    // INTERNALS //\n    // --------- //\n\n    /// @dev Whether quota params for token are initialized\n    function isInitialised(TokenQuotaParams storage tokenQuotaParams) internal view returns (bool) {\n        return tokenQuotaParams.cumulativeIndexLU != 0;\n    }\n\n    /// @dev Efficiently loads quota params of a token from storage\n    function _getTokenQuotaParamsOrRevert(TokenQuotaParams storage tokenQuotaParams)\n        internal\n        view\n        returns (uint16 rate, uint192 cumulativeIndexLU, uint16 quotaIncreaseFee)\n    {\n        // rate = tokenQuotaParams.rate;\n        // cumulativeIndexLU = tokenQuotaParams.cumulativeIndexLU;\n        // quotaIncreaseFee = tokenQuotaParams.quotaIncreaseFee;\n        assembly {\n            let data := sload(tokenQuotaParams.slot)\n            rate := and(data, 0xFFFF)\n            cumulativeIndexLU := and(shr(16, data), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\n            quotaIncreaseFee := shr(208, data)\n        }\n\n        if (cumulativeIndexLU == 0) {\n            revert TokenIsNotQuotedException(); // U:[PQK-14]\n        }\n    }\n\n    /// @dev Efficiently loads quota and limit of a token from storage\n    function _getTokenQuotaTotalAndLimit(TokenQuotaParams storage tokenQuotaParams)\n        internal\n        view\n        returns (uint96 totalQuoted, uint96 limit)\n    {\n        // totalQuoted = tokenQuotaParams.totalQuoted;\n        // limit = tokenQuotaParams.limit;\n        assembly {\n            let data := sload(add(tokenQuotaParams.slot, 1))\n            totalQuoted := and(data, 0xFFFFFFFFFFFFFFFFFFFFFFFF)\n            limit := shr(96, data)\n        }\n    }\n\n    /// @dev Reverts if `msg.sender` is not an allowed credit manager\n    function _revertIfCallerNotCreditManager() internal view {\n        if (!creditManagerSet.contains(msg.sender)) {\n            revert CallerNotCreditManagerException(); // U:[PQK-4]\n        }\n    }\n\n    /// @dev Reverts if `msg.sender` is not gauge\n    function _revertIfCallerNotGauge() internal view {\n        if (msg.sender != gauge) revert CallerNotGaugeException(); // U:[PQK-3]\n    }\n}\n"
      },
      "node_modules/@openzeppelin/contracts/utils/structs/EnumerableSet.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n *     // Add the library methods\n *     using EnumerableSet for EnumerableSet.AddressSet;\n *\n *     // Declare a set state variable\n *     EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n    // To implement this library for multiple types with as little code\n    // repetition as possible, we write it in terms of a generic Set type with\n    // bytes32 values.\n    // The Set implementation uses private functions, and user-facing\n    // implementations (such as AddressSet) are just wrappers around the\n    // underlying Set.\n    // This means that we can only create new EnumerableSets for types that fit\n    // in bytes32.\n\n    struct Set {\n        // Storage of set values\n        bytes32[] _values;\n        // Position of the value in the `values` array, plus 1 because index 0\n        // means a value is not in the set.\n        mapping(bytes32 => uint256) _indexes;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function _add(Set storage set, bytes32 value) private returns (bool) {\n        if (!_contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._indexes[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function _remove(Set storage set, bytes32 value) private returns (bool) {\n        // We read and store the value's index to prevent multiple reads from the same storage slot\n        uint256 valueIndex = set._indexes[value];\n\n        if (valueIndex != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 toDeleteIndex = valueIndex - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (lastIndex != toDeleteIndex) {\n                bytes32 lastValue = set._values[lastIndex];\n\n                // Move the last value to the index where the value to delete is\n                set._values[toDeleteIndex] = lastValue;\n                // Update the index for the moved value\n                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the index for the deleted slot\n            delete set._indexes[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function _contains(Set storage set, bytes32 value) private view returns (bool) {\n        return set._indexes[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function _length(Set storage set) private view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function _at(Set storage set, uint256 index) private view returns (bytes32) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function _values(Set storage set) private view returns (bytes32[] memory) {\n        return set._values;\n    }\n\n    // Bytes32Set\n\n    struct Bytes32Set {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _add(set._inner, value);\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _remove(set._inner, value);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n        return _contains(set._inner, value);\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(Bytes32Set storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n        return _at(set._inner, index);\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        bytes32[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // AddressSet\n\n    struct AddressSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(AddressSet storage set, address value) internal returns (bool) {\n        return _add(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(AddressSet storage set, address value) internal returns (bool) {\n        return _remove(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(AddressSet storage set, address value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(AddressSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(AddressSet storage set, uint256 index) internal view returns (address) {\n        return address(uint160(uint256(_at(set._inner, index))));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(AddressSet storage set) internal view returns (address[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        address[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // UintSet\n\n    struct UintSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(UintSet storage set, uint256 value) internal returns (bool) {\n        return _add(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(UintSet storage set, uint256 value) internal returns (bool) {\n        return _remove(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(UintSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n        return uint256(_at(set._inner, index));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(UintSet storage set) internal view returns (uint256[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        uint256[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/traits/ACLNonReentrantTrait.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Foundation, 2023.\npragma solidity ^0.8.17;\n\nimport {Pausable} from \"@openzeppelin/contracts/security/Pausable.sol\";\n\nimport {IACL} from \"@gearbox-protocol/core-v2/contracts/interfaces/IACL.sol\";\nimport {\n    CallerNotControllerException,\n    CallerNotPausableAdminException,\n    CallerNotUnpausableAdminException\n} from \"../interfaces/IExceptions.sol\";\n\nimport {ACLTrait} from \"./ACLTrait.sol\";\nimport {ReentrancyGuardTrait} from \"./ReentrancyGuardTrait.sol\";\n\n/// @title ACL non-reentrant trait\n/// @notice Extended version of `ACLTrait` that implements pausable functionality,\n///         reentrancy protection and external controller role\nabstract contract ACLNonReentrantTrait is ACLTrait, Pausable, ReentrancyGuardTrait {\n    /// @notice Emitted when new external controller is set\n    event NewController(address indexed newController);\n\n    /// @notice External controller address\n    address public controller;\n\n    /// @dev Ensures that function caller is external controller or configurator\n    modifier controllerOnly() {\n        _ensureCallerIsControllerOrConfigurator();\n        _;\n    }\n\n    /// @dev Reverts if the caller is not controller or configurator\n    /// @dev Used to cut contract size on modifiers\n    function _ensureCallerIsControllerOrConfigurator() internal view {\n        if (msg.sender != controller && !_isConfigurator({account: msg.sender})) {\n            revert CallerNotControllerException();\n        }\n    }\n\n    /// @dev Ensures that function caller has pausable admin role\n    modifier pausableAdminsOnly() {\n        _ensureCallerIsPausableAdmin();\n        _;\n    }\n\n    /// @dev Reverts if the caller is not pausable admin\n    /// @dev Used to cut contract size on modifiers\n    function _ensureCallerIsPausableAdmin() internal view {\n        if (!_isPausableAdmin({account: msg.sender})) {\n            revert CallerNotPausableAdminException();\n        }\n    }\n\n    /// @dev Ensures that function caller has unpausable admin role\n    modifier unpausableAdminsOnly() {\n        _ensureCallerIsUnpausableAdmin();\n        _;\n    }\n\n    /// @dev Reverts if the caller is not unpausable admin\n    /// @dev Used to cut contract size on modifiers\n    function _ensureCallerIsUnpausableAdmin() internal view {\n        if (!_isUnpausableAdmin({account: msg.sender})) {\n            revert CallerNotUnpausableAdminException();\n        }\n    }\n\n    /// @notice Constructor\n    /// @param addressProvider Address provider contract address\n    constructor(address addressProvider) ACLTrait(addressProvider) {\n        controller = IACL(acl).owner();\n    }\n\n    /// @notice Pauses contract, can only be called by an account with pausable admin role\n    function pause() external virtual pausableAdminsOnly {\n        _pause();\n    }\n\n    /// @notice Unpauses contract, can only be called by an account with unpausable admin role\n    function unpause() external virtual unpausableAdminsOnly {\n        _unpause();\n    }\n\n    /// @notice Sets new external controller, can only be called by configurator\n    function setController(address newController) external configuratorOnly {\n        if (controller == newController) return;\n        controller = newController;\n        emit NewController(newController);\n    }\n\n    /// @dev Checks whether given account has pausable admin role\n    function _isPausableAdmin(address account) internal view returns (bool) {\n        return IACL(acl).isPausableAdmin(account);\n    }\n\n    /// @dev Checks whether given account has unpausable admin role\n    function _isUnpausableAdmin(address account) internal view returns (bool) {\n        return IACL(acl).isUnpausableAdmin(account);\n    }\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/traits/ContractsRegisterTrait.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Foundation, 2023.\npragma solidity ^0.8.17;\n\nimport {IContractsRegister} from \"@gearbox-protocol/core-v2/contracts/interfaces/IContractsRegister.sol\";\n\nimport {AP_CONTRACTS_REGISTER, IAddressProviderV3, NO_VERSION_CONTROL} from \"../interfaces/IAddressProviderV3.sol\";\nimport {RegisteredCreditManagerOnlyException, RegisteredPoolOnlyException} from \"../interfaces/IExceptions.sol\";\n\nimport {SanityCheckTrait} from \"./SanityCheckTrait.sol\";\n\n/// @title Contracts register trait\n/// @notice Trait that simplifies validation of pools and credit managers\nabstract contract ContractsRegisterTrait is SanityCheckTrait {\n    /// @notice Contracts register contract address\n    address public immutable contractsRegister;\n\n    /// @dev Ensures that given address is a registered credit manager\n    modifier registeredPoolOnly(address addr) {\n        _ensureRegisteredPool(addr);\n        _;\n    }\n\n    /// @dev Ensures that given address is a registered pool\n    modifier registeredCreditManagerOnly(address addr) {\n        _ensureRegisteredCreditManager(addr);\n        _;\n    }\n\n    /// @notice Constructor\n    /// @param addressProvider Address provider contract address\n    constructor(address addressProvider) nonZeroAddress(addressProvider) {\n        contractsRegister =\n            IAddressProviderV3(addressProvider).getAddressOrRevert(AP_CONTRACTS_REGISTER, NO_VERSION_CONTROL);\n    }\n\n    /// @dev Ensures that given address is a registered pool\n    function _ensureRegisteredPool(address addr) internal view {\n        if (!_isRegisteredPool(addr)) revert RegisteredPoolOnlyException();\n    }\n\n    /// @dev Ensures that given address is a registered credit manager\n    function _ensureRegisteredCreditManager(address addr) internal view {\n        if (!_isRegisteredCreditManager(addr)) revert RegisteredCreditManagerOnlyException();\n    }\n\n    /// @dev Whether given address is a registered pool\n    function _isRegisteredPool(address addr) internal view returns (bool) {\n        return IContractsRegister(contractsRegister).isPool(addr);\n    }\n\n    /// @dev Whether given address is a registered credit manager\n    function _isRegisteredCreditManager(address addr) internal view returns (bool) {\n        return IContractsRegister(contractsRegister).isCreditManager(addr);\n    }\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/libraries/QuotasLogic.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Foundation, 2023.\npragma solidity ^0.8.17;\n\nimport {SafeCast} from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\nimport {RAY, SECONDS_PER_YEAR, PERCENTAGE_FACTOR} from \"@gearbox-protocol/core-v2/contracts/libraries/Constants.sol\";\n\nuint192 constant RAY_DIVIDED_BY_PERCENTAGE = uint192(RAY / PERCENTAGE_FACTOR);\n\n/// @title Quotas logic library\nlibrary QuotasLogic {\n    using SafeCast for uint256;\n\n    /// @dev Computes the new interest index value, given the previous value, the interest rate, and time delta\n    /// @dev Unlike pool's base interest, interest on quotas is not compounding, so additive index is used\n    function cumulativeIndexSince(uint192 cumulativeIndexLU, uint16 rate, uint256 lastQuotaRateUpdate)\n        internal\n        view\n        returns (uint192)\n    {\n        return uint192(\n            uint256(cumulativeIndexLU)\n                + RAY_DIVIDED_BY_PERCENTAGE * (block.timestamp - lastQuotaRateUpdate) * rate / SECONDS_PER_YEAR\n        ); // U:[QL-1]\n    }\n\n    /// @dev Computes interest accrued on the quota since the last update\n    function calcAccruedQuotaInterest(uint96 quoted, uint192 cumulativeIndexNow, uint192 cumulativeIndexLU)\n        internal\n        pure\n        returns (uint128)\n    {\n        // `quoted` is `uint96`, and `cumulativeIndex / RAY` won't reach `2 ** 32` in reasonable time, so casting is safe\n        return uint128(uint256(quoted) * (cumulativeIndexNow - cumulativeIndexLU) / RAY); // U:[QL-2]\n    }\n\n    /// @dev Computes the pool quota revenue change given the current rate and the quota change\n    function calcQuotaRevenueChange(uint16 rate, int256 change) internal pure returns (int256) {\n        return change * int256(uint256(rate)) / int16(PERCENTAGE_FACTOR);\n    }\n\n    /// @dev Upper-bounds requested quota increase such that the resulting total quota doesn't exceed the limit\n    function calcActualQuotaChange(uint96 totalQuoted, uint96 limit, int96 requestedChange)\n        internal\n        pure\n        returns (int96 quotaChange)\n    {\n        if (totalQuoted >= limit) {\n            return 0;\n        }\n\n        unchecked {\n            uint96 maxQuotaCapacity = limit - totalQuoted;\n            // The function is never called with `requestedChange < 0`, so casting it to `uint96` is safe\n            // With correct configuration, `limit < type(int96).max`, so casting `maxQuotaCapacity` to `int96` is safe\n            return uint96(requestedChange) > maxQuotaCapacity ? int96(maxQuotaCapacity) : requestedChange;\n        }\n    }\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/interfaces/IPoolV3.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Foundation, 2023.\npragma solidity ^0.8.17;\npragma abicoder v1;\n\nimport {IERC4626} from \"@openzeppelin/contracts/interfaces/IERC4626.sol\";\nimport {IERC20Permit} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\";\nimport {IVersion} from \"@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol\";\n\ninterface IPoolV3Events {\n    /// @notice Emitted when depositing liquidity with referral code\n    event Refer(address indexed onBehalfOf, uint256 indexed referralCode, uint256 amount);\n\n    /// @notice Emitted when credit account borrows funds from the pool\n    event Borrow(address indexed creditManager, address indexed creditAccount, uint256 amount);\n\n    /// @notice Emitted when credit account's debt is repaid to the pool\n    event Repay(address indexed creditManager, uint256 borrowedAmount, uint256 profit, uint256 loss);\n\n    /// @notice Emitted when incurred loss can't be fully covered by burning treasury's shares\n    event IncurUncoveredLoss(address indexed creditManager, uint256 loss);\n\n    /// @notice Emitted when new interest rate model contract is set\n    event SetInterestRateModel(address indexed newInterestRateModel);\n\n    /// @notice Emitted when new pool quota keeper contract is set\n    event SetPoolQuotaKeeper(address indexed newPoolQuotaKeeper);\n\n    /// @notice Emitted when new total debt limit is set\n    event SetTotalDebtLimit(uint256 limit);\n\n    /// @notice Emitted when new credit manager is connected to the pool\n    event AddCreditManager(address indexed creditManager);\n\n    /// @notice Emitted when new debt limit is set for a credit manager\n    event SetCreditManagerDebtLimit(address indexed creditManager, uint256 newLimit);\n\n    /// @notice Emitted when new withdrawal fee is set\n    event SetWithdrawFee(uint256 fee);\n}\n\n/// @title Pool V3 interface\ninterface IPoolV3 is IVersion, IPoolV3Events, IERC4626, IERC20Permit {\n    function addressProvider() external view returns (address);\n\n    function underlyingToken() external view returns (address);\n\n    function treasury() external view returns (address);\n\n    function withdrawFee() external view returns (uint16);\n\n    function creditManagers() external view returns (address[] memory);\n\n    function availableLiquidity() external view returns (uint256);\n\n    function expectedLiquidity() external view returns (uint256);\n\n    function expectedLiquidityLU() external view returns (uint256);\n\n    // ---------------- //\n    // ERC-4626 LENDING //\n    // ---------------- //\n\n    function depositWithReferral(uint256 assets, address receiver, uint256 referralCode)\n        external\n        returns (uint256 shares);\n\n    function mintWithReferral(uint256 shares, address receiver, uint256 referralCode)\n        external\n        returns (uint256 assets);\n\n    // --------- //\n    // BORROWING //\n    // --------- //\n\n    function totalBorrowed() external view returns (uint256);\n\n    function totalDebtLimit() external view returns (uint256);\n\n    function creditManagerBorrowed(address creditManager) external view returns (uint256);\n\n    function creditManagerDebtLimit(address creditManager) external view returns (uint256);\n\n    function creditManagerBorrowable(address creditManager) external view returns (uint256 borrowable);\n\n    function lendCreditAccount(uint256 borrowedAmount, address creditAccount) external;\n\n    function repayCreditAccount(uint256 repaidAmount, uint256 profit, uint256 loss) external;\n\n    // ------------- //\n    // INTEREST RATE //\n    // ------------- //\n\n    function interestRateModel() external view returns (address);\n\n    function baseInterestRate() external view returns (uint256);\n\n    function supplyRate() external view returns (uint256);\n\n    function baseInterestIndex() external view returns (uint256);\n\n    function baseInterestIndexLU() external view returns (uint256);\n\n    function lastBaseInterestUpdate() external view returns (uint40);\n\n    // ------ //\n    // QUOTAS //\n    // ------ //\n\n    function poolQuotaKeeper() external view returns (address);\n\n    function quotaRevenue() external view returns (uint256);\n\n    function lastQuotaRevenueUpdate() external view returns (uint40);\n\n    function updateQuotaRevenue(int256 quotaRevenueDelta) external;\n\n    function setQuotaRevenue(uint256 newQuotaRevenue) external;\n\n    // ------------- //\n    // CONFIGURATION //\n    // ------------- //\n\n    function setInterestRateModel(address newInterestRateModel) external;\n\n    function setPoolQuotaKeeper(address newPoolQuotaKeeper) external;\n\n    function setTotalDebtLimit(uint256 newLimit) external;\n\n    function setCreditManagerDebtLimit(address creditManager, uint256 newLimit) external;\n\n    function setWithdrawFee(uint256 newWithdrawFee) external;\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/interfaces/IPoolQuotaKeeperV3.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Foundation, 2023.\npragma solidity ^0.8.17;\n\nimport {IVersion} from \"@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol\";\n\nstruct TokenQuotaParams {\n    uint16 rate;\n    uint192 cumulativeIndexLU;\n    uint16 quotaIncreaseFee;\n    uint96 totalQuoted;\n    uint96 limit;\n}\n\nstruct AccountQuota {\n    uint96 quota;\n    uint192 cumulativeIndexLU;\n}\n\ninterface IPoolQuotaKeeperV3Events {\n    /// @notice Emitted when account's quota for a token is updated\n    event UpdateQuota(address indexed creditAccount, address indexed token, int96 quotaChange);\n\n    /// @notice Emitted when token's quota rate is updated\n    event UpdateTokenQuotaRate(address indexed token, uint16 rate);\n\n    /// @notice Emitted when the gauge is updated\n    event SetGauge(address indexed newGauge);\n\n    /// @notice Emitted when a new credit manager is allowed\n    event AddCreditManager(address indexed creditManager);\n\n    /// @notice Emitted when a new token is added as quoted\n    event AddQuotaToken(address indexed token);\n\n    /// @notice Emitted when a new total quota limit is set for a token\n    event SetTokenLimit(address indexed token, uint96 limit);\n\n    /// @notice Emitted when a new one-time quota increase fee is set for a token\n    event SetQuotaIncreaseFee(address indexed token, uint16 fee);\n}\n\n/// @title Pool quota keeper V3 interface\ninterface IPoolQuotaKeeperV3 is IPoolQuotaKeeperV3Events, IVersion {\n    function pool() external view returns (address);\n\n    function underlying() external view returns (address);\n\n    // ----------------- //\n    // QUOTAS MANAGEMENT //\n    // ----------------- //\n\n    function updateQuota(address creditAccount, address token, int96 requestedChange, uint96 minQuota, uint96 maxQuota)\n        external\n        returns (uint128 caQuotaInterestChange, uint128 fees, bool enableToken, bool disableToken);\n\n    function removeQuotas(address creditAccount, address[] calldata tokens, bool setLimitsToZero) external;\n\n    function accrueQuotaInterest(address creditAccount, address[] calldata tokens) external;\n\n    function getQuotaRate(address) external view returns (uint16);\n\n    function cumulativeIndex(address token) external view returns (uint192);\n\n    function isQuotedToken(address token) external view returns (bool);\n\n    function getQuota(address creditAccount, address token)\n        external\n        view\n        returns (uint96 quota, uint192 cumulativeIndexLU);\n\n    function getTokenQuotaParams(address token)\n        external\n        view\n        returns (\n            uint16 rate,\n            uint192 cumulativeIndexLU,\n            uint16 quotaIncreaseFee,\n            uint96 totalQuoted,\n            uint96 limit,\n            bool isActive\n        );\n\n    function getQuotaAndOutstandingInterest(address creditAccount, address token)\n        external\n        view\n        returns (uint96 quoted, uint128 outstandingInterest);\n\n    function poolQuotaRevenue() external view returns (uint256);\n\n    function lastQuotaRateUpdate() external view returns (uint40);\n\n    // ------------- //\n    // CONFIGURATION //\n    // ------------- //\n\n    function gauge() external view returns (address);\n\n    function setGauge(address _gauge) external;\n\n    function creditManagers() external view returns (address[] memory);\n\n    function addCreditManager(address _creditManager) external;\n\n    function quotedTokens() external view returns (address[] memory);\n\n    function addQuotaToken(address token) external;\n\n    function updateRates() external;\n\n    function setTokenLimit(address token, uint96 limit) external;\n\n    function setTokenQuotaIncreaseFee(address token, uint16 fee) external;\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/interfaces/IGaugeV3.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Foundation, 2023.\npragma solidity ^0.8.17;\n\nimport {IVersion} from \"@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol\";\n\nimport {IVotingContractV3} from \"./IVotingContractV3.sol\";\n\nstruct QuotaRateParams {\n    uint16 minRate;\n    uint16 maxRate;\n    uint96 totalVotesLpSide;\n    uint96 totalVotesCaSide;\n}\n\nstruct UserVotes {\n    uint96 votesLpSide;\n    uint96 votesCaSide;\n}\n\ninterface IGaugeV3Events {\n    /// @notice Emitted when epoch is updated\n    event UpdateEpoch(uint16 epochNow);\n\n    /// @notice Emitted when a user submits a vote\n    event Vote(address indexed user, address indexed token, uint96 votes, bool lpSide);\n\n    /// @notice Emitted when a user removes a vote\n    event Unvote(address indexed user, address indexed token, uint96 votes, bool lpSide);\n\n    /// @notice Emitted when a new quota token is added in the PoolQuotaKeeper\n    event AddQuotaToken(address indexed token, uint16 minRate, uint16 maxRate);\n\n    /// @notice Emitted when quota interest rate parameters are changed\n    event SetQuotaTokenParams(address indexed token, uint16 minRate, uint16 maxRate);\n\n    /// @notice Emitted when the frozen epoch status changes\n    event SetFrozenEpoch(bool status);\n}\n\n/// @title Gauge V3 interface\ninterface IGaugeV3 is IGaugeV3Events, IVotingContractV3, IVersion {\n    function pool() external view returns (address);\n\n    function voter() external view returns (address);\n\n    function updateEpoch() external;\n\n    function epochLastUpdate() external view returns (uint16);\n\n    function getRates(address[] calldata tokens) external view returns (uint16[] memory rates);\n\n    function userTokenVotes(address user, address token)\n        external\n        view\n        returns (uint96 votesLpSide, uint96 votesCaSide);\n\n    function quotaRateParams(address token)\n        external\n        view\n        returns (uint16 minRate, uint16 maxRate, uint96 totalVotesLpSide, uint96 totalVotesCaSide);\n\n    // ------------- //\n    // CONFIGURATION //\n    // ------------- //\n\n    function epochFrozen() external view returns (bool);\n\n    function setFrozenEpoch(bool status) external;\n\n    function isTokenAdded(address token) external view returns (bool);\n\n    function addQuotaToken(address token, uint16 minRate, uint16 maxRate) external;\n\n    function changeQuotaMinRate(address token, uint16 minRate) external;\n\n    function changeQuotaMaxRate(address token, uint16 maxRate) external;\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/interfaces/ICreditManagerV3.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Foundation, 2023.\npragma solidity ^0.8.17;\n\nimport {IVersion} from \"@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol\";\n\nuint8 constant BOT_PERMISSIONS_SET_FLAG = 1;\n\nuint8 constant DEFAULT_MAX_ENABLED_TOKENS = 4;\naddress constant INACTIVE_CREDIT_ACCOUNT_ADDRESS = address(1);\n\n/// @notice Debt management type\n///         - `INCREASE_DEBT` borrows additional funds from the pool, updates account's debt and cumulative interest index\n///         - `DECREASE_DEBT` repays debt components (quota interest and fees -> base interest and fees -> debt principal)\n///           and updates all corresponding state varibles (base interest index, quota interest and fees, debt).\n///           When repaying all the debt, ensures that account has no enabled quotas.\nenum ManageDebtAction {\n    INCREASE_DEBT,\n    DECREASE_DEBT\n}\n\n/// @notice Collateral/debt calculation mode\n///         - `GENERIC_PARAMS` returns generic data like account debt and cumulative indexes\n///         - `DEBT_ONLY` is same as `GENERIC_PARAMS` but includes more detailed debt info, like accrued base/quota\n///           interest and fees\n///         - `FULL_COLLATERAL_CHECK_LAZY` checks whether account is sufficiently collateralized in a lazy fashion,\n///           i.e. it stops iterating over collateral tokens once TWV reaches the desired target.\n///           Since it may return underestimated TWV, it's only available for internal use.\n///         - `DEBT_COLLATERAL` is same as `DEBT_ONLY` but also returns total value and total LT-weighted value of\n///           account's tokens, this mode is used during account liquidation\n///         - `DEBT_COLLATERAL_SAFE_PRICES` is same as `DEBT_COLLATERAL` but uses safe prices from price oracle\nenum CollateralCalcTask {\n    GENERIC_PARAMS,\n    DEBT_ONLY,\n    FULL_COLLATERAL_CHECK_LAZY,\n    DEBT_COLLATERAL,\n    DEBT_COLLATERAL_SAFE_PRICES\n}\n\nstruct CreditAccountInfo {\n    uint256 debt;\n    uint256 cumulativeIndexLastUpdate;\n    uint128 cumulativeQuotaInterest;\n    uint128 quotaFees;\n    uint256 enabledTokensMask;\n    uint16 flags;\n    uint64 lastDebtUpdate;\n    address borrower;\n}\n\nstruct CollateralDebtData {\n    uint256 debt;\n    uint256 cumulativeIndexNow;\n    uint256 cumulativeIndexLastUpdate;\n    uint128 cumulativeQuotaInterest;\n    uint256 accruedInterest;\n    uint256 accruedFees;\n    uint256 totalDebtUSD;\n    uint256 totalValue;\n    uint256 totalValueUSD;\n    uint256 twvUSD;\n    uint256 enabledTokensMask;\n    uint256 quotedTokensMask;\n    address[] quotedTokens;\n    address _poolQuotaKeeper;\n}\n\nstruct CollateralTokenData {\n    address token;\n    uint16 ltInitial;\n    uint16 ltFinal;\n    uint40 timestampRampStart;\n    uint24 rampDuration;\n}\n\nstruct RevocationPair {\n    address spender;\n    address token;\n}\n\ninterface ICreditManagerV3Events {\n    /// @notice Emitted when new credit configurator is set\n    event SetCreditConfigurator(address indexed newConfigurator);\n}\n\n/// @title Credit manager V3 interface\ninterface ICreditManagerV3 is IVersion, ICreditManagerV3Events {\n    function pool() external view returns (address);\n\n    function underlying() external view returns (address);\n\n    function creditFacade() external view returns (address);\n\n    function creditConfigurator() external view returns (address);\n\n    function addressProvider() external view returns (address);\n\n    function accountFactory() external view returns (address);\n\n    function name() external view returns (string memory);\n\n    // ------------------ //\n    // ACCOUNT MANAGEMENT //\n    // ------------------ //\n\n    function openCreditAccount(address onBehalfOf) external returns (address);\n\n    function closeCreditAccount(address creditAccount) external;\n\n    function liquidateCreditAccount(\n        address creditAccount,\n        CollateralDebtData calldata collateralDebtData,\n        address to,\n        bool isExpired\n    ) external returns (uint256 remainingFunds, uint256 loss);\n\n    function manageDebt(address creditAccount, uint256 amount, uint256 enabledTokensMask, ManageDebtAction action)\n        external\n        returns (uint256 newDebt, uint256 tokensToEnable, uint256 tokensToDisable);\n\n    function addCollateral(address payer, address creditAccount, address token, uint256 amount)\n        external\n        returns (uint256 tokensToEnable);\n\n    function withdrawCollateral(address creditAccount, address token, uint256 amount, address to)\n        external\n        returns (uint256 tokensToDisable);\n\n    function externalCall(address creditAccount, address target, bytes calldata callData)\n        external\n        returns (bytes memory result);\n\n    function approveToken(address creditAccount, address token, address spender, uint256 amount) external;\n\n    function revokeAdapterAllowances(address creditAccount, RevocationPair[] calldata revocations) external;\n\n    // -------- //\n    // ADAPTERS //\n    // -------- //\n\n    function adapterToContract(address adapter) external view returns (address targetContract);\n\n    function contractToAdapter(address targetContract) external view returns (address adapter);\n\n    function execute(bytes calldata data) external returns (bytes memory result);\n\n    function approveCreditAccount(address token, uint256 amount) external;\n\n    function setActiveCreditAccount(address creditAccount) external;\n\n    function getActiveCreditAccountOrRevert() external view returns (address creditAccount);\n\n    // ----------------- //\n    // COLLATERAL CHECKS //\n    // ----------------- //\n\n    function priceOracle() external view returns (address);\n\n    function fullCollateralCheck(\n        address creditAccount,\n        uint256 enabledTokensMask,\n        uint256[] calldata collateralHints,\n        uint16 minHealthFactor,\n        bool useSafePrices\n    ) external returns (uint256 enabledTokensMaskAfter);\n\n    function isLiquidatable(address creditAccount, uint16 minHealthFactor) external view returns (bool);\n\n    function calcDebtAndCollateral(address creditAccount, CollateralCalcTask task)\n        external\n        view\n        returns (CollateralDebtData memory cdd);\n\n    // ------ //\n    // QUOTAS //\n    // ------ //\n\n    function poolQuotaKeeper() external view returns (address);\n\n    function quotedTokensMask() external view returns (uint256);\n\n    function updateQuota(address creditAccount, address token, int96 quotaChange, uint96 minQuota, uint96 maxQuota)\n        external\n        returns (uint256 tokensToEnable, uint256 tokensToDisable);\n\n    // --------------------- //\n    // CREDIT MANAGER PARAMS //\n    // --------------------- //\n\n    function maxEnabledTokens() external view returns (uint8);\n\n    function fees()\n        external\n        view\n        returns (\n            uint16 feeInterest,\n            uint16 feeLiquidation,\n            uint16 liquidationDiscount,\n            uint16 feeLiquidationExpired,\n            uint16 liquidationDiscountExpired\n        );\n\n    function collateralTokensCount() external view returns (uint8);\n\n    function getTokenMaskOrRevert(address token) external view returns (uint256 tokenMask);\n\n    function getTokenByMask(uint256 tokenMask) external view returns (address token);\n\n    function liquidationThresholds(address token) external view returns (uint16 lt);\n\n    function ltParams(address token)\n        external\n        view\n        returns (uint16 ltInitial, uint16 ltFinal, uint40 timestampRampStart, uint24 rampDuration);\n\n    function collateralTokenByMask(uint256 tokenMask)\n        external\n        view\n        returns (address token, uint16 liquidationThreshold);\n\n    // ------------ //\n    // ACCOUNT INFO //\n    // ------------ //\n\n    function creditAccountInfo(address creditAccount)\n        external\n        view\n        returns (\n            uint256 debt,\n            uint256 cumulativeIndexLastUpdate,\n            uint128 cumulativeQuotaInterest,\n            uint128 quotaFees,\n            uint256 enabledTokensMask,\n            uint16 flags,\n            uint64 lastDebtUpdate,\n            address borrower\n        );\n\n    function getBorrowerOrRevert(address creditAccount) external view returns (address borrower);\n\n    function flagsOf(address creditAccount) external view returns (uint16);\n\n    function setFlagFor(address creditAccount, uint16 flag, bool value) external;\n\n    function enabledTokensMaskOf(address creditAccount) external view returns (uint256);\n\n    function creditAccounts() external view returns (address[] memory);\n\n    function creditAccounts(uint256 offset, uint256 limit) external view returns (address[] memory);\n\n    function creditAccountsLen() external view returns (uint256);\n\n    // ------------- //\n    // CONFIGURATION //\n    // ------------- //\n\n    function addToken(address token) external;\n\n    function setCollateralTokenData(\n        address token,\n        uint16 ltInitial,\n        uint16 ltFinal,\n        uint40 timestampRampStart,\n        uint24 rampDuration\n    ) external;\n\n    function setFees(\n        uint16 feeInterest,\n        uint16 feeLiquidation,\n        uint16 liquidationDiscount,\n        uint16 feeLiquidationExpired,\n        uint16 liquidationDiscountExpired\n    ) external;\n\n    function setQuotedMask(uint256 quotedTokensMask) external;\n\n    function setMaxEnabledTokens(uint8 maxEnabledTokens) external;\n\n    function setContractAllowance(address adapter, address targetContract) external;\n\n    function setCreditFacade(address creditFacade) external;\n\n    function setPriceOracle(address priceOracle) external;\n\n    function setCreditConfigurator(address creditConfigurator) external;\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v2/contracts/libraries/Constants.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Holdings, 2022\npragma solidity ^0.8.10;\n\n// Denominations\n\nuint256 constant WAD = 1e18;\nuint256 constant RAY = 1e27;\nuint16 constant PERCENTAGE_FACTOR = 1e4; //percentage plus two decimals\n\n// 25% of type(uint256).max\nuint256 constant ALLOWANCE_THRESHOLD = type(uint96).max >> 3;\n\n// FEE = 50%\nuint16 constant DEFAULT_FEE_INTEREST = 50_00; // 50%\n\n// LIQUIDATION_FEE 1.5%\nuint16 constant DEFAULT_FEE_LIQUIDATION = 1_50; // 1.5%\n\n// LIQUIDATION PREMIUM 4%\nuint16 constant DEFAULT_LIQUIDATION_PREMIUM = 4_00; // 4%\n\n// LIQUIDATION_FEE_EXPIRED 2%\nuint16 constant DEFAULT_FEE_LIQUIDATION_EXPIRED = 1_00; // 2%\n\n// LIQUIDATION PREMIUM EXPIRED 2%\nuint16 constant DEFAULT_LIQUIDATION_PREMIUM_EXPIRED = 2_00; // 2%\n\n// DEFAULT PROPORTION OF MAX BORROWED PER BLOCK TO MAX BORROWED PER ACCOUNT\nuint16 constant DEFAULT_LIMIT_PER_BLOCK_MULTIPLIER = 2;\n\n// Seconds in a year\nuint256 constant SECONDS_PER_YEAR = 365 days;\nuint256 constant SECONDS_PER_ONE_AND_HALF_YEAR = (SECONDS_PER_YEAR * 3) / 2;\n\n// OPERATIONS\n\n// Leverage decimals - 100 is equal to 2x leverage (100% * collateral amount + 100% * borrowed amount)\nuint8 constant LEVERAGE_DECIMALS = 100;\n\n// Maximum withdraw fee for pool in PERCENTAGE_FACTOR format\nuint8 constant MAX_WITHDRAW_FEE = 100;\n\nuint256 constant EXACT_INPUT = 1;\nuint256 constant EXACT_OUTPUT = 2;\n\naddress constant UNIVERSAL_CONTRACT = 0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC;\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/interfaces/IExceptions.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Foundation, 2023.\npragma solidity ^0.8.17;\n\n// ------- //\n// GENERAL //\n// ------- //\n\n/// @notice Thrown on attempting to set an important address to zero address\nerror ZeroAddressException();\n\n/// @notice Thrown when attempting to pass a zero amount to a funding-related operation\nerror AmountCantBeZeroException();\n\n/// @notice Thrown on incorrect input parameter\nerror IncorrectParameterException();\n\n/// @notice Thrown when balance is insufficient to perform an operation\nerror InsufficientBalanceException();\n\n/// @notice Thrown if parameter is out of range\nerror ValueOutOfRangeException();\n\n/// @notice Thrown when trying to send ETH to a contract that is not allowed to receive ETH directly\nerror ReceiveIsNotAllowedException();\n\n/// @notice Thrown on attempting to set an EOA as an important contract in the system\nerror AddressIsNotContractException(address);\n\n/// @notice Thrown on attempting to receive a token that is not a collateral token or was forbidden\nerror TokenNotAllowedException();\n\n/// @notice Thrown on attempting to add a token that is already in a collateral list\nerror TokenAlreadyAddedException();\n\n/// @notice Thrown when attempting to use quota-related logic for a token that is not quoted in quota keeper\nerror TokenIsNotQuotedException();\n\n/// @notice Thrown on attempting to interact with an address that is not a valid target contract\nerror TargetContractNotAllowedException();\n\n/// @notice Thrown if function is not implemented\nerror NotImplementedException();\n\n// ------------------ //\n// CONTRACTS REGISTER //\n// ------------------ //\n\n/// @notice Thrown when an address is expected to be a registered credit manager, but is not\nerror RegisteredCreditManagerOnlyException();\n\n/// @notice Thrown when an address is expected to be a registered pool, but is not\nerror RegisteredPoolOnlyException();\n\n// ---------------- //\n// ADDRESS PROVIDER //\n// ---------------- //\n\n/// @notice Reverts if address key isn't found in address provider\nerror AddressNotFoundException();\n\n// ----------------- //\n// POOL, PQK, GAUGES //\n// ----------------- //\n\n/// @notice Thrown by pool-adjacent contracts when a credit manager being connected has a wrong pool address\nerror IncompatibleCreditManagerException();\n\n/// @notice Thrown when attempting to set an incompatible successor staking contract\nerror IncompatibleSuccessorException();\n\n/// @notice Thrown when attempting to vote in a non-approved contract\nerror VotingContractNotAllowedException();\n\n/// @notice Thrown when attempting to unvote more votes than there are\nerror InsufficientVotesException();\n\n/// @notice Thrown when attempting to borrow more than the second point on a two-point curve\nerror BorrowingMoreThanU2ForbiddenException();\n\n/// @notice Thrown when a credit manager attempts to borrow more than its limit in the current block, or in general\nerror CreditManagerCantBorrowException();\n\n/// @notice Thrown when attempting to connect a quota keeper to an incompatible pool\nerror IncompatiblePoolQuotaKeeperException();\n\n/// @notice Thrown when the quota is outside of min/max bounds\nerror QuotaIsOutOfBoundsException();\n\n// -------------- //\n// CREDIT MANAGER //\n// -------------- //\n\n/// @notice Thrown on failing a full collateral check after multicall\nerror NotEnoughCollateralException();\n\n/// @notice Thrown if an attempt to approve a collateral token to adapter's target contract fails\nerror AllowanceFailedException();\n\n/// @notice Thrown on attempting to perform an action for a credit account that does not exist\nerror CreditAccountDoesNotExistException();\n\n/// @notice Thrown on configurator attempting to add more than 255 collateral tokens\nerror TooManyTokensException();\n\n/// @notice Thrown if more than the maximum number of tokens were enabled on a credit account\nerror TooManyEnabledTokensException();\n\n/// @notice Thrown when attempting to execute a protocol interaction without active credit account set\nerror ActiveCreditAccountNotSetException();\n\n/// @notice Thrown when trying to update credit account's debt more than once in the same block\nerror DebtUpdatedTwiceInOneBlockException();\n\n/// @notice Thrown when trying to repay all debt while having active quotas\nerror DebtToZeroWithActiveQuotasException();\n\n/// @notice Thrown when a zero-debt account attempts to update quota\nerror UpdateQuotaOnZeroDebtAccountException();\n\n/// @notice Thrown when attempting to close an account with non-zero debt\nerror CloseAccountWithNonZeroDebtException();\n\n/// @notice Thrown when value of funds remaining on the account after liquidation is insufficient\nerror InsufficientRemainingFundsException();\n\n/// @notice Thrown when Credit Facade tries to write over a non-zero active Credit Account\nerror ActiveCreditAccountOverridenException();\n\n// ------------------- //\n// CREDIT CONFIGURATOR //\n// ------------------- //\n\n/// @notice Thrown on attempting to use a non-ERC20 contract or an EOA as a token\nerror IncorrectTokenContractException();\n\n/// @notice Thrown if the newly set LT if zero or greater than the underlying's LT\nerror IncorrectLiquidationThresholdException();\n\n/// @notice Thrown if borrowing limits are incorrect: minLimit > maxLimit or maxLimit > blockLimit\nerror IncorrectLimitsException();\n\n/// @notice Thrown if the new expiration date is less than the current expiration date or current timestamp\nerror IncorrectExpirationDateException();\n\n/// @notice Thrown if a contract returns a wrong credit manager or reverts when trying to retrieve it\nerror IncompatibleContractException();\n\n/// @notice Thrown if attempting to forbid an adapter that is not registered in the credit manager\nerror AdapterIsNotRegisteredException();\n\n// ------------- //\n// CREDIT FACADE //\n// ------------- //\n\n/// @notice Thrown when attempting to perform an action that is forbidden in whitelisted mode\nerror ForbiddenInWhitelistedModeException();\n\n/// @notice Thrown if credit facade is not expirable, and attempted aciton requires expirability\nerror NotAllowedWhenNotExpirableException();\n\n/// @notice Thrown if a selector that doesn't match any allowed function is passed to the credit facade in a multicall\nerror UnknownMethodException();\n\n/// @notice Thrown when trying to close an account with enabled tokens\nerror CloseAccountWithEnabledTokensException();\n\n/// @notice Thrown if a liquidator tries to liquidate an account with a health factor above 1\nerror CreditAccountNotLiquidatableException();\n\n/// @notice Thrown if too much new debt was taken within a single block\nerror BorrowedBlockLimitException();\n\n/// @notice Thrown if the new debt principal for a credit account falls outside of borrowing limits\nerror BorrowAmountOutOfLimitsException();\n\n/// @notice Thrown if a user attempts to open an account via an expired credit facade\nerror NotAllowedAfterExpirationException();\n\n/// @notice Thrown if expected balances are attempted to be set twice without performing a slippage check\nerror ExpectedBalancesAlreadySetException();\n\n/// @notice Thrown if attempting to perform a slippage check when excepted balances are not set\nerror ExpectedBalancesNotSetException();\n\n/// @notice Thrown if balance of at least one token is less than expected during a slippage check\nerror BalanceLessThanExpectedException();\n\n/// @notice Thrown when trying to perform an action that is forbidden when credit account has enabled forbidden tokens\nerror ForbiddenTokensException();\n\n/// @notice Thrown when new forbidden tokens are enabled during the multicall\nerror ForbiddenTokenEnabledException();\n\n/// @notice Thrown when enabled forbidden token balance is increased during the multicall\nerror ForbiddenTokenBalanceIncreasedException();\n\n/// @notice Thrown when the remaining token balance is increased during the liquidation\nerror RemainingTokenBalanceIncreasedException();\n\n/// @notice Thrown if `botMulticall` is called by an address that is not approved by account owner or is forbidden\nerror NotApprovedBotException();\n\n/// @notice Thrown when attempting to perform a multicall action with no permission for it\nerror NoPermissionException(uint256 permission);\n\n/// @notice Thrown when attempting to give a bot unexpected permissions\nerror UnexpectedPermissionsException();\n\n/// @notice Thrown when a custom HF parameter lower than 10000 is passed into the full collateral check\nerror CustomHealthFactorTooLowException();\n\n/// @notice Thrown when submitted collateral hint is not a valid token mask\nerror InvalidCollateralHintException();\n\n// ------ //\n// ACCESS //\n// ------ //\n\n/// @notice Thrown on attempting to call an access restricted function not as credit account owner\nerror CallerNotCreditAccountOwnerException();\n\n/// @notice Thrown on attempting to call an access restricted function not as configurator\nerror CallerNotConfiguratorException();\n\n/// @notice Thrown on attempting to call an access-restructed function not as account factory\nerror CallerNotAccountFactoryException();\n\n/// @notice Thrown on attempting to call an access restricted function not as credit manager\nerror CallerNotCreditManagerException();\n\n/// @notice Thrown on attempting to call an access restricted function not as credit facade\nerror CallerNotCreditFacadeException();\n\n/// @notice Thrown on attempting to call an access restricted function not as controller or configurator\nerror CallerNotControllerException();\n\n/// @notice Thrown on attempting to pause a contract without pausable admin rights\nerror CallerNotPausableAdminException();\n\n/// @notice Thrown on attempting to unpause a contract without unpausable admin rights\nerror CallerNotUnpausableAdminException();\n\n/// @notice Thrown on attempting to call an access restricted function not as gauge\nerror CallerNotGaugeException();\n\n/// @notice Thrown on attempting to call an access restricted function not as quota keeper\nerror CallerNotPoolQuotaKeeperException();\n\n/// @notice Thrown on attempting to call an access restricted function not as voter\nerror CallerNotVoterException();\n\n/// @notice Thrown on attempting to call an access restricted function not as allowed adapter\nerror CallerNotAdapterException();\n\n/// @notice Thrown on attempting to call an access restricted function not as migrator\nerror CallerNotMigratorException();\n\n/// @notice Thrown when an address that is not the designated executor attempts to execute a transaction\nerror CallerNotExecutorException();\n\n/// @notice Thrown on attempting to call an access restricted function not as veto admin\nerror CallerNotVetoAdminException();\n\n// ------------------- //\n// CONTROLLER TIMELOCK //\n// ------------------- //\n\n/// @notice Thrown when the new parameter values do not satisfy required conditions\nerror ParameterChecksFailedException();\n\n/// @notice Thrown when attempting to execute a non-queued transaction\nerror TxNotQueuedException();\n\n/// @notice Thrown when attempting to execute a transaction that is either immature or stale\nerror TxExecutedOutsideTimeWindowException();\n\n/// @notice Thrown when execution of a transaction fails\nerror TxExecutionRevertedException();\n\n/// @notice Thrown when the value of a parameter on execution is different from the value on queue\nerror ParameterChangedAfterQueuedTxException();\n\n// -------- //\n// BOT LIST //\n// -------- //\n\n/// @notice Thrown when attempting to set non-zero permissions for a forbidden or special bot\nerror InvalidBotException();\n\n// --------------- //\n// ACCOUNT FACTORY //\n// --------------- //\n\n/// @notice Thrown when trying to deploy second master credit account for a credit manager\nerror MasterCreditAccountAlreadyDeployedException();\n\n/// @notice Thrown when trying to rescue funds from a credit account that is currently in use\nerror CreditAccountIsInUseException();\n\n// ------------ //\n// PRICE ORACLE //\n// ------------ //\n\n/// @notice Thrown on attempting to set a token price feed to an address that is not a correct price feed\nerror IncorrectPriceFeedException();\n\n/// @notice Thrown on attempting to interact with a price feed for a token not added to the price oracle\nerror PriceFeedDoesNotExistException();\n\n/// @notice Thrown when price feed returns incorrect price for a token\nerror IncorrectPriceException();\n\n/// @notice Thrown when token's price feed becomes stale\nerror StalePriceException();\n"
      },
      "node_modules/@openzeppelin/contracts/security/Pausable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    bool private _paused;\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    constructor() {\n        _paused = false;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        require(!paused(), \"Pausable: paused\");\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        require(paused(), \"Pausable: not paused\");\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v2/contracts/interfaces/IACL.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Holdings, 2022\npragma solidity ^0.8.10;\nimport { IVersion } from \"./IVersion.sol\";\n\ninterface IACLExceptions {\n    /// @dev Thrown when attempting to delete an address from a set that is not a pausable admin\n    error AddressNotPausableAdminException(address addr);\n\n    /// @dev Thrown when attempting to delete an address from a set that is not a unpausable admin\n    error AddressNotUnpausableAdminException(address addr);\n}\n\ninterface IACLEvents {\n    /// @dev Emits when a new admin is added that can pause contracts\n    event PausableAdminAdded(address indexed newAdmin);\n\n    /// @dev Emits when a Pausable admin is removed\n    event PausableAdminRemoved(address indexed admin);\n\n    /// @dev Emits when a new admin is added that can unpause contracts\n    event UnpausableAdminAdded(address indexed newAdmin);\n\n    /// @dev Emits when an Unpausable admin is removed\n    event UnpausableAdminRemoved(address indexed admin);\n}\n\n/// @title ACL interface\ninterface IACL is IACLEvents, IACLExceptions, IVersion {\n    /// @dev Returns true if the address is a pausable admin and false if not\n    /// @param addr Address to check\n    function isPausableAdmin(address addr) external view returns (bool);\n\n    /// @dev Returns true if the address is unpausable admin and false if not\n    /// @param addr Address to check\n    function isUnpausableAdmin(address addr) external view returns (bool);\n\n    /// @dev Returns true if an address has configurator rights\n    /// @param account Address to check\n    function isConfigurator(address account) external view returns (bool);\n\n    /// @dev Returns address of configurator\n    function owner() external view returns (address);\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/traits/ACLTrait.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Foundation, 2023.\npragma solidity ^0.8.17;\n\nimport {IACL} from \"@gearbox-protocol/core-v2/contracts/interfaces/IACL.sol\";\n\nimport {AP_ACL, IAddressProviderV3, NO_VERSION_CONTROL} from \"../interfaces/IAddressProviderV3.sol\";\nimport {CallerNotConfiguratorException} from \"../interfaces/IExceptions.sol\";\n\nimport {SanityCheckTrait} from \"./SanityCheckTrait.sol\";\n\n/// @title ACL trait\n/// @notice Utility class for ACL (access-control list) consumers\nabstract contract ACLTrait is SanityCheckTrait {\n    /// @notice ACL contract address\n    address public immutable acl;\n\n    /// @notice Constructor\n    /// @param addressProvider Address provider contract address\n    constructor(address addressProvider) nonZeroAddress(addressProvider) {\n        acl = IAddressProviderV3(addressProvider).getAddressOrRevert(AP_ACL, NO_VERSION_CONTROL);\n    }\n\n    /// @dev Ensures that function caller has configurator role\n    modifier configuratorOnly() {\n        _ensureCallerIsConfigurator();\n        _;\n    }\n\n    /// @dev Reverts if the caller is not the configurator\n    /// @dev Used to cut contract size on modifiers\n    function _ensureCallerIsConfigurator() internal view {\n        if (!_isConfigurator({account: msg.sender})) {\n            revert CallerNotConfiguratorException();\n        }\n    }\n\n    /// @dev Checks whether given account has configurator role\n    function _isConfigurator(address account) internal view returns (bool) {\n        return IACL(acl).isConfigurator(account);\n    }\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/traits/ReentrancyGuardTrait.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Foundation, 2023.\npragma solidity ^0.8.17;\n\nuint8 constant NOT_ENTERED = 1;\nuint8 constant ENTERED = 2;\n\n/// @title Reentrancy guard trait\n/// @notice Same as OpenZeppelin's `ReentrancyGuard` but only uses 1 byte of storage instead of 32\nabstract contract ReentrancyGuardTrait {\n    uint8 internal _reentrancyStatus = NOT_ENTERED;\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    modifier nonReentrant() {\n        // On the first call to nonReentrant, _notEntered will be true\n        _ensureNotEntered();\n\n        // Any calls to nonReentrant after this point will fail\n        _reentrancyStatus = ENTERED;\n\n        _;\n\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _reentrancyStatus = NOT_ENTERED;\n    }\n\n    /// @dev Reverts if the contract is currently entered\n    /// @dev Used to cut contract size on modifiers\n    function _ensureNotEntered() internal view {\n        require(_reentrancyStatus != ENTERED, \"ReentrancyGuard: reentrant call\");\n    }\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v2/contracts/interfaces/IContractsRegister.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Holdings, 2022\npragma solidity ^0.8.10;\nimport { IVersion } from \"./IVersion.sol\";\n\ninterface IContractsRegisterEvents {\n    /// @dev Emits when a new pool is registered in the system\n    event NewPoolAdded(address indexed pool);\n\n    /// @dev Emits when a new Credit Manager is registered in the system\n    event NewCreditManagerAdded(address indexed creditManager);\n}\n\ninterface IContractsRegister is IContractsRegisterEvents, IVersion {\n    //\n    // POOLS\n    //\n\n    /// @dev Returns the array of registered pools\n    function getPools() external view returns (address[] memory);\n\n    /// @dev Returns a pool address from the list under the passed index\n    /// @param i Index of the pool to retrieve\n    function pools(uint256 i) external view returns (address);\n\n    /// @return Returns the number of registered pools\n    function getPoolsCount() external view returns (uint256);\n\n    /// @dev Returns true if the passed address is a pool\n    function isPool(address) external view returns (bool);\n\n    //\n    // CREDIT MANAGERS\n    //\n\n    /// @dev Returns the array of registered Credit Managers\n    function getCreditManagers() external view returns (address[] memory);\n\n    /// @dev Returns a Credit Manager's address from the list under the passed index\n    /// @param i Index of the Credit Manager to retrieve\n    function creditManagers(uint256 i) external view returns (address);\n\n    /// @return Returns the number of registered Credit Managers\n    function getCreditManagersCount() external view returns (uint256);\n\n    /// @dev Returns true if the passed address is a Credit Manager\n    function isCreditManager(address) external view returns (bool);\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/interfaces/IAddressProviderV3.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Foundation, 2023.\npragma solidity ^0.8.17;\n\nimport {IVersion} from \"@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol\";\n\nuint256 constant NO_VERSION_CONTROL = 0;\n\nbytes32 constant AP_CONTRACTS_REGISTER = \"CONTRACTS_REGISTER\";\nbytes32 constant AP_ACL = \"ACL\";\nbytes32 constant AP_PRICE_ORACLE = \"PRICE_ORACLE\";\nbytes32 constant AP_ACCOUNT_FACTORY = \"ACCOUNT_FACTORY\";\nbytes32 constant AP_DATA_COMPRESSOR = \"DATA_COMPRESSOR\";\nbytes32 constant AP_TREASURY = \"TREASURY\";\nbytes32 constant AP_GEAR_TOKEN = \"GEAR_TOKEN\";\nbytes32 constant AP_WETH_TOKEN = \"WETH_TOKEN\";\nbytes32 constant AP_WETH_GATEWAY = \"WETH_GATEWAY\";\nbytes32 constant AP_ROUTER = \"ROUTER\";\nbytes32 constant AP_BOT_LIST = \"BOT_LIST\";\nbytes32 constant AP_GEAR_STAKING = \"GEAR_STAKING\";\nbytes32 constant AP_ZAPPER_REGISTER = \"ZAPPER_REGISTER\";\n\ninterface IAddressProviderV3Events {\n    /// @notice Emitted when an address is set for a contract key\n    event SetAddress(bytes32 indexed key, address indexed value, uint256 indexed version);\n}\n\n/// @title Address provider V3 interface\ninterface IAddressProviderV3 is IAddressProviderV3Events, IVersion {\n    function addresses(bytes32 key, uint256 _version) external view returns (address);\n\n    function getAddressOrRevert(bytes32 key, uint256 _version) external view returns (address result);\n\n    function setAddress(bytes32 key, address value, bool saveVersion) external;\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/traits/SanityCheckTrait.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Foundation, 2023.\npragma solidity ^0.8.17;\n\nimport {ZeroAddressException} from \"../interfaces/IExceptions.sol\";\n\n/// @title Sanity check trait\nabstract contract SanityCheckTrait {\n    /// @dev Ensures that passed address is non-zero\n    modifier nonZeroAddress(address addr) {\n        _revertIfZeroAddress(addr);\n        _;\n    }\n\n    /// @dev Reverts if address is zero\n    function _revertIfZeroAddress(address addr) private pure {\n        if (addr == address(0)) revert ZeroAddressException();\n    }\n}\n"
      },
      "node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value >= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n"
      },
      "node_modules/@openzeppelin/contracts/interfaces/IERC4626.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC4626.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../token/ERC20/IERC20.sol\";\nimport \"../token/ERC20/extensions/IERC20Metadata.sol\";\n\n/**\n * @dev Interface of the ERC4626 \"Tokenized Vault Standard\", as defined in\n * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].\n *\n * _Available since v4.7._\n */\ninterface IERC4626 is IERC20, IERC20Metadata {\n    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);\n\n    event Withdraw(\n        address indexed sender,\n        address indexed receiver,\n        address indexed owner,\n        uint256 assets,\n        uint256 shares\n    );\n\n    /**\n     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.\n     *\n     * - MUST be an ERC-20 token contract.\n     * - MUST NOT revert.\n     */\n    function asset() external view returns (address assetTokenAddress);\n\n    /**\n     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.\n     *\n     * - SHOULD include any compounding that occurs from yield.\n     * - MUST be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT revert.\n     */\n    function totalAssets() external view returns (uint256 totalManagedAssets);\n\n    /**\n     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToShares(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToAssets(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,\n     * through a deposit call.\n     *\n     * - MUST return a limited value if receiver is subject to some deposit limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.\n     * - MUST NOT revert.\n     */\n    function maxDeposit(address receiver) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit\n     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called\n     *   in the same transaction.\n     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the\n     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewDeposit(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   deposit execution, and are accounted for during deposit.\n     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function deposit(uint256 assets, address receiver) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.\n     * - MUST return a limited value if receiver is subject to some mint limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.\n     * - MUST NOT revert.\n     */\n    function maxMint(address receiver) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call\n     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the\n     *   same transaction.\n     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint\n     *   would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by minting.\n     */\n    function previewMint(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint\n     *   execution, and are accounted for during mint.\n     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function mint(uint256 shares, address receiver) external returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the\n     * Vault, through a withdraw call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxWithdraw(address owner) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw\n     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if\n     *   called\n     *   in the same transaction.\n     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though\n     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewWithdraw(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   withdraw execution, and are accounted for during withdraw.\n     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,\n     * through a redeem call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxRedeem(address owner) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call\n     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the\n     *   same transaction.\n     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the\n     *   redemption would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.\n     */\n    function previewRedeem(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   redeem execution, and are accounted for during redeem.\n     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);\n}\n"
      },
      "node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Holdings, 2022\npragma solidity ^0.8.10;\n\n/// @title Version interface\n/// @notice Defines contract version\ninterface IVersion {\n    /// @notice Contract version\n    function version() external view returns (uint256);\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/interfaces/IVotingContractV3.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Foundation, 2023.\npragma solidity ^0.8.17;\n\ninterface IVotingContractV3 {\n    function vote(address user, uint96 votes, bytes calldata extraData) external;\n    function unvote(address user, uint96 votes, bytes calldata extraData) external;\n}\n"
      },
      "node_modules/@openzeppelin/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\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 Context {\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"
      },
      "node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\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.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "@1inch/=node_modules/@1inch/",
        "@arbitrum/=node_modules/@arbitrum/",
        "@chainlink/=node_modules/@chainlink/",
        "@eth-optimism/=node_modules/@eth-optimism/",
        "@gearbox-protocol/=node_modules/@gearbox-protocol/",
        "@openzeppelin/=node_modules/@openzeppelin/",
        "@redstone-finance/=node_modules/@redstone-finance/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "eth-gas-reporter/=node_modules/eth-gas-reporter/",
        "forge-std/=lib/forge-std/src/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 1000
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs"
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "london",
      "libraries": {}
    }
  }}