creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "node_modules/@gearbox-protocol/core-v3/contracts/credit/CreditFacadeV3.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\n// THIRD-PARTY\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\nimport {SafeCast} from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IERC20Permit} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\";\nimport {SafeERC20} from \"@1inch/solidity-utils/contracts/libraries/SafeERC20.sol\";\n\n// LIBS & TRAITS\nimport {BalancesLogic, Balance, BalanceDelta, BalanceWithMask, Comparison} from \"../libraries/BalancesLogic.sol\";\nimport {ACLNonReentrantTrait} from \"../traits/ACLNonReentrantTrait.sol\";\nimport {BitMask, UNDERLYING_TOKEN_MASK} from \"../libraries/BitMask.sol\";\n\n// INTERFACES\nimport \"../interfaces/ICreditFacadeV3.sol\";\nimport \"../interfaces/IAddressProviderV3.sol\";\nimport {\n    ICreditManagerV3,\n    ManageDebtAction,\n    RevocationPair,\n    CollateralDebtData,\n    CollateralCalcTask,\n    BOT_PERMISSIONS_SET_FLAG,\n    INACTIVE_CREDIT_ACCOUNT_ADDRESS\n} from \"../interfaces/ICreditManagerV3.sol\";\nimport {AllowanceAction} from \"../interfaces/ICreditConfiguratorV3.sol\";\nimport {IPriceOracleV3} from \"../interfaces/IPriceOracleV3.sol\";\nimport {IUpdatablePriceFeed} from \"@gearbox-protocol/core-v2/contracts/interfaces/IPriceFeed.sol\";\n\nimport {IPoolV3} from \"../interfaces/IPoolV3.sol\";\nimport {IDegenNFTV2} from \"@gearbox-protocol/core-v2/contracts/interfaces/IDegenNFTV2.sol\";\nimport {IWETH} from \"@gearbox-protocol/core-v2/contracts/interfaces/external/IWETH.sol\";\nimport {IBotListV3} from \"../interfaces/IBotListV3.sol\";\n\n// CONSTANTS\nimport {PERCENTAGE_FACTOR} from \"@gearbox-protocol/core-v2/contracts/libraries/Constants.sol\";\n\n// EXCEPTIONS\nimport \"../interfaces/IExceptions.sol\";\n\nuint256 constant OPEN_CREDIT_ACCOUNT_FLAGS = ALL_PERMISSIONS & ~DECREASE_DEBT_PERMISSION;\n\nuint256 constant CLOSE_CREDIT_ACCOUNT_FLAGS = ALL_PERMISSIONS & ~INCREASE_DEBT_PERMISSION;\n\nuint256 constant LIQUIDATE_CREDIT_ACCOUNT_FLAGS =\n    EXTERNAL_CALLS_PERMISSION | ADD_COLLATERAL_PERMISSION | WITHDRAW_COLLATERAL_PERMISSION;\n\n/// @title Credit facade V3\n/// @notice Provides a user interface to open, close and liquidate leveraged positions in the credit manager,\n///         and implements the main entry-point for credit accounts management: multicall.\n/// @notice Multicall allows account owners to batch all the desired operations (adding or withdrawing collateral,\n///         changing debt size, interacting with external protocols via adapters or increasing quotas) into one call,\n///         followed by the collateral check that ensures that account is sufficiently collateralized.\n///         For more details on what one can achieve with multicalls, see `_multicall` and  `ICreditFacadeV3Multicall`.\n/// @notice Users can also let external bots manage their accounts via `botMulticall`. Bots can be relatively general,\n///         the facade only ensures that they can do no harm to the protocol by running the collateral check after the\n///         multicall and checking the permissions given to them by users. See `BotListV3` for additional details.\n/// @notice Credit facade implements a few safeguards on top of those present in the credit manager, including debt and\n///         quota size validation, pausing on large protocol losses, Degen NFT whitelist mode, and forbidden tokens\n///         (they count towards account value, but having them enabled as collateral restricts available actions and\n///         activates a safer version of collateral check).\ncontract CreditFacadeV3 is ICreditFacadeV3, ACLNonReentrantTrait {\n    using Address for address;\n    using Address for address payable;\n    using BitMask for uint256;\n    using SafeCast for uint256;\n    using SafeERC20 for IERC20;\n\n    /// @notice Contract version\n    uint256 public constant override version = 3_00;\n\n    /// @notice Maximum quota size, as a multiple of `maxDebt`\n    uint256 public constant override maxQuotaMultiplier = 2;\n\n    /// @notice Credit manager connected to this credit facade\n    address public immutable override creditManager;\n\n    /// @notice Whether credit facade is expirable\n    bool public immutable override expirable;\n\n    /// @notice WETH token address\n    address public immutable override weth;\n\n    /// @notice Degen NFT address\n    address public immutable override degenNFT;\n\n    /// @notice Expiration timestamp\n    uint40 public override expirationDate;\n\n    /// @notice Maximum amount that can be borrowed by a credit manager in a single block, as a multiple of `maxDebt`\n    uint8 public override maxDebtPerBlockMultiplier;\n\n    /// @notice Last block when underlying was borrowed by a credit manager\n    uint64 internal lastBlockBorrowed;\n\n    /// @notice The total amount borrowed by a credit manager in `lastBlockBorrowed`\n    uint128 internal totalBorrowedInBlock;\n\n    /// @notice Bot list address\n    address public override botList;\n\n    /// @notice Credit account debt limits packed into a single slot\n    DebtLimits public override debtLimits;\n\n    /// @notice Bit mask encoding a set of forbidden tokens\n    uint256 public override forbiddenTokenMask;\n\n    /// @notice Info on bad debt liquidation losses packed into a single slot\n    CumulativeLossParams public override lossParams;\n\n    /// @notice Mapping account => emergency liquidator status\n    mapping(address => bool) public override canLiquidateWhilePaused;\n\n    /// @dev Ensures that function caller is credit configurator\n    modifier creditConfiguratorOnly() {\n        _checkCreditConfigurator();\n        _;\n    }\n\n    /// @dev Ensures that function caller is `creditAccount`'s owner\n    modifier creditAccountOwnerOnly(address creditAccount) {\n        _checkCreditAccountOwner(creditAccount);\n        _;\n    }\n\n    /// @dev Ensures that function can't be called when the contract is paused, unless caller is an emergency liquidator\n    modifier whenNotPausedOrEmergency() {\n        require(!paused() || canLiquidateWhilePaused[msg.sender], \"Pausable: paused\");\n        _;\n    }\n\n    /// @dev Ensures that function can't be called when the contract is expired\n    modifier whenNotExpired() {\n        _checkExpired();\n        _;\n    }\n\n    /// @dev Wraps any ETH sent in a function call and sends it back to the caller\n    modifier wrapETH() {\n        _wrapETH();\n        _;\n    }\n\n    /// @notice Constructor\n    /// @param _creditManager Credit manager to connect this facade to\n    /// @param _degenNFT Degen NFT address or `address(0)`\n    /// @param _expirable Whether this facade should be expirable\n    constructor(address _creditManager, address _degenNFT, bool _expirable)\n        ACLNonReentrantTrait(ICreditManagerV3(_creditManager).addressProvider())\n    {\n        creditManager = _creditManager; // U:[FA-1]\n\n        address addressProvider = ICreditManagerV3(_creditManager).addressProvider();\n        weth = IAddressProviderV3(addressProvider).getAddressOrRevert(AP_WETH_TOKEN, NO_VERSION_CONTROL); // U:[FA-1]\n        botList = IAddressProviderV3(addressProvider).getAddressOrRevert(AP_BOT_LIST, 3_00); // U:[FA-1]\n\n        degenNFT = _degenNFT; // U:[FA-1]\n\n        expirable = _expirable; // U:[FA-1]\n    }\n\n    // ------------------ //\n    // ACCOUNT MANAGEMENT //\n    // ------------------ //\n\n    /// @notice Opens a new credit account\n    ///         - Wraps any ETH sent in the function call and sends it back to the caller\n    ///         - If Degen NFT is enabled, burns one from the caller\n    ///         - Opens an account in the credit manager\n    ///         - Performs a multicall (all calls allowed except debt decrease and withdrawals)\n    ///         - Runs the collateral check\n    /// @param onBehalfOf Address on whose behalf to open the account\n    /// @param calls List of calls to perform after opening the account\n    /// @param referralCode Referral code to use for potential rewards, 0 if no referral code is provided\n    /// @return creditAccount Address of the newly opened account\n    /// @dev Reverts if credit facade is paused or expired\n    /// @dev Reverts if `onBehalfOf` is not caller while Degen NFT is enabled\n    function openCreditAccount(address onBehalfOf, MultiCall[] calldata calls, uint256 referralCode)\n        external\n        payable\n        override\n        whenNotPaused // U:[FA-2]\n        whenNotExpired // U:[FA-3]\n        nonReentrant // U:[FA-4]\n        wrapETH // U:[FA-7]\n        returns (address creditAccount)\n    {\n        if (degenNFT != address(0)) {\n            if (msg.sender != onBehalfOf) {\n                revert ForbiddenInWhitelistedModeException(); // U:[FA-9]\n            }\n            IDegenNFTV2(degenNFT).burn(onBehalfOf, 1); // U:[FA-9]\n        }\n\n        creditAccount = ICreditManagerV3(creditManager).openCreditAccount({onBehalfOf: onBehalfOf}); // U:[FA-10]\n\n        emit OpenCreditAccount(creditAccount, onBehalfOf, msg.sender, referralCode); // U:[FA-10]\n\n        if (calls.length != 0) {\n            // same as `_multicallFullCollateralCheck` but leverages the fact that account is freshly opened to save gas\n            BalanceWithMask[] memory forbiddenBalances;\n\n            uint256 skipCalls = _applyOnDemandPriceUpdates(calls);\n            FullCheckParams memory fullCheckParams = _multicall({\n                creditAccount: creditAccount,\n                calls: calls,\n                enabledTokensMask: 0,\n                flags: OPEN_CREDIT_ACCOUNT_FLAGS,\n                skip: skipCalls\n            }); // U:[FA-10]\n\n            _fullCollateralCheck({\n                creditAccount: creditAccount,\n                enabledTokensMaskBefore: 0,\n                fullCheckParams: fullCheckParams,\n                forbiddenBalances: forbiddenBalances,\n                forbiddenTokensMask: forbiddenTokenMask\n            }); // U:[FA-10]\n        }\n    }\n\n    /// @notice Closes a credit account\n    ///         - Wraps any ETH sent in the function call and sends it back to the caller\n    ///         - Performs a multicall (all calls are allowed except debt increase)\n    ///         - Closes a credit account in the credit manager\n    ///         - Erases all bots permissions\n    /// @param creditAccount Account to close\n    /// @param calls List of calls to perform before closing the account\n    /// @dev Reverts if `creditAccount` is not opened in connected credit manager by caller\n    /// @dev Reverts if facade is paused\n    /// @dev Reverts if account has enabled tokens after executing `calls`\n    /// @dev Reverts if account's debt is not zero after executing `calls`\n    function closeCreditAccount(address creditAccount, MultiCall[] calldata calls)\n        external\n        payable\n        override\n        creditAccountOwnerOnly(creditAccount) // U:[FA-5]\n        whenNotPaused // U:[FA-2]\n        nonReentrant // U:[FA-4]\n        wrapETH // U:[FA-7]\n    {\n        uint256 enabledTokensMask = _enabledTokensMaskOf(creditAccount);\n\n        if (calls.length != 0) {\n            FullCheckParams memory fullCheckParams =\n                _multicall(creditAccount, calls, enabledTokensMask, CLOSE_CREDIT_ACCOUNT_FLAGS, 0); // U:[FA-11]\n            enabledTokensMask = fullCheckParams.enabledTokensMaskAfter;\n        }\n\n        if (enabledTokensMask != 0) revert CloseAccountWithEnabledTokensException(); // U:[FA-11]\n\n        if (_flagsOf(creditAccount) & BOT_PERMISSIONS_SET_FLAG != 0) {\n            IBotListV3(botList).eraseAllBotPermissions(creditManager, creditAccount); // U:[FA-11]\n        }\n\n        ICreditManagerV3(creditManager).closeCreditAccount(creditAccount); // U:[FA-11]\n\n        emit CloseCreditAccount(creditAccount, msg.sender); // U:[FA-11]\n    }\n\n    /// @notice Liquidates a credit account\n    ///         - Updates price feeds before running all computations if such calls are present in the multicall\n    ///         - Evaluates account's collateral and debt to determine whether liquidated account is unhealthy or expired\n    ///         - Performs a multicall (only `addCollateral`, `withdrawCollateral` and adapter calls are allowed)\n    ///         - Liquidates a credit account in the credit manager, which repays debt to the pool, removes quotas, and\n    ///           transfers underlying to the liquidator\n    ///         - If pool incurs a loss on liquidation, further borrowing through the facade is forbidden\n    ///         - If cumulative loss from bad debt liquidations exceeds the threshold, the facade is paused\n    /// @notice The function computes account’s total value (oracle value of enabled tokens), discounts it by liquidator’s\n    ///         premium, and uses this value to compute funds due to the pool and owner.\n    ///         Debt to the pool must be repaid in underlying, while funds due to owner might be covered by underlying\n    ///         as well as by tokens that counted towards total value calculation, with the only condition that balance\n    ///         of such tokens can’t be increased in the multicall.\n    ///         Typically, a liquidator would swap all holdings on the account to underlying via multicall and receive\n    ///         the premium in underlying.\n    ///         An alternative strategy would be to add underlying collateral to repay debt and withdraw desired tokens\n    ///         to handle them in another way, while remaining tokens would cover funds due to owner.\n    /// @param creditAccount Account to liquidate\n    /// @param to Address to transfer underlying left after liquidation\n    /// @param calls List of calls to perform before liquidating the account\n    /// @dev When the credit facade is paused, reverts if caller is not an approved emergency liquidator\n    /// @dev Reverts if `creditAccount` is not opened in connected credit manager\n    /// @dev Reverts if account has no debt or is neither unhealthy nor expired\n    /// @dev Reverts if remaining token balances increase during the multicall\n    function liquidateCreditAccount(address creditAccount, address to, MultiCall[] calldata calls)\n        external\n        override\n        whenNotPausedOrEmergency // U:[FA-2,12]\n        nonReentrant // U:[FA-4]\n    {\n        uint256 skipCalls = _applyOnDemandPriceUpdates(calls);\n\n        CollateralDebtData memory collateralDebtData =\n            ICreditManagerV3(creditManager).calcDebtAndCollateral(creditAccount, CollateralCalcTask.DEBT_COLLATERAL); // U:[FA-16]\n\n        bool isUnhealthy = collateralDebtData.twvUSD < collateralDebtData.totalDebtUSD;\n        if (collateralDebtData.debt == 0 || !isUnhealthy && !_isExpired()) {\n            revert CreditAccountNotLiquidatableException(); // U:[FA-13]\n        }\n\n        collateralDebtData.enabledTokensMask = collateralDebtData.enabledTokensMask.disable(UNDERLYING_TOKEN_MASK); // U:[FA-14]\n\n        BalanceWithMask[] memory initialBalances = BalancesLogic.storeBalances({\n            creditAccount: creditAccount,\n            tokensMask: collateralDebtData.enabledTokensMask,\n            getTokenByMaskFn: _getTokenByMask\n        });\n\n        FullCheckParams memory fullCheckParams = _multicall(\n            creditAccount, calls, collateralDebtData.enabledTokensMask, LIQUIDATE_CREDIT_ACCOUNT_FLAGS, skipCalls\n        ); // U:[FA-16]\n        collateralDebtData.enabledTokensMask &= fullCheckParams.enabledTokensMaskAfter; // U:[FA-16]\n\n        bool success = BalancesLogic.compareBalances({\n            creditAccount: creditAccount,\n            tokensMask: collateralDebtData.enabledTokensMask,\n            balances: initialBalances,\n            comparison: Comparison.LESS\n        });\n        if (!success) revert RemainingTokenBalanceIncreasedException(); // U:[FA-14]\n\n        collateralDebtData.enabledTokensMask = collateralDebtData.enabledTokensMask.enable(UNDERLYING_TOKEN_MASK); // U:[FA-16]\n\n        (uint256 remainingFunds, uint256 reportedLoss) = ICreditManagerV3(creditManager).liquidateCreditAccount({\n            creditAccount: creditAccount,\n            collateralDebtData: collateralDebtData,\n            to: to,\n            isExpired: !isUnhealthy\n        }); // U:[FA-15,16]\n\n        emit LiquidateCreditAccount(creditAccount, msg.sender, to, remainingFunds); // U:[FA-16]\n\n        if (reportedLoss != 0) {\n            maxDebtPerBlockMultiplier = 0; // U:[FA-17]\n\n            // both cast and addition are safe because amounts are of much smaller scale\n            lossParams.currentCumulativeLoss += uint128(reportedLoss); // U:[FA-17]\n\n            // can't pause an already paused contract\n            if (!paused() && lossParams.currentCumulativeLoss > lossParams.maxCumulativeLoss) {\n                _pause(); // U:[FA-17]\n            }\n        }\n    }\n\n    /// @notice Executes a batch of calls allowing user to manage their credit account\n    ///         - Wraps any ETH sent in the function call and sends it back to the caller\n    ///         - Performs a multicall (all calls are allowed)\n    ///         - Runs the collateral check\n    /// @param creditAccount Account to perform the calls on\n    /// @param calls List of calls to perform\n    /// @dev Reverts if `creditAccount` is not opened in connected credit manager by caller\n    /// @dev Reverts if credit facade is paused or expired\n    function multicall(address creditAccount, MultiCall[] calldata calls)\n        external\n        payable\n        override\n        creditAccountOwnerOnly(creditAccount) // U:[FA-5]\n        whenNotPaused // U:[FA-2]\n        whenNotExpired // U:[FA-3]\n        nonReentrant // U:[FA-4]\n        wrapETH // U:[FA-7]\n    {\n        _multicallFullCollateralCheck(creditAccount, calls, ALL_PERMISSIONS); // U:[FA-18]\n    }\n\n    /// @notice Executes a batch of calls allowing bot to manage a credit account\n    ///         - Performs a multicall (allowed calls are determined by permissions given by account's owner\n    ///           or by DAO in case bot has special permissions in the credit manager)\n    ///         - Runs the collateral check\n    /// @param creditAccount Account to perform the calls on\n    /// @param calls List of calls to perform\n    /// @dev Reverts if credit facade is paused or expired\n    /// @dev Reverts if `creditAccount` is not opened in connected credit manager\n    /// @dev Reverts if calling bot is forbidden or has no permissions to manage `creditAccount`\n    function botMulticall(address creditAccount, MultiCall[] calldata calls)\n        external\n        override\n        whenNotPaused // U:[FA-2]\n        whenNotExpired // U:[FA-3]\n        nonReentrant // U:[FA-4]\n    {\n        _getBorrowerOrRevert(creditAccount); // U:[FA-5]\n\n        (uint256 botPermissions, bool forbidden, bool hasSpecialPermissions) = IBotListV3(botList).getBotStatus({\n            bot: msg.sender,\n            creditManager: creditManager,\n            creditAccount: creditAccount\n        });\n\n        if (\n            botPermissions == 0 || forbidden\n                || (!hasSpecialPermissions && (_flagsOf(creditAccount) & BOT_PERMISSIONS_SET_FLAG == 0))\n        ) {\n            revert NotApprovedBotException(); // U:[FA-19]\n        }\n\n        _multicallFullCollateralCheck(creditAccount, calls, botPermissions); // U:[FA-19, 20]\n    }\n\n    /// @notice Sets `bot`'s permissions to manage `creditAccount`\n    /// @param creditAccount Account to set permissions for\n    /// @param bot Bot to set permissions for\n    /// @param permissions A bit mask encoding bot permissions\n    /// @dev Reverts if `creditAccount` is not opened in connected credit manager by caller\n    /// @dev Reverts if `permissions` has unexpected bits enabled\n    /// @dev Reverts if account has more active bots than allowed after changing permissions\n    /// @dev Changes account's `BOT_PERMISSIONS_SET_FLAG` in the credit manager if needed\n    function setBotPermissions(address creditAccount, address bot, uint192 permissions)\n        external\n        override\n        creditAccountOwnerOnly(creditAccount) // U:[FA-5]\n        nonReentrant // U:[FA-4]\n    {\n        if (permissions & ~ALL_PERMISSIONS != 0) revert UnexpectedPermissionsException(); // U:[FA-41]\n\n        uint256 remainingBots = IBotListV3(botList).setBotPermissions({\n            bot: bot,\n            creditManager: creditManager,\n            creditAccount: creditAccount,\n            permissions: permissions\n        }); // U:[FA-41]\n\n        if (remainingBots == 0) {\n            _setFlagFor({creditAccount: creditAccount, flag: BOT_PERMISSIONS_SET_FLAG, value: false}); // U:[FA-41]\n        } else if (_flagsOf(creditAccount) & BOT_PERMISSIONS_SET_FLAG == 0) {\n            _setFlagFor({creditAccount: creditAccount, flag: BOT_PERMISSIONS_SET_FLAG, value: true}); // U:[FA-41]\n        }\n    }\n\n    // --------- //\n    // MULTICALL //\n    // --------- //\n\n    /// @dev Batches price feed updates, multicall and collateral check into a single function\n    function _multicallFullCollateralCheck(address creditAccount, MultiCall[] calldata calls, uint256 flags) internal {\n        uint256 forbiddenTokensMask = forbiddenTokenMask;\n        uint256 enabledTokensMaskBefore = _enabledTokensMaskOf(creditAccount); // U:[FA-18]\n        BalanceWithMask[] memory forbiddenBalances = BalancesLogic.storeBalances({\n            creditAccount: creditAccount,\n            tokensMask: forbiddenTokensMask & enabledTokensMaskBefore,\n            getTokenByMaskFn: _getTokenByMask\n        });\n\n        uint256 skipCalls = _applyOnDemandPriceUpdates(calls);\n        FullCheckParams memory fullCheckParams = _multicall(\n            creditAccount,\n            calls,\n            enabledTokensMaskBefore,\n            forbiddenBalances.length != 0 ? flags.enable(FORBIDDEN_TOKENS_BEFORE_CALLS) : flags,\n            skipCalls\n        );\n\n        _fullCollateralCheck({\n            creditAccount: creditAccount,\n            enabledTokensMaskBefore: enabledTokensMaskBefore,\n            fullCheckParams: fullCheckParams,\n            forbiddenBalances: forbiddenBalances,\n            forbiddenTokensMask: forbiddenTokensMask\n        }); // U:[FA-18]\n    }\n\n    /// @dev Multicall implementation\n    /// @param creditAccount Account to perform actions with\n    /// @param calls Array of `(target, callData)` tuples representing a sequence of calls to perform\n    ///        - if `target` is this contract's address, `callData` must be an ABI-encoded calldata of a method\n    ///          from `ICreditFacadeV3Multicall`, which is dispatched and handled appropriately\n    ///        - otherwise, `target` must be an allowed adapter, which is called with `callData`, and is expected to\n    ///          return two ABI-encoded `uint256` masks of tokens that should be enabled/disabled after the call\n    /// @param enabledTokensMask Bitmask of account's enabled collateral tokens before the multicall\n    /// @param flags Permissions and flags that dictate what methods can be called\n    /// @param skip The number of calls that can be skipped (see `_applyOnDemandPriceUpdates`)\n    /// @return fullCheckParams Collateral check parameters, see `FullCheckParams` for details\n    function _multicall(\n        address creditAccount,\n        MultiCall[] calldata calls,\n        uint256 enabledTokensMask,\n        uint256 flags,\n        uint256 skip\n    ) internal returns (FullCheckParams memory fullCheckParams) {\n        emit StartMultiCall({creditAccount: creditAccount, caller: msg.sender}); // U:[FA-18]\n\n        uint256 quotedTokensMaskInverted;\n        Balance[] memory expectedBalances;\n        fullCheckParams.minHealthFactor = PERCENTAGE_FACTOR;\n\n        unchecked {\n            uint256 len = calls.length;\n            for (uint256 i = skip; i < len; ++i) {\n                MultiCall calldata mcall = calls[i];\n\n                // credit facade calls\n                if (mcall.target == address(this)) {\n                    bytes4 method = bytes4(mcall.callData);\n\n                    // storeExpectedBalances\n                    if (method == ICreditFacadeV3Multicall.storeExpectedBalances.selector) {\n                        if (expectedBalances.length != 0) revert ExpectedBalancesAlreadySetException(); // U:[FA-23]\n\n                        BalanceDelta[] memory balanceDeltas = abi.decode(mcall.callData[4:], (BalanceDelta[])); // U:[FA-23]\n                        expectedBalances = BalancesLogic.storeBalances(creditAccount, balanceDeltas); // U:[FA-23]\n                    }\n                    // compareBalances\n                    else if (method == ICreditFacadeV3Multicall.compareBalances.selector) {\n                        if (expectedBalances.length == 0) revert ExpectedBalancesNotSetException(); // U:[FA-23]\n\n                        if (!BalancesLogic.compareBalances(creditAccount, expectedBalances, Comparison.GREATER)) {\n                            revert BalanceLessThanExpectedException(); // U:[FA-23]\n                        }\n                        expectedBalances = new Balance[](0); // U:[FA-23]\n                    }\n                    // addCollateral\n                    else if (method == ICreditFacadeV3Multicall.addCollateral.selector) {\n                        _revertIfNoPermission(flags, ADD_COLLATERAL_PERMISSION); // U:[FA-21]\n\n                        quotedTokensMaskInverted = _quotedTokensMaskInvertedLoE(quotedTokensMaskInverted);\n\n                        enabledTokensMask = enabledTokensMask.enable({\n                            bitsToEnable: _addCollateral(creditAccount, mcall.callData[4:]),\n                            invertedSkipMask: quotedTokensMaskInverted\n                        }); // U:[FA-26]\n                    }\n                    // addCollateralWithPermit\n                    else if (method == ICreditFacadeV3Multicall.addCollateralWithPermit.selector) {\n                        _revertIfNoPermission(flags, ADD_COLLATERAL_PERMISSION); // U:[FA-21]\n\n                        quotedTokensMaskInverted = _quotedTokensMaskInvertedLoE(quotedTokensMaskInverted);\n\n                        enabledTokensMask = enabledTokensMask.enable({\n                            bitsToEnable: _addCollateralWithPermit(creditAccount, mcall.callData[4:]),\n                            invertedSkipMask: quotedTokensMaskInverted\n                        }); // U:[FA-26B]\n                    }\n                    // updateQuota\n                    else if (method == ICreditFacadeV3Multicall.updateQuota.selector) {\n                        _revertIfNoPermission(flags, UPDATE_QUOTA_PERMISSION); // U:[FA-21]\n\n                        (uint256 tokensToEnable, uint256 tokensToDisable) =\n                            _updateQuota(creditAccount, mcall.callData[4:], flags & FORBIDDEN_TOKENS_BEFORE_CALLS != 0); // U:[FA-34]\n                        enabledTokensMask = enabledTokensMask.enableDisable(tokensToEnable, tokensToDisable); // U:[FA-34]\n                    }\n                    // withdrawCollateral\n                    else if (method == ICreditFacadeV3Multicall.withdrawCollateral.selector) {\n                        _revertIfNoPermission(flags, WITHDRAW_COLLATERAL_PERMISSION); // U:[FA-21]\n\n                        fullCheckParams.revertOnForbiddenTokens = true; // U:[FA-30]\n                        fullCheckParams.useSafePrices = true;\n\n                        uint256 tokensToDisable = _withdrawCollateral(creditAccount, mcall.callData[4:]); // U:[FA-34]\n\n                        quotedTokensMaskInverted = _quotedTokensMaskInvertedLoE(quotedTokensMaskInverted);\n\n                        enabledTokensMask = enabledTokensMask.disable({\n                            bitsToDisable: tokensToDisable,\n                            invertedSkipMask: quotedTokensMaskInverted\n                        }); // U:[FA-35]\n                    }\n                    // increaseDebt\n                    else if (method == ICreditFacadeV3Multicall.increaseDebt.selector) {\n                        _revertIfNoPermission(flags, INCREASE_DEBT_PERMISSION); // U:[FA-21]\n\n                        fullCheckParams.revertOnForbiddenTokens = true; // U:[FA-30]\n\n                        (uint256 tokensToEnable,) = _manageDebt(\n                            creditAccount, mcall.callData[4:], enabledTokensMask, ManageDebtAction.INCREASE_DEBT\n                        ); // U:[FA-27]\n                        enabledTokensMask = enabledTokensMask.enable(tokensToEnable); // U:[FA-27]\n                    }\n                    // decreaseDebt\n                    else if (method == ICreditFacadeV3Multicall.decreaseDebt.selector) {\n                        _revertIfNoPermission(flags, DECREASE_DEBT_PERMISSION); // U:[FA-21]\n\n                        (, uint256 tokensToDisable) = _manageDebt(\n                            creditAccount, mcall.callData[4:], enabledTokensMask, ManageDebtAction.DECREASE_DEBT\n                        ); // U:[FA-31]\n                        enabledTokensMask = enabledTokensMask.disable(tokensToDisable); // U:[FA-31]\n                    }\n                    // setFullCheckParams\n                    else if (method == ICreditFacadeV3Multicall.setFullCheckParams.selector) {\n                        (fullCheckParams.collateralHints, fullCheckParams.minHealthFactor) =\n                            abi.decode(mcall.callData[4:], (uint256[], uint16)); // U:[FA-24]\n\n                        if (fullCheckParams.minHealthFactor < PERCENTAGE_FACTOR) {\n                            revert CustomHealthFactorTooLowException(); // U:[FA-24]\n                        }\n\n                        uint256 hintsLen = fullCheckParams.collateralHints.length;\n                        for (uint256 j; j < hintsLen; ++j) {\n                            uint256 mask = fullCheckParams.collateralHints[j];\n                            if (mask == 0 || mask & mask - 1 != 0) revert InvalidCollateralHintException(); // U:[FA-24]\n                        }\n                    }\n                    // enableToken\n                    else if (method == ICreditFacadeV3Multicall.enableToken.selector) {\n                        _revertIfNoPermission(flags, ENABLE_TOKEN_PERMISSION); // U:[FA-21]\n                        address token = abi.decode(mcall.callData[4:], (address)); // U:[FA-33]\n\n                        quotedTokensMaskInverted = _quotedTokensMaskInvertedLoE(quotedTokensMaskInverted);\n\n                        enabledTokensMask = enabledTokensMask.enable({\n                            bitsToEnable: _getTokenMaskOrRevert(token),\n                            invertedSkipMask: quotedTokensMaskInverted\n                        }); // U:[FA-33]\n                    }\n                    // disableToken\n                    else if (method == ICreditFacadeV3Multicall.disableToken.selector) {\n                        _revertIfNoPermission(flags, DISABLE_TOKEN_PERMISSION); // U:[FA-21]\n                        address token = abi.decode(mcall.callData[4:], (address)); // U:[FA-33]\n\n                        quotedTokensMaskInverted = _quotedTokensMaskInvertedLoE(quotedTokensMaskInverted);\n\n                        enabledTokensMask = enabledTokensMask.disable({\n                            bitsToDisable: _getTokenMaskOrRevert(token),\n                            invertedSkipMask: quotedTokensMaskInverted\n                        }); // U:[FA-33]\n                    }\n                    // revokeAdapterAllowances\n                    else if (method == ICreditFacadeV3Multicall.revokeAdapterAllowances.selector) {\n                        _revertIfNoPermission(flags, REVOKE_ALLOWANCES_PERMISSION); // U:[FA-21]\n                        _revokeAdapterAllowances(creditAccount, mcall.callData[4:]); // U:[FA-36]\n                    }\n                    // unknown method\n                    else {\n                        revert UnknownMethodException(); // U:[FA-22]\n                    }\n                }\n                // adapter calls\n                else {\n                    _revertIfNoPermission(flags, EXTERNAL_CALLS_PERMISSION); // U:[FA-21]\n\n                    bytes memory result;\n                    {\n                        address targetContract = ICreditManagerV3(creditManager).adapterToContract(mcall.target);\n                        if (targetContract == address(0)) {\n                            revert TargetContractNotAllowedException();\n                        }\n\n                        if (flags & EXTERNAL_CONTRACT_WAS_CALLED == 0) {\n                            flags = flags.enable(EXTERNAL_CONTRACT_WAS_CALLED);\n                            _setActiveCreditAccount(creditAccount); // U:[FA-38]\n                        }\n\n                        result = mcall.target.functionCall(mcall.callData); // U:[FA-38]\n\n                        emit Execute({creditAccount: creditAccount, targetContract: targetContract});\n                    }\n\n                    (uint256 tokensToEnable, uint256 tokensToDisable) = abi.decode(result, (uint256, uint256)); // U:[FA-38]\n\n                    quotedTokensMaskInverted = _quotedTokensMaskInvertedLoE(quotedTokensMaskInverted);\n\n                    enabledTokensMask = enabledTokensMask.enableDisable({\n                        bitsToEnable: tokensToEnable,\n                        bitsToDisable: tokensToDisable,\n                        invertedSkipMask: quotedTokensMaskInverted\n                    }); // U:[FA-38]\n                }\n            }\n        }\n\n        if (expectedBalances.length != 0) {\n            if (!BalancesLogic.compareBalances(creditAccount, expectedBalances, Comparison.GREATER)) {\n                revert BalanceLessThanExpectedException(); // U:[FA-23]\n            }\n        }\n\n        if (enabledTokensMask & forbiddenTokenMask != 0) {\n            fullCheckParams.useSafePrices = true;\n        }\n\n        if (flags & EXTERNAL_CONTRACT_WAS_CALLED != 0) {\n            _unsetActiveCreditAccount(); // U:[FA-38]\n        }\n\n        fullCheckParams.enabledTokensMaskAfter = enabledTokensMask; // U:[FA-38]\n\n        emit FinishMultiCall(); // U:[FA-18]\n    }\n\n    /// @dev Applies on-demand price feed updates placed at the beginning of the multicall (if there are any)\n    /// @return skipCalls Number of update calls made that can be skiped later in the `_multicall`\n    function _applyOnDemandPriceUpdates(MultiCall[] calldata calls) internal returns (uint256 skipCalls) {\n        address priceOracle;\n        unchecked {\n            uint256 len = calls.length;\n            for (uint256 i; i < len; ++i) {\n                MultiCall calldata mcall = calls[i];\n                if (\n                    mcall.target == address(this)\n                        && bytes4(mcall.callData) == ICreditFacadeV3Multicall.onDemandPriceUpdate.selector\n                ) {\n                    (address token, bool reserve, bytes memory data) =\n                        abi.decode(mcall.callData[4:], (address, bool, bytes)); // U:[FA-25]\n\n                    priceOracle = _priceOracleLoE(priceOracle); // U:[FA-25]\n                    address priceFeed = IPriceOracleV3(priceOracle).priceFeedsRaw(token, reserve); // U:[FA-25]\n\n                    if (priceFeed == address(0)) {\n                        revert PriceFeedDoesNotExistException(); // U:[FA-25]\n                    }\n\n                    IUpdatablePriceFeed(priceFeed).updatePrice(data); // U:[FA-25]\n                } else {\n                    return i;\n                }\n            }\n            return len;\n        }\n    }\n\n    /// @dev Performs collateral check to ensure that\n    ///      - account is sufficiently collateralized\n    ///      - account has no forbidden tokens after risky operations\n    ///      - no forbidden tokens have been enabled during the multicall\n    ///      - no enabled forbidden token balance has increased during the multicall\n    function _fullCollateralCheck(\n        address creditAccount,\n        uint256 enabledTokensMaskBefore,\n        FullCheckParams memory fullCheckParams,\n        BalanceWithMask[] memory forbiddenBalances,\n        uint256 forbiddenTokensMask\n    ) internal {\n        uint256 enabledTokensMask = ICreditManagerV3(creditManager).fullCollateralCheck(\n            creditAccount,\n            fullCheckParams.enabledTokensMaskAfter,\n            fullCheckParams.collateralHints,\n            fullCheckParams.minHealthFactor,\n            fullCheckParams.useSafePrices\n        ); // U:[FA-45]\n\n        uint256 enabledForbiddenTokensMask = enabledTokensMask & forbiddenTokensMask;\n        if (enabledForbiddenTokensMask != 0) {\n            if (fullCheckParams.revertOnForbiddenTokens) revert ForbiddenTokensException(); // U:[FA-45]\n\n            uint256 enabledForbiddenTokensMaskBefore = enabledTokensMaskBefore & forbiddenTokensMask;\n            if (enabledForbiddenTokensMask & ~enabledForbiddenTokensMaskBefore != 0) {\n                revert ForbiddenTokenEnabledException(); // U:[FA-45]\n            }\n\n            bool success = BalancesLogic.compareBalances({\n                creditAccount: creditAccount,\n                tokensMask: enabledForbiddenTokensMask,\n                balances: forbiddenBalances,\n                comparison: Comparison.LESS\n            });\n\n            if (!success) revert ForbiddenTokenBalanceIncreasedException(); // U:[FA-45]\n        }\n    }\n\n    /// @dev `ICreditFacadeV3Multicall.addCollateral` implementation\n    function _addCollateral(address creditAccount, bytes calldata callData) internal returns (uint256 tokensToEnable) {\n        (address token, uint256 amount) = abi.decode(callData, (address, uint256)); // U:[FA-26]\n\n        tokensToEnable = _addCollateral({payer: msg.sender, creditAccount: creditAccount, token: token, amount: amount}); // U:[FA-26]\n\n        emit AddCollateral(creditAccount, token, amount); // U:[FA-26]\n    }\n\n    /// @dev `ICreditFacadeV3Multicall.addCollateralWithPermit` implementation\n    function _addCollateralWithPermit(address creditAccount, bytes calldata callData)\n        internal\n        returns (uint256 tokensToEnable)\n    {\n        (address token, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) =\n            abi.decode(callData, (address, uint256, uint256, uint8, bytes32, bytes32)); // U:[FA-26B]\n\n        // `token` is only validated later in `addCollateral`, but to benefit off of it the attacker would have to make\n        // it recognizable as collateral in the credit manager, which requires gaining configurator access rights\n        try IERC20Permit(token).permit(msg.sender, creditManager, amount, deadline, v, r, s) {} catch {} // U:[FA-26B]\n\n        tokensToEnable = _addCollateral({payer: msg.sender, creditAccount: creditAccount, token: token, amount: amount}); // U:[FA-26B]\n\n        emit AddCollateral(creditAccount, token, amount); // U:[FA-26B]\n    }\n\n    /// @dev `ICreditFacadeV3Multicall.{increase|decrease}Debt` implementation\n    function _manageDebt(\n        address creditAccount,\n        bytes calldata callData,\n        uint256 enabledTokensMask,\n        ManageDebtAction action\n    ) internal returns (uint256 tokensToEnable, uint256 tokensToDisable) {\n        uint256 amount = abi.decode(callData, (uint256)); // U:[FA-27,31]\n\n        if (action == ManageDebtAction.INCREASE_DEBT) {\n            _revertIfOutOfBorrowingLimit(amount); // U:[FA-28]\n        }\n\n        uint256 newDebt;\n        (newDebt, tokensToEnable, tokensToDisable) =\n            ICreditManagerV3(creditManager).manageDebt(creditAccount, amount, enabledTokensMask, action); // U:[FA-27,31]\n\n        _revertIfOutOfDebtLimits(newDebt); // U:[FA-28, 32, 33, 33A]\n\n        if (action == ManageDebtAction.INCREASE_DEBT) {\n            emit IncreaseDebt({creditAccount: creditAccount, amount: amount}); // U:[FA-27]\n        } else {\n            emit DecreaseDebt({creditAccount: creditAccount, amount: amount}); // U:[FA-31]\n        }\n    }\n\n    /// @dev `ICreditFacadeV3Multicall.updateQuota` implementation\n    function _updateQuota(address creditAccount, bytes calldata callData, bool hasForbiddenTokens)\n        internal\n        returns (uint256 tokensToEnable, uint256 tokensToDisable)\n    {\n        (address token, int96 quotaChange, uint96 minQuota) = abi.decode(callData, (address, int96, uint96)); // U:[FA-34]\n\n        // Ensures that user is not trying to increase quota for a forbidden token. This happens implicitly when user\n        // has no enabled forbidden tokens because quota increase would try to enable the token, which is prohibited.\n        // Thus some gas is saved in this case by not querying token's mask.\n        if (hasForbiddenTokens && quotaChange > 0) {\n            if (_getTokenMaskOrRevert(token) & forbiddenTokenMask != 0) {\n                revert ForbiddenTokensException();\n            }\n        }\n\n        (tokensToEnable, tokensToDisable) = ICreditManagerV3(creditManager).updateQuota({\n            creditAccount: creditAccount,\n            token: token,\n            quotaChange: quotaChange,\n            minQuota: minQuota,\n            maxQuota: uint96(Math.min(type(uint96).max, maxQuotaMultiplier * debtLimits.maxDebt))\n        }); // U:[FA-34]\n    }\n\n    /// @dev `ICreditFacadeV3Multicall.withdrawCollateral` implementation\n    function _withdrawCollateral(address creditAccount, bytes calldata callData)\n        internal\n        returns (uint256 tokensToDisable)\n    {\n        (address token, uint256 amount, address to) = abi.decode(callData, (address, uint256, address)); // U:[FA-35]\n\n        if (amount == type(uint256).max) {\n            amount = IERC20(token).balanceOf(creditAccount);\n            if (amount <= 1) return 0;\n            unchecked {\n                --amount;\n            }\n        }\n        tokensToDisable = ICreditManagerV3(creditManager).withdrawCollateral(creditAccount, token, amount, to); // U:[FA-35]\n\n        emit WithdrawCollateral(creditAccount, token, amount, to); // U:[FA-35]\n    }\n\n    /// @dev `ICreditFacadeV3Multicall.revokeAdapterAllowances` implementation\n    function _revokeAdapterAllowances(address creditAccount, bytes calldata callData) internal {\n        RevocationPair[] memory revocations = abi.decode(callData, (RevocationPair[])); // U:[FA-36]\n\n        ICreditManagerV3(creditManager).revokeAdapterAllowances(creditAccount, revocations); // U:[FA-36]\n    }\n\n    // ------------- //\n    // CONFIGURATION //\n    // ------------- //\n\n    /// @notice Sets the credit facade expiration timestamp\n    /// @param newExpirationDate New expiration timestamp\n    /// @dev Reverts if caller is not credit configurator\n    /// @dev Reverts if credit facade is not expirable\n    function setExpirationDate(uint40 newExpirationDate)\n        external\n        override\n        creditConfiguratorOnly // U:[FA-6]\n    {\n        if (!expirable) {\n            revert NotAllowedWhenNotExpirableException(); // U:[FA-48]\n        }\n        expirationDate = newExpirationDate; // U:[FA-48]\n    }\n\n    /// @notice Sets debt limits per credit account\n    /// @param newMinDebt New minimum debt amount per credit account\n    /// @param newMaxDebt New maximum debt amount per credit account\n    /// @param newMaxDebtPerBlockMultiplier New max debt per block multiplier, `type(uint8).max` to disable the check\n    /// @dev Reverts if caller is not credit configurator\n    /// @dev Reverts if `maxDebt * maxDebtPerBlockMultiplier` doesn't fit into `uint128`\n    function setDebtLimits(uint128 newMinDebt, uint128 newMaxDebt, uint8 newMaxDebtPerBlockMultiplier)\n        external\n        override\n        creditConfiguratorOnly // U:[FA-6]\n    {\n        if ((uint256(newMaxDebtPerBlockMultiplier) * newMaxDebt) >= type(uint128).max) {\n            revert IncorrectParameterException(); // U:[FA-49]\n        }\n\n        debtLimits.minDebt = newMinDebt; // U:[FA-49]\n        debtLimits.maxDebt = newMaxDebt; // U:[FA-49]\n        maxDebtPerBlockMultiplier = newMaxDebtPerBlockMultiplier; // U:[FA-49]\n    }\n\n    /// @notice Sets the new bot list\n    /// @param newBotList New bot list address\n    /// @dev Reverts if caller is not credit configurator\n    function setBotList(address newBotList)\n        external\n        override\n        creditConfiguratorOnly // U:[FA-6]\n    {\n        botList = newBotList; // U:[FA-50]\n    }\n\n    /// @notice Sets the new max cumulative loss\n    /// @param newMaxCumulativeLoss New max cumulative loss\n    /// @param resetCumulativeLoss Whether to reset the current cumulative loss to zero\n    /// @dev Reverts if caller is not credit configurator\n    function setCumulativeLossParams(uint128 newMaxCumulativeLoss, bool resetCumulativeLoss)\n        external\n        override\n        creditConfiguratorOnly // U:[FA-6]\n    {\n        lossParams.maxCumulativeLoss = newMaxCumulativeLoss; // U:[FA-51]\n        if (resetCumulativeLoss) {\n            lossParams.currentCumulativeLoss = 0; // U:[FA-51]\n        }\n    }\n\n    /// @notice Changes token's forbidden status\n    /// @param token Token to change the status for\n    /// @param allowance Status to set\n    /// @dev Reverts if caller is not credit configurator\n    function setTokenAllowance(address token, AllowanceAction allowance)\n        external\n        override\n        creditConfiguratorOnly // U:[FA-6]\n    {\n        uint256 tokenMask = _getTokenMaskOrRevert(token); // U:[FA-52]\n\n        forbiddenTokenMask = (allowance == AllowanceAction.ALLOW)\n            ? forbiddenTokenMask.disable(tokenMask)\n            : forbiddenTokenMask.enable(tokenMask); // U:[FA-52]\n    }\n\n    /// @notice Changes account's status as emergency liquidator\n    /// @param liquidator Account to change the status for\n    /// @param allowance Status to set\n    /// @dev Reverts if caller is not credit configurator\n    function setEmergencyLiquidator(address liquidator, AllowanceAction allowance)\n        external\n        override\n        creditConfiguratorOnly // U:[FA-6]\n    {\n        canLiquidateWhilePaused[liquidator] = allowance == AllowanceAction.ALLOW; // U:[FA-53]\n    }\n\n    // --------- //\n    // INTERNALS //\n    // --------- //\n\n    /// @dev Ensures that amount borrowed by credit manager in the current block does not exceed the limit\n    /// @dev Skipped when `maxDebtPerBlockMultiplier == type(uint8).max`\n    function _revertIfOutOfBorrowingLimit(uint256 amount) internal {\n        uint8 _maxDebtPerBlockMultiplier = maxDebtPerBlockMultiplier; // U:[FA-43]\n        if (_maxDebtPerBlockMultiplier == type(uint8).max) return; // U:[FA-43]\n\n        uint256 newDebtInCurrentBlock;\n        if (lastBlockBorrowed == block.number) {\n            newDebtInCurrentBlock = amount + totalBorrowedInBlock; // U:[FA-43]\n        } else {\n            newDebtInCurrentBlock = amount;\n            lastBlockBorrowed = uint64(block.number); // U:[FA-43]\n        }\n\n        if (newDebtInCurrentBlock > uint256(_maxDebtPerBlockMultiplier) * debtLimits.maxDebt) {\n            revert BorrowedBlockLimitException(); // U:[FA-43]\n        }\n\n        // the conversion is safe because of the check in `setDebtLimits`\n        totalBorrowedInBlock = uint128(newDebtInCurrentBlock); // U:[FA-43]\n    }\n\n    /// @dev Ensures that account's debt principal is within allowed range or is zero\n    function _revertIfOutOfDebtLimits(uint256 debt) internal view {\n        uint256 minDebt;\n        uint256 maxDebt;\n\n        // minDebt = debtLimits.minDebt;\n        // maxDebt = debtLimits.maxDebt;\n        assembly {\n            let data := sload(debtLimits.slot)\n            maxDebt := shr(128, data)\n            minDebt := and(data, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\n        }\n\n        if (debt != 0 && ((debt < minDebt) || (debt > maxDebt))) {\n            revert BorrowAmountOutOfLimitsException(); // U:[FA-44]\n        }\n    }\n\n    /// @dev Ensures that `flags` has the `permission` bit enabled\n    function _revertIfNoPermission(uint256 flags, uint256 permission) internal pure {\n        if (flags & permission == 0) {\n            revert NoPermissionException(permission); // U:[FA-39]\n        }\n    }\n\n    /// @dev Load-on-empty function to read inverted quoted tokens mask at most once if it's needed,\n    ///      returns its argument if it's not empty or inverted `quotedTokensMask` from credit manager otherwise\n    /// @dev Non-empty inverted quoted tokens mask always has it's LSB set to 1 since underlying can't be quoted\n    function _quotedTokensMaskInvertedLoE(uint256 quotedTokensMaskInvertedOrEmpty) internal view returns (uint256) {\n        return quotedTokensMaskInvertedOrEmpty == 0\n            ? ~ICreditManagerV3(creditManager).quotedTokensMask()\n            : quotedTokensMaskInvertedOrEmpty;\n    }\n\n    /// @dev Load-on-empty function to read price oracle at most once if it's needed,\n    ///      returns its argument if it's not empty or `priceOracle` from credit manager otherwise\n    /// @dev Non-empty price oracle always has non-zero address\n    function _priceOracleLoE(address priceOracleOrEmpty) internal view returns (address) {\n        return priceOracleOrEmpty == address(0) ? ICreditManagerV3(creditManager).priceOracle() : priceOracleOrEmpty;\n    }\n\n    /// @dev Wraps any ETH sent in the function call and sends it back to `msg.sender`\n    function _wrapETH() internal {\n        if (msg.value != 0) {\n            IWETH(weth).deposit{value: msg.value}(); // U:[FA-7]\n            IERC20(weth).safeTransfer(msg.sender, msg.value); // U:[FA-7]\n        }\n    }\n\n    /// @dev Whether credit facade has expired (`false` if it's not expirable or expiration timestamp is not set)\n    function _isExpired() internal view returns (bool) {\n        if (!expirable) return false; // U:[FA-46]\n        uint40 _expirationDate = expirationDate;\n        return _expirationDate != 0 && block.timestamp >= _expirationDate; // U:[FA-46]\n    }\n\n    /// @dev Internal wrapper for `creditManager.getBorrowerOrRevert` call to reduce contract size\n    function _getBorrowerOrRevert(address creditAccount) internal view returns (address) {\n        return ICreditManagerV3(creditManager).getBorrowerOrRevert({creditAccount: creditAccount});\n    }\n\n    /// @dev Internal wrapper for `creditManager.getTokenMaskOrRevert` call to reduce contract size\n    function _getTokenMaskOrRevert(address token) internal view returns (uint256) {\n        return ICreditManagerV3(creditManager).getTokenMaskOrRevert(token);\n    }\n\n    /// @dev Internal wrapper for `creditManager.getTokenByMask` call to reduce contract size\n    function _getTokenByMask(uint256 mask) internal view returns (address) {\n        return ICreditManagerV3(creditManager).getTokenByMask(mask);\n    }\n\n    /// @dev Internal wrapper for `creditManager.flagsOf` call to reduce contract size\n    function _flagsOf(address creditAccount) internal view returns (uint16) {\n        return ICreditManagerV3(creditManager).flagsOf(creditAccount);\n    }\n\n    /// @dev Internal wrapper for `creditManager.setFlagFor` call to reduce contract size\n    function _setFlagFor(address creditAccount, uint16 flag, bool value) internal {\n        ICreditManagerV3(creditManager).setFlagFor(creditAccount, flag, value);\n    }\n\n    /// @dev Internal wrapper for `creditManager.setActiveCreditAccount` call to reduce contract size\n    function _setActiveCreditAccount(address creditAccount) internal {\n        ICreditManagerV3(creditManager).setActiveCreditAccount(creditAccount);\n    }\n\n    /// @dev Same as above but unsets active credit account\n    function _unsetActiveCreditAccount() internal {\n        _setActiveCreditAccount(INACTIVE_CREDIT_ACCOUNT_ADDRESS);\n    }\n\n    /// @dev Internal wrapper for `creditManager.addCollateral` call to reduce contract size\n    function _addCollateral(address payer, address creditAccount, address token, uint256 amount)\n        internal\n        returns (uint256 tokenMask)\n    {\n        tokenMask = ICreditManagerV3(creditManager).addCollateral({\n            payer: payer,\n            creditAccount: creditAccount,\n            token: token,\n            amount: amount\n        });\n    }\n\n    /// @dev Internal wrapper for `creditManager.enabledTokensMaskOf` call to reduce contract size\n    function _enabledTokensMaskOf(address creditAccount) internal view returns (uint256) {\n        return ICreditManagerV3(creditManager).enabledTokensMaskOf(creditAccount);\n    }\n\n    /// @dev Reverts if `msg.sender` is not credit configurator\n    function _checkCreditConfigurator() internal view {\n        if (msg.sender != ICreditManagerV3(creditManager).creditConfigurator()) {\n            revert CallerNotConfiguratorException();\n        }\n    }\n\n    /// @dev Reverts if `msg.sender` is not `creditAccount` owner\n    function _checkCreditAccountOwner(address creditAccount) internal view {\n        if (msg.sender != _getBorrowerOrRevert(creditAccount)) {\n            revert CallerNotCreditAccountOwnerException();\n        }\n    }\n\n    /// @dev Reverts if credit facade is expired\n    function _checkExpired() internal view {\n        if (_isExpired()) {\n            revert NotAllowedAfterExpirationException();\n        }\n    }\n}\n"
      },
      "node_modules/@openzeppelin/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, \"Math: mulDiv overflow\");\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "node_modules/@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "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/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/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/@1inch/solidity-utils/contracts/libraries/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\";\nimport \"../interfaces/IDaiLikePermit.sol\";\nimport \"../interfaces/IPermit2.sol\";\nimport \"../interfaces/IWETH.sol\";\nimport \"../libraries/RevertReasonForwarder.sol\";\n\n/// @title Implements efficient safe methods for ERC20 interface.\nlibrary SafeERC20 {\n    error SafeTransferFailed();\n    error SafeTransferFromFailed();\n    error ForceApproveFailed();\n    error SafeIncreaseAllowanceFailed();\n    error SafeDecreaseAllowanceFailed();\n    error SafePermitBadLength();\n    error Permit2TransferAmountTooHigh();\n\n    address private constant _PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;\n    bytes4 private constant _PERMIT_LENGTH_ERROR = 0x68275857;  // SafePermitBadLength.selector\n    uint256 private constant _RAW_CALL_GAS_LIMIT = 5000;\n\n    function safeBalanceOf(\n        IERC20 token,\n        address account\n    ) internal view returns(uint256 tokenBalance) {\n        bytes4 selector = IERC20.balanceOf.selector;\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            mstore(0x00, selector)\n            mstore(0x04, account)\n            let success := staticcall(gas(), token, 0x00, 0x24, 0x00, 0x20)\n            tokenBalance := mload(0)\n\n            if or(iszero(success), lt(returndatasize(), 0x20)) {\n                let ptr := mload(0x40)\n                returndatacopy(ptr, 0, returndatasize())\n                revert(ptr, returndatasize())\n            }\n        }\n    }\n\n    /// @dev Ensures method do not revert or return boolean `true`, admits call to non-smart-contract.\n    function safeTransferFromUniversal(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 amount,\n        bool permit2\n    ) internal {\n        if (permit2) {\n            safeTransferFromPermit2(token, from, to, amount);\n        } else {\n            safeTransferFrom(token, from, to, amount);\n        }\n    }\n\n    /// @dev Ensures method do not revert or return boolean `true`, admits call to non-smart-contract.\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 amount\n    ) internal {\n        bytes4 selector = token.transferFrom.selector;\n        bool success;\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let data := mload(0x40)\n\n            mstore(data, selector)\n            mstore(add(data, 0x04), from)\n            mstore(add(data, 0x24), to)\n            mstore(add(data, 0x44), amount)\n            success := call(gas(), token, 0, data, 100, 0x0, 0x20)\n            if success {\n                switch returndatasize()\n                case 0 {\n                    success := gt(extcodesize(token), 0)\n                }\n                default {\n                    success := and(gt(returndatasize(), 31), eq(mload(0), 1))\n                }\n            }\n        }\n        if (!success) revert SafeTransferFromFailed();\n    }\n\n    /// @dev Permit2 version of safeTransferFrom above.\n    function safeTransferFromPermit2(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 amount\n    ) internal {\n        if (amount > type(uint160).max) revert Permit2TransferAmountTooHigh();\n        bytes4 selector = IPermit2.transferFrom.selector;\n        bool success;\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let data := mload(0x40)\n\n            mstore(data, selector)\n            mstore(add(data, 0x04), from)\n            mstore(add(data, 0x24), to)\n            mstore(add(data, 0x44), amount)\n            mstore(add(data, 0x64), token)\n            success := call(gas(), _PERMIT2, 0, data, 0x84, 0x0, 0x0)\n            if success {\n                success := gt(extcodesize(_PERMIT2), 0)\n            }\n        }\n        if (!success) revert SafeTransferFromFailed();\n    }\n\n    /// @dev Ensures method do not revert or return boolean `true`, admits call to non-smart-contract.\n    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        if (!_makeCall(token, token.transfer.selector, to, value)) {\n            revert SafeTransferFailed();\n        }\n    }\n\n    /// @dev If `approve(from, to, amount)` fails, try to `approve(from, to, 0)` before retry.\n    function forceApprove(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        if (!_makeCall(token, token.approve.selector, spender, value)) {\n            if (\n                !_makeCall(token, token.approve.selector, spender, 0) ||\n                !_makeCall(token, token.approve.selector, spender, value)\n            ) {\n                revert ForceApproveFailed();\n            }\n        }\n    }\n\n    /// @dev Allowance increase with safe math check.\n    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 allowance = token.allowance(address(this), spender);\n        if (value > type(uint256).max - allowance) revert SafeIncreaseAllowanceFailed();\n        forceApprove(token, spender, allowance + value);\n    }\n\n    /// @dev Allowance decrease with safe math check.\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 allowance = token.allowance(address(this), spender);\n        if (value > allowance) revert SafeDecreaseAllowanceFailed();\n        forceApprove(token, spender, allowance - value);\n    }\n\n    function safePermit(IERC20 token, bytes calldata permit) internal {\n        if (!tryPermit(token, msg.sender, address(this), permit)) RevertReasonForwarder.reRevert();\n    }\n\n    function safePermit(IERC20 token, address owner, address spender, bytes calldata permit) internal {\n        if (!tryPermit(token, owner, spender, permit)) RevertReasonForwarder.reRevert();\n    }\n\n    function tryPermit(IERC20 token, bytes calldata permit) internal returns(bool success) {\n        return tryPermit(token, msg.sender, address(this), permit);\n    }\n\n    function tryPermit(IERC20 token, address owner, address spender, bytes calldata permit) internal returns(bool success) {\n        bytes4 permitSelector = IERC20Permit.permit.selector;\n        bytes4 daiPermitSelector = IDaiLikePermit.permit.selector;\n        bytes4 permit2Selector = IPermit2.permit.selector;\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let ptr := mload(0x40)\n            switch permit.length\n            case 100 {\n                mstore(ptr, permitSelector)\n                mstore(add(ptr, 0x04), owner)\n                mstore(add(ptr, 0x24), spender)\n\n                // Compact IERC20Permit.permit(uint256 value, uint32 deadline, uint256 r, uint256 vs)\n                {  // stack too deep\n                    let deadline := shr(224, calldataload(add(permit.offset, 0x20)))\n                    let vs := calldataload(add(permit.offset, 0x44))\n\n                    calldatacopy(add(ptr, 0x44), permit.offset, 0x20) // value\n                    mstore(add(ptr, 0x64), sub(deadline, 1))\n                    mstore(add(ptr, 0x84), add(27, shr(255, vs)))\n                    calldatacopy(add(ptr, 0xa4), add(permit.offset, 0x24), 0x20) // r\n                    mstore(add(ptr, 0xc4), shr(1, shl(1, vs)))\n                }\n                // IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)\n                success := call(gas(), token, 0, ptr, 0xe4, 0, 0)\n            }\n            case 72 {\n                mstore(ptr, daiPermitSelector)\n                mstore(add(ptr, 0x04), owner)\n                mstore(add(ptr, 0x24), spender)\n\n                // Compact IDaiLikePermit.permit(uint32 nonce, uint32 expiry, uint256 r, uint256 vs)\n                {  // stack too deep\n                    let expiry := shr(224, calldataload(add(permit.offset, 0x04)))\n                    let vs := calldataload(add(permit.offset, 0x28))\n\n                    mstore(add(ptr, 0x44), shr(224, calldataload(permit.offset)))\n                    mstore(add(ptr, 0x64), sub(expiry, 1))\n                    mstore(add(ptr, 0x84), true)\n                    mstore(add(ptr, 0xa4), add(27, shr(255, vs)))\n                    calldatacopy(add(ptr, 0xc4), add(permit.offset, 0x08), 0x20) // r\n                    mstore(add(ptr, 0xe4), shr(1, shl(1, vs)))\n                }\n                // IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s)\n                success := call(gas(), token, 0, ptr, 0x104, 0, 0)\n            }\n            case 224 {\n                mstore(ptr, permitSelector)\n                calldatacopy(add(ptr, 0x04), permit.offset, permit.length)\n                // IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)\n                success := call(gas(), token, 0, ptr, 0xe4, 0, 0)\n            }\n            case 256 {\n                mstore(ptr, daiPermitSelector)\n                calldatacopy(add(ptr, 0x04), permit.offset, permit.length)\n                // IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s)\n                success := call(gas(), token, 0, ptr, 0x104, 0, 0)\n            }\n            case 96 {\n                // Compact IPermit2.permit(uint160 amount, uint32 expiration, uint32 nonce, uint32 sigDeadline, uint256 r, uint256 vs)\n                mstore(ptr, permit2Selector)\n                mstore(add(ptr, 0x04), owner)\n                mstore(add(ptr, 0x24), token)\n                calldatacopy(add(ptr, 0x50), permit.offset, 0x14) // amount\n                mstore(add(ptr, 0x64), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x14))), 1))) // expiration\n                mstore(add(ptr, 0x84), shr(224, calldataload(add(permit.offset, 0x18)))) // nonce\n                mstore(add(ptr, 0xa4), spender)\n                mstore(add(ptr, 0xc4), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x1c))), 1))) // sigDeadline\n                mstore(add(ptr, 0xe4), 0x100)\n                mstore(add(ptr, 0x104), 0x40)\n                calldatacopy(add(ptr, 0x124), add(permit.offset, 0x20), 0x20) // r\n                calldatacopy(add(ptr, 0x144), add(permit.offset, 0x40), 0x20) // vs\n                // IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature)\n                success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0)\n            }\n            case 352 {\n                mstore(ptr, permit2Selector)\n                calldatacopy(add(ptr, 0x04), permit.offset, permit.length)\n                // IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature)\n                success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0)\n            }\n            default {\n                mstore(ptr, _PERMIT_LENGTH_ERROR)\n                revert(ptr, 4)\n            }\n        }\n    }\n\n    function _makeCall(\n        IERC20 token,\n        bytes4 selector,\n        address to,\n        uint256 amount\n    ) private returns (bool success) {\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let data := mload(0x40)\n\n            mstore(data, selector)\n            mstore(add(data, 0x04), to)\n            mstore(add(data, 0x24), amount)\n            success := call(gas(), token, 0, data, 0x44, 0x0, 0x20)\n            if success {\n                switch returndatasize()\n                case 0 {\n                    success := gt(extcodesize(token), 0)\n                }\n                default {\n                    success := and(gt(returndatasize(), 31), eq(mload(0), 1))\n                }\n            }\n        }\n    }\n\n    function safeDeposit(IWETH weth, uint256 amount) internal {\n        if (amount > 0) {\n            bytes4 selector = IWETH.deposit.selector;\n            assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n                mstore(0, selector)\n                if iszero(call(gas(), weth, amount, 0, 4, 0, 0)) {\n                    returndatacopy(0, 0, returndatasize())\n                    revert(0, returndatasize())\n                }\n            }\n        }\n    }\n\n    function safeWithdraw(IWETH weth, uint256 amount) internal {\n        bytes4 selector = IWETH.withdraw.selector;\n        assembly (\"memory-safe\") {  // solhint-disable-line no-inline-assembly\n            mstore(0, selector)\n            mstore(4, amount)\n            if iszero(call(gas(), weth, 0, 0, 0x24, 0, 0)) {\n                let ptr := mload(0x40)\n                returndatacopy(ptr, 0, returndatasize())\n                revert(ptr, returndatasize())\n            }\n        }\n    }\n\n    function safeWithdrawTo(IWETH weth, uint256 amount, address to) internal {\n        safeWithdraw(weth, amount);\n        if (to != address(this)) {\n            assembly (\"memory-safe\") {  // solhint-disable-line no-inline-assembly\n                if iszero(call(_RAW_CALL_GAS_LIMIT, to, amount, 0, 0, 0, 0)) {\n                    let ptr := mload(0x40)\n                    returndatacopy(ptr, 0, returndatasize())\n                    revert(ptr, returndatasize())\n                }\n            }\n        }\n    }\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/libraries/BalancesLogic.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 {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeCast} from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\nimport {SafeERC20} from \"@1inch/solidity-utils/contracts/libraries/SafeERC20.sol\";\n\nimport {BitMask} from \"./BitMask.sol\";\n\nimport {Balance} from \"@gearbox-protocol/core-v2/contracts/libraries/Balances.sol\";\n\nstruct BalanceWithMask {\n    address token;\n    uint256 tokenMask;\n    uint256 balance;\n}\n\nstruct BalanceDelta {\n    address token;\n    int256 amount;\n}\n\nenum Comparison {\n    GREATER,\n    LESS\n}\n\n/// @title Balances logic library\n/// @notice Implements functions for before-and-after balance comparisons\nlibrary BalancesLogic {\n    using BitMask for uint256;\n    using SafeCast for int256;\n    using SafeCast for uint256;\n    using SafeERC20 for IERC20;\n\n    /// @dev Compares current `token` balance with `value`\n    /// @param token Token to check balance for\n    /// @param value Value to compare current token balance with\n    /// @param comparison Whether current balance must be greater/less than or equal to `value`\n    function checkBalance(address creditAccount, address token, uint256 value, Comparison comparison)\n        internal\n        view\n        returns (bool)\n    {\n        uint256 current = IERC20(token).safeBalanceOf(creditAccount);\n        return (comparison == Comparison.GREATER && current >= value)\n            || (comparison == Comparison.LESS && current <= value); // U:[BLL-1]\n    }\n\n    /// @dev Returns an array of expected token balances after operations\n    /// @param creditAccount Credit account to compute balances for\n    /// @param deltas Array of expected token balance changes\n    function storeBalances(address creditAccount, BalanceDelta[] memory deltas)\n        internal\n        view\n        returns (Balance[] memory balances)\n    {\n        uint256 len = deltas.length;\n        balances = new Balance[](len); // U:[BLL-2]\n        for (uint256 i = 0; i < len;) {\n            int256 balance = IERC20(deltas[i].token).safeBalanceOf(creditAccount).toInt256();\n            balances[i] = Balance({token: deltas[i].token, balance: (balance + deltas[i].amount).toUint256()}); // U:[BLL-2]\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /// @dev Compares current balances with the previously stored ones\n    /// @param creditAccount Credit account to compare balances for\n    /// @param balances Array of previously stored balances\n    /// @param comparison Whether current balances must be greater/less than or equal to stored ones\n    /// @return success True if condition specified by `comparison` holds for all tokens, false otherwise\n    function compareBalances(address creditAccount, Balance[] memory balances, Comparison comparison)\n        internal\n        view\n        returns (bool success)\n    {\n        uint256 len = balances.length;\n        unchecked {\n            for (uint256 i = 0; i < len; ++i) {\n                if (!BalancesLogic.checkBalance(creditAccount, balances[i].token, balances[i].balance, comparison)) {\n                    return false; // U:[BLL-3]\n                }\n            }\n        }\n        return true; // U:[BLL-3]\n    }\n\n    /// @dev Returns balances of specified tokens on the credit account\n    /// @param creditAccount Credit account to compute balances for\n    /// @param tokensMask Bit mask of tokens to compute balances for\n    /// @param getTokenByMaskFn Function that returns token's address by its mask\n    function storeBalances(\n        address creditAccount,\n        uint256 tokensMask,\n        function (uint256) view returns (address) getTokenByMaskFn\n    ) internal view returns (BalanceWithMask[] memory balances) {\n        if (tokensMask == 0) return balances;\n\n        balances = new BalanceWithMask[](tokensMask.calcEnabledTokens()); // U:[BLL-4]\n        unchecked {\n            uint256 i;\n            while (tokensMask != 0) {\n                uint256 tokenMask = tokensMask & uint256(-int256(tokensMask));\n                tokensMask ^= tokenMask;\n\n                address token = getTokenByMaskFn(tokenMask);\n                balances[i] = BalanceWithMask({\n                    token: token,\n                    tokenMask: tokenMask,\n                    balance: IERC20(token).safeBalanceOf(creditAccount)\n                }); // U:[BLL-4]\n                ++i;\n            }\n        }\n    }\n\n    /// @dev Compares current balances of specified tokens with the previously stored ones\n    /// @param creditAccount Credit account to compare balances for\n    /// @param tokensMask Bit mask of tokens to compare balances for\n    /// @param balances Array of previously stored balances\n    /// @param comparison Whether current balances must be greater/less than or equal to stored ones\n    /// @return success True if condition specified by `comparison` holds for all tokens, false otherwise\n    function compareBalances(\n        address creditAccount,\n        uint256 tokensMask,\n        BalanceWithMask[] memory balances,\n        Comparison comparison\n    ) internal view returns (bool) {\n        if (tokensMask == 0) return true;\n\n        unchecked {\n            uint256 len = balances.length;\n            for (uint256 i; i < len; ++i) {\n                if (tokensMask & balances[i].tokenMask != 0) {\n                    if (!BalancesLogic.checkBalance(creditAccount, balances[i].token, balances[i].balance, comparison))\n                    {\n                        return false; // U:[BLL-5]\n                    }\n                }\n            }\n        }\n        return true; // U:[BLL-5]\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/libraries/BitMask.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 {IncorrectParameterException} from \"../interfaces/IExceptions.sol\";\n\nuint256 constant UNDERLYING_TOKEN_MASK = 1;\n\n/// @title Bit mask library\n/// @notice Implements functions that manipulate bit masks\n///         Bit masks are utilized extensively by Gearbox to efficiently store token sets (enabled tokens on accounts\n///         or forbidden tokens) and check for set inclusion. A mask is a uint256 number that has its i-th bit set to\n///         1 if i-th item is included into the set. For example, each token has a mask equal to 2**i, so set inclusion\n///         can be checked by checking tokenMask & setMask != 0.\nlibrary BitMask {\n    /// @dev Calculates an index of an item based on its mask (using a binary search)\n    /// @dev The input should always have only 1 bit set, otherwise the result may be unpredictable\n    function calcIndex(uint256 mask) internal pure returns (uint8 index) {\n        if (mask == 0) revert IncorrectParameterException(); // U:[BM-1]\n        uint16 lb = 0; // U:[BM-2]\n        uint16 ub = 256; // U:[BM-2]\n        uint16 mid = 128; // U:[BM-2]\n\n        unchecked {\n            while (true) {\n                uint256 newMask = 1 << mid;\n                if (newMask & mask != 0) return uint8(mid); // U:[BM-2]\n\n                if (newMask > mask) ub = mid; // U:[BM-2]\n\n                else lb = mid; // U:[BM-2]\n                mid = (lb + ub) >> 1; // U:[BM-2]\n            }\n        }\n    }\n\n    /// @dev Calculates the number of `1` bits\n    /// @param enabledTokensMask Bit mask to compute the number of `1` bits in\n    function calcEnabledTokens(uint256 enabledTokensMask) internal pure returns (uint256 totalTokensEnabled) {\n        unchecked {\n            while (enabledTokensMask > 0) {\n                enabledTokensMask &= enabledTokensMask - 1; // U:[BM-3]\n                ++totalTokensEnabled; // U:[BM-3]\n            }\n        }\n    }\n\n    /// @dev Enables bits from the second mask in the first mask\n    /// @param enabledTokenMask The initial mask\n    /// @param bitsToEnable Mask of bits to enable\n    function enable(uint256 enabledTokenMask, uint256 bitsToEnable) internal pure returns (uint256) {\n        return enabledTokenMask | bitsToEnable; // U:[BM-4]\n    }\n\n    /// @dev Disables bits from the second mask in the first mask\n    /// @param enabledTokenMask The initial mask\n    /// @param bitsToDisable Mask of bits to disable\n    function disable(uint256 enabledTokenMask, uint256 bitsToDisable) internal pure returns (uint256) {\n        return enabledTokenMask & ~bitsToDisable; // U:[BM-4]\n    }\n\n    /// @dev Computes a new mask with sets of new enabled and disabled bits\n    /// @dev bitsToEnable and bitsToDisable are applied sequentially to original mask\n    /// @param enabledTokensMask The initial mask\n    /// @param bitsToEnable Mask with bits to enable\n    /// @param bitsToDisable Mask with bits to disable\n    function enableDisable(uint256 enabledTokensMask, uint256 bitsToEnable, uint256 bitsToDisable)\n        internal\n        pure\n        returns (uint256)\n    {\n        return (enabledTokensMask | bitsToEnable) & (~bitsToDisable); // U:[BM-5]\n    }\n\n    /// @dev Enables bits from the second mask in the first mask, skipping specified bits\n    /// @param enabledTokenMask The initial mask\n    /// @param bitsToEnable Mask with bits to enable\n    /// @param invertedSkipMask An inversion of mask of immutable bits\n    function enable(uint256 enabledTokenMask, uint256 bitsToEnable, uint256 invertedSkipMask)\n        internal\n        pure\n        returns (uint256)\n    {\n        return enabledTokenMask | (bitsToEnable & invertedSkipMask); // U:[BM-6]\n    }\n\n    /// @dev Disables bits from the second mask in the first mask, skipping specified bits\n    /// @param enabledTokenMask The initial mask\n    /// @param bitsToDisable Mask with bits to disable\n    /// @param invertedSkipMask An inversion of mask of immutable bits\n    function disable(uint256 enabledTokenMask, uint256 bitsToDisable, uint256 invertedSkipMask)\n        internal\n        pure\n        returns (uint256)\n    {\n        return enabledTokenMask & (~(bitsToDisable & invertedSkipMask)); // U:[BM-6]\n    }\n\n    /// @dev Computes a new mask with sets of new enabled and disabled bits, skipping some bits\n    /// @dev bitsToEnable and bitsToDisable are applied sequentially to original mask. Skipmask is applied in both cases.\n    /// @param enabledTokensMask The initial mask\n    /// @param bitsToEnable Mask with bits to enable\n    /// @param bitsToDisable Mask with bits to disable\n    /// @param invertedSkipMask An inversion of mask of immutable bits\n    function enableDisable(\n        uint256 enabledTokensMask,\n        uint256 bitsToEnable,\n        uint256 bitsToDisable,\n        uint256 invertedSkipMask\n    ) internal pure returns (uint256) {\n        return (enabledTokensMask | (bitsToEnable & invertedSkipMask)) & (~(bitsToDisable & invertedSkipMask)); // U:[BM-7]\n    }\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/interfaces/ICreditFacadeV3.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 {MultiCall} from \"@gearbox-protocol/core-v2/contracts/libraries/MultiCall.sol\";\n\nimport {IVersion} from \"@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol\";\nimport \"./ICreditFacadeV3Multicall.sol\";\nimport {AllowanceAction} from \"../interfaces/ICreditConfiguratorV3.sol\";\n\n/// @notice Debt limits packed into a single slot\n/// @param minDebt Minimum debt amount per credit account\n/// @param maxDebt Maximum debt amount per credit account\nstruct DebtLimits {\n    uint128 minDebt;\n    uint128 maxDebt;\n}\n\n/// @notice Info on bad debt liquidation losses packed into a single slot\n/// @param currentCumulativeLoss Current cumulative loss from bad debt liquidations\n/// @param maxCumulativeLoss Max cumulative loss incurred before the facade gets paused\nstruct CumulativeLossParams {\n    uint128 currentCumulativeLoss;\n    uint128 maxCumulativeLoss;\n}\n\n/// @notice Collateral check params\n/// @param collateralHints Optional array of token masks to check first to reduce the amount of computation\n///        when known subset of account's collateral tokens covers all the debt\n/// @param minHealthFactor Min account's health factor in bps in order not to revert\n/// @param enabledTokensMaskAfter Bitmask of account's enabled collateral tokens after the multicall\n/// @param revertOnForbiddenTokens Whether to revert on enabled forbidden tokens after the multicall\n/// @param useSafePrices Whether to use safe pricing (min of main and reserve feeds) when evaluating collateral\nstruct FullCheckParams {\n    uint256[] collateralHints;\n    uint16 minHealthFactor;\n    uint256 enabledTokensMaskAfter;\n    bool revertOnForbiddenTokens;\n    bool useSafePrices;\n}\n\ninterface ICreditFacadeV3Events {\n    /// @notice Emitted when a new credit account is opened\n    event OpenCreditAccount(\n        address indexed creditAccount, address indexed onBehalfOf, address indexed caller, uint256 referralCode\n    );\n\n    /// @notice Emitted when account is closed\n    event CloseCreditAccount(address indexed creditAccount, address indexed borrower);\n\n    /// @notice Emitted when account is liquidated\n    event LiquidateCreditAccount(\n        address indexed creditAccount, address indexed liquidator, address to, uint256 remainingFunds\n    );\n\n    /// @notice Emitted when account's debt is increased\n    event IncreaseDebt(address indexed creditAccount, uint256 amount);\n\n    /// @notice Emitted when account's debt is decreased\n    event DecreaseDebt(address indexed creditAccount, uint256 amount);\n\n    /// @notice Emitted when collateral is added to account\n    event AddCollateral(address indexed creditAccount, address indexed token, uint256 amount);\n\n    /// @notice Emitted when collateral is withdrawn from account\n    event WithdrawCollateral(address indexed creditAccount, address indexed token, uint256 amount, address to);\n\n    /// @notice Emitted when a multicall is started\n    event StartMultiCall(address indexed creditAccount, address indexed caller);\n\n    /// @notice Emitted when a call from account to an external contract is made during a multicall\n    event Execute(address indexed creditAccount, address indexed targetContract);\n\n    /// @notice Emitted when a multicall is finished\n    event FinishMultiCall();\n}\n\n/// @title Credit facade V3 interface\ninterface ICreditFacadeV3 is IVersion, ICreditFacadeV3Events {\n    function creditManager() external view returns (address);\n\n    function degenNFT() external view returns (address);\n\n    function weth() external view returns (address);\n\n    function botList() external view returns (address);\n\n    function maxDebtPerBlockMultiplier() external view returns (uint8);\n\n    function maxQuotaMultiplier() external view returns (uint256);\n\n    function expirable() external view returns (bool);\n\n    function expirationDate() external view returns (uint40);\n\n    function debtLimits() external view returns (uint128 minDebt, uint128 maxDebt);\n\n    function lossParams() external view returns (uint128 currentCumulativeLoss, uint128 maxCumulativeLoss);\n\n    function forbiddenTokenMask() external view returns (uint256);\n\n    function canLiquidateWhilePaused(address) external view returns (bool);\n\n    // ------------------ //\n    // ACCOUNT MANAGEMENT //\n    // ------------------ //\n\n    function openCreditAccount(address onBehalfOf, MultiCall[] calldata calls, uint256 referralCode)\n        external\n        payable\n        returns (address creditAccount);\n\n    function closeCreditAccount(address creditAccount, MultiCall[] calldata calls) external payable;\n\n    function liquidateCreditAccount(address creditAccount, address to, MultiCall[] calldata calls) external;\n\n    function multicall(address creditAccount, MultiCall[] calldata calls) external payable;\n\n    function botMulticall(address creditAccount, MultiCall[] calldata calls) external;\n\n    function setBotPermissions(address creditAccount, address bot, uint192 permissions) external;\n\n    // ------------- //\n    // CONFIGURATION //\n    // ------------- //\n\n    function setExpirationDate(uint40 newExpirationDate) external;\n\n    function setDebtLimits(uint128 newMinDebt, uint128 newMaxDebt, uint8 newMaxDebtPerBlockMultiplier) external;\n\n    function setBotList(address newBotList) external;\n\n    function setCumulativeLossParams(uint128 newMaxCumulativeLoss, bool resetCumulativeLoss) external;\n\n    function setTokenAllowance(address token, AllowanceAction allowance) external;\n\n    function setEmergencyLiquidator(address liquidator, AllowanceAction allowance) external;\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/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-v3/contracts/interfaces/ICreditConfiguratorV3.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\nenum AllowanceAction {\n    FORBID,\n    ALLOW\n}\n\n/// @notice Struct with credit manager configuration parameters\n/// @param minDebt Minimum debt amount per account\n/// @param maxDebt Maximum debt amount per account\n/// @param degenNFT Whether to apply Degen NFT whitelist logic\n/// @param expirable Whether facade must be expirable\n/// @param name Credit manager name\nstruct CreditManagerOpts {\n    uint128 minDebt;\n    uint128 maxDebt;\n    address degenNFT;\n    bool expirable;\n    string name;\n}\n\ninterface ICreditConfiguratorV3Events {\n    // ------ //\n    // TOKENS //\n    // ------ //\n\n    /// @notice Emitted when a token is made recognizable as collateral in the credit manager\n    event AddCollateralToken(address indexed token);\n\n    /// @notice Emitted when a new collateral token liquidation threshold is set\n    event SetTokenLiquidationThreshold(address indexed token, uint16 liquidationThreshold);\n\n    /// @notice Emitted when a collateral token liquidation threshold ramping is scheduled\n    event ScheduleTokenLiquidationThresholdRamp(\n        address indexed token,\n        uint16 liquidationThresholdInitial,\n        uint16 liquidationThresholdFinal,\n        uint40 timestampRampStart,\n        uint40 timestampRampEnd\n    );\n\n    /// @notice Emitted when a collateral token is forbidden\n    event ForbidToken(address indexed token);\n\n    /// @notice Emitted when a previously forbidden collateral token is allowed\n    event AllowToken(address indexed token);\n\n    /// @notice Emitted when a token is made quoted\n    event QuoteToken(address indexed token);\n\n    // -------- //\n    // ADAPTERS //\n    // -------- //\n\n    /// @notice Emitted when a new adapter and its target contract are allowed in the credit manager\n    event AllowAdapter(address indexed targetContract, address indexed adapter);\n\n    /// @notice Emitted when adapter and its target contract are forbidden in the credit manager\n    event ForbidAdapter(address indexed targetContract, address indexed adapter);\n\n    // -------------- //\n    // CREDIT MANAGER //\n    // -------------- //\n\n    /// @notice Emitted when a new maximum number of enabled tokens is set in the credit manager\n    event SetMaxEnabledTokens(uint8 maxEnabledTokens);\n\n    /// @notice Emitted when new fee parameters are set in the credit manager\n    event UpdateFees(\n        uint16 feeInterest,\n        uint16 feeLiquidation,\n        uint16 liquidationPremium,\n        uint16 feeLiquidationExpired,\n        uint16 liquidationPremiumExpired\n    );\n\n    // -------- //\n    // UPGRADES //\n    // -------- //\n\n    /// @notice Emitted when a new price oracle is set in the credit manager\n    event SetPriceOracle(address indexed priceOracle);\n\n    /// @notice Emitted when a new bot list is set in the credit facade\n    event SetBotList(address indexed botList);\n\n    /// @notice Emitted when a new facade is connected to the credit manager\n    event SetCreditFacade(address indexed creditFacade);\n\n    /// @notice Emitted when credit manager's configurator contract is upgraded\n    event CreditConfiguratorUpgraded(address indexed creditConfigurator);\n\n    // ------------- //\n    // CREDIT FACADE //\n    // ------------- //\n\n    /// @notice Emitted when new debt principal limits are set\n    event SetBorrowingLimits(uint256 minDebt, uint256 maxDebt);\n\n    /// @notice Emitted when a new max debt per block multiplier is set\n    event SetMaxDebtPerBlockMultiplier(uint8 maxDebtPerBlockMultiplier);\n\n    /// @notice Emitted when a new max cumulative loss is set\n    event SetMaxCumulativeLoss(uint128 maxCumulativeLoss);\n\n    /// @notice Emitted when cumulative loss is reset to zero in the credit facade\n    event ResetCumulativeLoss();\n\n    /// @notice Emitted when a new expiration timestamp is set in the credit facade\n    event SetExpirationDate(uint40 expirationDate);\n\n    /// @notice Emitted when an address is added to the list of emergency liquidators\n    event AddEmergencyLiquidator(address indexed liquidator);\n\n    /// @notice Emitted when an address is removed from the list of emergency liquidators\n    event RemoveEmergencyLiquidator(address indexed liquidator);\n}\n\n/// @title Credit configurator V3 interface\ninterface ICreditConfiguratorV3 is IVersion, ICreditConfiguratorV3Events {\n    function addressProvider() external view returns (address);\n\n    function creditManager() external view returns (address);\n\n    function creditFacade() external view returns (address);\n\n    function underlying() external view returns (address);\n\n    // ------ //\n    // TOKENS //\n    // ------ //\n\n    function addCollateralToken(address token, uint16 liquidationThreshold) external;\n\n    function setLiquidationThreshold(address token, uint16 liquidationThreshold) external;\n\n    function rampLiquidationThreshold(\n        address token,\n        uint16 liquidationThresholdFinal,\n        uint40 rampStart,\n        uint24 rampDuration\n    ) external;\n\n    function forbidToken(address token) external;\n\n    function allowToken(address token) external;\n\n    function makeTokenQuoted(address token) external;\n\n    // -------- //\n    // ADAPTERS //\n    // -------- //\n\n    function allowedAdapters() external view returns (address[] memory);\n\n    function allowAdapter(address adapter) external;\n\n    function forbidAdapter(address adapter) external;\n\n    // -------------- //\n    // CREDIT MANAGER //\n    // -------------- //\n\n    function setFees(\n        uint16 feeInterest,\n        uint16 feeLiquidation,\n        uint16 liquidationPremium,\n        uint16 feeLiquidationExpired,\n        uint16 liquidationPremiumExpired\n    ) external;\n\n    function setMaxEnabledTokens(uint8 newMaxEnabledTokens) external;\n\n    // -------- //\n    // UPGRADES //\n    // -------- //\n\n    function setPriceOracle(uint256 newVersion) external;\n\n    function setBotList(uint256 newVersion) external;\n\n    function setCreditFacade(address newCreditFacade, bool migrateParams) external;\n\n    function upgradeCreditConfigurator(address newCreditConfigurator) external;\n\n    // ------------- //\n    // CREDIT FACADE //\n    // ------------- //\n\n    function setMinDebtLimit(uint128 newMinDebt) external;\n\n    function setMaxDebtLimit(uint128 newMaxDebt) external;\n\n    function setMaxDebtPerBlockMultiplier(uint8 newMaxDebtLimitPerBlockMultiplier) external;\n\n    function forbidBorrowing() external;\n\n    function setMaxCumulativeLoss(uint128 newMaxCumulativeLoss) external;\n\n    function resetCumulativeLoss() external;\n\n    function setExpirationDate(uint40 newExpirationDate) external;\n\n    function emergencyLiquidators() external view returns (address[] memory);\n\n    function addEmergencyLiquidator(address liquidator) external;\n\n    function removeEmergencyLiquidator(address liquidator) external;\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/interfaces/IPriceOracleV3.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 {IPriceOracleBase} from \"@gearbox-protocol/core-v2/contracts/interfaces/IPriceOracleBase.sol\";\n\nstruct PriceFeedParams {\n    address priceFeed;\n    uint32 stalenessPeriod;\n    bool skipCheck;\n    uint8 decimals;\n    bool useReserve;\n    bool trusted;\n}\n\ninterface IPriceOracleV3Events {\n    /// @notice Emitted when new price feed is set for token\n    event SetPriceFeed(\n        address indexed token, address indexed priceFeed, uint32 stalenessPeriod, bool skipCheck, bool trusted\n    );\n\n    /// @notice Emitted when new reserve price feed is set for token\n    event SetReservePriceFeed(address indexed token, address indexed priceFeed, uint32 stalenessPeriod, bool skipCheck);\n\n    /// @notice Emitted when new reserve price feed status is set for a token\n    event SetReservePriceFeedStatus(address indexed token, bool active);\n}\n\n/// @title Price oracle V3 interface\ninterface IPriceOracleV3 is IPriceOracleBase, IPriceOracleV3Events {\n    function getPriceSafe(address token) external view returns (uint256);\n\n    function getPriceRaw(address token, bool reserve) external view returns (uint256);\n\n    function priceFeedsRaw(address token, bool reserve) external view returns (address);\n\n    function priceFeedParams(address token)\n        external\n        view\n        returns (address priceFeed, uint32 stalenessPeriod, bool skipCheck, uint8 decimals, bool trusted);\n\n    function safeConvertToUSD(uint256 amount, address token) external view returns (uint256);\n\n    // ------------- //\n    // CONFIGURATION //\n    // ------------- //\n\n    function setPriceFeed(address token, address priceFeed, uint32 stalenessPeriod, bool trusted) external;\n\n    function setReservePriceFeed(address token, address priceFeed, uint32 stalenessPeriod) external;\n\n    function setReservePriceFeedStatus(address token, bool active) external;\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v2/contracts/interfaces/IPriceFeed.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Gearbox Protocol. Generalized leverage for DeFi protocols\n// (c) Gearbox Foundation, 2023.\npragma solidity ^0.8.0;\n\nimport { PriceFeedType } from \"@gearbox-protocol/sdk-gov/contracts/PriceFeedType.sol\";\n\n/// @title Price feed interface\ninterface IPriceFeed {\n    function priceFeedType() external view returns (PriceFeedType);\n\n    function version() external view returns (uint256);\n\n    function decimals() external view returns (uint8);\n\n    function description() external view returns (string memory);\n\n    function skipPriceCheck() external view returns (bool);\n\n    function latestRoundData()\n        external\n        view\n        returns (uint80, int256 answer, uint256, uint256 updatedAt, uint80);\n}\n\n/// @title Updatable price feed interface\ninterface IUpdatablePriceFeed is IPriceFeed {\n    function updatable() external view returns (bool);\n\n    function updatePrice(bytes calldata data) external;\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-v2/contracts/interfaces/IDegenNFTV2.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\";\nimport { IERC721Metadata } from \"@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\n\ninterface IDegenNFTV2Exceptions {\n    /// @dev Thrown if an access-restricted function was called by non-CreditFacade\n    error CreditFacadeOrConfiguratorOnlyException();\n\n    /// @dev Thrown if an access-restricted function was called by non-minter\n    error MinterOnlyException();\n\n    /// @dev Thrown if trying to add a burner address that is not a correct Credit Facade\n    error InvalidCreditFacadeException();\n\n    /// @dev Thrown if the account's balance is not sufficient for an action (usually a burn)\n    error InsufficientBalanceException();\n}\n\ninterface IDegenNFTV2Events {\n    /// @dev Minted when new minter set\n    event NewMinterSet(address indexed);\n\n    /// @dev Minted each time when new credit facade added\n    event NewCreditFacadeAdded(address indexed);\n\n    /// @dev Minted each time when new credit facade added\n    event NewCreditFacadeRemoved(address indexed);\n}\n\ninterface IDegenNFTV2 is\n    IDegenNFTV2Exceptions,\n    IDegenNFTV2Events,\n    IVersion,\n    IERC721Metadata\n{\n    /// @dev address of the current minter\n    function minter() external view returns (address);\n\n    /// @dev Stores the total number of tokens on holder accounts\n    function totalSupply() external view returns (uint256);\n\n    /// @dev Stores the base URI for NFT metadata\n    function baseURI() external view returns (string memory);\n\n    /// @dev Mints a specified amount of tokens to the address\n    /// @param to Address the tokens are minted to\n    /// @param amount The number of tokens to mint\n    function mint(address to, uint256 amount) external;\n\n    /// @dev Burns a number of tokens from a specified address\n    /// @param from The address a token will be burnt from\n    /// @param amount The number of tokens to burn\n    function burn(address from, uint256 amount) external;\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v2/contracts/interfaces/external/IWETH.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.7.4;\n\ninterface IWETH {\n    /// @dev Deposits native ETH into the contract and mints WETH\n    function deposit() external payable;\n\n    /// @dev Transfers WETH to another account\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /// @dev Burns WETH from msg.sender and send back native ETH\n    function withdraw(uint256) external;\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v3/contracts/interfaces/IBotListV3.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\n/// @notice Bot info\n/// @param forbidden Whether bot is forbidden\n/// @param specialPermissions Mapping credit manager => bot's special permissions\n/// @param permissions Mapping credit manager => credit account => bot's permissions\nstruct BotInfo {\n    bool forbidden;\n    mapping(address => uint192) specialPermissions;\n    mapping(address => mapping(address => uint192)) permissions;\n}\n\ninterface IBotListV3Events {\n    // ----------- //\n    // PERMISSIONS //\n    // ----------- //\n\n    /// @notice Emitted when new `bot`'s permissions and funding params are set for `creditAccount` in `creditManager`\n    event SetBotPermissions(\n        address indexed bot, address indexed creditManager, address indexed creditAccount, uint192 permissions\n    );\n\n    /// @notice Emitted when `bot`'s permissions and funding params are removed for `creditAccount` in `creditManager`\n    event EraseBot(address indexed bot, address indexed creditManager, address indexed creditAccount);\n\n    // ------------- //\n    // CONFIGURATION //\n    // ------------- //\n\n    /// @notice Emitted when `bot`'s forbidden status is set\n    event SetBotForbiddenStatus(address indexed bot, bool forbidden);\n\n    /// @notice Emitted when `bot`'s special permissions in `creditManager` are set\n    event SetBotSpecialPermissions(address indexed bot, address indexed creditManager, uint192 permissions);\n\n    /// @notice Emitted when `creditManager`'s approved status is set\n    event SetCreditManagerApprovedStatus(address indexed creditManager, bool approved);\n}\n\n/// @title Bot list V3 interface\ninterface IBotListV3 is IBotListV3Events, IVersion {\n    // ----------- //\n    // PERMISSIONS //\n    // ----------- //\n\n    function botPermissions(address bot, address creditManager, address creditAccount)\n        external\n        view\n        returns (uint192);\n\n    function activeBots(address creditManager, address creditAccount) external view returns (address[] memory);\n\n    function getBotStatus(address bot, address creditManager, address creditAccount)\n        external\n        view\n        returns (uint192 permissions, bool forbidden, bool hasSpecialPermissions);\n\n    function setBotPermissions(address bot, address creditManager, address creditAccount, uint192 permissions)\n        external\n        returns (uint256 activeBotsRemaining);\n\n    function eraseAllBotPermissions(address creditManager, address creditAccount) external;\n\n    // ------------- //\n    // CONFIGURATION //\n    // ------------- //\n\n    function botForbiddenStatus(address bot) external view returns (bool);\n\n    function botSpecialPermissions(address bot, address creditManager) external view returns (uint192);\n\n    function approvedCreditManager(address creditManager) external view returns (bool);\n\n    function setBotForbiddenStatus(address bot, bool forbidden) external;\n\n    function setBotSpecialPermissions(address bot, address creditManager, uint192 permissions) external;\n\n    function setCreditManagerApprovedStatus(address creditManager, bool approved) 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/token/ERC20/extensions/draft-IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-2612 is Final as of 2022-11-01. This file is deprecated.\n\nimport \"./IERC20Permit.sol\";\n"
      },
      "node_modules/@1inch/solidity-utils/contracts/interfaces/IDaiLikePermit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IDaiLikePermit {\n    function permit(\n        address holder,\n        address spender,\n        uint256 nonce,\n        uint256 expiry,\n        bool allowed,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n}\n"
      },
      "node_modules/@1inch/solidity-utils/contracts/interfaces/IPermit2.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IPermit2 {\n    struct PermitDetails {\n        // ERC20 token address\n        address token;\n        // the maximum amount allowed to spend\n        uint160 amount;\n        // timestamp at which a spender's token allowances become invalid\n        uint48 expiration;\n        // an incrementing value indexed per owner,token,and spender for each signature\n        uint48 nonce;\n    }\n    /// @notice The permit message signed for a single token allownce\n    struct PermitSingle {\n        // the permit data for a single token alownce\n        PermitDetails details;\n        // address permissioned on the allowed tokens\n        address spender;\n        // deadline on the permit signature\n        uint256 sigDeadline;\n    }\n    /// @notice Packed allowance\n    struct PackedAllowance {\n        // amount allowed\n        uint160 amount;\n        // permission expiry\n        uint48 expiration;\n        // an incrementing value indexed per owner,token,and spender for each signature\n        uint48 nonce;\n    }\n\n    function transferFrom(address user, address spender, uint160 amount, address token) external;\n\n    function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external;\n\n    function allowance(address user, address token, address spender) external view returns (PackedAllowance memory);\n}\n"
      },
      "node_modules/@1inch/solidity-utils/contracts/interfaces/IWETH.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IWETH is IERC20 {\n    function deposit() external payable;\n\n    function withdraw(uint256 amount) external;\n}\n"
      },
      "node_modules/@1inch/solidity-utils/contracts/libraries/RevertReasonForwarder.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/// @title Revert reason forwarder.\nlibrary RevertReasonForwarder {\n    /// @dev Forwards latest externall call revert.\n    function reRevert() internal pure {\n        // bubble up revert reason from latest external call\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let ptr := mload(0x40)\n            returndatacopy(ptr, 0, returndatasize())\n            revert(ptr, returndatasize())\n        }\n    }\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v2/contracts/libraries/Balances.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\nstruct Balance {\n    address token;\n    uint256 balance;\n}\n\nlibrary BalanceOps {\n    error UnknownToken(address);\n\n    function copyBalance(Balance memory b)\n        internal\n        pure\n        returns (Balance memory)\n    {\n        return Balance({ token: b.token, balance: b.balance });\n    }\n\n    function addBalance(\n        Balance[] memory b,\n        address token,\n        uint256 amount\n    ) internal pure {\n        b[getIndex(b, token)].balance += amount;\n    }\n\n    function subBalance(\n        Balance[] memory b,\n        address token,\n        uint256 amount\n    ) internal pure {\n        b[getIndex(b, token)].balance -= amount;\n    }\n\n    function getBalance(Balance[] memory b, address token)\n        internal\n        pure\n        returns (uint256 amount)\n    {\n        return b[getIndex(b, token)].balance;\n    }\n\n    function setBalance(\n        Balance[] memory b,\n        address token,\n        uint256 amount\n    ) internal pure {\n        b[getIndex(b, token)].balance = amount;\n    }\n\n    function getIndex(Balance[] memory b, address token)\n        internal\n        pure\n        returns (uint256 index)\n    {\n        for (uint256 i; i < b.length; ) {\n            if (b[i].token == token) {\n                return i;\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n        revert UnknownToken(token);\n    }\n\n    function copy(Balance[] memory b, uint256 len)\n        internal\n        pure\n        returns (Balance[] memory res)\n    {\n        res = new Balance[](len);\n        for (uint256 i; i < len; ) {\n            res[i] = copyBalance(b[i]);\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    function clone(Balance[] memory b)\n        internal\n        pure\n        returns (Balance[] memory)\n    {\n        return copy(b, b.length);\n    }\n\n    function getModifiedAfterSwap(\n        Balance[] memory b,\n        address tokenFrom,\n        uint256 amountFrom,\n        address tokenTo,\n        uint256 amountTo\n    ) internal pure returns (Balance[] memory res) {\n        res = copy(b, b.length);\n        setBalance(res, tokenFrom, getBalance(b, tokenFrom) - amountFrom);\n        setBalance(res, tokenTo, getBalance(b, tokenTo) + amountTo);\n    }\n}\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/libraries/MultiCall.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nstruct MultiCall {\n    address target;\n    bytes callData;\n}\n\nlibrary MultiCallOps {\n    function copyMulticall(MultiCall memory call)\n        internal\n        pure\n        returns (MultiCall memory)\n    {\n        return MultiCall({ target: call.target, callData: call.callData });\n    }\n\n    function trim(MultiCall[] memory calls)\n        internal\n        pure\n        returns (MultiCall[] memory trimmed)\n    {\n        uint256 len = calls.length;\n\n        if (len == 0) return calls;\n\n        uint256 foundLen;\n        while (calls[foundLen].target != address(0)) {\n            unchecked {\n                ++foundLen;\n                if (foundLen == len) return calls;\n            }\n        }\n\n        if (foundLen > 0) return copy(calls, foundLen);\n    }\n\n    function copy(MultiCall[] memory calls, uint256 len)\n        internal\n        pure\n        returns (MultiCall[] memory res)\n    {\n        res = new MultiCall[](len);\n        for (uint256 i; i < len; ) {\n            res[i] = copyMulticall(calls[i]);\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    function clone(MultiCall[] memory calls)\n        internal\n        pure\n        returns (MultiCall[] memory res)\n    {\n        return copy(calls, calls.length);\n    }\n\n    function append(MultiCall[] memory calls, MultiCall memory newCall)\n        internal\n        pure\n        returns (MultiCall[] memory res)\n    {\n        uint256 len = calls.length;\n        res = new MultiCall[](len + 1);\n        for (uint256 i; i < len; ) {\n            res[i] = copyMulticall(calls[i]);\n            unchecked {\n                ++i;\n            }\n        }\n        res[len] = copyMulticall(newCall);\n    }\n\n    function prepend(MultiCall[] memory calls, MultiCall memory newCall)\n        internal\n        pure\n        returns (MultiCall[] memory res)\n    {\n        uint256 len = calls.length;\n        res = new MultiCall[](len + 1);\n        res[0] = copyMulticall(newCall);\n\n        for (uint256 i = 1; i < len + 1; ) {\n            res[i] = copyMulticall(calls[i]);\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    function concat(MultiCall[] memory calls1, MultiCall[] memory calls2)\n        internal\n        pure\n        returns (MultiCall[] memory res)\n    {\n        uint256 len1 = calls1.length;\n        uint256 lenTotal = len1 + calls2.length;\n\n        if (lenTotal == calls1.length) return clone(calls1);\n        if (lenTotal == calls2.length) return clone(calls2);\n\n        res = new MultiCall[](lenTotal);\n\n        for (uint256 i; i < lenTotal; ) {\n            res[i] = (i < len1)\n                ? copyMulticall(calls1[i])\n                : copyMulticall(calls2[i - len1]);\n            unchecked {\n                ++i;\n            }\n        }\n    }\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/ICreditFacadeV3Multicall.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 {BalanceDelta} from \"../libraries/BalancesLogic.sol\";\nimport {RevocationPair} from \"./ICreditManagerV3.sol\";\n\n// ----------- //\n// PERMISSIONS //\n// ----------- //\n\nuint192 constant ADD_COLLATERAL_PERMISSION = 1;\nuint192 constant INCREASE_DEBT_PERMISSION = 1 << 1;\nuint192 constant DECREASE_DEBT_PERMISSION = 1 << 2;\nuint192 constant ENABLE_TOKEN_PERMISSION = 1 << 3;\nuint192 constant DISABLE_TOKEN_PERMISSION = 1 << 4;\nuint192 constant WITHDRAW_COLLATERAL_PERMISSION = 1 << 5;\nuint192 constant UPDATE_QUOTA_PERMISSION = 1 << 6;\nuint192 constant REVOKE_ALLOWANCES_PERMISSION = 1 << 7;\n\nuint192 constant EXTERNAL_CALLS_PERMISSION = 1 << 16;\n\nuint256 constant ALL_CREDIT_FACADE_CALLS_PERMISSION = ADD_COLLATERAL_PERMISSION | WITHDRAW_COLLATERAL_PERMISSION\n    | INCREASE_DEBT_PERMISSION | DECREASE_DEBT_PERMISSION | ENABLE_TOKEN_PERMISSION | DISABLE_TOKEN_PERMISSION\n    | UPDATE_QUOTA_PERMISSION | REVOKE_ALLOWANCES_PERMISSION;\n\nuint256 constant ALL_PERMISSIONS = ALL_CREDIT_FACADE_CALLS_PERMISSION | EXTERNAL_CALLS_PERMISSION;\n\n// ----- //\n// FLAGS //\n// ----- //\n\n/// @dev Indicates that there are enabled forbidden tokens on the account before multicall\nuint256 constant FORBIDDEN_TOKENS_BEFORE_CALLS = 1 << 192;\n\n/// @dev Indicates that external calls from credit account to adapters were made during multicall,\n///      set to true on the first call to the adapter\nuint256 constant EXTERNAL_CONTRACT_WAS_CALLED = 1 << 193;\n\n/// @title Credit facade V3 multicall interface\n/// @dev Unless specified otherwise, all these methods are only available in `openCreditAccount`,\n///      `closeCreditAccount`, `multicall`, and, with account owner's permission, `botMulticall`\ninterface ICreditFacadeV3Multicall {\n    /// @notice Updates the price for a token with on-demand updatable price feed\n    /// @param token Token to push the price update for\n    /// @param reserve Whether to update reserve price feed or main price feed\n    /// @param data Data to call `updatePrice` with\n    /// @dev Calls of this type must be placed before all other calls in the multicall not to revert\n    /// @dev This method is available in all kinds of multicalls\n    function onDemandPriceUpdate(address token, bool reserve, bytes calldata data) external;\n\n    /// @notice Stores expected token balances (current balance + delta) after operations for a slippage check.\n    ///         Normally, a check is performed automatically at the end of the multicall, but more fine-grained\n    ///         behavior can be achieved by placing `storeExpectedBalances` and `compareBalances` where needed.\n    /// @param balanceDeltas Array of (token, minBalanceDelta) pairs, deltas are allowed to be negative\n    /// @dev Reverts if expected balances are already set\n    /// @dev This method is available in all kinds of multicalls\n    function storeExpectedBalances(BalanceDelta[] calldata balanceDeltas) external;\n\n    /// @notice Performs a slippage check ensuring that current token balances are greater than saved expected ones\n    /// @dev Resets stored expected balances\n    /// @dev Reverts if expected balances are not stored\n    /// @dev This method is available in all kinds of multicalls\n    function compareBalances() external;\n\n    /// @notice Adds collateral to account\n    /// @param token Token to add\n    /// @param amount Amount to add\n    /// @dev Requires token approval from caller to the credit manager\n    /// @dev This method can also be called during liquidation\n    function addCollateral(address token, uint256 amount) external;\n\n    /// @notice Adds collateral to account using signed EIP-2612 permit message\n    /// @param token Token to add\n    /// @param amount Amount to add\n    /// @param deadline Permit deadline\n    /// @dev `v`, `r`, `s` must be a valid signature of the permit message from caller to the credit manager\n    /// @dev This method can also be called during liquidation\n    function addCollateralWithPermit(address token, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s)\n        external;\n\n    /// @notice Increases account's debt\n    /// @param amount Underlying amount to borrow\n    /// @dev Increasing debt is prohibited when closing an account\n    /// @dev Increasing debt is prohibited if it was previously updated in the same block\n    /// @dev The resulting debt amount must be within allowed range\n    /// @dev Increasing debt is prohibited if there are forbidden tokens enabled as collateral on the account\n    /// @dev After debt increase, total amount borrowed by the credit manager in the current block must not exceed\n    ///      the limit defined in the facade\n    function increaseDebt(uint256 amount) external;\n\n    /// @notice Decreases account's debt\n    /// @param amount Underlying amount to repay, value above account's total debt indicates full repayment\n    /// @dev Decreasing debt is prohibited when opening an account\n    /// @dev Decreasing debt is prohibited if it was previously updated in the same block\n    /// @dev The resulting debt amount must be within allowed range or zero\n    /// @dev Full repayment brings account into a special mode that skips collateral checks and thus requires\n    ///      an account to have no potential debt sources, e.g., all quotas must be disabled\n    function decreaseDebt(uint256 amount) external;\n\n    /// @notice Updates account's quota for a token\n    /// @param token Token to update the quota for\n    /// @param quotaChange Desired quota change in underlying token units (`type(int96).min` to disable quota)\n    /// @param minQuota Minimum resulting account's quota for token required not to revert\n    /// @dev Enables token as collateral if quota is increased from zero, disables if decreased to zero\n    /// @dev Quota increase is prohibited if there are forbidden tokens enabled as collateral on the account\n    /// @dev Quota update is prohibited if account has zero debt\n    /// @dev Resulting account's quota for token must not exceed the limit defined in the facade\n    function updateQuota(address token, int96 quotaChange, uint96 minQuota) external;\n\n    /// @notice Withdraws collateral from account\n    /// @param token Token to withdraw\n    /// @param amount Amount to withdraw, `type(uint256).max` to withdraw all balance\n    /// @param to Token recipient\n    /// @dev This method can also be called during liquidation\n    /// @dev Withdrawals are prohibited in multicalls if there are forbidden tokens enabled as collateral on the account\n    /// @dev Withdrawals activate safe pricing (min of main and reserve feeds) in collateral check\n    function withdrawCollateral(address token, uint256 amount, address to) external;\n\n    /// @notice Sets advanced collateral check parameters\n    /// @param collateralHints Optional array of token masks to check first to reduce the amount of computation\n    ///        when known subset of account's collateral tokens covers all the debt\n    /// @param minHealthFactor Min account's health factor in bps in order not to revert, must be at least 10000\n    function setFullCheckParams(uint256[] calldata collateralHints, uint16 minHealthFactor) external;\n\n    /// @notice Enables token as account's collateral, which makes it count towards account's total value\n    /// @param token Token to enable as collateral\n    /// @dev Enabling forbidden tokens is prohibited\n    /// @dev Quoted tokens can only be enabled via `updateQuota`, this method is no-op for them\n    function enableToken(address token) external;\n\n    /// @notice Disables token as account's collateral\n    /// @param token Token to disable as collateral\n    /// @dev Quoted tokens can only be disabled via `updateQuota`, this method is no-op for them\n    function disableToken(address token) external;\n\n    /// @notice Revokes account's allowances for specified spender/token pairs\n    /// @param revocations Array of spender/token pairs\n    /// @dev Exists primarily to allow users to revoke allowances on accounts from old account factory on mainnet\n    function revokeAdapterAllowances(RevocationPair[] calldata revocations) external;\n}\n"
      },
      "node_modules/@gearbox-protocol/core-v2/contracts/interfaces/IPriceOracleBase.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\nimport { IVersion } from \"./IVersion.sol\";\n\n/// @title Price oracle base interface\n/// @notice Functions shared accross newer and older versions\ninterface IPriceOracleBase is IVersion {\n    function getPrice(address token) external view returns (uint256);\n\n    function convertToUSD(\n        uint256 amount,\n        address token\n    ) external view returns (uint256);\n\n    function convertFromUSD(\n        uint256 amount,\n        address token\n    ) external view returns (uint256);\n\n    function convert(\n        uint256 amount,\n        address tokenFrom,\n        address tokenTo\n    ) external view returns (uint256);\n\n    function priceFeeds(\n        address token\n    ) external view returns (address priceFeed);\n}\n"
      },
      "node_modules/@gearbox-protocol/sdk-gov/contracts/PriceFeedType.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n// Gearbox. Generalized leverage protocol that allows to take leverage and then use it across other DeFi protocols and platforms in a composable way.\n// (c) Gearbox Foundation, 2023\npragma solidity ^0.8.17;\n\nenum PriceFeedType {\n    CHAINLINK_ORACLE,\n    YEARN_ORACLE,\n    CURVE_2LP_ORACLE,\n    CURVE_3LP_ORACLE,\n    CURVE_4LP_ORACLE,\n    ZERO_ORACLE,\n    WSTETH_ORACLE,\n    BOUNDED_ORACLE,\n    COMPOSITE_ORACLE,\n    WRAPPED_AAVE_V2_ORACLE,\n    COMPOUND_V2_ORACLE,\n    BALANCER_STABLE_LP_ORACLE,\n    BALANCER_WEIGHTED_LP_ORACLE,\n    CURVE_CRYPTO_ORACLE,\n    THE_SAME_AS,\n    REDSTONE_ORACLE,\n    ERC4626_VAULT_ORACLE,\n    NETWORK_DEPENDENT,\n    CURVE_USD_ORACLE\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/ERC721/extensions/IERC721Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n    /**\n     * @dev Returns the token collection name.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the token collection symbol.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n     */\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n"
      },
      "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/@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/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"
      },
      "node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n     * understand this adds an external call which potentially creates a reentrancy vulnerability.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the caller.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n"
      },
      "node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      }
    },
    "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": {}
    }
  }}