Lucene search

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

position can be opened without premium

2023-12-2100:00:00
Code4rena
github.com
2
vulnerability details
premium usage
liquidation reward
borrower supply
incentive removal
liquidation incentives
minimum premium
mitigation steps
manual audit

7 High

AI Score

Confidence

Low

Lines of code

Vulnerability details

Description

Premium in ParticlePositionManager is used to cover trading fees accrued for the liquidity borrowed. When liquidating, a portion of the premium is also used for the liquidation reward.

The issue is that a borrower can open a position without any premium at all:

ParticlePositionManager::openPosition:

File: contracts/protocol/ParticlePositionManager.sol

240:            if (
241:                cache.token0PremiumPortion < params.tokenToPremiumPortionMin ||
242:                cache.token1PremiumPortion < params.tokenFromPremiumPortionMin
243:            ) revert Errors.InsufficientPremium();

params.tokenFrom/ToPremiumPortionMin are supplied by the borrower hence can be 0.

This removes any liquidation reward, since closeCache.tokenFrom/ToPremium is 0:
ParticlePositionManager::liquidatePosition:

File: contracts/protocol/ParticlePositionManager.sol

349:        liquidateCache.liquidationRewardFrom =
350:            ((closeCache.tokenFromPremium) * LIQUIDATION_REWARD_FACTOR) /
351:            uint128(Base.BASIS_POINT);
352:        liquidateCache.liquidationRewardTo =
353:            ((closeCache.tokenToPremium) * LIQUIDATION_REWARD_FACTOR) /
354:            uint128(Base.BASIS_POINT);

Thus any liquidation incentives are removed. Even if the position would immediately be liquidatable there would be no incentive to liquidate it. Other than possibly for the LP as they would get their liquidity back.

0 premium also robs the liquidity provider of any fees that would have been accrued for their borrowed liquidity:
ParticlePositionManager::_closePosition (same for the other branch of zeroForOne):

File: contracts/protocol/ParticlePositionManager.sol

461:            cache.token0Owed = cache.token0Owed < cache.tokenToPremium ? cache.token0Owed : cache.tokenToPremium;
462:            cache.token1Owed = cache.token1Owed < cache.tokenFromPremium ? cache.token1Owed : cache.tokenFromPremium;

Here, min(tokenOwed,tokenPremium) is taken, since tokenPremium would be 0 no fees would be owed.

Impact

A borrower can open a position without any premium. This removes any incentive to liquidate the position and also robs the liquidity provider of fees that would have been accrued.

In the extreme, if you for example open a long position above the price (thus with no leverage), a borrower will not need to provide any funds at all. Thus can spam positions like this locking liquidity providers liquidity and denying them fees (if the trading moves in their direction).

Proof of Concept

Actually, the basic test testBaseOpenLongPosition in OpenPosition.t.sol already reproduces this:

    function testOpenPositionWithoutPremium() public {
        testBaseOpenLongPosition();

        (,, uint128 token0Premium, uint128 token1Premium,,) = particleInfoReader.getOwedInfo(SWAPPER, 0);
        assertEq(0,token0Premium);
        assertEq(0,token1Premium);
    }

Tools Used

Manual audit

Recommended Mitigation Steps

Consider implementing a minimum enforced premium portion. Any premium portion would guarantee a reward to the liquidator.

Assessed type

Invalid Validation


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

All reactions

7 High

AI Score

Confidence

Low