code-423n4 / 2024-08-superposition-validation

0 stars 0 forks source link

Silent Overflow in get_amount_0_delta and get_amount_1_delta #207

Closed c4-bot-6 closed 1 month ago

c4-bot-6 commented 1 month ago

Lines of code

https://github.com/code-423n4/2024-08-superposition/blob/main/pkg/seawater/src/maths/sqrt_price_math.rs#L203 https://github.com/code-423n4/2024-08-superposition/blob/main/pkg/seawater/src/maths/sqrt_price_math.rs#L210 https://github.com/code-423n4/2024-08-superposition/blob/main/pkg/seawater/src/maths/sqrt_price_math.rs#L227 https://github.com/code-423n4/2024-08-superposition/blob/main/pkg/seawater/src/maths/sqrt_price_math.rs#L234

Vulnerability details

Description

In both functions get_amount_0_delta and get_amount_1_delta, there are unchecked conversion from U256 (which the function _get_amount_0_delta or _get_amount_1_delta returns) to I256. The issue is that the value returned from _get_amount_0_delta can be greater than what I256 represents, which will result in a faulty conversion.

pub fn get_amount_0_delta(
    sqrt_ratio_a_x_96: U256,
    sqrt_ratio_b_x_96: U256,
    liquidity: i128,
) -> Result<I256, Error> {
    if liquidity < 0 {
        Ok(-I256::from_raw(_get_amount_0_delta(
            sqrt_ratio_a_x_96,
            sqrt_ratio_b_x_96,
            -liquidity as u128,
            false,
        )?)) //@audit-issue overflow can happen here since _get_amount_0_delta can return a number bigger than what I256 can hold
    } else {
        Ok(I256::from_raw(_get_amount_0_delta(
            sqrt_ratio_a_x_96,
            sqrt_ratio_b_x_96,
            liquidity as u128,
            true,
        )?)) //@audit-issue overflow can happen here since _get_amount_0_delta can return a number bigger than what I256 can hold
    }
}

As you can see from the function above if the overflow happens this wont revert and will silently returns 0.

Impact

The impact of this issue as we can see from the POC below, the tx wont revert or fail with overflow instead it returns 0.

Proof of Concept

You can add the test function below in pkg/seawater/src/maths/sqrt_price_maths.rs

    use crate::tick_math;
    #[test]
    fn poc_silent_overflow() -> Result<(), Error> {
        let lower_tick = 700; //  large negative tick
        let upper_tick = 10000;  //  large positive tick
        // Get the sqrt ratios for these ticks
        let sqrt_ratio_a = tick_math::get_sqrt_ratio_at_tick(lower_tick)?;
        let sqrt_ratio_b = tick_math::get_sqrt_ratio_at_tick(upper_tick)?;
        let liquidity = -2; 
        println!("Calculated sqrt_ratio_a: {:?}", sqrt_ratio_a);
        println!("Calculated sqrt_ratio_b: {:?}", sqrt_ratio_b);
        // Now call the function get_amount_0_delta
        let delta = get_amount_0_delta(sqrt_ratio_a, sqrt_ratio_b, liquidity)?;
        println!("Calculated delta: {:?}", delta);
        Ok(())
    }

Run the test with

cargo test --features testing --package seawater -- poc_silent_overflow --nocapture

Tools Used

Manual Analysis

Recommended Mitigation Steps

Dont allow values bigger than I256 to be converted instead revert.

Assessed type

Under/Overflow