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

0 stars 0 forks source link

Token Amount Discrepancy in swap_2_internal_erc20 #184

Open c4-bot-4 opened 2 months ago

c4-bot-4 commented 2 months ago

Lines of code

https://github.com/code-423n4/2024-08-superposition/blob/4528c9d2dbe1550d2660dac903a8246076044905/pkg/seawater/src/lib.rs#L273-L291

Vulnerability details

Impact

In the swap_2_internal_erc20 function, there is a critical discrepancy between the amount of tokens that should be taken from the user (amount_in) and the amount that is actually being taken (original_amount).

Proof of Concept

pub fn swap_2_internal_erc20(
        pools: &mut Pools,
        from: Address,
        to: Address,
        amount: U256,
        min_out: U256,
        permit2: Option<Permit2Args>,
    ) -> Result<(U256, U256), Revert> {
        #[cfg(feature = "testing-dbg")]
        dbg!((
            "swap 2 internal erc20 at start",
            amount.to_string(),
            min_out.to_string()
        ));

        let (
            original_amount,
            amount_in,
            amount_out,
            _interim_usdc_out,
            _final_tick_in,
            _final_tick_out,
        ) = Self::swap_2_internal(pools, from, to, amount, min_out)?;

        #[cfg(feature = "testing-dbg")]
        dbg!((
            "swap 2 internal erc20 after internal",
            amount_in.to_string(),
            amount_out.to_string()
        ));

        // transfer tokens
        //@audit-info ------>>> program should take amount in , not original amount
        erc20::take(from, original_amount, permit2)?;
        erc20::transfer_to_sender(to, amount_out)?;

        #[cfg(feature = "log-events")]
        evm::log(events::Swap2 {
            user: msg::sender(),
            from,
            to,
            amountIn: amount_in,
            amountOut: amount_out,
            fluidVolume: _interim_usdc_out.abs().into_raw(),
            finalTick0: _final_tick_in,
            finalTick1: _final_tick_out,
        });

        // return amount - amount_in to the user
        // send amount_out to the user
        Ok((amount_in, amount_out))
    }
}

The function is currently using original_amount when calling erc20::take(). This means the protocol is taking the initial amount the user intended to swap, rather than the actual amount used in the swap operation.

Tools Used

mnaual view

Recommended Mitigation Steps

change to taking the amount in , not the original amount

Assessed type

Context

af-afk commented 2 months ago

We mitigated this with https://github.com/fluidity-money/long.so/commit/e87f25180d0d0e65df4b2bc495652e9f50cc2cdd