creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "lib/blueberry-core/contracts/spell/ConvexSpellV2.sol": {
        "content": "// SPDX-License-Identifier: MIT\n/*\n██████╗ ██╗     ██╗   ██╗███████╗██████╗ ███████╗██████╗ ██████╗ ██╗   ██╗\n██╔══██╗██║     ██║   ██║██╔════╝██╔══██╗██╔════╝██╔══██╗██╔══██╗╚██╗ ██╔╝\n██████╔╝██║     ██║   ██║█████╗  ██████╔╝█████╗  ██████╔╝██████╔╝ ╚████╔╝\n██╔══██╗██║     ██║   ██║██╔══╝  ██╔══██╗██╔══╝  ██╔══██╗██╔══██╗  ╚██╔╝\n██████╔╝███████╗╚██████╔╝███████╗██████╔╝███████╗██║  ██║██║  ██║   ██║\n╚═════╝ ╚══════╝ ╚═════╝ ╚══════╝╚═════╝ ╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝   ╚═╝\n*/\n\npragma solidity 0.8.22;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport { PSwapLib } from \"../libraries/Paraswap/PSwapLib.sol\";\nimport { UniversalERC20, IERC20 } from \"../libraries/UniversalERC20.sol\";\n\nimport \"../utils/BlueberryErrors.sol\" as Errors;\n\nimport { BasicSpell } from \"./BasicSpell.sol\";\n\nimport { IBank } from \"../interfaces/IBank.sol\";\nimport { ICurveOracle } from \"../interfaces/ICurveOracle.sol\";\nimport { ICurveZapDepositor } from \"../interfaces/ICurveZapDepositor.sol\";\nimport { ICurvePool } from \"../interfaces/curve/ICurvePool.sol\";\nimport { IWConvexBooster } from \"../interfaces/IWConvexBooster.sol\";\nimport { IWETH } from \"../interfaces/IWETH.sol\";\n\nimport { IConvexSpell } from \"../interfaces/spell/IConvexSpell.sol\";\n\n/**\n * @title ConvexSpell\n * @author BlueberryProtocol\n * @notice This contract serves as the factory for defining how the Blueberry Protocol\n        interacts with Convex pools. It handles strategies, interactions with \n        external contracts, and facilitates operations related to liquidity provision.\n * @dev This contract will be used for Curve Volatile Pools and Curve Tricrypto Pools.\n */\ncontract ConvexSpellV2 is IConvexSpell, BasicSpell {\n    using SafeERC20Upgradeable for IERC20Upgradeable;\n    using UniversalERC20 for IERC20;\n\n    /*//////////////////////////////////////////////////////////////////////////\n                                     STORAGE\n    //////////////////////////////////////////////////////////////////////////*/\n\n    /// @dev Address of the Wrapped Convex Pools\n    IWConvexBooster private _wConvexBooster;\n    /// @dev address of CurveOracle to retrieve pool information\n    ICurveOracle private _crvOracle;\n    /// @dev address of CVX token\n    address private _cvxToken;\n\n    /// @dev Curve Zap Depositor for USD metapools\n    address private constant _CURVE_ZAP_DEPOSITOR = 0xA79828DF1850E8a3A3064576f380D90aECDD3359;\n    /// @dev _THREE_CRV token address\n    address private constant _THREE_CRV = 0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490;\n    /// @dev _DAI token address\n    address private constant _DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\n    /// @dev _USDC token address\n    address private constant _USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;\n    /// @dev _USDT token address\n    address private constant _USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7;\n\n    /*//////////////////////////////////////////////////////////////////////////\n                                     CONSTRUCTOR\n    //////////////////////////////////////////////////////////////////////////*/\n\n    /// @custom:oz-upgrades-unsafe-allow constructor\n    constructor() {\n        _disableInitializers();\n    }\n\n    /*//////////////////////////////////////////////////////////////////////////\n                                      FUNCTIONS\n    //////////////////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Initializes the ConvexSpell contract with required parameters.\n     * @param bank Address of the bank contract.\n     * @param werc20 Address of the wrapped ERC20 contract.\n     * @param weth Address of the wrapped Ethereum contract.\n     * @param wConvexBooster Address of the wrapped Convex pools contract.\n     * @param crvOracle Address of the Curve Oracle contract.\n     * @param augustusSwapper Address of the paraswap AugustusSwapper.\n     * @param tokenTransferProxy Address of the paraswap TokenTransferProxy.\n     * @param owner Address of the owner of the contract.\n     */\n    function initialize(\n        IBank bank,\n        address werc20,\n        address weth,\n        address wConvexBooster,\n        address crvOracle,\n        address augustusSwapper,\n        address tokenTransferProxy,\n        address owner\n    ) external initializer {\n        __BasicSpell_init(bank, werc20, weth, augustusSwapper, tokenTransferProxy, owner);\n        if (wConvexBooster == address(0) || crvOracle == address(0)) {\n            revert Errors.ZERO_ADDRESS();\n        }\n\n        _wConvexBooster = IWConvexBooster(wConvexBooster);\n        _cvxToken = address(IWConvexBooster(wConvexBooster).getCvxToken());\n        _crvOracle = ICurveOracle(crvOracle);\n        IWConvexBooster(wConvexBooster).setApprovalForAll(address(bank), true);\n    }\n\n    /// @inheritdoc IConvexSpell\n    function addStrategy(address crvLp, uint256 minCollSize, uint256 maxPosSize) external onlyOwner {\n        _addStrategy(crvLp, minCollSize, maxPosSize);\n    }\n\n    /// @inheritdoc IConvexSpell\n    function openPositionFarm(\n        OpenPosParam calldata param,\n        uint256 minLPMint\n    ) external existingStrategy(param.strategyId) existingCollateral(param.strategyId, param.collToken) {\n        uint256 _minLPMint = minLPMint;\n        Strategy memory strategy = _strategies[param.strategyId];\n\n        IWConvexBooster wConvexBooster = getWConvexBooster();\n\n        (address lpToken, , , , , ) = wConvexBooster.getPoolInfoFromPoolId(param.farmingPoolId);\n        if (strategy.vault != lpToken) revert Errors.INCORRECT_LP(lpToken);\n\n        /// 1. Deposit isolated collaterals on Blueberry Money Market\n        _doLend(param.collToken, param.collAmount);\n\n        /// 2. Borrow specific amounts\n        uint256 borrowBalance = _doBorrow(param.borrowToken, param.borrowAmount);\n\n        (address pool, address[] memory tokens, ) = _crvOracle.getPoolInfo(lpToken);\n\n        /// 3. Add liquidity on curve, get crvLp\n        {\n            address borrowToken = param.borrowToken;\n            IERC20(borrowToken).universalApprove(pool, borrowBalance);\n            uint256 ethValue;\n            uint256 tokenBalance = IERC20(borrowToken).balanceOf(address(this));\n\n            if (borrowBalance > tokenBalance) {\n                revert Errors.INSUFFICIENT_COLLATERAL();\n            }\n\n            bool isBorrowTokenWeth = borrowToken == _weth;\n            if (isBorrowTokenWeth) {\n                bool hasEth;\n                uint256 tokenLength = tokens.length;\n                for (uint256 i; i < tokenLength; ++i) {\n                    if (tokens[i] == _ETH) {\n                        hasEth = true;\n                        break;\n                    }\n                }\n\n                if (hasEth) {\n                    IWETH(borrowToken).withdraw(tokenBalance);\n                    ethValue = tokenBalance;\n                }\n            }\n\n            if (tokens.length == 2) {\n                if (tokens[1] == _THREE_CRV) {\n                    uint256[4] memory suppliedAmts;\n\n                    if (tokens[0] == borrowToken) {\n                        suppliedAmts[0] = tokenBalance;\n                    } else if (_DAI == borrowToken) {\n                        suppliedAmts[1] = tokenBalance;\n                    } else if (_USDC == borrowToken) {\n                        suppliedAmts[2] = tokenBalance;\n                    } else {\n                        suppliedAmts[3] = tokenBalance;\n                    }\n\n                    IERC20(borrowToken).universalApprove(pool, 0);\n                    IERC20(borrowToken).universalApprove(_CURVE_ZAP_DEPOSITOR, borrowBalance);\n\n                    ICurveZapDepositor(_CURVE_ZAP_DEPOSITOR).add_liquidity(pool, suppliedAmts, _minLPMint);\n                } else {\n                    uint256[2] memory suppliedAmts;\n\n                    for (uint256 i; i < 2; ++i) {\n                        if ((tokens[i] == borrowToken) || (tokens[i] == _ETH && isBorrowTokenWeth)) {\n                            suppliedAmts[i] = tokenBalance;\n                            break;\n                        }\n                    }\n                    ICurvePool(pool).add_liquidity{ value: ethValue }(suppliedAmts, _minLPMint);\n                }\n            } else if (tokens.length == 3) {\n                uint256[3] memory suppliedAmts;\n\n                for (uint256 i; i < 3; ++i) {\n                    if ((tokens[i] == borrowToken) || (tokens[i] == _ETH && isBorrowTokenWeth)) {\n                        suppliedAmts[i] = tokenBalance;\n                        break;\n                    }\n                }\n\n                ICurvePool(pool).add_liquidity{ value: ethValue }(suppliedAmts, _minLPMint);\n            } else if (tokens.length == 4) {\n                uint256[4] memory suppliedAmts;\n\n                for (uint256 i; i < 4; ++i) {\n                    if ((tokens[i] == borrowToken) || (tokens[i] == _ETH && isBorrowTokenWeth)) {\n                        suppliedAmts[i] = tokenBalance;\n                        break;\n                    }\n                }\n\n                ICurvePool(pool).add_liquidity{ value: ethValue }(suppliedAmts, _minLPMint);\n            }\n        }\n\n        /// 4. Validate MAX LTV\n        _validateMaxLTV(param.strategyId);\n\n        /// 5. Validate Max Pos Size\n        _validatePosSize(param.strategyId);\n\n        {\n            IBank bank = getBank();\n            /// 6. Take out existing collateral and burn\n            IBank.Position memory pos = bank.getCurrentPositionInfo();\n            if (pos.collateralSize > 0) {\n                (uint256 pid, ) = wConvexBooster.decodeId(pos.collId);\n\n                if (param.farmingPoolId != pid) {\n                    revert Errors.INCORRECT_PID(param.farmingPoolId);\n                }\n\n                if (pos.collToken != address(wConvexBooster)) {\n                    revert Errors.INCORRECT_COLTOKEN(pos.collToken);\n                }\n\n                (address[] memory rewardTokens, ) = wConvexBooster.burn(pos.collId, pos.collateralSize);\n                // distribute multiple rewards to users\n                uint256 tokensLength = rewardTokens.length;\n\n                for (uint256 i; i < tokensLength; ++i) {\n                    _doRefundRewards(rewardTokens[i]);\n                }\n            }\n        }\n        {\n            /// 7. Deposit on Convex Pool, Put wrapped collateral tokens on Blueberry Bank\n            uint256 lpAmount = IERC20(lpToken).balanceOf(address(this));\n            IERC20(lpToken).universalApprove(address(wConvexBooster), lpAmount);\n\n            uint256 id = wConvexBooster.mint(param.farmingPoolId, lpAmount);\n            _bank.putCollateral(address(wConvexBooster), id, lpAmount);\n        }\n    }\n\n    /// @inheritdoc IConvexSpell\n    function closePositionFarm(\n        ClosePositionFarmParam calldata closePosParam\n    )\n        external\n        existingStrategy(closePosParam.param.strategyId)\n        existingCollateral(closePosParam.param.strategyId, closePosParam.param.collToken)\n    {\n        IBank bank = getBank();\n        address crvLp = _strategies[closePosParam.param.strategyId].vault;\n        IBank.Position memory pos = bank.getCurrentPositionInfo();\n\n        IWConvexBooster wConvexBooster = getWConvexBooster();\n\n        if (pos.collToken != address(wConvexBooster)) {\n            revert Errors.INCORRECT_COLTOKEN(pos.collToken);\n        }\n\n        if (wConvexBooster.getUnderlyingToken(pos.collId) != crvLp) {\n            revert Errors.INCORRECT_UNDERLYING(crvLp);\n        }\n\n        uint256 amountPosRemove = closePosParam.param.amountPosRemove;\n\n        /// 1. Take out collateral - Burn wrapped tokens, receive crv lp tokens and harvest CRV\n        amountPosRemove = bank.takeCollateral(amountPosRemove);\n        (address[] memory rewardTokens, ) = wConvexBooster.burn(pos.collId, amountPosRemove);\n\n        /// 2. Swap rewards tokens to debt token\n        _sellRewards(rewardTokens, closePosParam);\n\n        /// 3. Remove liquidity\n        _removeLiquidity(closePosParam.param, pos, crvLp, amountPosRemove);\n\n        /// 4. Withdraw isolated collateral from Bank\n        _doWithdraw(closePosParam.param.collToken, closePosParam.param.amountShareWithdraw);\n\n        /// 5. Swap some collateral to repay debt(for negative PnL)\n        _swapCollToDebt(closePosParam.param.collToken, closePosParam.param.amountToSwap, closePosParam.param.swapData);\n\n        /// 6. Repay\n        {\n            /// Compute repay amount if MAX_INT is supplied (max debt)\n            uint256 amountRepay = closePosParam.param.amountRepay;\n            if (amountRepay == type(uint256).max) {\n                amountRepay = bank.currentPositionDebt(bank.POSITION_ID());\n            }\n            _doRepay(closePosParam.param.borrowToken, amountRepay);\n        }\n\n        _validateMaxLTV(closePosParam.param.strategyId);\n\n        /// 7. Refund\n        _doRefund(closePosParam.param.borrowToken);\n        _doRefund(closePosParam.param.collToken);\n        _doRefund(getCvxToken());\n    }\n\n    /// @inheritdoc IConvexSpell\n    function getWConvexBooster() public view override returns (IWConvexBooster) {\n        return _wConvexBooster;\n    }\n\n    /// @inheritdoc IConvexSpell\n    function getCvxToken() public view override returns (address) {\n        return _cvxToken;\n    }\n\n    /// @inheritdoc IConvexSpell\n    function getCrvOracle() public view override returns (ICurveOracle) {\n        return _crvOracle;\n    }\n\n    /**\n     * @notice Removes liquidity from a Curve pool for a given position.\n     * @param param Contains data required to close the position.\n     * @param pos Data structure representing the current bank position.\n     * @param crvLp Address of the Curve LP token.\n     * @param amountPosRemove Amount of LP tokens to be removed from the pool.\n     *        If set to max, will remove all available LP tokens.\n     */\n    function _removeLiquidity(\n        ClosePosParam memory param,\n        IBank.Position memory pos,\n        address crvLp,\n        uint256 amountPosRemove\n    ) internal returns (address[] memory tokens) {\n        address pool;\n        (pool, tokens, ) = _crvOracle.getPoolInfo(crvLp);\n\n        if (amountPosRemove == type(uint256).max) {\n            amountPosRemove = IERC20(crvLp).balanceOf(address(this));\n        }\n\n        uint256 tokenIndex;\n        uint256 len = tokens.length;\n        for (uint256 i; i < len; ++i) {\n            if (tokens[i] == pos.debtToken) {\n                tokenIndex = i;\n                break;\n            }\n        }\n\n        if (len == 2 && tokens[1] == _THREE_CRV) {\n            int128 index;\n            if (tokens[0] == param.borrowToken) {\n                index = 0;\n            } else if (_DAI == param.borrowToken) {\n                index = 1;\n            } else if (_USDC == param.borrowToken) {\n                index = 2;\n            } else {\n                index = 3;\n            }\n            IERC20(pool).universalApprove(_CURVE_ZAP_DEPOSITOR, amountPosRemove);\n            ICurveZapDepositor(_CURVE_ZAP_DEPOSITOR).remove_liquidity_one_coin(\n                pool,\n                amountPosRemove,\n                index,\n                param.amountOutMin\n            );\n            return _getMetaPoolTokens(tokens[0]);\n        } else {\n            /// Removes liquidity from the Curve pool for the specified token.\n            ICurvePool(pool).remove_liquidity_one_coin(amountPosRemove, tokenIndex, param.amountOutMin);\n        }\n\n        if (tokens[uint128(tokenIndex)] == _ETH) {\n            IWETH(_weth).deposit{ value: address(this).balance }();\n        }\n    }\n\n    /**\n     * @notice Returns an array of addresses of the tokens in the Curve metapool.\n     * @param token Address of the token to be swapped.\n     * @return tokens An array of addresses of the tokens in the Curve metapool.\n     */\n    function _getMetaPoolTokens(address token) internal pure returns (address[] memory tokens) {\n        tokens = new address[](4);\n        tokens[0] = token;\n        tokens[1] = _DAI;\n        tokens[2] = _USDC;\n        tokens[3] = _USDT;\n    }\n\n    /**\n     * @notice Sells the accumulated reward tokens.\n     * @param rewardTokens An array of addresses of the reward tokens to be sold.\n     * @param closePosParam Struct containing all required parameters for closing a position.\n     */\n    function _sellRewards(address[] memory rewardTokens, ClosePositionFarmParam calldata closePosParam) internal {\n        uint256 tokensLength = rewardTokens.length;\n        for (uint256 i; i < tokensLength; ++i) {\n            address sellToken = rewardTokens[i];\n\n            /// Apply any potential fees on the reward.\n            _doCutRewardsFee(sellToken);\n\n            if (sellToken != closePosParam.param.borrowToken) {\n                uint256 expectedReward = closePosParam.amounts[i];\n                /// If the expected reward is zero, skip to the next token.\n                _swapOnParaswap(sellToken, expectedReward, closePosParam.swapDatas[i]);\n            }\n        }\n    }\n\n    /**\n     * @notice Swaps token on Paraswap and refunds the rest amount to owner.\n     * @param token Token to swap for\n     * @param amount Amount of token to swap for\n     * @param swapData Call data for the swap\n     */\n    function _swapOnParaswap(address token, uint256 amount, bytes calldata swapData) internal {\n        if (amount == 0) return;\n        if (!PSwapLib.swap(_augustusSwapper, _tokenTransferProxy, token, amount, swapData))\n            revert Errors.SWAP_FAILED(token);\n\n        // Refund rest amount to owner\n        _doRefund(token);\n    }\n}\n"
      },
      "lib/blueberry-core/node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n    using AddressUpgradeable for address;\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n     * Revert on invalid signature.\n     */\n    function safePermit(\n        IERC20PermitUpgradeable token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return\n            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n    }\n}\n"
      },
      "lib/blueberry-core/node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "lib/blueberry-core/contracts/libraries/Paraswap/PSwapLib.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"../../interfaces/paraswap/IParaswap.sol\";\nimport \"../../libraries/UniversalERC20.sol\";\nimport \"./Utils.sol\";\n\nlibrary PSwapLib {\n    function _approve(\n        IERC20 inToken,\n        address spender,\n        uint256 amount\n    ) internal {\n        // approve zero before reset allocation\n        UniversalERC20.universalApprove(inToken, spender, 0);\n        UniversalERC20.universalApprove(inToken, spender, amount);\n    }\n\n    function swap(\n        address augustusSwapper,\n        address tokenTransferProxy,\n        address fromToken,\n        uint256 fromAmount,\n        bytes calldata data\n    ) internal returns (bool success) {\n        _approve(IERC20(fromToken), tokenTransferProxy, fromAmount);\n\n        bytes memory returndata;\n\n        (success, returndata) = augustusSwapper.call(data);\n\n        UniversalERC20.universalApprove(IERC20(fromToken), tokenTransferProxy, 0);\n    }\n\n    function megaSwap(\n        address augustusSwapper,\n        address tokenTransferProxy,\n        Utils.MegaSwapSellData calldata data\n    ) internal returns (uint256) {\n        _approve(IERC20(data.fromToken), tokenTransferProxy, data.fromAmount);\n\n        uint256 result = IParaswap(augustusSwapper).megaSwap(data);\n\n        UniversalERC20.universalApprove(IERC20(data.fromToken), tokenTransferProxy, 0);\n\n        return result;\n    }\n}\n"
      },
      "lib/blueberry-core/contracts/libraries/UniversalERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n/*\n██████╗ ██╗     ██╗   ██╗███████╗██████╗ ███████╗██████╗ ██████╗ ██╗   ██╗\n██╔══██╗██║     ██║   ██║██╔════╝██╔══██╗██╔════╝██╔══██╗██╔══██╗╚██╗ ██╔╝\n██████╔╝██║     ██║   ██║█████╗  ██████╔╝█████╗  ██████╔╝██████╔╝ ╚████╔╝\n██╔══██╗██║     ██║   ██║██╔══╝  ██╔══██╗██╔══╝  ██╔══██╗██╔══██╗  ╚██╔╝\n██████╔╝███████╗╚██████╔╝███████╗██████╔╝███████╗██║  ██║██║  ██║   ██║\n╚═════╝ ╚══════╝ ╚═════╝ ╚══════╝╚═════╝ ╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝   ╚═╝\n*/\n\npragma solidity 0.8.22;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @title UniversalERC20\n * @dev UniversalERC20 is a helper contract that allows to work around ERC20\n *      limitations when dealing with missing return values.\n *      UniversalERC20 executes a low level call to the token contract.\n *      If it fails, it assumes that the token does not implement the method.\n *      If it succeeds, it returns the value returned by the method.\n *      Also supports if the token address is native ETH.\n */\nlibrary UniversalERC20 {\n    using SafeERC20 for IERC20;\n\n    address private constant _ZERO_ADDRESS = address(0);\n    address private constant _ETH_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);\n\n    /// @notice UniversalERC20's safeTransfer function that is similar to ERC20's transfer function.\n    /// @dev Works around non-standard ERC20's that throw on 0 transfer and supports Native ETH.\n    function universalTransfer(IERC20 token, address to, uint256 amount) internal returns (bool) {\n        if (amount == 0) {\n            return true;\n        }\n        if (isETH(token)) {\n            (bool success, ) = to.call{ value: amount }(\"\");\n            require(success, \"ETH transfer failed\");\n            return true;\n        } else {\n            token.safeTransfer(to, amount);\n            return true;\n        }\n    }\n\n    /// @notice UniversalERC20's safeTransferFrom function that is similar to ERC20's transferFrom function.\n    /// @dev Works around non-standard ERC20's that throw on 0 transfer and supports native ETH.\n    function universalTransferFrom(IERC20 token, address from, address to, uint256 amount) internal {\n        if (amount == 0) {\n            return;\n        }\n\n        if (isETH(token)) {\n            require(from == msg.sender && msg.value == amount, \"Wrong useage of ETH.universalTransferFrom()\");\n            if (to != address(this)) {\n                (bool success, ) = to.call{ value: amount }(\"\");\n                require(success, \"ETH transfer failed\");\n            }\n        } else {\n            token.safeTransferFrom(from, to, amount);\n        }\n    }\n\n    function universalApprove(IERC20 token, address to, uint256 amount) internal {\n        if (!isETH(token)) {\n            token.forceApprove(to, amount);\n        }\n    }\n\n    /// @notice UniversalBalanceOf returns the balance of a token for an address.\n    /// @dev Is able to tell the balance of a token or natie ETH.\n    function universalBalanceOf(IERC20 token, address who) internal view returns (uint256) {\n        if (isETH(token)) {\n            return who.balance;\n        } else {\n            return token.balanceOf(who);\n        }\n    }\n\n    /// @notice returns if the token is ETH or not.\n    function isETH(IERC20 token) internal pure returns (bool) {\n        return (address(token) == address(_ZERO_ADDRESS) || address(token) == address(_ETH_ADDRESS));\n    }\n}\n"
      },
      "lib/blueberry-core/contracts/utils/BlueberryErrors.sol": {
        "content": "// SPDX-License-Identifier: MIT\n/*\n██████╗ ██╗     ██╗   ██╗███████╗██████╗ ███████╗██████╗ ██████╗ ██╗   ██╗\n██╔══██╗██║     ██║   ██║██╔════╝██╔══██╗██╔════╝██╔══██╗██╔══██╗╚██╗ ██╔╝\n██████╔╝██║     ██║   ██║█████╗  ██████╔╝█████╗  ██████╔╝██████╔╝ ╚████╔╝\n██╔══██╗██║     ██║   ██║██╔══╝  ██╔══██╗██╔══╝  ██╔══██╗██╔══██╗  ╚██╔╝\n██████╔╝███████╗╚██████╔╝███████╗██████╔╝███████╗██║  ██║██║  ██║   ██║\n╚═════╝ ╚══════╝ ╚═════╝ ╚══════╝╚═════╝ ╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝   ╚═╝\n*/\n/**\n * @title BlueberryErrors\n * @author BlueberryProtocol\n * @notice containing all errors used in Blueberry protocol\n */\n/// title BlueberryErrors\n/// @notice containing all errors used in Blueberry protocol\npragma solidity 0.8.22;\n\n/*//////////////////////////////////////////////////////////////////////////\n                                COMMON ERRORS\n//////////////////////////////////////////////////////////////////////////*/\n\n/// @notice Thrown when an action involves zero amount of tokens.\nerror ZERO_AMOUNT();\n\n/// @notice Thrown when the address provided is the zero address.\nerror ZERO_ADDRESS();\n\n/// @notice Thrown when the lengths of input arrays do not match.\nerror INPUT_ARRAY_MISMATCH();\n\n/// @notice Thrown when the caller is not authorized to call the function.\nerror UNAUTHORIZED();\n\n/*//////////////////////////////////////////////////////////////////////////\n                                ORACLE ERRORS\n//////////////////////////////////////////////////////////////////////////*/\n\n/// @notice Thrown when the delay time exceeds allowed limits.\nerror TOO_LONG_DELAY(uint256 delayTime);\n\n/// @notice Thrown when there's no maximum delay set for a token.\nerror NO_MAX_DELAY(address token);\n\n/// @notice Thrown when the price information for a token is outdated.\nerror PRICE_OUTDATED(address token);\n\n/// @notice Thrown when the price obtained is negative.\nerror PRICE_NEGATIVE(address token);\n\n/// @notice Thrown when the sequencer is offline\nerror SEQUENCER_DOWN(address sequencer);\n\n/// @notice Thrown when the grace period for a sequencer is not over yet.\nerror SEQUENCER_GRACE_PERIOD_NOT_OVER(address sequencer);\n\n/// @notice Thrown when the price deviation exceeds allowed limits.\nerror OUT_OF_DEVIATION_CAP(uint256 deviation);\n\n/// @notice Thrown when the number of sources exceeds the allowed length.\nerror EXCEED_SOURCE_LEN(uint256 length);\n\n/// @notice Thrown when no primary source is available for the token.\nerror NO_PRIMARY_SOURCE(address token);\n\n/// @notice Thrown when no valid price source is available for the token.\nerror NO_VALID_SOURCE(address token);\n\n/// @notice Thrown when the deviation value exceeds the threshold.\nerror EXCEED_DEVIATION();\n\n/// @notice Thrown when the mean price is below the acceptable threshold.\nerror TOO_LOW_MEAN(uint256 mean);\n\n/// @notice Thrown when no mean price is set for the token.\nerror NO_MEAN(address token);\n\n/// @notice Thrown when no stable pool exists for the token.\nerror NO_STABLEPOOL(address token);\n\n/// @notice Thrown when the price fetch process fails for a token.\nerror PRICE_FAILED(address token);\n\n/// @notice Thrown when the liquidation threshold is set too high.\nerror LIQ_THRESHOLD_TOO_HIGH(uint256 threshold);\n\n/// @notice Thrown when the liquidation threshold is set too low.\nerror LIQ_THRESHOLD_TOO_LOW(uint256 threshold);\n\n/// @notice Thrown when the oracle doesn't support a specific token.\nerror ORACLE_NOT_SUPPORT(address token);\n\n/// @notice Thrown when the oracle doesn't support a specific LP pair token.\nerror ORACLE_NOT_SUPPORT_LP(address lp);\n\n/// @notice Thrown when the oracle doesn't support a specific wToken.\nerror ORACLE_NOT_SUPPORT_WTOKEN(address wToken);\n\n/// @notice Thrown when there is no route to fetch data for the oracle\nerror NO_ORACLE_ROUTE(address token);\n\n/// @notice Thrown when a value is out of an acceptable range.\nerror VALUE_OUT_OF_RANGE();\n\n/// @notice Thrown when specified limits are incorrect.\nerror INCORRECT_LIMITS();\n\n/// @notice Thrown when Curve LP is already registered.\nerror CRV_LP_ALREADY_REGISTERED(address lp);\n\n/// @notice Thrown when a pool is subject to read-only reentrancy manipulation.\nerror REENTRANCY_RISK(address pool);\n\n/*//////////////////////////////////////////////////////////////////////////\n                            GENERAL SPELL ERRORS\n//////////////////////////////////////////////////////////////////////////*/\n\n/// @notice Thrown when the caller isn't recognized as a bank.\nerror NOT_BANK(address caller);\n\n/// @notice Thrown when the collateral doesn't exist for a strategy.\nerror COLLATERAL_NOT_EXIST(uint256 strategyId, address colToken);\n\n/// @notice Thrown when the strategy ID doesn't correspond to an existing strategy.\nerror STRATEGY_NOT_EXIST(address spell, uint256 strategyId);\n\n/// @notice Thrown when the position size exceeds maximum limits.\nerror EXCEED_MAX_POS_SIZE(uint256 strategyId);\n\n/// @notice Thrown when the user has not deposited enough isolated collateral for a strategy.\nerror BELOW_MIN_ISOLATED_COLLATERAL(uint256 strategyId);\n\n/// @notice Thrown when the loan-to-value ratio exceeds allowed maximum.\nerror EXCEED_MAX_LTV();\n\n/// @notice Thrown when the strategy ID provided is incorrect.\nerror INCORRECT_STRATEGY_ID(uint256 strategyId);\n\n/// @notice Thrown when the position size is invalid.\nerror INVALID_POS_SIZE();\n\n/// @notice Thrown when an incorrect liquidity pool token is provided.\nerror INCORRECT_LP(address lpToken);\n\n/// @notice Thrown when an incorrect pool ID is provided.\nerror INCORRECT_PID(uint256 pid);\n\n/// @notice Thrown when an incorrect collateral token is provided.\nerror INCORRECT_COLTOKEN(address colToken);\n\n/// @notice Thrown when an incorrect underlying token is provided.\nerror INCORRECT_UNDERLYING(address uToken);\n\n/// @notice Thrown when an incorrect debt token is provided.\nerror INCORRECT_DEBT(address debtToken);\n\n/// @notice Thrown when a swap fails.\nerror SWAP_FAILED(address swapToken);\n\n/*//////////////////////////////////////////////////////////////////////////\n                                VAULT ERRORS\n//////////////////////////////////////////////////////////////////////////*/\n\n/// @notice Thrown when borrowing from the vault fails.\nerror BORROW_FAILED(uint256 amount);\n\n/// @notice Thrown when repaying to the vault fails.\nerror REPAY_FAILED(uint256 amount);\n\n/// @notice Thrown when lending to the vault fails.\nerror LEND_FAILED(uint256 amount);\n\n/// @notice Thrown when redeeming from the vault fails.\nerror REDEEM_FAILED(uint256 amount);\n\n/*//////////////////////////////////////////////////////////////////////////\n                                WRAPPER ERRORS\n//////////////////////////////////////////////////////////////////////////*/\n\n/// @notice Thrown when a duplicate tokenId is added.\nerror DUPLICATE_TOKEN_ID(uint256 tokenId);\n\n/// @notice Thrown when an invalid token ID is provided.\nerror INVALID_TOKEN_ID(uint256 tokenId);\n\n/// @notice Thrown when an incorrect pool ID is provided.\nerror BAD_PID(uint256 pid);\n\n/// @notice Thrown when a mismatch in reward per share is detected.\nerror BAD_REWARD_PER_SHARE(uint256 rewardPerShare);\n\n/*//////////////////////////////////////////////////////////////////////////\n                                BANK ERRORS\n//////////////////////////////////////////////////////////////////////////*/\n\n/// @notice Thrown when a function is called without a required execution flag.\nerror NOT_UNDER_EXECUTION();\n\n/// @notice Thrown when a transaction isn't initiated by the expected spell.\nerror NOT_FROM_SPELL(address from);\n\n/// @notice Thrown when the sender is not the owner of a given position ID.\nerror NOT_FROM_OWNER(uint256 positionId, address sender);\n\n/// @notice Thrown when a spell address isn't whitelisted.\nerror SPELL_NOT_WHITELISTED(address spell);\n\n/// @notice Thrown when a token isn't whitelisted.\nerror TOKEN_NOT_WHITELISTED(address token);\n\n/// @notice Thrown when a bank isn't listed for a given token.\nerror BANK_NOT_LISTED(address token);\n\n/// @notice Thrown when a bank doesn't exist for an index.\nerror BANK_NOT_EXIST(uint8 index);\n\n/// @notice Thrown when a bank is already listed for a given token.\nerror BANK_ALREADY_LISTED();\n\n/// @notice Thrown when the bank limit is reached.\nerror BANK_LIMIT();\n\n/// @notice Thrown when the BTOKEN is already added.\nerror BTOKEN_ALREADY_ADDED();\n\n/// @notice Thrown when the lending action isn't allowed.\nerror LEND_NOT_ALLOWED();\n\n/// @notice Thrown when the borrowing action isn't allowed.\nerror BORROW_NOT_ALLOWED();\n\n/// @notice Thrown when the repaying action isn't allowed.\nerror REPAY_NOT_ALLOWED();\n\n/// @notice Thrown when the redeeming action isn't allowed.\nerror WITHDRAW_LEND_NOT_ALLOWED();\n\n/// @notice Thrown when certain actions are locked.\nerror LOCKED();\n\n/// @notice Thrown when an action isn't executed.\nerror NOT_IN_EXEC();\n\n/// @notice Thrown when the repayment allowance hasn't been warmed up.\nerror REPAY_ALLOW_NOT_WARMED_UP();\n\n/// @notice Thrown when a different collateral type exists.\nerror DIFF_COL_EXIST(address collToken);\n\n/// @notice Thrown when a position is not eligible for liquidation.\nerror NOT_LIQUIDATABLE(uint256 positionId);\n\n/// @notice Thrown when a position is flagged as bad or invalid.\nerror BAD_POSITION(uint256 posId);\n\n/// @notice Thrown when collateral for a specific position is flagged as bad or invalid.\nerror BAD_COLLATERAL(uint256 positionId);\n\n/// @notice Thrown when there's insufficient collateral for an operation.\nerror INSUFFICIENT_COLLATERAL();\n\n/// @notice Thrown when an attempted repayment exceeds the actual debt.\nerror REPAY_EXCEEDS_DEBT(uint256 repay, uint256 debt);\n\n/// @notice Thrown when an invalid utility token is provided.\nerror INVALID_UTOKEN(address uToken);\n\n/// @notice Thrown when a borrow operation results in zero shares.\nerror BORROW_ZERO_SHARE(uint256 borrowAmount);\n\n/*//////////////////////////////////////////////////////////////////////////\n                            CONFIGURATION ERRORS\n//////////////////////////////////////////////////////////////////////////*/\n\n/// @notice Thrown when a certain ratio is too high for an operation.\nerror RATIO_TOO_HIGH(uint256 ratio);\n\n/// @notice Thrown when an invalid fee distribution is detected.\nerror INVALID_FEE_DISTRIBUTION();\n\n/// @notice Thrown when no treasury is set for fee distribution.\nerror NO_TREASURY_SET();\n\n/// @notice Thrown when a fee window has already started.\nerror FEE_WINDOW_ALREADY_STARTED();\n\n/// @notice Thrown when a fee window duration is too long.\nerror FEE_WINDOW_TOO_LONG(uint256 windowTime);\n\n/*//////////////////////////////////////////////////////////////////////////\n                                UTILITY ERRORS\n//////////////////////////////////////////////////////////////////////////*/\n\n/// @notice Thrown when an operation has surpassed its deadline.\nerror EXPIRED(uint256 deadline);\n"
      },
      "lib/blueberry-core/contracts/spell/BasicSpell.sol": {
        "content": "// SPDX-License-Identifier: MIT\n/*\n██████╗ ██╗     ██╗   ██╗███████╗██████╗ ███████╗██████╗ ██████╗ ██╗   ██╗\n██╔══██╗██║     ██║   ██║██╔════╝██╔══██╗██╔════╝██╔══██╗██╔══██╗╚██╗ ██╔╝\n██████╔╝██║     ██║   ██║█████╗  ██████╔╝█████╗  ██████╔╝██████╔╝ ╚████╔╝\n██╔══██╗██║     ██║   ██║██╔══╝  ██╔══██╗██╔══╝  ██╔══██╗██╔══██╗  ╚██╔╝\n██████╔╝███████╗╚██████╔╝███████╗██████╔╝███████╗██║  ██║██║  ██║   ██║\n╚═════╝ ╚══════╝ ╚═════╝ ╚══════╝╚═════╝ ╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝   ╚═╝\n*/\n\npragma solidity 0.8.22;\n\n/* solhint-disable max-line-length */\nimport { IERC20MetadataUpgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\n/* solhint-enable max-line-length */\n\nimport { PSwapLib } from \"../libraries/Paraswap/PSwapLib.sol\";\nimport { UniversalERC20, IERC20 } from \"../libraries/UniversalERC20.sol\";\n\nimport \"../utils/BlueberryConst.sol\" as Constants;\nimport \"../utils/BlueberryErrors.sol\" as Errors;\nimport { ERC1155NaiveReceiver } from \"../utils/ERC1155NaiveReceiver.sol\";\n\nimport { IBank } from \"../interfaces/IBank.sol\";\nimport { IERC20Wrapper } from \"../interfaces/IERC20Wrapper.sol\";\nimport { IWERC20 } from \"../interfaces/IWERC20.sol\";\nimport { IWETH } from \"../interfaces/IWETH.sol\";\nimport { IBasicSpell } from \"../interfaces/spell/IBasicSpell.sol\";\n\n/**\n * @title BasicSpell\n * @author BlueberryProtocol\n * @notice BasicSpell is the abstract contract that other spells utilize\n * @dev Inherits from IBasicSpell, ERC1155NaiveReceiver, Ownable2StepUpgradeable\n */\nabstract contract BasicSpell is IBasicSpell, ERC1155NaiveReceiver, Ownable2StepUpgradeable {\n    using UniversalERC20 for IERC20;\n\n    /*//////////////////////////////////////////////////////////////////////////\n                                    STORAGE\n    //////////////////////////////////////////////////////////////////////////*/\n\n    /// @dev Reference to the bank contract interface.\n    IBank internal _bank;\n    /// @dev Reference to the WERC20 contract interface.\n    IWERC20 internal _werc20;\n    /// @dev Address of the Wrapped Ether contract.\n    address internal _weth;\n    /// @dev paraswap AugustusSwapper Address\n    address internal _augustusSwapper;\n    /// @dev paraswap TokenTransferProxy Address\n    address internal _tokenTransferProxy;\n    /// @dev strategyId => vault\n    Strategy[] internal _strategies;\n\n    /// @dev Mapping from strategy ID to collateral token and its maximum Loan-To-Value ratio.\n    /// Note: LTV is in base 1e4 to provide precision.\n    mapping(uint256 => mapping(address => uint256)) internal _maxLTV;\n    /// @dev ETH address\n    address internal constant _ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n    /*//////////////////////////////////////////////////////////////////////////\n                                      MODIFIERS\n    //////////////////////////////////////////////////////////////////////////*/\n\n    /**\n     * @dev Modifier to ensure the provided strategyId exists within the strategies array.\n     * @param strategyId The ID of the strategy to validate.\n     */\n    modifier existingStrategy(uint256 strategyId) {\n        if (strategyId >= _strategies.length) {\n            revert Errors.STRATEGY_NOT_EXIST(address(this), strategyId);\n        }\n        _;\n    }\n\n    /**\n     * @dev Modifier to ensure the provided collateral address exists within the given strategy.\n     * @param strategyId The ID of the strategy to validate.\n     * @param col Address of the collateral token.\n     */\n    modifier existingCollateral(uint256 strategyId, address col) {\n        if (_maxLTV[strategyId][col] == 0) {\n            revert Errors.COLLATERAL_NOT_EXIST(strategyId, col);\n        }\n        _;\n    }\n\n    /*//////////////////////////////////////////////////////////////////////////\n                                     CONSTRUCTOR\n    //////////////////////////////////////////////////////////////////////////*/\n\n    /// @custom:oz-upgrades-unsafe-allow constructor\n    constructor() {\n        _disableInitializers();\n    }\n\n    /*//////////////////////////////////////////////////////////////////////////\n                                      FUNCTIONS\n    //////////////////////////////////////////////////////////////////////////*/\n    /* solhint-disable func-name-mixedcase */\n    /**\n     * @notice Initializes the contract and sets the deployer as the initial owner.\n     * @param bank The address of the bank contract.\n     * @param werc20 The address of the wrapped ERC20 contract.\n     * @param weth The address of the wrapped Ether token.\n     * @param augustusSwapper Address of the paraswap AugustusSwapper.\n     * @param tokenTransferProxy Address of the paraswap TokenTransferProxy.\n     * @param owner Address of the owner of the contract.\n     */\n    function __BasicSpell_init(\n        IBank bank,\n        address werc20,\n        address weth,\n        address augustusSwapper,\n        address tokenTransferProxy,\n        address owner\n    ) internal onlyInitializing {\n        if (address(bank) == address(0) || address(werc20) == address(0) || address(weth) == address(0)) {\n            revert Errors.ZERO_ADDRESS();\n        }\n\n        __Ownable2Step_init();\n        _transferOwnership(owner);\n\n        _bank = bank;\n        _werc20 = IWERC20(werc20);\n        _weth = weth;\n        _augustusSwapper = augustusSwapper;\n        _tokenTransferProxy = tokenTransferProxy;\n\n        IWERC20(werc20).setApprovalForAll(address(bank), true);\n    }\n\n    /* solhint-enable func-name-mixedcase */\n\n    /**\n     * @notice Adds a new strategy to the list of available strategies.\n     * @dev Internal function that appends to the strategies array.\n     * @dev Emit {StrategyAdded} event.\n     * @param vault The address of the vault associated with this strategy.\n     * @param minCollSize The minimum isolated collateral size (USD value) for this strategy. Value is based on 1e18.\n     * @param maxPosSize The maximum position size (USD value) for this strategy. Value is based on 1e18.\n     */\n    function _addStrategy(address vault, uint256 minCollSize, uint256 maxPosSize) internal {\n        if (vault == address(0)) revert Errors.ZERO_ADDRESS();\n        if (maxPosSize == 0) revert Errors.ZERO_AMOUNT();\n        if (minCollSize >= maxPosSize) revert Errors.INVALID_POS_SIZE();\n\n        _strategies.push(Strategy({ vault: vault, minIsolatedCollateral: minCollSize, maxPositionSize: maxPosSize }));\n\n        emit StrategyAdded(_strategies.length - 1, vault, minCollSize, maxPosSize);\n    }\n\n    /// @inheritdoc IBasicSpell\n    function setPosSize(\n        uint256 strategyId,\n        uint256 minCollSize,\n        uint256 maxPosSize\n    ) external existingStrategy(strategyId) onlyOwner {\n        if (maxPosSize == 0) revert Errors.ZERO_AMOUNT();\n        if (minCollSize >= maxPosSize) revert Errors.INVALID_POS_SIZE();\n\n        _strategies[strategyId].minIsolatedCollateral = minCollSize;\n        _strategies[strategyId].maxPositionSize = maxPosSize;\n\n        emit StrategyPosSizeUpdated(strategyId, minCollSize, maxPosSize);\n    }\n\n    /// @inheritdoc IBasicSpell\n    function setCollateralsMaxLTVs(\n        uint256 strategyId,\n        address[] memory collaterals,\n        uint256[] memory maxLTVs\n    ) external existingStrategy(strategyId) onlyOwner {\n        if (collaterals.length != maxLTVs.length || collaterals.length == 0) {\n            revert Errors.INPUT_ARRAY_MISMATCH();\n        }\n\n        for (uint256 i = 0; i < collaterals.length; ++i) {\n            if (collaterals[i] == address(0)) revert Errors.ZERO_ADDRESS();\n            if (maxLTVs[i] == 0) revert Errors.ZERO_AMOUNT();\n            _maxLTV[strategyId][collaterals[i]] = maxLTVs[i];\n        }\n\n        emit CollateralsMaxLTVSet(strategyId, collaterals, maxLTVs);\n    }\n\n    /**\n     * @notice Increase isolated collateral to support the position\n     * @param token Isolated collateral token address\n     * @param amount Amount of token to deposit and increase position\n     */\n    function increasePosition(address token, uint256 amount) external {\n        /// 1. Deposit isolated collaterals on Blueberry Money Market\n        _doLend(token, amount);\n    }\n\n    /**\n     * @dev Reduce the isolated collateral of a position.\n     * @param strategyId The ID of the strategy being used.\n     * @param collToken Address of the isolated collateral token.\n     * @param collShareAmount Amount of isolated collateral to reduce.\n     */\n    function reducePosition(uint256 strategyId, address collToken, uint256 collShareAmount) external {\n        // Validate strategy id\n        IBank.Position memory pos = _bank.getCurrentPositionInfo();\n        address unwrappedCollToken = IERC20Wrapper(pos.collToken).getUnderlyingToken(pos.collId);\n        if (_strategies[strategyId].vault != unwrappedCollToken) {\n            revert Errors.INCORRECT_STRATEGY_ID(strategyId);\n        }\n\n        _doWithdraw(collToken, collShareAmount);\n        _doRefund(collToken);\n        _validateMaxLTV(strategyId);\n    }\n\n    /// @notice Fetch the bank contract address.\n    function getBank() public view returns (IBank) {\n        return _bank;\n    }\n\n    /// @notice Fetch the WERC20 contract address.\n    function getWrappedERC20() public view returns (IWERC20) {\n        return _werc20;\n    }\n\n    /// @notice Fetch the WETH contract address.\n    function getWETH() public view returns (address) {\n        return _weth;\n    }\n\n    /// @notice Fetch the AugustusSwapper contract address.\n    function getAugustusSwapper() external view returns (address) {\n        return _augustusSwapper;\n    }\n\n    /// @notice Fetch the TokenTransferProxy contract address.\n    function getTokenTransferProxy() external view returns (address) {\n        return _tokenTransferProxy;\n    }\n\n    /**\n     * @notice Fetch the strategy by its strategyId.\n     * @param strategyId The ID of the strategy to fetch.\n     * @return Strategy struct containing the vault address, min/max position sizes.\n     */\n    function getStrategy(uint256 strategyId) external view returns (Strategy memory) {\n        return _strategies[strategyId];\n    }\n\n    /**\n     * @notice Fetch the maximum Loan-To-Value (LTV) ratio for a given collateral token.\n     * @param strategyId The ID of the strategy to fetch the LTV for.\n     * @param collateral The address of the collateral token.\n     * @return The maximum LTV ratio for the given collateral token.\n     */\n    function getMaxLTV(uint256 strategyId, address collateral) public view returns (uint256) {\n        return _maxLTV[strategyId][collateral];\n    }\n\n    /**\n     * @notice Internal function to validate if the current position adheres to the maxLTV of the strategy.\n     * @dev If the debtValue of the position is greater than permissible, the transaction will revert.\n     * @param strategyId Strategy ID to validate against.\n     */\n    function _validateMaxLTV(uint256 strategyId) internal view {\n        IBank bank = getBank();\n\n        uint256 positionId = bank.POSITION_ID();\n        IBank.Position memory pos = bank.getPositionInfo(positionId);\n        uint256 debtValue = bank.getDebtValue(positionId);\n        uint256 uValue = bank.getIsolatedCollateralValue(positionId);\n\n        if (debtValue > (uValue * getMaxLTV(strategyId, pos.underlyingToken)) / Constants.DENOMINATOR) {\n            revert Errors.EXCEED_MAX_LTV();\n        }\n    }\n\n    /**\n     * @notice Internal function to validate if the current position size is within the strategy's bounds.\n     * @param strategyId Strategy ID to validate against.\n     */\n    function _validatePosSize(uint256 strategyId) internal view {\n        IBank bank = getBank();\n        Strategy memory strategy = _strategies[strategyId];\n        IBank.Position memory pos = bank.getCurrentPositionInfo();\n\n        /// Get previous position size\n        uint256 prevPosSize;\n        if (pos.collToken != address(0)) {\n            prevPosSize = bank.getOracle().getWrappedTokenValue(pos.collToken, pos.collId, pos.collateralSize);\n        }\n\n        /// Get newly added position size\n        uint256 addedPosSize;\n        IERC20 lpToken = IERC20(strategy.vault);\n        uint256 lpBalance = lpToken.balanceOf(address(this));\n        uint256 lpPrice = bank.getOracle().getPrice(address(lpToken));\n\n        addedPosSize = (lpPrice * lpBalance) / 10 ** IERC20MetadataUpgradeable(address(lpToken)).decimals();\n\n        // Check if position size is within bounds\n        if (prevPosSize + addedPosSize > strategy.maxPositionSize) {\n            revert Errors.EXCEED_MAX_POS_SIZE(strategyId);\n        }\n\n        // Get isolated collateral value\n        uint256 isolatedCollateralValue = bank.getIsolatedCollateralValue(bank.POSITION_ID());\n\n        // Check if isolated collateral size is within bounds\n        if (isolatedCollateralValue < strategy.minIsolatedCollateral) {\n            revert Errors.BELOW_MIN_ISOLATED_COLLATERAL(strategyId);\n        }\n    }\n\n    /**\n     * @notice Internal function to refund the specified tokens to the current executor of the bank.\n     * @param token Address of the token to refund.\n     */\n    function _doRefund(address token) internal {\n        uint256 balance = IERC20(token).universalBalanceOf(address(this));\n        if (balance > 0) {\n            IERC20(token).universalTransfer(_bank.EXECUTOR(), balance);\n        }\n    }\n\n    /**\n     * @notice Internal function to cut a fee from the rewards.\n     * @param token Address of the reward token.\n     * @return left Amount remaining after the fee cut.\n     */\n    function _doCutRewardsFee(address token) internal returns (uint256 left) {\n        uint256 rewardsBalance = IERC20(token).balanceOf(address(this));\n        if (rewardsBalance > 0) {\n            IBank bank = getBank();\n            IERC20(token).universalApprove(address(bank.getFeeManager()), rewardsBalance);\n            left = bank.getFeeManager().doCutRewardsFee(token, rewardsBalance);\n        }\n    }\n\n    /**\n     * @notice Internal function to cut the reward fee and refund the remaining rewards to the current bank executor.\n     * @param token Address of the reward token.\n     */\n    function _doRefundRewards(address token) internal {\n        _doCutRewardsFee(token);\n        _doRefund(token);\n    }\n\n    /**\n     * @notice Internall function Deposit specified collateral into the bank.\n     * @dev Only deposits the collateral if the amount specified is greater than zero.\n     * @param token Address of the isolated collateral token to be deposited.\n     * @param amount Amount of tokens to be deposited.\n     */\n    function _doLend(address token, uint256 amount) internal {\n        if (amount > 0) {\n            _bank.lend(token, amount);\n        }\n    }\n\n    /**\n     * @notice Internal function Withdraw specified collateral from the bank.\n     * @dev Only withdraws the collateral if the amount specified is greater than zero.\n     * @param token Address of the isolated collateral token to be withdrawn.\n     * @param amount Amount of tokens to be withdrawn.\n     */\n    function _doWithdraw(address token, uint256 amount) internal {\n        if (amount > 0) {\n            _bank.withdrawLend(token, amount);\n        }\n    }\n\n    /**\n     * @notice Internal function Withdraw specified collateral from the bank.\n     * @dev Only withdraws the collateral if the amount specified is greater than zero.\n     * @param collToken Address of the isolated collateral token to be withdrawn.\n     * @param amount Amount of tokens to be withdrawn.\n     * @param swapData Paraswap calldata\n     */\n    function _swapCollToDebt(address collToken, uint256 amount, bytes calldata swapData) internal {\n        if (amount > 0 && swapData.length != 0) {\n            PSwapLib.swap(_augustusSwapper, _tokenTransferProxy, collToken, amount, swapData);\n        }\n    }\n\n    /**\n     * @notice Internal function Borrow specified tokens from the bank for the current executor.\n     * @dev The borrowing happens only if the specified amount is greater than zero.\n     * @param token Address of the token to be borrowed.\n     * @param amount Amount of tokens to borrow.\n     * @return borrowedAmount Actual amount of tokens borrowed.\n     */\n    function _doBorrow(address token, uint256 amount) internal returns (uint256 borrowedAmount) {\n        if (amount > 0) {\n            bool isETH = IERC20(token).isETH();\n\n            IBank bank = getBank();\n            address weth = getWETH();\n\n            if (isETH) {\n                borrowedAmount = bank.borrow(weth, amount);\n                IWETH(weth).withdraw(borrowedAmount);\n            } else {\n                borrowedAmount = bank.borrow(token, amount);\n            }\n        }\n    }\n\n    /**\n     * @notice Internall function Repay specified tokens to the bank for the current executor.\n     * @dev Ensures approval of tokens to the bank and repays them.\n     *      Only repays if the specified amount is greater than zero.\n     * @param token Address of the token to be repaid to the bank.\n     * @param amount Amount of tokens to repay.\n     */\n    function _doRepay(address token, uint256 amount) internal {\n        if (amount > 0) {\n            address t;\n            bool isETH = IERC20(token).isETH();\n\n            address weth = getWETH();\n\n            if (isETH) {\n                IWETH(weth).deposit{ value: amount }();\n                t = weth;\n            } else {\n                t = token;\n            }\n\n            IBank bank = getBank();\n            IERC20(t).universalApprove(address(bank), amount);\n            bank.repay(t, amount);\n        }\n    }\n\n    /**\n     * @notice Internal function Deposit collateral tokens into the bank.\n     * @dev Ensures approval of tokens to the werc20 contract, mints them,\n     *      and then deposits them as collateral in the bank.\n     *      Only deposits if the specified amount is greater than zero.\n     * @param token Address of the collateral token to be deposited.\n     * @param amount Amount of collateral tokens to deposit.\n     */\n    function _doPutCollateral(address token, uint256 amount) internal {\n        if (amount > 0) {\n            IWERC20 werc20 = getWrappedERC20();\n            IERC20(token).universalApprove(address(werc20), amount);\n            werc20.mint(token, amount);\n            _bank.putCollateral(address(werc20), uint256(uint160(token)), amount);\n        }\n    }\n\n    /**\n     * @notice Internal function Withdraw collateral tokens from the bank.\n     * @dev Burns the withdrawn tokens from werc20 contract after retrieval.\n     *      Only withdraws if the specified amount is greater than zero.\n     * @param token Address of the collateral token to be withdrawn.\n     * @param amount Amount of collateral tokens to withdraw.\n     */\n    function _doTakeCollateral(address token, uint256 amount) internal {\n        if (amount > 0) {\n            amount = _bank.takeCollateral(amount);\n            _werc20.burn(token, amount);\n        }\n    }\n\n    /// @dev Fallback function.\n    /// NOTE: may remove this function in the future\n    receive() external payable {}\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     *      variables without shifting down storage in the inheritance chain.\n     *      See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[43] private __gap;\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/IBank.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\nimport { IProtocolConfig } from \"./IProtocolConfig.sol\";\nimport { IFeeManager } from \"./IFeeManager.sol\";\nimport { ICoreOracle } from \"./ICoreOracle.sol\";\n\n/**\n * @title IBank\n * @notice Interface for the bank operations, including lending, borrowing, and management of collateral positions.\n */\ninterface IBank {\n    /*//////////////////////////////////////////////////////////////////////////\n                                       STRUCTS\n    //////////////////////////////////////////////////////////////////////////*/\n\n    /// @notice Represents the configuration and current state of a bank.\n    struct Bank {\n        bool isListed; /// @dev Indicates if this bank is active.\n        uint8 index; /// @dev Index for reverse lookups.\n        address hardVault; /// @dev Address of the hard vault.\n        address softVault; /// @dev Address of the soft vault.\n        address bToken; /// @dev Address of the bToken associated with the bank.\n        uint256 totalShare; /// @dev Total shares of debt across all open positions.\n        uint256 liqThreshold; /// @dev Liquidation threshold (e.g., 85% for volatile tokens,\n        /// 90% for stablecoins). Base: 1e4\n    }\n\n    /// @notice Represents a position in the bank, including both debt and collateral.\n    struct Position {\n        address owner; /// @dev Address of the position's owner.\n        address collToken; /// @dev Address of the ERC1155 token used as collateral.\n        address underlyingToken; /// @dev Address of the isolated underlying collateral token.\n        address debtToken; /// @dev Address of the debt token.\n        uint256 underlyingVaultShare; /// @dev Amount of vault share for isolated underlying collateral.\n        uint256 collId; /// @dev Token ID of the ERC1155 collateral.\n        uint256 collateralSize; /// @dev Amount of wrapped token used as collateral.\n        uint256 debtShare; /// @dev Debt share of the given debt token for the bank.\n    }\n\n    /*//////////////////////////////////////////////////////////////////////////\n                                       EVENTS\n    //////////////////////////////////////////////////////////////////////////*/\n\n    /// @notice Emitted when a new bank is added by the owner.\n    event AddBank(\n        address token, /// @dev The primary token associated with the bank.\n        address bToken, /// @dev The corresponding bToken for the bank.\n        address softVault, /// @dev Address of the soft vault.\n        address hardVault /// @dev Address of the hard vault.\n    );\n\n    /// @notice Emitted when a bank is modified by the owner.\n    event ModifyBank(\n        address token, /// @dev The primary token associated with the bank.\n        address bToken, /// @dev The corresponding bToken for the bank.\n        address softVault, /// @dev Address of the soft vault.\n        address hardVault /// @dev Address of the hard vault.\n    );\n\n    /// @notice Emitted when the oracle's address is updated by the owner.\n    event SetOracle(address oracle); /// New address of the oracle.\n\n    /// @notice Emitted when a Wrapped ERC1155 token is whitelisted or removed by the owner.\n    event SetWhitelistERC1155(\n        address indexed token, /// Address of the Wrapped ERC1155 token.\n        bool isWhitelisted /// True if whitelisted, false otherwise.\n    );\n\n    /// @notice Emitted when a token is whitelisted or removed by the owner.\n    event SetWhitelistToken(\n        address indexed token, /// Address of the token.\n        bool isWhitelisted /// True if whitelisted, false otherwise.\n    );\n\n    /// @notice Emitted when tokens are lent to the bank.\n    event Lend(\n        uint256 positionId, /// Position ID associated with the lending.\n        address caller, /// Address of the spell caller.\n        address token, /// Address of the lent token.\n        uint256 amount /// Amount of tokens lent.\n    );\n\n    /// @notice Emitted when lent tokens are withdrawn from the bank.\n    event WithdrawLend(\n        uint256 positionId, /// Position ID associated with the withdrawal.\n        address caller, /// Address of the spell caller.\n        address token, ///Address of the token being withdrawn.\n        uint256 amount /// Amount of tokens withdrawn.\n    );\n\n    /// @notice Emitted when a user borrows tokens from a bank.\n    event Borrow(\n        uint256 positionId, /// Position ID associated with the borrowing.\n        address caller, /// Address of the spell caller that initiates the borrowing.\n        address token, /// Token being borrowed.\n        uint256 amount, /// Amount of tokens borrowed.\n        uint256 share /// Debt share associated with the borrowed amount.\n    );\n\n    /// @notice Emitted when a user repays borrowed tokens to a bank.\n    event Repay(\n        uint256 positionId, /// Position ID associated with the repayment.\n        address caller, /// Address of the spell caller initiating the repayment.\n        address token, /// Token being repaid.\n        uint256 amount, /// Amount of tokens repaid.\n        uint256 share /// Debt share associated with the repaid amount.\n    );\n\n    /// @notice Emitted when a user adds tokens as collateral.\n    event PutCollateral(\n        uint256 positionId, /// Position ID associated with the collateral.\n        address owner, /// Owner of the collateral position.\n        address caller, /// Address of the spell caller adding the collateral.\n        address token, /// Token used as collateral.\n        uint256 id, /// ID of the wrapped token.\n        uint256 amount /// Amount of tokens put as collateral.\n    );\n\n    /// @notice Emitted when a user retrieves tokens from their collateral.\n    event TakeCollateral(\n        uint256 positionId, /// Position ID associated with the collateral.\n        address caller, /// Address of the spell caller retrieving the collateral.\n        address token, /// Token taken from the collateral.\n        uint256 id, /// ID of the wrapped token.\n        uint256 amount /// Amount of tokens taken from collateral.\n    );\n\n    /// @notice Emitted when a position is liquidated.\n    event Liquidate(\n        uint256 positionId, /// Position ID being liquidated.\n        address liquidator, /// Address of the user performing the liquidation.\n        address debtToken, /// Debt token associated with the position.\n        uint256 amount, /// Amount used for liquidation.\n        uint256 share, /// Debt share associated with the liquidation.\n        uint256 positionSize, /// Size of the position being liquidated.\n        uint256 underlyingVaultSize /// Vault size underlying the liquidated position.\n    );\n\n    /// @notice Emitted when a position is executed.\n    event Execute(\n        uint256 positionId, /// Position ID being executed.\n        address owner /// Owner of the position.\n    );\n\n    /*//////////////////////////////////////////////////////////////////////////\n                                      FUNCTIONS\n    //////////////////////////////////////////////////////////////////////////*/\n\n    /**\n     * @dev Returns the next available position ID.\n     * @return Next position ID.\n     */\n    function getNextPositionId() external view returns (uint256);\n\n    /// @notice Provides the protocol configuration settings.\n    function getConfig() external view returns (IProtocolConfig);\n\n    /// @notice Provides the current oracle responsible for price feeds.\n    function getOracle() external view returns (ICoreOracle);\n\n    /// @notice Provides all banks in the Blueberry Bank.\n    function getAllBanks() external view returns (address[] memory);\n\n    /**\n     * @dev Get the current FeeManager interface from the configuration.\n     * @return An interface representing the current FeeManager.\n     */\n    function getFeeManager() external view returns (IFeeManager);\n\n    /**\n     * @notice Returns whitelist status of a given token.\n     * @param token Address of the token.\n     */\n    function isTokenWhitelisted(address token) external view returns (bool);\n\n    /**\n     * @notice Returns whitelist status of a given wrapped token.\n     * @param token Address of the wrapped token.\n     */\n    function isWrappedTokenWhitelisted(address token) external view returns (bool);\n\n    /**\n     * @notice Returns whitelist status of a given spell.\n     * @param spell Address of the spell.\n     */\n    function isSpellWhitelisted(address spell) external view returns (bool);\n\n    /**\n     * @dev Determine if lending is currently allowed based on the bank's status flags.\n     * @notice Check the third-to-last bit of _bankStatus.\n     * @return A boolean indicating whether lending is permitted.\n     */\n    function isLendAllowed() external view returns (bool);\n\n    /**\n     * @dev Determine if withdrawing from lending is currently allowed based on the bank's status flags.\n     * @notice Check the fourth-to-last bit of _bankStatus.\n     * @return A boolean indicating whether withdrawing from lending is permitted.\n     */\n    function isWithdrawLendAllowed() external view returns (bool);\n\n    /**\n     * @dev Determine if repayments are currently allowed based on the bank's status flags.\n     * @notice Check the second-to-last bit of _bankStatus.\n     * @return A boolean indicating whether repayments are permitted.\n     */\n    function isRepayAllowed() external view returns (bool);\n\n    /**\n     * @dev Determine if borrowing is currently allowed based on the bank's status flags.\n     * @notice Check the last bit of _bankStatus.\n     * @return A boolean indicating whether borrowing is permitted.\n     */\n    function isBorrowAllowed() external view returns (bool);\n\n    /// @notice Fetches details of a bank given its token.\n    function getBankInfo(address token) external view returns (Bank memory bank);\n\n    /**\n     * @notice Gets the status of the bank\n     * @return The status of the bank\n     * @dev 1: Borrow is allowed\n     *      2: Repay is allowed\n     *      4: Lend is allowed\n     *      8: WithdrawLend is allowed\n     */\n    function getBankStatus() external view returns (uint256);\n\n    /**\n     * @dev Computes the total USD value of the debt of a given position.\n     * @notice Ensure to call `accrue` beforehand to account for any interest changes.\n     * @param positionId ID of the position to compute the debt value for.\n     * @return debtValue Total USD value of the position's debt.\n     */\n    function getDebtValue(uint256 positionId) external view returns (uint256 debtValue);\n\n    /**\n     * @notice Gets the repay resumed timestamp of the bank\n     * @return The timestamp when repay is resumed\n     */\n    function getRepayResumedTimestamp() external view returns (uint256);\n\n    /**\n     * @dev Computes the risk ratio of a specified position.\n     * @notice A higher risk ratio implies greater risk associated with the position.\n     * @dev    when:  riskRatio = (ov - pv) / cv\n     *         where: riskRatio = (debt - positionValue) / isolatedCollateralValue\n     * @param positionId ID of the position to assess risk for.\n     * @return risk The risk ratio of the position (based on a scale of 1e4).\n     */\n    function getPositionRisk(uint256 positionId) external view returns (uint256 risk);\n\n    /**\n     * @notice Retrieve the debt of a given position, considering the stored debt interest.\n     * @dev Should call accrue first to obtain the current debt.\n     * @param positionId The ID of the position to query.\n     */\n    function getPositionDebt(uint256 positionId) external view returns (uint256 debt);\n\n    /**\n     * @notice Determines if a given position can be liquidated based on its risk ratio.\n     * @param positionId ID of the position to check.\n     * @return True if the position can be liquidated; otherwise, false.\n     */\n    function isLiquidatable(uint256 positionId) external view returns (bool);\n\n    /**\n     * @notice Computes the total USD value of the collateral of a given position.\n     * @dev The returned value includes both the collateral and any pending rewards.\n     * @param positionId ID of the position to compute the value for.\n     * @return positionValue Total USD value of the collateral and pending rewards.\n     */\n    function getPositionValue(uint256 positionId) external view returns (uint256);\n\n    /**\n     * @notice Computes the isolated collateral value for a particular position.\n     * @dev Should call accrue first to get current debt.\n     * @param positionId The unique ID of the position.\n     * @return icollValue The value of the isolated collateral in USD.\n     */\n    function getIsolatedCollateralValue(uint256 positionId) external view returns (uint256 icollValue);\n\n    /**\n     * @notice Provides comprehensive details about a position using its ID.\n     * @param positionId The unique ID of the position.\n     * @return A Position struct containing details of the position.\n     */\n    function getPositionInfo(uint256 positionId) external view returns (Position memory);\n\n    /**\n     * @notice Fetches information about the currently active position.\n     * @return A Position struct with details of the current position.\n     */\n    function getCurrentPositionInfo() external view returns (Position memory);\n\n    /**\n     * @notice Triggers interest accumulation and fetches the updated borrow balance.\n     * @param positionId The unique ID of the position.\n     * @return The updated debt balance after accruing interest.\n     */\n    function currentPositionDebt(uint256 positionId) external returns (uint256);\n\n    /**\n     * @dev Lend tokens to the bank as isolated collateral.\n     * @dev Emit a {Lend} event.\n     * @notice The tokens lent will be used as collateral in the bank and might earn interest or other rewards.\n     * @param token The address of the token to lend.\n     * @param amount The number of tokens to lend.\n     */\n    function lend(address token, uint256 amount) external;\n\n    /**\n     * @dev Withdraw isolated collateral tokens previously lent to the bank.\n     * @dev Emit a {WithdrawLend} event.\n     * @notice This will reduce the isolated collateral and might also reduce the position's overall health.\n     * @param token The address of the isolated collateral token to withdraw.\n     * @param shareAmount The number of vault share tokens to withdraw.\n     */\n    function withdrawLend(address token, uint256 shareAmount) external;\n\n    /**\n     * @notice Allows users to borrow tokens from the specified bank.\n     * @dev This function must only be called from a spell while under execution.\n     * @dev Emit a {Borrow} event.\n     * @param token The token to borrow from the bank.\n     * @param amount The amount of tokens the user wishes to borrow.\n     * @return borrowedAmount Returns the actual amount borrowed from the bank.\n     */\n    function borrow(address token, uint256 amount) external returns (uint256);\n\n    /**\n     * @dev Executes a specific action on a position.\n     * @dev Emit an {Execute} event.\n     * @notice This can be used for various operations like adjusting collateral, repaying debt, etc.\n     * @param positionId Unique identifier of the position, or zero for a new position.\n     * @param spell Address of the contract (\"spell\") that contains the logic for the action to be executed.\n     * @param data Data payload to pass to the spell for execution.\n     */\n    function execute(uint256 positionId, address spell, bytes memory data) external returns (uint256);\n\n    /**\n     * @notice Allows users to repay their borrowed tokens to the bank.\n     * @dev This function must only be called while under execution.\n     * @dev Emit a {Repay} event.\n     * @param token The token to repay to the bank.\n     * @param amountCall The amount of tokens to be repaid.\n     */\n    function repay(address token, uint256 amountCall) external;\n\n    /**\n     * @notice Allows users to provide additional collateral.\n     * @dev Must only be called during execution.\n     * @param collToken The ERC1155 token wrapped for collateral (i.e., Wrapped token of LP).\n     * @param collId The token ID for collateral (i.e., uint256 format of LP address).\n     * @param amountCall The amount of tokens to add as collateral.\n     */\n    function putCollateral(address collToken, uint256 collId, uint256 amountCall) external;\n\n    /**\n     * @notice Allows users to withdraw a portion of their collateral.\n     * @dev Must only be called during execution.\n     * @param amount The amount of tokens to be withdrawn as collateral.\n     * @return Returns the amount of collateral withdrawn.\n     */\n    function takeCollateral(uint256 amount) external returns (uint256);\n\n    /**\n     * @dev Liquidates a position by repaying its debt and taking the collateral.\n     * @dev Emit a {Liquidate} event.\n     * @notice Liquidation can only be triggered if the position is deemed liquidatable\n     *         and other conditions are met.\n     * @param positionId The unique identifier of the position to liquidate.\n     * @param debtToken The token in which the debt is denominated.\n     * @param amountCall The amount of debt to be repaid when calling transferFrom.\n     */\n    function liquidate(uint256 positionId, address debtToken, uint256 amountCall) external;\n\n    /**\n     * @notice Accrues interest for a given token.\n     * @param token Address of the token to accrue interest for.\n     */\n    function accrue(address token) external;\n\n    /**\n     * @notice Accrues interest for a given list of tokens.\n     * @param tokens An array of token addresses to accrue interest for.\n     */\n    function accrueAll(address[] memory tokens) external;\n\n    /* solhint-disable func-name-mixedcase */\n\n    /**\n     * @notice Returns the current executor's address, which is the owner of the current position.\n     * @return Address of the current executor.\n     */\n    function EXECUTOR() external view returns (address);\n\n    /**\n     * @notice Returns the ID of the currently executed position.\n     * @return Current position ID.\n     */\n    function POSITION_ID() external view returns (uint256);\n\n    /**\n     * @notice Returns the address of the currently executed bank.\n     * @return Current bank address.\n     */\n    function SPELL() external view returns (address);\n\n    /* solhint-enable func-name-mixedcase */\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/ICurveOracle.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\nimport { IBaseOracle } from \"./IBaseOracle.sol\";\nimport { ICurveAddressProvider } from \"../interfaces/curve/ICurveAddressProvider.sol\";\n\n/**\n * @title ICurveOracle\n * @notice Interface for the CurveOracle contract which provides price feed data for assets on Curve Finance.\n */\ninterface ICurveOracle is IBaseOracle {\n    /**\n     * @notice Fetches relevant information about a Curve liquidity pool.\n     * @param crvLp The address of the Curve liquidity pool token (LP token).\n     * @return pool Address of the pool contract.\n     * @return coins A list of underlying tokens in the Curve liquidity pool.\n     * @return virtualPrice The current virtual price of the LP token for the given Curve liquidity pool.\n     */\n    function getPoolInfo(address crvLp) external returns (address pool, address[] memory coins, uint256 virtualPrice);\n\n    /// @notice Returns the Curve Address Provider.\n    function getAddressProvider() external view returns (ICurveAddressProvider);\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/ICurveZapDepositor.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\n/* solhint-disable func-name-mixedcase */\n\n/**\n * @title ICurveZapDepositor\n * @notice Interface for the Curve Zap Depositor contract.\n */\ninterface ICurveZapDepositor {\n    function add_liquidity(address pool, uint256[4] memory amounts, uint256 minMint) external;\n\n    function remove_liquidity(address pool, uint256 amount, uint256[4] memory minAmounts) external;\n\n    function remove_liquidity_one_coin(address pool, uint256 amount, int128 i, uint256 minAmount) external;\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/curve/ICurvePool.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\ninterface ICurvePool {\n    function add_liquidity(uint256[2] calldata, uint256) external payable;\n\n    function add_liquidity(uint256[3] calldata, uint256) external payable;\n\n    function add_liquidity(uint256[4] calldata, uint256) external payable;\n\n    function remove_liquidity(uint256, uint256[2] calldata) external;\n\n    function remove_liquidity(uint256, uint256[3] calldata) external;\n\n    function remove_liquidity(uint256, uint256[4] calldata) external;\n\n    function remove_liquidity_imbalance(uint256[2] calldata, uint256) external;\n\n    function remove_liquidity_imbalance(uint256[3] calldata, uint256) external;\n\n    function remove_liquidity_imbalance(uint256[4] calldata, uint256) external;\n\n    function remove_liquidity_one_coin(uint256, uint256, uint256) external;\n\n    function remove_liquidity_one_coin(uint256, int128, uint256) external;\n\n    function exchange(uint256, uint128, uint256, uint256) external;\n\n    function remove_liquidity_one_coin(uint256, uint256, uint256, bool, address) external;\n\n    function get_virtual_price() external view returns (uint256);\n\n    function lp_token() external view returns (address); // v1\n\n    function token() external view returns (address); // v2\n\n    function balances(uint256 i) external view returns (uint256);\n\n    function withdraw_admin_fees() external;\n\n    function claim_admin_fees() external;\n\n    function get_dy(uint256 i, uint256 j, uint256 dx) external view returns (uint256);\n\n    function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external returns (uint256);\n\n    function coins(uint256 i) external view returns (address);\n\n    // 3crv pool specific functions\n\n    function owner() external view returns (address);\n\n    function kill_me() external;\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/IWConvexBooster.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\n/* solhint-disable max-line-length */\nimport { IERC1155Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol\";\n/* solhint-enable max-line-length */\n\nimport { IConvex } from \"./convex/IConvex.sol\";\nimport { ICvxBooster } from \"./convex/ICvxBooster.sol\";\nimport { IERC20Wrapper } from \"./IERC20Wrapper.sol\";\nimport { ICvxBooster } from \"./convex/ICvxBooster.sol\";\nimport { IPoolEscrowFactory } from \"../wrapper/escrow/interfaces/IPoolEscrowFactory.sol\";\n\n/**\n * @title IWConvexBooster\n * @author Interface for interacting with Convex pools represented as ERC1155 tokens.\n * @notice Convex Pools allow users to stake liquidity pool tokens in return for CVX and other rewards.\n */\ninterface IWConvexBooster is IERC1155Upgradeable, IERC20Wrapper {\n    /// @notice Emitted when a user stakes liquidity provider tokens and a new ERC1155 token is minted.\n    event Minted(uint256 indexed id, uint256 indexed pid, uint256 amount);\n\n    /// @notice Emitted when a user burns an ERC1155 token to claim rewards and close their position.\n    event Burned(uint256 indexed id, uint256 indexed pid, uint256 amount);\n\n    /**\n     * @notice Struct for storing information regarding an Cvx Pools Stash Token.\n     * @param stashToken The address of the stash token.\n     * @param rewarder The address of the rewarder contract.\n     * @param lastStashRewardPerToken The last reward per token value for the stash token.\n     * @param stashCvxReceived The amount of Cvx received by the stash token.\n     */\n    struct StashTokenInfo {\n        address stashToken;\n        address rewarder;\n        uint256 lastStashRewardPerToken;\n        uint256 stashCvxReceived;\n    }\n\n    /**\n     * @notice Encodes pool id and BAL per share into an ERC1155 token id\n     * @param pid The pool id (The first 16-bits)\n     * @param cvxPerShare CVX amount per share, which should be multiplied by 1e18 and is the last 240 bits.\n     * @return The resulting ERC1155 token id\n     */\n    function encodeId(uint256 pid, uint256 cvxPerShare) external pure returns (uint256);\n\n    /**\n     * @notice Decode an encoded ID into two separate uint values.\n     * @param id The encoded uint ID to decode.\n     * @return pid The pool ID representing the specific Convex pool.\n     * @return cvxPerShare Original CVX amount per share, which should be multiplied by 1e18.\n     */\n    function decodeId(uint256 id) external pure returns (uint256 pid, uint256 cvxPerShare);\n\n    /**\n     *\n     * @param pid The pool ID representing the specific Convex pool.\n     * @param amount The amount of liquidity provider tokens to stake.\n     * @return id The ID of the newly minted ERC1155 token representing the staked position.\n     */\n    function mint(uint256 pid, uint256 amount) external returns (uint256 id);\n\n    /**\n     * @notice Burn an ERC1155 token to redeem staked liquidity provider tokens and any earned rewards.\n     * @param id The ID of the ERC1155 token representing the staked position.\n     * @param amount The amount of ERC1155 tokens to burn.\n     * @return rewardTokens An array of reward token addresses.\n     * @return rewards An array of reward amounts corresponding to the reward token addresses.\n     */\n    function burn(\n        uint256 id,\n        uint256 amount\n    ) external returns (address[] memory rewardTokens, uint256[] memory rewards);\n\n    /**\n     * @notice Syncs extra rewards for a given tokenId\n     * @dev Due to the way rewards can be added to an Aura pool, this function is necessary to\n     *    sync the extra rewards for a given tokenId before users can access any newly added rewards.\n     * @dev It is the responsibility of the user to call this function when new rewards are added.\n     * @param pid The pool ID representing the specific Aura pool.\n     * @param tokenId The ID of the ERC1155 token representing the staked position.\n     */\n    function syncExtraRewards(uint256 pid, uint256 tokenId) external;\n\n    /// @notice Get the Convex token's contract address.\n    function getCvxToken() external view returns (IConvex);\n\n    /// @notice Get the Convex Booster contract address.\n    function getCvxBooster() external view returns (ICvxBooster);\n\n    /// @notice Get the Pool Escrow Factory contract address.\n    function getEscrowFactory() external view returns (IPoolEscrowFactory);\n\n    /**\n     *\n     * @param pid The pool ID representing the specific Convex pool.\n     * @return lptoken The liquidity provider token's address for the specific pool.\n     * @return token The reward token's address for the specific pool.\n     * @return gauge The gauge contract's address for the specific pool.\n     * @return crvRewards The Curve rewards contract's address associated with the specific pool.\n     * @return stash The stash contract's address associated with the specific pool.\n     * @return shutdown A boolean indicating if the pool is in shutdown mode.\n     */\n    function getPoolInfoFromPoolId(\n        uint256 pid\n    )\n        external\n        view\n        returns (address lptoken, address token, address gauge, address crvRewards, address stash, bool shutdown);\n\n    /**\n     * @notice Fetch the escrow for a given pool ID.\n     * @param pid The pool ID representing the specific Convex pool.\n     * @return The address of the escrow contract.\n     */\n    function getEscrow(uint256 pid) external view returns (address);\n\n    /**\n     * @notice Fetch the length of the extra rewarder array for a given pool ID.\n     * @param pid The pool ID representing the specific Convex pool.\n     * @return The length of the extra rewarder array.\n     */\n    function extraRewardsLength(uint256 pid) external view returns (uint256);\n\n    /**\n     * @notice Fetch the extra rewarder for a given pool ID and index.\n     * @param pid The pool ID representing the specific Convex pool.\n     * @param index The index to access in the extraRewarder array.\n     * @return The address of the extra rewarder contract.\n     */\n    function getExtraRewarder(uint256 pid, uint256 index) external view returns (address);\n\n    /**\n     * @notice Receive the starting rewardPerToken value for a specific reward token for a given tokenId.\n     * @param tokenId The ID of the ERC1155 token representing the staked position.\n     * @param token The address of the reward token.\n     * @return The reward amount per token share.\n     */\n    function getInitialTokenPerShare(uint256 tokenId, address token) external view returns (uint256);\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/IWETH.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\n/// @title IWETH\n/// @notice This is the interface for the Wrapped Ether (WETH) contract.\n/// @dev WETH is an ERC20-compatible version of Ether, facilitating interactions in smart contracts.\ninterface IWETH {\n    /// @notice Fetch the balance of `user` in terms of WETH.\n    /// @param user The address of the account whose balance will be retrieved.\n    /// @return The balance of the given user's address.\n    function balanceOf(address user) external view returns (uint256);\n\n    /// @notice Approve an address to spend WETH on behalf of the message sender.\n    /// @param to The address to grant spending rights.\n    /// @param value The amount of WETH the spender is allowed to transfer.\n    /// @return A boolean value indicating whether the operation succeeded.\n    function approve(address to, uint256 value) external returns (bool);\n\n    /// @notice Transfer WETH from the message sender to another address.\n    /// @param to The recipient address.\n    /// @param value The amount of WETH to be transferred.\n    /// @return A boolean value indicating whether the transfer was successful.\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /// @notice Convert Ether to WETH by sending Ether to the contract.\n    /// @dev This function should be called with a payable modifier to attach Ether.\n    function deposit() external payable;\n\n    /// @notice Convert WETH back into Ether and send it to the message sender.\n    function withdraw(uint256) external;\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/spell/IConvexSpell.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\nimport { IBasicSpell } from \"./IBasicSpell.sol\";\nimport { ICurveOracle } from \"../ICurveOracle.sol\";\nimport { IWConvexBooster } from \"../IWConvexBooster.sol\";\n\n/**\n * @title IConvexSpell\n * @notice Interface for the Convex Spell contract.\n */\ninterface IConvexSpell is IBasicSpell {\n    struct ClosePositionFarmParam {\n        ClosePosParam param;\n        uint256[] amounts;\n        bytes[] swapDatas;\n    }\n\n    /**\n     * @notice Closes an existing liquidity position, unstakes from Curve gauge, and swaps rewards.\n     * @param closePosParam Struct containing all required parameters for closing a position.\n     */\n    function closePositionFarm(ClosePositionFarmParam calldata closePosParam) external;\n\n    /**\n     * @notice Adds liquidity to a Curve pool with two underlying tokens and stakes in Curve gauge.\n     * @param param Struct containing all required parameters for opening a position.\n     * @param minLPMint Minimum LP tokens expected to mint for slippage control.\n     */\n    function openPositionFarm(OpenPosParam calldata param, uint256 minLPMint) external;\n\n    /**\n     * @notice Adds a new strategy to the spell.\n     * @param crvLp Address of the Curve LP token for the strategy.\n     * @param minCollSize Minimum isolated collateral in USD for the strategy (with 1e18 precision).\n     * @param maxPosSize Maximum position size in USD for the strategy (with 1e18 precision).\n     */\n    function addStrategy(address crvLp, uint256 minCollSize, uint256 maxPosSize) external;\n\n    /// @notice Returns the address of the Cvx oracle.\n    function getCrvOracle() external view returns (ICurveOracle);\n\n    /// @notice Returns the address of the Cvx token.\n    function getCvxToken() external view returns (address);\n\n    /// @notice Returns the address of the wrapped Aura Booster contract.\n    function getWConvexBooster() external view returns (IWConvexBooster);\n}\n"
      },
      "lib/blueberry-core/node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (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 *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n *     doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n *     token.safeTransferFrom(msg.sender, address(this), value);\n *     ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20PermitUpgradeable {\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     * CAUTION: See Security Considerations above.\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"
      },
      "lib/blueberry-core/node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\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 value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\n     * 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 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` 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 value) external returns (bool);\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/paraswap/IParaswap.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"../../libraries/Paraswap/Utils.sol\";\n\ninterface IParaswap {\n    event Swapped(\n        bytes16 uuid,\n        address initiator,\n        address indexed beneficiary,\n        address indexed srcToken,\n        address indexed destToken,\n        uint256 srcAmount,\n        uint256 receivedAmount,\n        uint256 expectedAmount\n    );\n\n    event Bought(\n        bytes16 uuid,\n        address initiator,\n        address indexed beneficiary,\n        address indexed srcToken,\n        address indexed destToken,\n        uint256 srcAmount,\n        uint256 receivedAmount\n    );\n\n    event FeeTaken(uint256 fee, uint256 partnerShare, uint256 paraswapShare);\n\n    function multiSwap(Utils.SellData calldata data) external payable returns (uint256);\n\n    function megaSwap(Utils.MegaSwapSellData calldata data) external payable returns (uint256);\n\n    function protectedMultiSwap(Utils.SellData calldata data) external payable returns (uint256);\n\n    function protectedMegaSwap(Utils.MegaSwapSellData calldata data) external payable returns (uint256);\n\n    function protectedSimpleSwap(Utils.SimpleData calldata data) external payable returns (uint256 receivedAmount);\n\n    function protectedSimpleBuy(Utils.SimpleData calldata data) external payable;\n\n    function simpleSwap(Utils.SimpleData calldata data) external payable returns (uint256 receivedAmount);\n\n    function simpleBuy(Utils.SimpleData calldata data) external payable;\n\n    function swapOnUniswap(uint256 amountIn, uint256 amountOutMin, address[] calldata path) external payable;\n\n    function swapOnUniswapFork(\n        address factory,\n        bytes32 initCode,\n        uint256 amountIn,\n        uint256 amountOutMin,\n        address[] calldata path\n    ) external payable;\n\n    function buyOnUniswap(uint256 amountInMax, uint256 amountOut, address[] calldata path) external payable;\n\n    function buyOnUniswapFork(\n        address factory,\n        bytes32 initCode,\n        uint256 amountInMax,\n        uint256 amountOut,\n        address[] calldata path\n    ) external payable;\n\n    function swapOnUniswapV2Fork(\n        address tokenIn,\n        uint256 amountIn,\n        uint256 amountOutMin,\n        address weth,\n        uint256[] calldata pools\n    ) external payable;\n\n    function buyOnUniswapV2Fork(\n        address tokenIn,\n        uint256 amountInMax,\n        uint256 amountOut,\n        address weth,\n        uint256[] calldata pools\n    ) external payable;\n\n    function swapOnZeroXv2(\n        IERC20 fromToken,\n        IERC20 toToken,\n        uint256 fromAmount,\n        uint256 amountOutMin,\n        address exchange,\n        bytes calldata payload\n    ) external payable;\n\n    function swapOnZeroXv4(\n        IERC20 fromToken,\n        IERC20 toToken,\n        uint256 fromAmount,\n        uint256 amountOutMin,\n        address exchange,\n        bytes calldata payload\n    ) external payable;\n}\n"
      },
      "lib/blueberry-core/contracts/libraries/Paraswap/Utils.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\nlibrary Utils {\n    /**\n   * @param fromToken Address of the source token\n   * @param fromAmount Amount of source tokens to be swapped\n   * @param toAmount Minimum destination token amount expected out of this swap\n   * @param expectedAmount Expected amount of destination tokens without slippage\n   * @param beneficiary Beneficiary address\n   * 0 then 100% will be transferred to beneficiary. Pass 10000 for 100%\n   * @param path Route to be taken for this swap to take place\n   */\n    struct SellData {\n        address fromToken;\n        uint256 fromAmount;\n        uint256 toAmount;\n        uint256 expectedAmount;\n        address payable beneficiary;\n        Utils.Path[] path;\n        address payable partner;\n        uint256 feePercent;\n        bytes permit;\n        uint256 deadline;\n        bytes16 uuid;\n    }\n\n    struct MegaSwapSellData {\n        address fromToken;\n        uint256 fromAmount;\n        uint256 toAmount;\n        uint256 expectedAmount;\n        address payable beneficiary;\n        Utils.MegaSwapPath[] path;\n        address payable partner;\n        uint256 feePercent;\n        bytes permit;\n        uint256 deadline;\n        bytes16 uuid;\n    }\n\n    struct SimpleData {\n        address fromToken;\n        address toToken;\n        uint256 fromAmount;\n        uint256 toAmount;\n        uint256 expectedAmount;\n        address[] callees;\n        bytes exchangeData;\n        uint256[] startIndexes;\n        uint256[] values;\n        address payable beneficiary;\n        address payable partner;\n        uint256 feePercent;\n        bytes permit;\n        uint256 deadline;\n        bytes16 uuid;\n    }\n\n    struct Adapter {\n        address payable adapter;\n        uint256 percent;\n        uint256 networkFee;\n        Route[] route;\n    }\n\n    struct Route {\n        uint256 index; //Adapter at which index needs to be used\n        address targetExchange;\n        uint256 percent;\n        bytes payload;\n        uint256 networkFee; //Network fee is associated with 0xv3 trades\n    }\n\n    struct MegaSwapPath {\n        uint256 fromAmountPercent;\n        Path[] path;\n    }\n\n    struct Path {\n        address to;\n        uint256 totalNetworkFee; //Network fee is associated with 0xv3 trades\n        Adapter[] adapters;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC1363} from \"../../../interfaces/IERC1363.sol\";\nimport {Address} from \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    /**\n     * @dev An operation with an ERC-20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            safeTransfer(token, to, value);\n        } else if (!token.transferAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\n     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferFromAndCallRelaxed(\n        IERC1363 token,\n        address from,\n        address to,\n        uint256 value,\n        bytes memory data\n    ) internal {\n        if (to.code.length == 0) {\n            safeTransferFrom(token, from, to, value);\n        } else if (!token.transferFromAndCall(from, to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\n     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\n     * once without retrying, and relies on the returned value to be true.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            forceApprove(token, to, value);\n        } else if (!token.approveAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data);\n        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\n    }\n}\n"
      },
      "lib/blueberry-core/node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.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 \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\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"
      },
      "lib/blueberry-core/node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
      },
      "lib/blueberry-core/contracts/utils/BlueberryConst.sol": {
        "content": "// SPDX-License-Identifier: MIT\n/*\n██████╗ ██╗     ██╗   ██╗███████╗██████╗ ███████╗██████╗ ██████╗ ██╗   ██╗\n██╔══██╗██║     ██║   ██║██╔════╝██╔══██╗██╔════╝██╔══██╗██╔══██╗╚██╗ ██╔╝\n██████╔╝██║     ██║   ██║█████╗  ██████╔╝█████╗  ██████╔╝██████╔╝ ╚████╔╝\n██╔══██╗██║     ██║   ██║██╔══╝  ██╔══██╗██╔══╝  ██╔══██╗██╔══██╗  ╚██╔╝\n██████╔╝███████╗╚██████╔╝███████╗██████╔╝███████╗██║  ██║██║  ██║   ██║\n╚═════╝ ╚══════╝ ╚═════╝ ╚══════╝╚═════╝ ╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝   ╚═╝\n*/\n\n/**\n * @title BlueberryErrors\n * @author BlueberryProtocol\n * @notice This contract contains the error messages for Blueberry Protocol.\n */\npragma solidity 0.8.22;\n\n/// @dev Common denominator for percentage-based calculations.\nuint256 constant DENOMINATOR = 10000;\n\n/// @dev Minimum threshold for liquidity operations, represented as a fraction of the DENOMINATOR.\nuint256 constant MIN_LIQ_THRESHOLD = 8000; // represent 80%\n\n/// @dev Precision factor to maintain price accuracy.\nuint256 constant PRICE_PRECISION = 1e18;\n\n/// @dev Maximum allowed price deviation, represented as a fraction of the DENOMINATOR.\nuint256 constant MAX_PRICE_DEVIATION = 1000; // represent 10%\n\n/// @dev Minimum time interval for specific time-dependent operations.\nuint32 constant MIN_TIME_GAP = 3 minutes;\n\n/// @dev Maximum time interval for specific time-dependent operations.\nuint32 constant MAX_TIME_GAP = 2 days;\n\n/// @dev Maximum allowed fee rate, represented as a fraction of the DENOMINATOR.\nuint256 constant MAX_FEE_RATE = 2000; // represent 20%\n\n/// @dev Maximum allowed time for vault withdrawal fee calculations.\nuint256 constant MAX_WITHDRAW_VAULT_FEE_WINDOW = 60 days;\n\n/// @dev Maximum delay permitted for swap operations.\nuint32 constant MAX_DELAY_ON_SWAP = 2 hours;\n\n/// @dev Allowed grace period time for sequencer operations.\nuint32 constant SEQUENCER_GRACE_PERIOD_TIME = 3600;\n\n/// @dev Precision factor for Chainlink price feed values.\nuint256 constant CHAINLINK_PRICE_FEED_PRECISION = 1e8;\n\n/// @dev Warm-up period before a liquidation repayment can be initiated.\nuint256 constant LIQUIDATION_REPAY_WARM_UP_PERIOD = 4 hours;\n"
      },
      "lib/blueberry-core/contracts/utils/ERC1155NaiveReceiver.sol": {
        "content": "// SPDX-License-Identifier: MIT\n/*\n██████╗ ██╗     ██╗   ██╗███████╗██████╗ ███████╗██████╗ ██████╗ ██╗   ██╗\n██╔══██╗██║     ██║   ██║██╔════╝██╔══██╗██╔════╝██╔══██╗██╔══██╗╚██╗ ██╔╝\n██████╔╝██║     ██║   ██║█████╗  ██████╔╝█████╗  ██████╔╝██████╔╝ ╚████╔╝\n██╔══██╗██║     ██║   ██║██╔══╝  ██╔══██╗██╔══╝  ██╔══██╗██╔══██╗  ╚██╔╝\n██████╔╝███████╗╚██████╔╝███████╗██████╔╝███████╗██║  ██║██║  ██║   ██║\n╚═════╝ ╚══════╝ ╚═════╝ ╚══════╝╚═════╝ ╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝   ╚═╝\n*/\n\npragma solidity 0.8.22;\n\nimport { IERC1155Receiver } from \"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\";\n\n/**\n * @title ERC1155NaiveReceiver\n * @author BlueberryProtocol\n * @notice A receiver contract that naively accepts all ERC1155 transfers.\n */\ncontract ERC1155NaiveReceiver is IERC1155Receiver {\n    /// @notice Handle the receipt of a single ERC1155 token type.\n    /// @dev This function is called at the end of a\n    /// `safeTransferFrom` after the balance has been updated.\n    function onERC1155Received(\n        address /* operator */,\n        address /* from */,\n        uint256 /* id */,\n        uint256 /* value */,\n        bytes calldata /* data */\n    ) external pure override returns (bytes4) {\n        return this.onERC1155Received.selector;\n    }\n\n    /// @notice Handle the receipt of multiple ERC1155 token types.\n    /// @dev This function is called at the end of a\n    /// `safeBatchTransferFrom` after the balances have been updated.\n    function onERC1155BatchReceived(\n        address /* operator */,\n        address /* from */,\n        uint256[] calldata /* ids */,\n        uint256[] calldata /* values */,\n        bytes calldata /* data */\n    ) external pure override returns (bytes4) {\n        return this.onERC1155BatchReceived.selector;\n    }\n\n    /// @notice Checks if the contract supports a given interface.\n    /// @dev Returns true if the interfaceId is 0x01ffc9a7 (IERC1155Receiver).\n    function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) {\n        return interfaceId == type(IERC1155Receiver).interfaceId;\n    }\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/IERC20Wrapper.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\n/**\n * @title IERC20Wrapper\n * @author BlueberryProtocol\n * @notice Interface for the ERC20Wrapper contract which allows the wrapping\n *         of ERC-20 tokens with associated ERC-1155 token IDs.\n */\ninterface IERC20Wrapper {\n    /**\n     * @notice Fetches the underlying ERC-20 token address associated with the provided ERC-1155 token ID.\n     * @param tokenId The ERC-1155 token ID for which the underlying ERC-20 token address is to be fetched.\n     * @return The address of the underlying ERC-20 token.\n     */\n    function getUnderlyingToken(uint256 tokenId) external view returns (address);\n\n    /**\n     * @notice Fetches pending rewards for a particular ERC-1155 token ID and given amount.\n     * @param id The ERC-1155 token ID for which the pending rewards are to be fetched.\n     * @param amount The amount for which pending rewards are to be calculated.\n     * @return tokens A list of addresses representing reward tokens.\n     * @return amounts A list of amounts corresponding to each reward token in the `tokens` list.\n     */\n    function pendingRewards(uint256 id, uint256 amount) external view returns (address[] memory, uint256[] memory);\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/IWERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\n/* solhint-disable max-line-length */\nimport { IERC1155Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol\";\n/* solhint-enable max-line-length */\n\nimport { IERC20Wrapper } from \"./IERC20Wrapper.sol\";\n\n/**\n * @title IWERC20\n * @author This interface defines the functionality of the Wrapped ERC20 (WERC20) token.\n * @notice WERC20 tokens enable ERC20 tokens to be represented\n *         as ERC1155 tokens, providing batch transfer capabilities and more.\n */\ninterface IWERC20 is IERC1155Upgradeable, IERC20Wrapper {\n    /// @notice Emitted when a token is minted.\n    event Minted(uint256 indexed id, uint256 amount);\n\n    /// @notice Emitted when a token is burned.\n    event Burned(uint256 indexed id, uint256 amount);\n\n    /**\n     * @notice Fetches the balance of the underlying ERC20 token for a specific user.\n     * @param token The ERC20 token address.\n     * @param user The user's address.\n     * @return The user's balance of the specified ERC20 token.\n     */\n    function balanceOfERC20(address token, address user) external view returns (uint256);\n\n    /**\n     * @notice Allows users to wrap their ERC20 tokens into the corresponding ERC1155 tokenId.\n     * @param token The address of the ERC20 token to wrap.\n     * @param amount The amount of the ERC20 token to wrap.\n     * @return id The tokenId of the wrapped ERC20 token.\n     */\n    function mint(address token, uint256 amount) external returns (uint256 id);\n\n    /**\n     * @notice Allows users to burn their ERC1155 token to retrieve the original ERC20 tokens.\n     * @param token The address of the ERC20 token to unwrap.\n     * @param amount The amount of the ERC20 token to unwrap.\n     */\n    function burn(address token, uint256 amount) external;\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/spell/IBasicSpell.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\n/**\n * @title IBasicSpell\n * @notice Interface for the Basic Spell contract.\n */\ninterface IBasicSpell {\n    /**\n     * @dev Defines strategies for Blueberry Protocol.\n     * @param vault Address of the vault where assets are held.\n     * @param minIsolatedCollateral Minimum size of isolated collateral in USD.\n     * @param maxPositionSize Maximum size of the position in USD.\n     */\n    struct Strategy {\n        address vault;\n        uint256 minIsolatedCollateral;\n        uint256 maxPositionSize;\n    }\n\n    /**\n     * @dev Defines parameters required for opening a new position.\n     * @param strategyId Identifier for the strategy.\n     * @param collToken Address of the collateral token (e.g., USDC).\n     * @param collAmount Amount of user's collateral to deposit.\n     * @param borrowToken Address of the token to borrow.\n     * @param borrowAmount Amount to borrow from the bank.\n     * @param farmingPoolId Identifier for the farming pool.\n     */\n    struct OpenPosParam {\n        uint256 strategyId;\n        address collToken;\n        uint256 collAmount;\n        address borrowToken;\n        uint256 borrowAmount;\n        uint256 farmingPoolId;\n    }\n\n    /**\n     * @dev Defines parameters required for closing a position.\n     * @param strategyId Identifier for the strategy to close.\n     * @param collToken Address of the isolated collateral token.\n     * @param borrowToken Address of the token representing the debt.\n     * @param amountRepay Amount of debt to repay.\n     * @param amountPosRemove Amount of position to withdraw.\n     * @param amountShareWithdraw Amount of isolated collateral tokens to withdraw.\n     * @param amountOutMin Minimum amount to receive after the operation (used to handle slippage).\n     * @param amountToSwap Collateral amount to swap to repay debt for negative PnL\n     * @param swapData Paraswap sawp data to swap collateral to borrow token\n     */\n    struct ClosePosParam {\n        uint256 strategyId;\n        address collToken;\n        address borrowToken;\n        uint256 amountRepay;\n        uint256 amountPosRemove;\n        uint256 amountShareWithdraw;\n        uint256 amountOutMin;\n        uint256 amountToSwap;\n        bytes swapData;\n    }\n\n    /**\n     * @notice This event is emitted when a new strategy is added.\n     * @param strategyId Unique identifier for the strategy.\n     * @param vault Address of the vault where assets are held.\n     * @param minCollSize Minimum size of the isolated collateral in USD.\n     * @param maxPosSize Maximum size of the position in USD.\n     */\n    event StrategyAdded(uint256 strategyId, address vault, uint256 minCollSize, uint256 maxPosSize);\n\n    /**\n     * @notice This event is emitted when a strategy's min/max position size is updated.\n     * @param strategyId Unique identifier for the strategy.\n     * @param minCollSize Minimum size of the isolated collateral in USD.\n     * @param maxPosSize Maximum size of the position in USD.\n     */\n    event StrategyPosSizeUpdated(uint256 strategyId, uint256 minCollSize, uint256 maxPosSize);\n\n    /**\n     * @notice This event is emitted when a strategy's collateral max LTV is updated.\n     * @param strategyId Unique identifier for the strategy.\n     * @param collaterals Array of collateral token addresses.\n     * @param maxLTVs Array of maximum LTVs corresponding to the collaterals. (base 1e4)\n     */\n    event CollateralsMaxLTVSet(uint256 strategyId, address[] collaterals, uint256[] maxLTVs);\n\n    /**\n     * @notice Update the position sizes for a specific strategy.\n     * @dev This function validates the inputs, updates the strategy's position sizes, and emits an event.\n     * @param strategyId ID of the strategy to be updated.\n     * @param minCollSize New minimum size of the isolated collateral for the strategy.\n     * @param maxPosSize New maximum position size for the strategy.\n     */\n    function setPosSize(uint256 strategyId, uint256 minCollSize, uint256 maxPosSize) external;\n\n    /**\n     * @notice Set maximum Loan-To-Value (LTV) ratios for collaterals in a given strategy.\n     * @dev This function validates the input arrays, sets the maxLTVs for each collateral, and emits an event.\n     * @param strategyId ID of the strategy for which the maxLTVs are being set.\n     * @param collaterals Array of addresses for each collateral token.\n     * @param maxLTVs Array of maxLTV values corresponding to each collateral token.\n     */\n    function setCollateralsMaxLTVs(uint256 strategyId, address[] memory collaterals, uint256[] memory maxLTVs) external;\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/IProtocolConfig.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\nimport { IFeeManager } from \"./IFeeManager.sol\";\n\n/**\n * @title IProtocolConfig\n * @author BlueberryProtocol\n * @notice Interface for the Protocol Configuration,\n *         encapsulating various fees and related configuration parameters.\n * @dev This interface defines methods to retrieve fees\n *      and related parameters that govern the behavior of the protocol.\n */\ninterface IProtocolConfig {\n    /**\n     * @notice Retrieve the deposit fee rate applied when users deposit into the protocol.\n     * @return The deposit fee rate.\n     */\n    function getDepositFee() external view returns (uint256);\n\n    /**\n     * @notice Retrieve the withdrawal fee rate applied when users withdraw from the protocol.\n     * @return The withdrawal fee rate.\n     */\n    function getWithdrawFee() external view returns (uint256);\n\n    /**\n     * @notice Retrieve the reward fee rate applied when users claim rewards from the protocol.\n     * @return The reward fee rate.\n     */\n    function getRewardFee() external view returns (uint256);\n\n    /**\n     * @notice Get the address where protocol's collected fees are stored and managed.\n     * @return The treasury address of the protocol.\n     */\n    function getTreasury() external view returns (address);\n\n    /**\n     * @notice Retrieve the fee rate applied for withdrawals from vaults.\n     * @return The fee rate for vault withdrawals.\n     */\n    function getTreasuryFeeRate() external view returns (uint256);\n\n    /**\n     * @notice Retrieve the fee rate applied for withdrawals from vaults.\n     * @return The fee rate for vault withdrawals.\n     */\n    function getWithdrawVaultFee() external view returns (uint256);\n\n    /**\n     * @notice Retrieve the window of time where the vault withdrawal fee is applied.\n     * @return The window of time where the vault withdrawal fee is applied.\n     */\n    function getWithdrawVaultFeeWindow() external view returns (uint256);\n\n    /**\n     * @notice Retrieve the start time of the window of time where the vault withdrawal fee is applied.\n     * @return The start time of the window of time where the vault withdrawal fee is applied.\n     */\n    function getWithdrawVaultFeeWindowStartTime() external view returns (uint256);\n\n    /**\n     * @notice Get the fee manager that handles fee calculations and distributions.\n     * @return An instance of the IFeeManager interface that manages fees within the protocol.\n     */\n    function getFeeManager() external view returns (IFeeManager);\n\n    /**\n     * @notice Get the address of the $BLB-ICHI vault.\n     * @return The address of the $BLB-ICHI vault.\n     */\n    function getBlbUsdcIchiVault() external view returns (address);\n\n    /**\n     * @notice Get the address of the $BLB stability pool.\n     * @return The address of the $BLB stability pool.\n     */\n    function getBlbStabilityPool() external view returns (address);\n\n    /**\n     * @notice Get the fee rate applied for withdrawals from the $BLB-ICHI vault.\n     * @return The fee rate for $BLB-ICHI vault withdrawals.\n     */\n    function getBlbIchiVaultFeeRate() external view returns (uint256);\n\n    /**\n     * @notice Get the fee rate applied for withdrawals from the $BLB-ICHI vault.\n     * @return The fee rate for $BLB-ICHI vault withdrawals.\n     */\n    function getBlbStablePoolFeeRate() external view returns (uint256);\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/IFeeManager.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport { IProtocolConfig } from \"./IProtocolConfig.sol\";\n\n/**\n * @title IFeeManager\n * @notice Interface for FeeManager, the central fee management contract in the Blueberry Protocol.\n * @dev FeeManager is responsible for cutting various fees in the protocol and sending them to the treasury.\n */\ninterface IFeeManager {\n    /**\n     * @notice Calculates and deducts the deposit fee when lending\n     *         isolated underlying assets to Blueberry Money Market.\n     * @param token The address of the underlying token for which the deposit fee is to be calculated.\n     * @param amount The gross deposit amount before fees.\n     * @return The net deposit amount after the fee deduction.\n     */\n    function doCutDepositFee(address token, uint256 amount) external returns (uint256);\n\n    /**\n     * @notice Calculates and deducts the withdrawal fee when redeeming\n     *         isolated underlying tokens from Blueberry Money Market.\n     * @param token The address of the underlying token for which the withdrawal fee is to be calculated.\n     * @param amount The gross withdrawal amount before fees.\n     * @return The net withdrawal amount after the fee deduction.\n     */\n    function doCutWithdrawFee(address token, uint256 amount) external returns (uint256);\n\n    /**\n     * @notice Calculates and deducts the performance fee from the\n     *         rewards generated due to the leveraged position.\n     * @param token The address of the reward token for which the reward fee is to be calculated.\n     * @param amount The gross reward amount before fees.\n     * @return The net reward amount after the fee deduction.\n     */\n    function doCutRewardsFee(address token, uint256 amount) external returns (uint256);\n\n    /**\n     * @notice Calculates and deducts the vault withdrawal fee if\n     *         the withdrawal occurs within the specified fee window in the Blueberry Money Market.\n     * @param token The address of the underlying token for which the vault withdrawal fee is to be calculated.\n     * @param amount The gross vault withdrawal amount before fees.\n     * @return The net vault withdrawal amount after the fee deduction.\n     */\n    function doCutVaultWithdrawFee(address token, uint256 amount) external returns (uint256);\n\n    /**\n     * @notice Gets the protocol config contract address.\n     */\n    function getConfig() external view returns (IProtocolConfig);\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/ICoreOracle.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\nimport { IBaseOracle } from \"./IBaseOracle.sol\";\n\n/**\n *  @title ICoreOracle\n *  @notice Interface for the CoreOracle contract which provides price feed data for assets in the Blueberry protocol.\n */\ninterface ICoreOracle is IBaseOracle {\n    /*//////////////////////////////////////////////////////////////////////////\n                                       EVENTS\n    //////////////////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Event emitted when the owner sets a new oracle route for a given token.\n     * @param token The ERC20 token for which the oracle route is set.\n     * @param route The address of the oracle route.\n     */\n    event SetRoute(address indexed token, address route);\n\n    /*//////////////////////////////////////////////////////////////////////////\n                                      FUNCTIONS\n    //////////////////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Check if the given ERC20 token is supported by the oracle.\n     * @param token The ERC20 token to check support for.\n     * @return A boolean indicating whether the token is supported or not.\n     */\n    function isTokenSupported(address token) external view returns (bool);\n\n    /**\n     * @notice Check if the oracle supports the underlying token of a given ERC1155 wrapper.\n     * @dev Only meant to validate wrappers of the Blueberry protocol, such as WERC20.\n     * @param token ERC1155 token address to check support for.\n     * @param tokenId ERC1155 token id to check support for.\n     * @return A boolean indicating whether the wrapped token is supported or not.\n     */\n    function isWrappedTokenSupported(address token, uint256 tokenId) external view returns (bool);\n\n    /**\n     * @notice Returns the USD value of a specific wrapped ERC1155 token.\n     * @param token ERC1155 token address.\n     * @param id ERC1155 token id.\n     * @param amount Amount of the token for which to get the USD value, normalized to 1e18 decimals.\n     * @return The USD value of the given wrapped token amount.\n     */\n    function getWrappedTokenValue(address token, uint256 id, uint256 amount) external view returns (uint256);\n\n    /**\n     * @notice Returns the USD value of a given amount of a specific ERC20 token.\n     * @param token ERC20 token address.\n     * @param amount Amount of the ERC20 token for which to get the USD value.\n     * @return The USD value of the given token amount.\n     */\n    function getTokenValue(address token, uint256 amount) external view returns (uint256);\n\n    /**\n     * @notice Fetches the oracle route for the given token.\n     * @param token Address of the token to get the route for.\n     * @return The address of the oracle route for the given token.\n     */\n    function getRoute(address token) external view returns (address);\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/IBaseOracle.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\n/**\n * @title IBaseOracle\n * @author BlueberryProtocol\n * @notice Interface for a basic oracle that provides price data for assets.\n */\ninterface IBaseOracle {\n    /**\n     * @notice Event emitted when a new LP token is registered within its respective implementation.\n     * @param token Address of the LP token being registered\n     */\n    event RegisterLpToken(address token);\n\n    /**\n     * @notice Fetches the price of the given token in USD with 18 decimals precision.\n     * @param token Address of the ERC-20 token for which the price is requested.\n     * @return The USD price of the given token, multiplied by 10**18.\n     */\n    function getPrice(address token) external view returns (uint256);\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/curve/ICurveAddressProvider.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\n/* solhint-disable func-name-mixedcase */\n\ninterface ICurveAddressProvider {\n    function get_registry() external view returns (address);\n\n    function get_id_info(\n        uint256\n    )\n        external\n        view\n        returns (address addr, bool is_active, uint256 version, uint256 last_modified, string memory description);\n\n    function get_address(uint256 id) external view returns (address);\n}\n"
      },
      "lib/blueberry-core/node_modules/@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155Upgradeable is IERC165Upgradeable {\n    /**\n     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n     */\n    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n    /**\n     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n     * transfers.\n     */\n    event TransferBatch(\n        address indexed operator,\n        address indexed from,\n        address indexed to,\n        uint256[] ids,\n        uint256[] values\n    );\n\n    /**\n     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n     * `approved`.\n     */\n    event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n    /**\n     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n     *\n     * If an {URI} event was emitted for `id`, the standard\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n     * returned by {IERC1155MetadataURI-uri}.\n     */\n    event URI(string value, uint256 indexed id);\n\n    /**\n     * @dev Returns the amount of tokens of token type `id` owned by `account`.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function balanceOf(address account, uint256 id) external view returns (uint256);\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n     *\n     * Requirements:\n     *\n     * - `accounts` and `ids` must have the same length.\n     */\n    function balanceOfBatch(\n        address[] calldata accounts,\n        uint256[] calldata ids\n    ) external view returns (uint256[] memory);\n\n    /**\n     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n     *\n     * Emits an {ApprovalForAll} event.\n     *\n     * Requirements:\n     *\n     * - `operator` cannot be the caller.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n     *\n     * See {setApprovalForAll}.\n     */\n    function isApprovedForAll(address account, address operator) external view returns (bool);\n\n    /**\n     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n     *\n     * Emits a {TransferSingle} event.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n     * - `from` must have a balance of tokens of type `id` of at least `amount`.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n     * acceptance magic value.\n     */\n    function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n     *\n     * Emits a {TransferBatch} event.\n     *\n     * Requirements:\n     *\n     * - `ids` and `amounts` must have the same length.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n     * acceptance magic value.\n     */\n    function safeBatchTransferFrom(\n        address from,\n        address to,\n        uint256[] calldata ids,\n        uint256[] calldata amounts,\n        bytes calldata data\n    ) external;\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/convex/IConvex.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\n\ninterface IConvex is IERC20MetadataUpgradeable {\n    function reductionPerCliff() external view returns (uint256);\n\n    function totalCliffs() external view returns (uint256);\n\n    function maxSupply() external view returns (uint256);\n}\n"
      },
      "lib/blueberry-core/contracts/interfaces/convex/ICvxBooster.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.22;\n\ninterface ICvxBooster {\n    function deposit(uint256 _pid, uint256 _amount, bool _stake) external returns (bool);\n\n    function withdraw(uint256 _pid, uint256 _amount) external returns (bool);\n\n    function withdrawTo(uint256 _pid, uint256 _amount, address _to) external returns (bool);\n\n    function addPool(address _lptoken, address _gauge, uint256 _stashVersion) external returns (bool);\n\n    function forceAddPool(address _lptoken, address _gauge, uint256 _stashVersion) external returns (bool);\n\n    function shutdownPool(uint256 _pid) external returns (bool);\n\n    function poolInfo(\n        uint256\n    )\n        external\n        view\n        returns (address lptoken, address token, address gauge, address crvRewards, address stash, bool shutdown);\n\n    function poolLength() external view returns (uint256);\n\n    function gaugeMap(address) external view returns (bool);\n\n    function setPoolManager(address _poolM) external;\n\n    function shutdownSystem() external;\n\n    function setUsedAddress(address[] memory) external;\n}\n"
      },
      "lib/blueberry-core/contracts/wrapper/escrow/interfaces/IPoolEscrowFactory.sol": {
        "content": "// SPDX-License-Identifier: MIT\n/*\n██████╗ ██╗     ██╗   ██╗███████╗██████╗ ███████╗██████╗ ██████╗ ██╗   ██╗\n██╔══██╗██║     ██║   ██║██╔════╝██╔══██╗██╔════╝██╔══██╗██╔══██╗╚██╗ ██╔╝\n██████╔╝██║     ██║   ██║█████╗  ██████╔╝█████╗  ██████╔╝██████╔╝ ╚████╔╝\n██╔══██╗██║     ██║   ██║██╔══╝  ██╔══██╗██╔══╝  ██╔══██╗██╔══██╗  ╚██╔╝\n██████╔╝███████╗╚██████╔╝███████╗██████╔╝███████╗██║  ██║██║  ██║   ██║\n╚═════╝ ╚══════╝ ╚═════╝ ╚══════╝╚═════╝ ╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝   ╚═╝\n*/\npragma solidity 0.8.22;\n\ninterface IPoolEscrowFactory {\n    /*//////////////////////////////////////////////////////////////////////////\n                                      EVENTS\n    //////////////////////////////////////////////////////////////////////////*/\n    /// @notice Emitted when a new escrow contract is created\n    event EscrowCreated(address);\n\n    /*//////////////////////////////////////////////////////////////////////////\n                                      FUNCTIONS\n    //////////////////////////////////////////////////////////////////////////*/\n    /**\n     * @notice Creates an escrow contract for a given PID\n     * @param _pid The pool id (The first 16-bits)\n     * @param _booster The booster address\n     * @param _rewards The rewards address\n     * @param _lpToken The LP token address\n     */\n    function createEscrow(\n        uint256 _pid,\n        address _booster,\n        address _rewards,\n        address _lpToken\n    ) external payable returns (address _escrow);\n}\n"
      },
      "lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1363.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @title IERC1363\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\n *\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\n */\ninterface IERC1363 is IERC20, IERC165 {\n    /*\n     * Note: the ERC-165 identifier for this interface is 0xb0202a11.\n     * 0xb0202a11 ===\n     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\n     */\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @param data Additional data with no specified format, sent in call to `spender`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error AddressInsufficientBalance(address account);\n\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedInnerCall();\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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert AddressInsufficientBalance(address(this));\n        }\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            revert FailedInnerCall();\n        }\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 or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {FailedInnerCall} error.\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    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\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    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert AddressInsufficientBalance(address(this));\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n     * unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {FailedInnerCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n     */\n    function _revert(bytes memory returndata) 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 FailedInnerCall();\n        }\n    }\n}\n"
      },
      "lib/blueberry-core/node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
      },
      "lib/blueberry-core/node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Interface that must be implemented by smart contracts in order to receive\n * ERC-1155 token transfers.\n */\ninterface IERC1155Receiver is IERC165 {\n    /**\n     * @dev Handles the receipt of a single ERC-1155 token type. This function is\n     * called at the end of a `safeTransferFrom` after the balance has been updated.\n     *\n     * NOTE: To accept the transfer, this must return\n     * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n     * (i.e. 0xf23a6e61, or its own function selector).\n     *\n     * @param operator The address which initiated the transfer (i.e. msg.sender)\n     * @param from The address which previously owned the token\n     * @param id The ID of the token being transferred\n     * @param value The amount of tokens being transferred\n     * @param data Additional data with no specified format\n     * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n     */\n    function onERC1155Received(\n        address operator,\n        address from,\n        uint256 id,\n        uint256 value,\n        bytes calldata data\n    ) external returns (bytes4);\n\n    /**\n     * @dev Handles the receipt of a multiple ERC-1155 token types. This function\n     * is called at the end of a `safeBatchTransferFrom` after the balances have\n     * been updated.\n     *\n     * NOTE: To accept the transfer(s), this must return\n     * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n     * (i.e. 0xbc197c81, or its own function selector).\n     *\n     * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n     * @param from The address which previously owned the token\n     * @param ids An array containing ids of each token being transferred (order and length must match values array)\n     * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n     * @param data Additional data with no specified format\n     * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n     */\n    function onERC1155BatchReceived(\n        address operator,\n        address from,\n        uint256[] calldata ids,\n        uint256[] calldata values,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"
      },
      "lib/blueberry-core/node_modules/@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165Upgradeable {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\n"
      },
      "lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"../utils/introspection/IERC165.sol\";\n"
      },
      "lib/blueberry-core/node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n"
      },
      "lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\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[ERC 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": [
        "@blueberry/=lib/blueberry-core/contracts/",
        "@blueberry-stakevest/=lib/blueberry-stakevest/src/",
        "@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
        "@openzeppelin/contracts-upgradeable/=lib/blueberry-core/node_modules/@openzeppelin/contracts-upgradeable/",
        "src/=src/BlueberryContracts/",
        "openzeppelin-contracts-upgradeable/contracts/=lib/blueberry-stakevest/lib/openzeppelin-contracts-upgradeable/contracts/",
        "solady/=lib/blueberry-stakevest/lib/solady/",
        "@chainlink/=lib/blueberry-core/node_modules/@chainlink/",
        "@aave/=lib/blueberry-core/node_modules/@aave/",
        "@contracts/=lib/blueberry-core/contracts/",
        "@eth-optimism/=lib/blueberry-core/node_modules/@eth-optimism/contracts/",
        "@test/=lib/blueberry-core/test/foundry/",
        "@uniswap/=lib/blueberry-core/node_modules/@uniswap/",
        "base64-sol/=lib/blueberry-core/node_modules/base64-sol/",
        "blueberry-core/=lib/blueberry-core/",
        "blueberry-stakevest/=lib/blueberry-stakevest/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
        "eth-gas-reporter/=lib/blueberry-core/node_modules/eth-gas-reporter/",
        "forge-std/=lib/forge-std/src/",
        "hardhat-deploy/=lib/blueberry-core/node_modules/hardhat-deploy/",
        "hardhat/=lib/blueberry-core/node_modules/hardhat/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/",
        "openzeppelin/=lib/blueberry-stakevest/lib/openzeppelin-contracts-upgradeable/contracts/",
        "solidity-stringutils/=lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/",
        "v3-core/=lib/blueberry-stakevest/lib/v3-core/contracts/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "viaIR": false,
      "libraries": {}
    }
  }}