Bad debt liquidation doesn't allow liquidator to receive its ETH bonus (ante)
More detailed scenario\\nAlice account goes into bad debt for whatever reason. For example, the account has 150 DAI borrowed, but only 100 DAI assets.\\nBob tries to `liquidate` Alice account, but his transaction reverts, because remaining DAI liability after repaying 100 DAI assets Alice has, will be 50 DAI bad debt. `liquidate` code will try to call Bob's callee contract to swap 0.03 WETH to 50 DAI sending it 0.03 WETH. However, since Alice account has 0 WETH, the transfer will revert.\\nBob tries to work around the liquidation problem: 3.1. Bob calls `liquidate` with `strain` set to `type(uint256).max`. Liquidation succeeds, but Bob doesn't receive anything for his liquidation (he receives 0 ETH bonus). Alice's ante is stuck in the contract until Alice bad debt is fully repaid. 3.2. Bob sends 0.03 WETH directly to Alice account and calls `liquidate` normally. It succeeds and Bob gets his bonus for liquidation (0.01 ETH). He has 0.02 ETH net loss from liquidaiton (in addition to gas fees).\\nIn both cases there is no incentive for Bob to liquidate Alice. So it's likely Alice account won't be liquidated and a borrow of 150 will be stuck in Alice account for a long time. Some lender depositors who can't withdraw might still have incentive to liquidate Alice to be able to withdraw from lender, but Alice's ante will still be stuck in the contract.\\nThe scenario above is demonstrated in the test, add it to test/Liquidator.t.sol:\\n```\\n    function test_badDebtLiquidationAnte() public {\\n\\n        // malicious user borrows at max leverage + some safety margin\\n        uint256 margin0 = 1e18;\\n        uint256 borrows0 = 100e18;\\n\\n        deal(address(asset0), address(account), margin0);\\n\\n        bytes memory data = abi.encode(Action.BORROW, borrows0, 0);\\n        account.modify(this, data, (1 << 32));\\n\\n        // borrow increased by 50%\\n        _setInterest(lender0, 15000);\\n\\n        emit log_named_uint("User borrow:", lender0.borrowBalance(address(account)));\\n        emit log_named_uint("User assets:", asset0.balanceOf(address(account)));\\n\\n        // warn account\\n        account.warn((1 << 32));\\n\\n        // skip warning time\\n        skip(LIQUIDATION_GRACE_PERIOD);\\n        lender0.accrueInterest();\\n\\n        // liquidation reverts because it requires asset the account doesn't have to swap\\n        vm.expectRevert();\\n        account.liquidate(this, bytes(""), 1, (1 << 32));\\n\\n        // liquidate with max strain to avoid revert when trying to swap assets account doesn't have\\n        account.liquidate(this, bytes(""), type(uint256).max, (1 << 32));\\n\\n        emit log_named_uint("Liquidated User borrow:", lender0.borrowBalance(address(account)));\\n        emit log_named_uint("Liquidated User assets:", asset0.balanceOf(address(account)));\\n        emit log_named_uint("Liquidated User ante:", address(account).balance);\\n    }\\n```\\n\\nExecution console log:\\n```\\n  User borrow:: 150000000000000000000\\n  User assets:: 101000000000000000000\\n  Liquidated User borrow:: 49000000162000000001\\n  Liquidated User assets:: 0\\n  Liquidated User ante:: 10000000000000001\\n```\\n
Consider verifying the bad debt situation and not forcing swap which will fail, so that liquidation can repay whatever assets account still has and give liquidator its full bonus.
Liquidators are not compensated for bad debt liquidations in some cases. Ante (liquidator bonus) is stuck in the borrower smart contract until bad debt is repaid. There is not enough incentive to liquidate such bad debt accounts, which can lead for these accounts to accumulate even bigger bad debt and lender depositors being unable to withdraw their funds from lender.
```\\n    function test_badDebtLiquidationAnte() public {\\n\\n        // malicious user borrows at max leverage + some safety margin\\n        uint256 margin0 = 1e18;\\n        uint256 borrows0 = 100e18;\\n\\n        deal(address(asset0), address(account), margin0);\\n\\n        bytes memory data = abi.encode(Action.BORROW, borrows0, 0);\\n        account.modify(this, data, (1 << 32));\\n\\n        // borrow increased by 50%\\n        _setInterest(lender0, 15000);\\n\\n        emit log_named_uint("User borrow:", lender0.borrowBalance(address(account)));\\n        emit log_named_uint("User assets:", asset0.balanceOf(address(account)));\\n\\n        // warn account\\n        account.warn((1 << 32));\\n\\n        // skip warning time\\n        skip(LIQUIDATION_GRACE_PERIOD);\\n        lender0.accrueInterest();\\n\\n        // liquidation reverts because it requires asset the account doesn't have to swap\\n        vm.expectRevert();\\n        account.liquidate(this, bytes(""), 1, (1 << 32));\\n\\n        // liquidate with max strain to avoid revert when trying to swap assets account doesn't have\\n        account.liquidate(this, bytes(""), type(uint256).max, (1 << 32));\\n\\n        emit log_named_uint("Liquidated User borrow:", lender0.borrowBalance(address(account)));\\n        emit log_named_uint("Liquidated User assets:", asset0.balanceOf(address(account)));\\n        emit log_named_uint("Liquidated User ante:", address(account).balance);\\n    }\\n```\\n