Primary liquidation fee distribution may revert due to the inability to cover the caller fees
Fee distribution during the primary short liquidation may revert due to an arithmetic underflow error in case the TAPP's escrowed ETH balance is insufficient to cover the caller (liquidator) fees.\\nDuring the primary liquidation, the `_marginFeeHandler` function called in line 126 handles the fee distribution for the liquidator (i.e., caller).\\nIf the eligible caller fee (callerFee) is less or equal to the ETH escrowed by the TAPP, the fee is deducted from `TAPP.ethEscrowed` and added to the liquidators escrowed ETH balance, `VaultUser.ethEscrowed`, in lines 271-274.\\nOtherwise, if the TAPP's escrowed ETH is insufficient to cover the caller fees, i.e., the `else` branch in line 274, the caller is given the `tappFee` instead of `gasFee`.\\nHowever, if `m.totalFee` exceeds the TAPP's `ethEscrowed`, it reverts with an arithmetic underflow error in line 278. This can be the case if the TAPP has little to no ETH escrowed after placing the forced bid as part of the liquidation, attempting to buy the debt token amount required to repay the short position's debt. In case the short's collateral is not sufficient to buy the debt tokens, the TAPP's escrowed ETH is utilized as well, potentially depleting the TAPP's escrowed ETH.\\nConsequently, the remaining `TAPP.ethEscrowed` is potentially lower than the calculated `m.totalFee`, resulting in the arithmetic underflow error in line 278.\\ncontracts/facets/MarginCallPrimaryFacet.sol#L278\\n```\\nfunction _marginFeeHandler(MTypes.MarginCallPrimary memory m) private {\\n    STypes.VaultUser storage VaultUser = s.vaultUser[m.vault][msg.sender];\\n    STypes.VaultUser storage TAPP = s.vaultUser[m.vault][address(this)];\\n    // distribute fees to TAPP and caller\\n    uint88 tappFee = m.ethFilled.mulU88(m.tappFeePct);\\n    uint88 callerFee = m.ethFilled.mulU88(m.callerFeePct) + m.gasFee;\\n    m.totalFee += tappFee + callerFee;\\n    //@dev TAPP already received the gasFee for being the forcedBid caller. tappFee nets out.\\n    if (TAPP.ethEscrowed >= callerFee) {\\n        TAPP.ethEscrowed -= callerFee;\\n        VaultUser.ethEscrowed += callerFee;\\n    } else {\\n        // Give caller (portion of?) tappFee instead of gasFee\\n        VaultUser.ethEscrowed += callerFee - m.gasFee + tappFee;\\n        m.totalFee -= m.gasFee;\\n❌      TAPP.ethEscrowed -= m.totalFee;\\n    }\\n}\\n```\\n
Primary liquidation fee distribution may revert due to the inability to cover the caller fees\\nConsider checking if the TAPP's `ethEscrowed` is sufficient to cover the `m.totalFee` before deducting the fee from the TAPP's `ethEscrowed` balance and if not, give the caller the TAPP's `ethEscrowed` balance.
The primary short liquidation fails, requiring to wait until the short position's collateral is sufficient to buy the debt tokens or the TAPP has sufficient collateral, or, if the short's collateral ratio further decreases, the short position is liquidated via the secondary liquidation (which adds additional risk to the peg of the asset as the overall collateral ratio could fall below 100%).
```\\nfunction _marginFeeHandler(MTypes.MarginCallPrimary memory m) private {\\n    STypes.VaultUser storage VaultUser = s.vaultUser[m.vault][msg.sender];\\n    STypes.VaultUser storage TAPP = s.vaultUser[m.vault][address(this)];\\n    // distribute fees to TAPP and caller\\n    uint88 tappFee = m.ethFilled.mulU88(m.tappFeePct);\\n    uint88 callerFee = m.ethFilled.mulU88(m.callerFeePct) + m.gasFee;\\n    m.totalFee += tappFee + callerFee;\\n    //@dev TAPP already received the gasFee for being the forcedBid caller. tappFee nets out.\\n    if (TAPP.ethEscrowed >= callerFee) {\\n        TAPP.ethEscrowed -= callerFee;\\n        VaultUser.ethEscrowed += callerFee;\\n    } else {\\n        // Give caller (portion of?) tappFee instead of gasFee\\n        VaultUser.ethEscrowed += callerFee - m.gasFee + tappFee;\\n        m.totalFee -= m.gasFee;\\n❌      TAPP.ethEscrowed -= m.totalFee;\\n    }\\n}\\n```\\n