code-423n4 / 2024-05-predy-validation

0 stars 0 forks source link

Incorrect Range Calculation When Available Amount is Zero Results in Suboptimal Trading Efficiency #671

Closed c4-bot-4 closed 3 months ago

c4-bot-4 commented 3 months ago

Lines of code

https://github.com/code-423n4/2024-05-predy/blob/a9246db5f874a91fb71c296aac6a66902289306a/src/libraries/Reallocation.sol#L56

Vulnerability details

Impact

When availableAmount is 0, the _getNewRange function calculates the lower and upper ticks based on unadjusted values. This leads to an incorrect range calculation where the range is not centered around the current tick. As a result, the liquidity provision and trading functionality of the contract may not behave as expected. This can lead to suboptimal liquidity distribution, reduced trading efficiency, and potential financial losses for users.

Proof of Concept

if (availableAmount > 0) {
    if (currentTick < previousCenterTick) {
        // move to lower
        int24 minLowerTick = calculateMinLowerTick(
            sqrtAssetStatus.tickLower,
            ScaledAsset.getAvailableCollateralValue(_token1Status),
            availableAmount,
            tickSpacing
        );
        if (lower < minLowerTick && minLowerTick < currentTick) {
            lower = minLowerTick;
            upper = lower + _assetStatusUnderlying.riskParams.rangeSize * 2;
        }
    } else {
        // move to upper
        int24 maxUpperTick = calculateMaxUpperTick(
            sqrtAssetStatus.tickUpper,
            ScaledAsset.getAvailableCollateralValue(_token0Status),
            availableAmount,
            tickSpacing
        );
        if (upper > maxUpperTick && maxUpperTick >= currentTick) {
            upper = maxUpperTick;
            lower = upper - _assetStatusUnderlying.riskParams.rangeSize * 2;
        }
    }
}
lower = calculateUsableTick(lower, tickSpacing);
upper = calculateUsableTick(upper, tickSpacing);

When availableAmount is 0, the code skips the adjustment logic inside the if block and directly calculates the usable ticks based on the unadjusted lower and upper values.

Tools Used

Manual

Recommended Mitigation Steps

Add an else block to handle the case when availableAmount is 0. The else block should set the lower and upper ticks to the currentTick to ensure that the range is centered around the current tick when there is no available amount.

if (availableAmount > 0) {
    if (currentTick < previousCenterTick) {
        // move to lower
        // ...
    } else {
        // move to upper
        // ...
    }
} else {
    // Set lower and upper ticks to the current tick when availableAmount is 0
    lower = currentTick;
    upper = currentTick;
}
lower = calculateUsableTick(lower, tickSpacing);
upper = calculateUsableTick(upper, tickSpacing);

Assessed type

Invalid Validation