Lines of code
<https://github.com/code-423n4/2023-12-particle/blob/main/contracts/protocol/ParticlePositionManager.sol#L415-L420>
A liquidator can manipulate the pool they are swapping in to take any potential left over premium from the borrower.
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 > cache.collateralFrom + cache.tokenFromPremium - cache.amountSpent ||
417: cache.amountToAdd > 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.
Manual audit
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.
MEV
The text was updated successfully, but these errors were encountered:
All reactions