Incorrect liquidation process will make liquidations impossible to repay and protocol take the amount that is intended for repaying debt instead of penalty amount
Audit: 2024-07-loopfi-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-07-loopfi/blame/57871f64bdea450c1f04c9a53dc1a78223719164/src/CDPVault.sol#L509


# Vulnerability details

## Impact
Incorrect liquidation process will make liquidations impossible to repay and protocol take the amount that is intended for repaying debt instead of penalty amount and potential collateral loss of the liquidatable position.

## Proof of Concept
The liquidation happens when user position become unhealthy. In simple terms the protocol implements liquidation penalty when liquidating users and to stop profitable self liquidations. The collateral is sent to liquidator and the penalty goes to the protocol.
The issue arise how `penalty` and `deltaDebt` are implemented in the function.

For the sake of simplicity I will use the following amounts:
repayAmount = 100
liquidationPenalty = 0.1 (10%)
WAD = 1

The function calculate penalty amount as follows:
```js
uint256 deltaDebt = wmul(repayAmount, liqConfig_.liquidationPenalty);
```
Which will make the `deltaDebt` = 10 (100 * 0.1 = 10).

Then the remaining amount after penalty is calculated as follows:
```js
uint256 penalty = wmul(repayAmount, WAD - liqConfig_.liquidationPenalty);
```
Which will make the `penalty` = 90 (100 * (1 - 0.1) = 100 * 0.9 = 90).

First issue arise when transferring the repay amount from the liquidator to the vault:
```js
        // transfer the repay amount from the liquidator to the vault
        poolUnderlying.safeTransferFrom(msg.sender, address(pool), repayAmount - penalty);
```
Using the example above only the amount that is meant as a penalty would be transfered, not the amount that is intended to repay the debt, because `repayAmount - penalty = 10 ` (100 - 90 = 10)

The second issue arise in the following comparation:
```js
       if (deltaDebt == maxRepayment) {
```
It compare the liquidation penalty amount which is 10 in our example (`deltaDebt` = 10, the 10% of the repay amount) with the total debt because maxRepayment represent the whole debt amount as we can see here:
```js
        uint256 maxRepayment = calcTotalDebt(debtData); // debt + accruetInterest
```
This will make liquidations in full impossible.

And finally the last issue lies here:
```js
        // Mint the penalty from the vault to the treasury
        poolUnderlying.safeTransferFrom(msg.sender, address(pool), penalty);
        IPoolV3Loop(address(pool)).mintProfit(penalty);
```
This is intended to sent the penalty amount to the treasury and not the amount that is intended for repaying debt, because as we saw above in the example `penalty` = 90 which is the amount intended for repaying debt not the penalty amount that should go to the protocol treasury.
This will make the liquidations impossible and the position data incorrect, but it can still send the whole collateral to the liquidator as we can see here:
```js
uint256 takeCollateral = wdiv(repayAmount, discountedPrice);
.
.
.
        // transfer the collateral amount from the vault to the