Lucene search

K
code423n4Code4renaCODE423N4:2023-12-PARTICLE-FINDINGS-ISSUES-30
HistoryDec 21, 2023 - 12:00 a.m.

In some pools, borrowers can maliciously prevent liquidatePosition()

2023-12-2100:00:00
Code4rena
github.com
6
vulnerability
liquidateposition
malicious borrowers
prevention
manipulation
liquidation
rewards
mitigation
conditions
transfer
quantity
erc20

AI Score

7.4

Confidence

Low

Lines of code

Vulnerability details

Vulnerability details

in liquidatePosition()

At the end of the liquidation, the liquidation fee will be transferred to the liquidator.

    function liquidatePosition(
        DataStruct.ClosePositionParams calldata params,
        address borrower
    ) external override nonReentrant {
...

        liquidateCache.liquidationRewardFrom =
            ((closeCache.tokenFromPremium) * LIQUIDATION_REWARD_FACTOR) /
            uint128(Base.BASIS_POINT);
        liquidateCache.liquidationRewardTo =
            ((closeCache.tokenToPremium) * LIQUIDATION_REWARD_FACTOR) /
            uint128(Base.BASIS_POINT);
        closeCache.tokenFromPremium -= liquidateCache.liquidationRewardFrom;
        closeCache.tokenToPremium -= liquidateCache.liquidationRewardTo;

        delete liens[lienKey];

        // execute actual position closing
        _closePosition(params, closeCache, lien, borrower);

        // reward liquidator
@>      TransferHelper.safeTransfer(closeCache.tokenFrom, msg.sender, liquidateCache.liquidationRewardFrom);
@>      TransferHelper.safeTransfer(closeCache.tokenTo, msg.sender, liquidateCache.liquidationRewardTo);

        emit LiquidatePosition(borrower, lien.tokenId, closeCache.amountFromAdd, closeCache.amountToAdd);
    }

The problem with the above code is that when transferring to the liquidator, it does not judge whether liquidationRewardFrom/ liquidationRewardTo is greater than 0.

Some tokens will revert when the transfer quantity is 0 (e.g. LEND).

<https://github.com/d-xo/weird-erc20/?tab=readme-ov-file#revert-on-zero-value-transfers&gt;

In this way, a malicious borrower can deliberately keep token0PremiumPortion/token1PremiumPortion at 0 or very small amount
when openPosition(), causing liquidationRewardFrom/ liquidationRewardTo to always be 0, causing this method liquidatePosition() to always fail and cannot be executed.

Impact

When the transfer quantity of some tokens is 0, it will revert.
In pools that include such tokens, malicious borrowers can control tokenPremiumPortion==0 to prevent forced liquidation.

Recommended Mitigation

    function liquidatePosition(
        DataStruct.ClosePositionParams calldata params,
        address borrower
    ) external override nonReentrant {

+     if (liquidateCache.liquidationRewardFrom&gt;0){
        TransferHelper.safeTransfer(closeCache.tokenFrom, msg.sender, liquidateCache.liquidationRewardFrom);
+     }
+     if (liquidateCache.liquidationRewardTo&gt;0){
        TransferHelper.safeTransfer(closeCache.tokenTo, msg.sender, liquidateCache.liquidationRewardTo);
+      }
        emit LiquidatePosition(borrower, lien.tokenId, closeCache.amountFromAdd, closeCache.amountToAdd);
    }

Assessed type

ERC20


The text was updated successfully, but these errors were encountered:

All reactions

AI Score

7.4

Confidence

Low