Lucene search

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

liquidator will always take what is left of borrowers premium

2023-12-2100:00:00
Code4rena
github.com
6
liquidator
borrower premium
position close
manipulation
swap
refund
slippage protection
mev

7 High

AI Score

Confidence

Low

Lines of code
<https://github.com/code-423n4/2023-12-particle/blob/main/contracts/protocol/ParticlePositionManager.sol#L415-L420&gt;

Vulnerability details

Impact

A liquidator can manipulate the pool they are swapping in to take any potential left over premium from the borrower.

Proof of Concept

When liquidating a position the liquidator essentially closes the position on behalf of the borrower for a liquidation reward.

When closing a position the token held by the borrower is potentially traded back to cover the debt to the liquidity provider:

ParticlePositionManager::_closePosition#L399-L406:

File: contracts/protocol/ParticlePositionManager.sol

399:        (cache.amountSpent, cache.amountReceived) = Base.swap(
400:            cache.tokenFrom,
401:            cache.tokenTo,
402:            params.amountSwap,
403:            0, /// @dev we check cache.amountReceived is sufficient to repay LP in below
404:            DEX_AGGREGATOR,
405:            params.data
406:        );

Then these amounts are used to check that the amount swapped will cover repaying the lender:

ParticlePositionManager::_closePosition#L415-L420:

File: contracts/protocol/ParticlePositionManager.sol

415:        if (
416:            cache.amountFromAdd &gt; cache.collateralFrom + cache.tokenFromPremium - cache.amountSpent ||
417:            cache.amountToAdd &gt; cache.amountReceived + cache.tokenToPremium
418:        ) {
419:            revert Errors.InsufficientRepay();
420:        }

Where amountTo/FromAdd is the amounts needed to repay the liquidity borrowed from the liquidity provider.

The issue here is that there can be tokenFrom/ToPremium left. The liquidation requirement is that only one of the sides needs to be under water. These leftovers will however be taken in the swap. The liquidator can manipulate the pool being swapped in such that amountSpent and amountReceived uses all the premium from the borrower.

This would have otherwise been returned to the borrower in the refunds at the end of _closePosition.

Tools Used

Manual audit

Recommended Mitigation Steps

Consider if this is a feature or not.

If it is intended behavior for the liquidator to take what is left of the borrowers premium, consider refunding the liquidator instead of borrower in case of liquidation.

If this is not a feature and the borrower is entitled to whatever premium they have left, consider enforcing better slippage protection on the swap in _closePosition.

Assessed type

MEV


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

All reactions

7 High

AI Score

Confidence

Low