Lucene search

K
code423n4Code4renaCODE423N4:2023-10-CANTO-FINDINGS-ISSUES-228
HistoryOct 06, 2023 - 12:00 a.m.

CrossTicks is not called when Users claimConcentratedRewards.

2023-10-0600:00:00
Code4rena
github.com
2
price tracking
data accuracy
vulnerability mitigation
tick crossings
claim rewards

7 High

AI Score

Confidence

Low

Lines of code
<https://github.com/code-423n4/2023-10-canto/blob/37a1d64cf3a10bf37cbc287a22e8991f04298fa0/canto_ambient/contracts/mixins/LiquidityMining.sol#L156&gt;

Vulnerability details

Vulnerability Details

The crossTicks() function is called to keep track and update the ticks whenever a tick is crossed, as specified by the Natspec

    /// @notice Keeps track of the tick crossings
    /// @dev Needs to be called whenever a tick is crossed
    function crossTicks(
        bytes32 poolIdx,
        int24 exitTick,
        int24 entryTick
    ) internal {
        uint256 numElementsExit = tickTracking_[poolIdx][exitTick].length;
        tickTracking_[poolIdx][exitTick][numElementsExit - 1]
            .exitTimestamp = uint32(block.timestamp);
        StorageLayout.TickTracking memory tickTrackingData = StorageLayout
            .TickTracking(uint32(block.timestamp), 0);
        tickTracking_[poolIdx][entryTick].push(tickTrackingData);
    }

it should be called whenever a tick is crossed however that is not so and will lead to incomplete Price Tracking or data accuracy as ticks are used to track price movements.

Impact

if ticks are not tracked when they are crossed it could lead to incorrect accruals and inaccuracies when analyzing historical price movements.

Proof of Concept

You can see in accrueConcentratedGlobalTimeWeightedLiquidity() and claimConcentratedRewards() functions respectively

    /// @notice Keeps track of the global in-range time-weighted concentrated liquidity per week
    /// @dev Needs to be called whenever the concentrated liquidity is modified (tick crossed, positions changed)
    function accrueConcentratedGlobalTimeWeightedLiquidity(
        bytes32 poolIdx,
        CurveMath.CurveState memory curve
    ) internal {


    function claimConcentratedRewards(
        address payable owner,
        bytes32 poolIdx,
        int24 lowerTick,
        int24 upperTick,
        uint32[] memory weeksToClaim
    ) internal {
        accrueConcentratedPositionTimeWeightedLiquidity(
            owner,
            poolIdx,
            lowerTick,
            upperTick
        );
        CurveMath.CurveState memory curve = curves_[poolIdx];
        // Need to do a global accrual in case the current tick was already in range for a long time without any modifications that triggered an accrual
        accrueConcentratedGlobalTimeWeightedLiquidity(poolIdx, curve);

you can see that when claiming rewards from the concentrated liquidity pool, the claimConcentratedRewards() function doesn’t keep track of the tick crossings.

Tools Used

Manual Review

Recommended Mitigation Steps

The crossTicks() function should be called in order to track the tick crossings whenever users claim rewards via claimConcentratedRewards().

Assessed type

Other


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

All reactions

7 High

AI Score

Confidence

Low