Boost _ Folks Finance 33947 - [Smart Contract - Low] During liquidations when borrowToRepay collateral the liquidator pays more borrowAmount than they should and receives no bonus
Submitted on Fri Aug 02 2024 09:38:03 GMT-0400 (Atlantic Standard Time) by @iamandreiski for Boost | Folks Finance
Report ID: #33947
Report type: Smart Contract
Report severity: Low
Target: https://testnet.snowtrace.io/address/0xc1FBF54B25816B60ADF322d8A1eaCA37D9A50317
Impacts:
Protocol insolvency
Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield
Description
Brief/Intro
When a user is undercollateralized and eligible for liquidation, a liquidator can initiate a liquidation process in which the borrowed amount(either partial or whole) of the token-in-question + interest will be transferred to the liquidator for later repayment as well as the collateral in the amount of the borrowed token + 10% liquidation bonus. The problem arises when the borrow amount that should be repaid is greater than the collateral amount to-be-received by the liquidator. In those cases, due to invalid calculations, the liquidator will actually receive 10% more borrow amount to repay (or 10% less collateral than the borrow amount), effectively damaging the liquidator.
Vulnerability Details
There are more than one outcome in which this can result:
Violator will pay 10% less collateral for the borrowed amount, effectively "incentivizing" users with underwater loans.
This will disincentivize liquidators to liquidate these kind of loans effectively leading to the accumulation of more bad debt and essentially undercollateralized loans / protocol/pool insolvency.
When a user initiates a liquidation, eventually calcLiquidationAmounts()
will be called in order to calculate the collateral and borrow amounts based on amounts owed, user input, etc.
First the repayBorrowAmount
will be calculated based on the following "formula":
It will take the smaller amount between a user-input value of the amount that they'd want to liquidate OR either the balance of the loan OR the maxRepayBorrowAmount (which is a calculation based upon the amount that needs to be liquidated to make the loan healthy).
For the sake of this situation let's say that the violatorLoanBorrow.balance
was picked as the "smallest" to be liquidated, which is the total balance of the loan of that pool.
After the above-mentioned amount was determined, it will be converted to its equivalent collateral value:
For the sake of this example, let's say that the borrowed amount to be repaid is 1 WETH, and the collateral is USDC, with the WETH/USDC price at 3000 USDC.
In underlying collateral amount, this would be 3300 USDC (Taking in consideration the liquidation bonus(if it's 10%)).
The problem arises if the collateral that the user has in the pool is less than this, let's say 2500 USDC.
The following will occur:
The seizeUnderlyingCollateralAmount
will be the violatorUnderlingCollateralBalance
which is the underlying amount OR 2500 USDC.
But when the repayBorrowAmount
is calculated in order to determine how much of the borrow amount should the liquidator repay:
This would result in converting 2500 USDC to WETH, or 0.83 WETH, the problem is that the liquidation bonus would be added to this value:
This would cause the liquidator to receive only 2500 USDC collateral, but pay the equivalent of 2750 USDC in borrow amount, due to the incorrect calculation.
It should be : assetAmount * 1e4 / (1e4 + liquidationBonus)
Even if liquidators intentionally input lower-than-collateral maxAmountToRepay
values, after some time this will also result in bad debt accumulation as the collateral would be transferred to liquidators, but there would be "residual" borrow amounts.
Impact Details
Loans in which the collateral is less than the amount-to-be-repayed will result in the liquidator paying 10% more borrowAmount, while receiving 10% less collateral amount. This is effectively damaging the liquidator in the benefit of the borrower, and could potentially lead to a pool insolvency if enough bad debt is accumulated.
References
Below PoC is in Foundry, the only thing needed to run it is the importation of MathUtils in the test suite.