Long traders unable to withdraw their assets
Whenever the protocol reaches a state where the long trader's profit is larger than LP's stable collateral total, the protocol will be bricked. As a result, the margin deposited and gain of the long traders can no longer be withdrawn and the LPs cannot withdraw their collateral, leading to a loss of assets for the users.\\nPer Line 97 below, if the collateral balance is less than the tracked balance, the `_getCollateralNet` invariant check will revert.\\n```\\nFile: InvariantChecks.sol\\n    /// @dev Returns the difference between actual total collateral balance in the vault vs tracked collateral\\n    ///      Tracked collateral should be updated when depositing to stable LP (stableCollateralTotal) or\\n    ///      opening leveraged positions (marginDepositedTotal).\\n    /// TODO: Account for margin of error due to rounding.\\n    function _getCollateralNet(IFlatcoinVault vault) private view returns (uint256 netCollateral) {\\n        uint256 collateralBalance = vault.collateral().balanceOf(address(vault));\\n        uint256 trackedCollateral = vault.stableCollateralTotal() + vault.getGlobalPositions().marginDepositedTotal;\\n\\n        if (collateralBalance < trackedCollateral) revert FlatcoinErrors.InvariantViolation("collateralNet");\\n\\n        return collateralBalance - trackedCollateral;\\n    }\\n```\\n\\nAssume that:\\nBob's long position: Margin = 50 ETH\\nAlice's LP: Deposited = 50 ETH\\nCollateral Balance = 100 ETH\\nTracked Balance = 100 ETH (Stable Collateral Total = 50 ETH, Margin Deposited Total = 50 ETH)\\nAssume that Bob's long position gains a profit of 51 ETH.\\nThe following actions will trigger the `updateGlobalPositionData` function internally: executeOpen, executeAdjust, executeClose, and liquidation.\\nWhen the `FlatcoinVault.updateGlobalPositionData` function is triggered to update the global position data:\\n```\\nprofitLossTotal = 51 ETH (gain by long)\\n\\nnewMarginDepositedTotal = marginDepositedTotal + marginDelta + profitLossTotal\\nnewMarginDepositedTotal = 50 ETH + 0 + 51 ETH = 101 ETH\\n\\n_updateStableCollateralTotal(-51 ETH)\\nnewStableCollateralTotal = stableCollateralTotal + _stableCollateralAdjustment\\nnewStableCollateralTotal = 50 ETH + (-51 ETH) = -1 ETH\\nstableCollateralTotal = (newStableCollateralTotal > 0) ? newStableCollateralTotal : 0;\\nstableCollateralTotal = 0\\n```\\n\\nIn this case, the state becomes as follows:\\nCollateral Balance = 100 ETH\\nTracked Balance = 101 ETH (Stable Collateral Total = 0 ETH, Margin Deposited Total = 101 ETH)\\nNotice that the Collateral Balance and Tracked Balance are no longer in sync. As such, the revert will occur when the `_getCollateralNet` invariant checks are performed.\\nWhenever the protocol reaches a state where the long trader's profit is larger than LP's stable collateral total, this issue will occur, and the protocol will be bricked. The margin deposited and gain of the long traders can no longer be withdrawn from the protocol. The LPs also cannot withdraw their collateral.\\nThe reason is that the `_getCollateralNet` invariant checks are performed in all functions of the protocol that can be accessed by users (listed below):\\nDeposit\\nWithdraw\\nOpen Position\\nAdjust Position\\nClose Position\\nLiquidate
Currently, when the loss of the LP is more than the existing `stableCollateralTotal`, the loss will be capped at zero, and it will not go negative. In the above example, the `stableCollateralTotal` is 50, and the loss is 51. Thus, the `stableCollateralTotal` is set to zero instead of -1.\\nThe loss of LP and the gain of the trader should be aligned or symmetric. However, this is not the case in the current implementation. In the above example, the gain of traders is 51, while the loss of LP is 50, which results in a discrepancy here.\\nTo fix the issue, the loss of LP and the gain of the trader should be aligned. For instance, in the above example, if the loss of LP is capped at 50, then the profit of traders must also be capped at 50.\\nFollowing is a high-level logic of the fix:\\n```\\nIf (profitLossTotal > stableCollateralTotal): // (51 > 50) => True\\n profitLossTotal = stableCollateralTotal // profitLossTotal = 50\\n \\nnewMarginDepositedTotal = marginDepositedTotal + marginDelta + profitLossTotal // 50 + 0 + 50 = 100\\n \\nnewStableCollateralTotal = stableCollateralTotal + (-profitLossTotal) // 50 + (-50) = 0\\nstableCollateralTotal = (newStableCollateralTotal > 0) ? newStableCollateralTotal : 0; // stableCollateralTotal = 0\\n```\\n\\nThe comment above verifies that the logic is working as intended.
Loss of assets for the users. Since the protocol is bricked due to revert, the long traders are unable to withdraw their deposited margin and gain and the LPs cannot withdraw their collateral.
```\\nFile: InvariantChecks.sol\\n    /// @dev Returns the difference between actual total collateral balance in the vault vs tracked collateral\\n    ///      Tracked collateral should be updated when depositing to stable LP (stableCollateralTotal) or\\n    ///      opening leveraged positions (marginDepositedTotal).\\n    /// TODO: Account for margin of error due to rounding.\\n    function _getCollateralNet(IFlatcoinVault vault) private view returns (uint256 netCollateral) {\\n        uint256 collateralBalance = vault.collateral().balanceOf(address(vault));\\n        uint256 trackedCollateral = vault.stableCollateralTotal() + vault.getGlobalPositions().marginDepositedTotal;\\n\\n        if (collateralBalance < trackedCollateral) revert FlatcoinErrors.InvariantViolation("collateralNet");\\n\\n        return collateralBalance - trackedCollateral;\\n    }\\n```\\n