Fees are ignored when checks skew max in Stable Withdrawal / Leverage Open / Leverage Adjust
Fees are ignored when checks skew max in Stable Withdrawal / Leverage Open / Leverage Adjust.\\nWhen user withdrawal from the stable LP, vault total stable collateral is updated:\\n```\\n        vault.updateStableCollateralTotal(-int256(_amountOut));\\n```\\n\\nThen _withdrawFee is calculated and checkSkewMax(...) function is called to ensure that the system will not be too skewed towards longs:\\n```\\n            // Apply the withdraw fee if it's not the final withdrawal.\\n            _withdrawFee = (stableWithdrawFee * _amountOut) / 1e18;\\n\\n            // additionalSkew = 0 because withdrawal was already processed above.\\n            vault.checkSkewMax({additionalSkew: 0});\\n```\\n\\nAt the end of the execution, vault collateral is settled again with withdrawFee, keeper receives keeperFee and `(amountOut - totalFee)` amount of collaterals are transferred to the user:\\n```\\n        // include the fees here to check for slippage\\n        amountOut -= totalFee;\\n\\n        if (amountOut < stableWithdraw.minAmountOut)\\n            revert FlatcoinErrors.HighSlippage(amountOut, stableWithdraw.minAmountOut);\\n\\n        // Settle the collateral\\n        vault.updateStableCollateralTotal(int256(withdrawFee)); // pay the withdrawal fee to stable LPs\\n        vault.sendCollateral({to: msg.sender, amount: order.keeperFee}); // pay the keeper their fee\\n        vault.sendCollateral({to: account, amount: amountOut}); // transfer remaining amount to the trader\\n```\\n\\nThe `totalFee` is composed of keeper fee and withdrawal fee:\\n```\\n        uint256 totalFee = order.keeperFee + withdrawFee;\\n```\\n\\nThis means withdrawal fee is still in the vault, however this fee is ignored when checks skew max and protocol may revert on a safe withdrawal. Consider the following scenario:\\nskewFractionMax is `120%` and stableWithdrawFee is 1%;\\nAlice deposits `100` collateral and Bob opens a leverage position with size 100;\\nAt the moment, there is `100` collaterals in the Vault, skew is `0` and skew fraction is 100%;\\nAlice tries to withdraw `16.8` collaterals, withdrawFee is `0.168`, after withdrawal, it is expected that there is `83.368` stable collaterals in the Vault, so skewFraction should be `119.5%`, which is less than skewFractionMax;\\nHowever, the withdrawal will actually fail because when protocol checks skew max, withdrawFee is ignored and the skewFraction turns out to be `120.19%`, which is higher than skewFractionMax.\\nThe same issue may occur when protocol executes a leverage open and leverage adjust, in both executions, tradeFee is ignored when checks skew max.\\nPlease see the test codes:\\n```\\n    function test_audit_withdraw_fee_ignored_when_checks_skew_max() public {\\n        // skewFractionMax is 120%\\n        uint256 skewFractionMax = vaultProxy.skewFractionMax();\\n        assertEq(skewFractionMax, 120e16);\\n\\n        // withdraw fee is 1%\\n        vm.prank(vaultProxy.owner());\\n        stableModProxy.setStableWithdrawFee(1e16);\\n\\n        uint256 collateralPrice = 1000e8;\\n\\n        uint256 depositAmount = 100e18;\\n        announceAndExecuteDeposit({\\n            traderAccount: alice,\\n            keeperAccount: keeper,\\n            depositAmount: depositAmount,\\n            oraclePrice: collateralPrice,\\n            keeperFeeAmount: 0\\n        });\\n\\n        uint256 additionalSize = 100e18;\\n        announceAndExecuteLeverageOpen({\\n            traderAccount: bob,\\n            keeperAccount: keeper,\\n            margin: 50e18,\\n            additionalSize: 100e18,\\n            oraclePrice: collateralPrice,\\n            keeperFeeAmount: 0\\n        });\\n\\n        // After leverage Open, skew is 0\\n        int256 skewAfterLeverageOpen = vaultProxy.getCurrentSkew();\\n        assertEq(skewAfterLeverageOpen, 0);\\n        // skew fraction is 100%\\n        uint256 skewFractionAfterLeverageOpen = getLongSkewFraction();\\n        assertEq(skewFractionAfterLeverageOpen, 1e18);\\n\\n        // Note: comment out `vault.checkSkewMax({additionalSkew: 0})` and below lines to see the actual skew fraction\\n        // Alice withdraws 16.8 collateral\\n        // uint256 aliceLpBalance = stableModProxy.balanceOf(alice);\\n        // announceAndExecuteWithdraw({\\n        //     traderAccount: alice, \\n        //     keeperAccount: keeper, \\n        //     withdrawAmount: 168e17, \\n        //     oraclePrice: collateralPrice, \\n        //     keeperFeeAmount: 0\\n        // });\\n\\n        // // After withdrawal, the actual skew fraction is 119.9%, less than skewFractionMax\\n        // uint256 skewFactionAfterWithdrawal = getLongSkewFraction();\\n        // assertEq(skewFactionAfterWithdrawal, 1199501007580846367);\\n\\n        // console2.log(WETH.balanceOf(address(vaultProxy)));\\n    }\\n```\\n
Include withdrawal fee / trade fee when check skew max.
Protocol may wrongly prevent a Stable Withdrawal / Leverage Open / Leverage Adjust even if the execution is essentially safe.
```\\n        vault.updateStableCollateralTotal(-int256(_amountOut));\\n```\\n