Vulnerability: ConvexSpell/CurveSpell.openPositionFarm will revert in some cases
Severity: medium

Description:
The fix for this issue from this contest is as following:\\n```\\nFile: blueberry-core\\contracts\\spell\\CurveSpell.sol\\n        // 2. Borrow specific amounts\\n        uint256 borrowBalance = _doBorrow(\\n            param.borrowToken,\\n            param.borrowAmount\\n        );\\n\\n        // 3. Add liquidity on curve\\n        address borrowToken = param.borrowToken;\\n        _ensureApprove(param.borrowToken, pool, borrowBalance);\\n        if (tokens.length == 2) {\\n            uint256[2] memory suppliedAmts;\\n            for (uint256 i = 0; i < 2; i++) {\\n                     //this 'if' check is the fix from the previous contest\\n110:->               if (tokens[i] == borrowToken) {\\n                    suppliedAmts[i] = IERC20Upgradeable(tokens[i]).balanceOf(\\n                        address(this)\\n                    );\\n                    break;\\n                }\\n            }\\n            ICurvePool(pool).add_liquidity(suppliedAmts, minLPMint);\\n        } else if (tokens.length == 3) {\\n```\\n\\nThe key to this issue is that `borrowBalance` may be smaller than `IERC20Upgradeable(borrowToken).balanceOf(address(this))`. For simplicity, assume that CurveSpell supports an lptoken which contains two tokens : A and B.\\nBob transferred 1wei of A and B to the CurveSpell contract. Alice opens a position by calling `BlueBerryBank#execute`, and the flow is as follows:\\nenter `CurveSpell#openPositionFarm`.\\ncall `_doLend` to deposit isolated collaterals.\\ncall `_doBorrow` to borrow 100e18 A token. borrowBalance = 100e18.\\n`A.approve(pool, 100e18)`.\\n`suppliedAmts[0] = A.balance(address(this)) = 100e18+1wei`, `suppliedAmts[1] = 0`.\\ncall `ICurvePool(pool).add_liquidity(suppliedAmts, minLPMint)`, then revert because the approved amount is not enough.\\nTherefore, no one can successfully open a position.\\nOf course, bob can also transfer 1wei of `borrowToken` to contract by front-running `openPositionFarm` for a specific user or all users.

Impact:
`ConvexSpell/CurveSpell.openPositionFarm` will revert due to this issue.

Recommended mitigation:
The following fix is for CurveSpell, but please don't forget ConvexSpell.\\nTwo ways for fix it:\\n```\\n--- a/blueberry-core/contracts/spell/CurveSpell.sol\\n+++ b/blueberry-core/contracts/spell/CurveSpell.sol\\n@@ -108,9 +108,7 @@ contract CurveSpell is BasicSpell {\\n             uint256[2] memory suppliedAmts;\\n             for (uint256 i = 0; i < 2; i++) {\\n                 if (tokens[i] == borrowToken) {\\n-                    suppliedAmts[i] = IERC20Upgradeable(tokens[i]).balanceOf(\\n-                        address(this)\\n-                    );\\n+                    suppliedAmts[i] = borrowBalance;\\n                     break;\\n                 }\\n             }\\n@@ -119,9 +117,7 @@ contract CurveSpell is BasicSpell {\\n             uint256[3] memory suppliedAmts;\\n             for (uint256 i = 0; i < 3; i++) {\\n                 if (tokens[i] == borrowToken) {\\n-                    suppliedAmts[i] = IERC20Upgradeable(tokens[i]).balanceOf(\\n-                        address(this)\\n-                    );\\n+                    suppliedAmts[i] = borrowBalance;\\n                     break;\\n                 }\\n             }\\n@@ -130,9 +126,7 @@ contract CurveSpell is BasicSpell {\\n             uint256[4] memory suppliedAmts;\\n             for (uint256 i = 0; i < 4; i++) {\\n                 if (tokens[i] == borrowToken) {\\n-                    suppliedAmts[i] = IERC20Upgradeable(tokens[i]).balanceOf(\\n-                        address(this)\\n-                    );\\n+                    suppliedAmts[i] = borrowBalance;\\n                     break;\\n                 }\\n             }\\n```\\n\\n```\\n--- a/blueberry-core/contracts/spell/CurveSpell.sol\\n+++ b/blueberry-core/contracts/spell/CurveSpell.sol\\n@@ -103,7 +103,8 @@ contract CurveSpell is BasicSpell {\\n\\n         // 3. Add liquidity on curve\\n         address borrowToken = param.borrowToken;\\n-        _ensureApprove(param.borrowToken, pool, borrowBalance);\\n+        require(borrowBalance <= IERC20Upgradeable(borrowToken).balanceOf(address(this)), "impossible");\\n+        _ensureApprove(param.borrowToken, pool, IERC20Upgradeable(borrowToken).balanceOf(address(this)));\\n         if (tokens.length == 2) {\\n             uint256[2] memory suppliedAmts;\\n             for (uint256 i = 0; i < 2; i++) {\\n```\\n