code-423n4 / 2023-10-canto-findings

0 stars 1 forks source link

Lack of tick range validation allows initialization of invalid ticks. #259

Closed c4-submissions closed 1 year ago

c4-submissions commented 1 year ago

Lines of code

https://github.com/code-423n4/2023-10-canto/blob/40edbe0c9558b478c84336aaad9b9626e5d99f34/canto_ambient/contracts/mixins/LiquidityMining.sol#L16-L20

Vulnerability details

Impact

Function initTickTracking initializes the tick tracking data structure, but does not validate that tick is within the min/max tick range for the pool. This could allow initializing invalid tick values.

Proof of Concept

Here is the line in initTickTracking that could initialize invalid tick values.

function initTickTracking(bytes32 poolIdx, int24 tick) internal {
  StorageLayout.TickTracking memory tickTrackingData = StorageLayout
            .TickTracking(uint32(block.timestamp), 0);  
  tickTracking_[poolIdx][tick].push(tickTrackingData);
}

The tick parameter is used to index into the tickTracking_ mapping without validating it is within the min/max tick range for the pool.

The initTickTracking function is used to initialize the tick tracking data structure for a specific tick in a pool. This data structure tracks when ticks become activated/deactivated over time.

It is defined as:

function initTickTracking(bytes32 poolIdx, int24 tick) internal {

  //...

}

The key parameters are:

Within the function, it does the following:

  1. Creates a TickTracking struct to represent the initial data for this tick:
  StorageLayout.TickTracking memory tickTrackingData = StorageLayout
            .TickTracking(uint32(block.timestamp), 0);
  1. Pushes this tick tracking data into the mapping that stores the info per tick:
  tickTracking_[poolIdx][tick].push(tickTrackingData); 

The issue here is that tick is used to index directly into the tickTracking_ mapping without validating it is within the min/max range for the pool.

The min/max ticks are set for each pool based on the tick spacing (number of ticks in the entire range). This range is stored in the PoolRegistry.

By not validating tick is within range, it is possible to initialize tick tracking for arbitrary tick values, even those outside the min/max bounds for the pool.

This could then corrupt the tick tracking data structure by inserting invalid entries. Later accounting logic relies on this structure being valid.

Here is a simple proof of concept that demonstrates initializing the tick tracking for an invalid, out-of-range tick value in the initTickTracking function:


contract Exploit {

  address constant pool = 0x...; // some pool address

  function exploitInitTickTracking() external {

    IUniswapV3Pool poolContract = IUniswapV3Pool(pool);

    bytes32 poolKey = poolContract.poolId();

    // Let's say this pool has a min tick of -887272 and max tick of -887270

    // Calling initTickTracking with a tick below the min 
    LiquidityMining(pool).initTickTracking(poolKey, -887300);

    // This initializes tick tracking for an invalid tick below the min

    // Now the tickTracking mapping has an invalid entry for tick -887300

  }

}

Key points:

This simple exploit shows how failing to validate the tick input can lead to improper state in the contract's data structures.

Tools Used

Vs

Recommended Mitigation Steps

The min/max tick values for a pool can be obtained from the PoolRegistry contract using PoolRegistry.getPoolData(poolIdx). So to validate, you could add something like:

function initTickTracking(bytes32 poolIdx, int24 tick) internal {

  (,,int24 tickSpacing,, int24 minTick, int24 maxTick,) = PoolRegistry.getPoolData(poolIdx);

  require(tick >= minTick && tick < maxTick, "Invalid tick");

  //...rest of function
}

This would prevent initializing the tick tracking data structure for invalid tick values outside the min/max range.

Assessed type

Invalid Validation

c4-pre-sort commented 1 year ago

141345 marked the issue as low quality report

c4-judge commented 1 year ago

dmvt marked the issue as unsatisfactory: Insufficient quality