HIGH severity: MixedSwapRouter — Arbitrary Call, controllable data.pool.. ![Screenshot 2024-07-02 at 2.15.44 PM.png](Arbitrary%20Call%202ed71b9e124b497c9c027d982bb83bbf/Screenshot_2024-07-02_at_2.15.44_PM.png)

Vulnerable code:
//AlgebraSwap v3 callback
function algebraSwapCallback(
    int256 amount0,
    int256 amount1,
    bytes calldata data <-- vulnerable point
) public {
    _processV3Callback(amount0, amount1, data);
}
    
function _processV3Callback(
    int256 amount0Delta,
    int256 amount1Delta,
    bytes calldata _data
) internal {
    require(_reentrancyGuardEntered(), "FBD");
    require(amount0Delta > 0 || amount1Delta > 0, "Invalid amount"); // swaps entirely within 0-liquidity regions are not supported
    SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));
    require(msg.sender == data.pool, "Invalid caller");
    (address tokenIn, address tokenOut, ) = data.path.decodeFirstPool();
    _validatePoolTokens(
        tokenIn,
        tokenOut,
        data.pool
    );

    (bool isExactInput, uint256 amountToPay) =
        amount0Delta > 0
            ? (tokenIn < tokenOut, uint256(amount0Delta))
            : (tokenOut < tokenIn, uint256(amount1Delta));
    if (isExactInput) {
        pay(tokenIn, data.payer, msg.sender, amountToPay);
    } else {
        // either initiate the next swap or pay
        if (data.path.hasMultiplePools()) {
            data.path = data.path.skipToken();
            _exactOutputInternalV3(
                amountToPay,
                msg.sender,
                0,
                data. <-- vulnerable point
            );
        } else {
            tokenIn = tokenOut; // swap in/out because exact output swaps are reversed
            pay(tokenIn, data.payer, msg.sender, amountToPay);
        }
    }
}

/// @dev Performs a single exact output swap
function _exactOutputInternalV3(
    uint256 amountOut,
    address recipient,
    uint160 sqrtPriceLimitX96,
    SwapCallbackData memory data.  
) private returns (uint256 amountIn) {
    require(data.pool != address(0), "InvalidPool");
    // allow swapping to the router address with address 0
    if (recipient == address(0)) recipient = address(this);

    (address tokenA, address tokenB, ) = data.path.decodeFirstPool();
    _validatePoolTokens(
        tokenA,
        tokenB,
        data.pool.  
    );
    bool zeroForOne = tokenA < tokenB;

    (int256 amount0Delta, int256 amount1Delta) = IUniswap(data.pool).swap(    <-- data.pool vulnerable point
            recipient,
            zeroForOne,
            -amountOut.toInt256(),
            sqrtPriceLimitX96 == 0
                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)
                : sqrtPriceLimitX96,
            abi.encode(data)
        );

    uint256 amountOutReceived;
    (amountIn, amountOutReceived) = zeroForOne
        ? (uint256(amount0Delta), uint256(-amount1Delta))
        : (uint256(amount1Delta), uint256(-amount0Delta));
    // it's technically possible to not receive the full output amount,
    // so if no price limit has been specified, require this possibility away
    if (sqrtPriceLimitX96 == 0) require(amountOutReceived == amountOut);
}

Vulnerability type: Arbitrary Call