Skip to content

Conversation

@minhnhathoang
Copy link
Member

@minhnhathoang minhnhathoang commented Jan 12, 2026

User description

Follow-up to #1253


PR Type

Enhancement, Tests


Description

  • Comprehensive integration of Ekubo v3 DEX support with full pool simulator, tracker, and event parsing implementations

  • Implements multiple pool types: Base, FullRange, Stableswap, Oracle, MEV-Capture, and TWAMM pools with quote calculations

  • Adds complete mathematical library for swap computations including tick conversions, amount deltas, sqrt ratio calculations, and TWAMM-specific exponential functions

  • Extensive test coverage with 30+ test files covering pool simulators, trackers, event parsers, and mathematical operations

  • Integrates on-chain data fetching with subgraph support and RPC fallback mechanisms for pool state management

  • Registers Ekubo v3 as a supported DEX type in factory and pool type systems with msgpack serialization support

  • Fixes address conversion utilities to use standardized ZeroToWrappedLower function and corrects zero value cloning in delta calculations

  • Refactors test utilities to use helper functions for CI detection and log sorting


Diagram Walkthrough

flowchart LR
  A["Ekubo v3<br/>Integration"] --> B["Pool Types"]
  A --> C["Math Library"]
  A --> D["Data Fetching"]
  A --> E["Event Parsing"]
  A --> F["Pool Tracking"]
  
  B --> B1["Base Pool"]
  B --> B2["FullRange Pool"]
  B --> B3["Stableswap Pool"]
  B --> B4["Oracle Pool"]
  B --> B5["MEV-Capture Pool"]
  B --> B6["TWAMM Pool"]
  
  C --> C1["Swap Computation"]
  C --> C2["Tick Conversion"]
  C --> C3["Amount Deltas"]
  C --> C4["Sqrt Ratio"]
  C --> C5["TWAMM Math"]
  
  D --> D1["Subgraph Integration"]
  D --> D2["RPC Fallback"]
  
  E --> E1["Event Decoding"]
  E --> E2["Pool Address Extraction"]
  
  F --> F1["State Updates"]
  F --> F2["Reorg Detection"]
  
  A --> G["Pool Simulator"]
  G --> H["Swap Calculations"]
  
  A --> I["Factory Registration"]
  I --> J["DEX Type Support"]
Loading

File Walkthrough

Relevant files
Tests
18 files
pool_simulator_test.go
Pool simulator test suite with comprehensive swap calculations

pkg/liquidity-source/ekubo/v3/pool_simulator_test.go

  • Comprehensive test suite for PoolSimulator with 5 real pool
    configurations (lvlUSD-USDC, ETH-USDC, ETH-EKUBO in multiple variants)
  • Tests CalcAmountOut with 20+ test cases covering various swap
    scenarios, amounts, and expected outputs
  • Tests CalcAmountIn for all pool configurations using utility function
  • Additional tests for base and oracle pool types with state cloning and
    balance updates
+673/-0 
twamm_test.go
TWAMM pool quoting test suite                                                       

pkg/liquidity-source/ekubo/v3/pools/twamm_test.go

  • Test suite for TWAMM (Time-Weighted Average Market Maker) pool quoting
    functionality
  • 20+ test cases covering zero/non-zero sale rates, price boundaries,
    virtual order deltas, and complex scenarios
  • Tests quote calculations for both token0 and token1 inputs with
    various liquidity and sale rate configurations
+425/-0 
base_test.go
Base pool quoting and tick management tests                           

pkg/liquidity-source/ekubo/v3/pools/base_test.go

  • Test suite for base pool quote calculations with various liquidity and
    tick configurations
  • Tests for NearestInitializedTickIndex function with edge cases and
    multiple tick scenarios
  • Tests for AddLiquidityCutoffs with positive/negative liquidity deltas
    and tick boundary conditions
+443/-0 
pool_tracker_test.go
Pool tracker integration tests with real transactions       

pkg/liquidity-source/ekubo/v3/pool_tracker_test.go

  • Integration tests for PoolTracker with real Ethereum transactions and
    event logs
  • Tests position updates, swaps, and virtual order execution for
    different pool types (base, oracle, TWAMM)
  • Validates pool state transitions before and after blockchain events
+256/-0 
stableswap_test.go
Stableswap pool unit tests                                                             

pkg/liquidity-source/ekubo/v3/pools/stableswap_test.go

  • Tests stableswap pool quoting with various amplification factors and
    tick positions
  • Validates liquidity calculations within and outside active price
    ranges
  • Tests swap execution through range boundaries with proper fee
    accounting
  • Includes helper functions for pool setup and liquidity computation
+223/-0 
swap_test.go
Swap computation unit tests                                                           

pkg/liquidity-source/ekubo/v3/math/swap_test.go

  • Tests swap computation with various input/output scenarios and fee
    calculations
  • Validates edge cases including zero amounts, price limit constraints,
    and overflow conditions
  • Tests both exact-in and exact-out swap mechanics with proper fee
    handling
  • Includes tests for limited swaps that hit price boundaries
+184/-0 
muldiv_test.go
Multiplication and division unit tests                                     

pkg/liquidity-source/ekubo/v3/math/muldiv_test.go

  • Tests multiplication and division operations with rounding behavior on
    large numbers
  • Validates edge cases including zero numerators, max values, and
    overflow conditions
  • Tests rounding up/down behavior with various denominator values
  • Includes tests for division by zero error handling
+192/-0 
sqrt_ratio_test.go
TWAMM sqrt ratio calculation tests                                             

pkg/liquidity-source/ekubo/v3/math/twamm/sqrt_ratio_test.go

  • Tests TWAMM sqrt ratio calculation with various liquidity and sale
    rate combinations
  • Validates price calculations with different token sale rate ratios and
    time elapsed
  • Tests edge cases including zero liquidity and extreme price movements
  • Includes rounding direction validation for price calculations
+132/-0 
delta_test.go
Amount delta calculation unit tests                                           

pkg/liquidity-source/ekubo/v3/math/delta_test.go

  • Tests amount delta calculations for both token0 and token1 across
    price ranges
  • Validates rounding behavior (up/down) for amount calculations
  • Tests edge cases including zero liquidity and price boundary
    conditions
  • Includes overflow detection tests for extreme liquidity values
+158/-0 
sqrt_ratio_test.go
Sqrt ratio conversion unit tests                                                 

pkg/liquidity-source/ekubo/v3/math/sqrt_ratio_test.go

  • Tests next sqrt ratio calculations for both token amounts with various
    liquidity levels
  • Validates float to fixed sqrt ratio conversions with precision checks
  • Tests edge cases including overflow conditions and extreme amounts
  • Includes tests for price direction validation
+107/-0 
mev_capture_test.go
MEV capture pool unit tests                                                           

pkg/liquidity-source/ekubo/v3/pools/mev_capture_test.go

  • Tests MEV capture pool swap calculations for both input and output
    amounts
  • Validates quote consistency across multiple sequential swaps
  • Tests token0 and token1 swap scenarios with fee calculations
  • Includes state update validation between consecutive swaps
+96/-0   
tick_test.go
Tick conversion unit tests                                                             

pkg/liquidity-source/ekubo/v3/math/tick_test.go

  • Tests tick to sqrt ratio conversion with positive and negative tick
    values
  • Validates min/max tick boundary conversions
  • Tests approximate tick spacing crossing calculations
  • Includes reverse conversion validation (sqrt ratio to tick)
+76/-0   
factory_test.go
Add ekubo-v3 to factory test DEX types                                     

pkg/pooltypes/factory_test.go

  • Added ekubov3 to the list of supported DEX types in
    TestCanCalcAmountIn
  • Added ekubov3 to the list of supported DEX types in
    TestPoolListerFactory
  • Added ekubov3 to the list of supported DEX types in
    TestPoolTrackerFactory
+3/-3     
event_parser_test.go
Add ekubo-v3 event parser test suite                                         

pkg/liquidity-source/ekubo/v3/event_parser_test.go

  • New test file for ekubo-v3 event parser functionality
  • Tests event decoding for Swapped, PositionUpdated,
    VirtualOrdersExecuted, and OrderUpdated events
  • Validates pool address extraction from transaction receipts
+85/-0   
pools_list_updater_test.go
Add ekubo-v3 pool list updater test                                           

pkg/liquidity-source/ekubo/v3/pools_list_updater_test.go

  • New test file for ekubo-v3 pool list updater
  • Tests pool discovery and validation against mainnet configuration
  • Verifies pool key matching and configuration parsing
+61/-0   
full_range_test.go
Add full-range pool quote calculation tests                           

pkg/liquidity-source/ekubo/v3/pools/full_range_test.go

  • Tests full-range pool quote calculations with various liquidity
    scenarios
  • Validates zero liquidity, token0/token1 input, and fee handling
  • Ensures correct calculated amounts and fee calculations
+81/-0   
exp2_test.go
Add exp2 function tests for TWAMM math                                     

pkg/liquidity-source/ekubo/v3/math/twamm/exp2_test.go

  • New test file for exponential base-2 calculation function
  • Tests various exponent values and precision scenarios
  • Validates correctness of exp2 implementation
+72/-0   
oracle_test.go
Add oracle pool quote calculation tests                                   

pkg/liquidity-source/ekubo/v3/pools/oracle_test.go

  • Tests oracle pool quote calculations for both token inputs
  • Validates consumed and calculated amounts match expected values
+55/-0   
Enhancement
36 files
exp2.go
Fixed-point exponential base-2 computation implementation

pkg/liquidity-source/ekubo/v3/math/twamm/exp2.go

  • Implements exponential base-2 calculation (exp2) using precomputed
    masks and factors for fixed-point arithmetic
  • Provides 64 mask-factor pairs for binary exponentiation with precision
    handling
  • Includes exponent limit validation to prevent overflow
+293/-0 
data_fetchers.go
On-chain pool data fetching and state construction             

pkg/liquidity-source/ekubo/v3/data_fetchers.go

  • Implements data fetching for Ekubo v3 pools from on-chain quote data
    fetchers
  • Supports multiple pool types: base, full-range, stableswap, oracle,
    MEV-capture, and TWAMM pools
  • Handles batch fetching with configurable batch sizes and state
    construction from RPC data
+268/-0 
base.go
Base pool swap computation and tick management                     

pkg/liquidity-source/ekubo/v3/pools/base.go

  • Core implementation of base pool swap logic with tick-based liquidity
    management
  • Implements Quote method for computing swap amounts with tick crossing
    and fee calculations
  • Provides tick management utilities: UpdateTick, AddLiquidityCutoffs,
    and NearestInitializedTickIndex
+306/-0 
events.go
Event parsing and state update handlers for Ekubo pools   

pkg/liquidity-source/ekubo/v3/pools/events.go

  • Implements event handling for multiple pool types (BasePool,
    StableswapPool, FullRangePool, TwammPool) with ApplyEvent methods
  • Parses Swapped and PositionUpdated events from blockchain logs to
    update pool state
  • Handles TWAMM-specific events (VirtualOrdersExecuted, OrderUpdated)
    with virtual order delta tracking
  • Provides helper functions to parse and validate event data against
    pool identifiers
+297/-0 
twamm.go
TWAMM pool implementation with virtual order execution     

pkg/liquidity-source/ekubo/v3/pools/twamm.go

  • Implements TwammPool type with time-weighted average market maker
    (TWAMM) functionality
  • Provides quote calculation with virtual order execution simulation
    over time periods
  • Manages token sale rates and virtual order deltas for TWAMM order
    processing
  • Includes state management methods (GetState, CloneState, SetSwapState)
+237/-0 
keys.go
Pool key structures and serialization logic                           

pkg/liquidity-source/ekubo/v3/pools/keys.go

  • Defines generic PoolKey structure with support for multiple pool type
    configurations
  • Implements pool key serialization, compression, and numerical ID
    computation using Keccak256
  • Provides JSON unmarshaling for dynamic pool type detection
    (Concentrated, FullRange, Stableswap)
  • Includes helper functions for pool key conversion and address
    generation
+291/-0 
pools_list_updater.go
Pool list updater with subgraph integration                           

pkg/liquidity-source/ekubo/v3/pools_list_updater.go

  • Fetches new pool initializations from subgraph with block number
    tracking for incremental updates
  • Handles subgraph reorg detection and recovery by refetching all pools
    when needed
  • Converts pool initialization data into entity.Pool objects with proper
    token and reserve formatting
  • Manages pool type configuration detection based on tick spacing and
    stableswap parameters
+256/-0 
pool_tracker.go
Pool state tracker with event and RPC updates                       

pkg/liquidity-source/ekubo/v3/pool_tracker.go

  • Implements pool state tracking with event log processing and RPC
    fallback mechanisms
  • Applies blockchain events to update pool state incrementally, with
    reorg detection
  • Fetches pool state via RPC when logs are unavailable or event
    processing fails
  • Manages block header timestamps for TWAMM virtual order execution
    timing
+213/-0 
swap.go
Swap step computation logic                                                           

pkg/liquidity-source/ekubo/v3/math/swap.go

  • Implements core swap step computation with price impact and fee
    calculations
  • Handles both exact-in and exact-out swap scenarios with proper
    rounding
  • Validates swap direction and liquidity constraints with comprehensive
    error handling
  • Computes next sqrt ratio and fee amounts for swap execution
+183/-0 
pool_simulator.go
Pool simulator for swap calculations                                         

pkg/liquidity-source/ekubo/v3/pool_simulator.go

  • Implements PoolSimulator for swap amount calculations (in/out) using
    Ekubo pool quotes
  • Provides state cloning and balance updates from swap execution results
  • Handles amount overflow checks and zero amount validation with proper
    error handling
  • Includes metadata generation for pool information retrieval
+162/-0 
stableswap.go
Stableswap pool implementation                                                     

pkg/liquidity-source/ekubo/v3/pools/stableswap.go

  • Implements StableswapPool with quote calculation across price
    boundaries
  • Manages active price range bounds and liquidity tracking
  • Handles multi-step swaps with proper fee accounting and tick crossing
    detection
  • Provides state management methods for swap state updates
+136/-0 
sqrt_ratio.go
Sqrt ratio conversion and calculation utilities                   

pkg/liquidity-source/ekubo/v3/math/sqrt_ratio.go

  • Implements dynamic fixed-point sqrt ratio conversion (float to fixed
    and vice versa)
  • Provides next sqrt ratio calculations for token0 and token1 amounts
  • Handles rounding behavior and overflow/underflow detection
  • Includes bit manipulation for mantissa-based floating point
    representation
+116/-0 
event_parser.go
Event parser for pool address extraction                                 

pkg/liquidity-source/ekubo/v3/event_parser.go

  • Parses blockchain logs from Core and TWAMM contracts to extract pool
    addresses
  • Handles Swapped, PositionUpdated, VirtualOrdersExecuted, and
    OrderUpdated events
  • Decodes event data to compute pool identifiers for log grouping
  • Provides context-aware event routing based on contract address
+117/-0 
balances.go
Add balance calculation methods for ekubo-v3 pools             

pkg/liquidity-source/ekubo/v3/pools/balances.go

  • Implements CalcBalances() method for BasePoolState to calculate token
    balances from ticks
  • Implements CalcBalances() for FullRangePoolState using amount delta
    calculations
  • Implements CalcBalances() for StableswapPool with conditional amount
    calculations
+79/-0   
full_range.go
Add full-range pool implementation for ekubo-v3                   

pkg/liquidity-source/ekubo/v3/pools/full_range.go

  • Defines FullRangePool struct and related state types for full-range
    liquidity pools
  • Implements quote calculation with swap state management
  • Provides pool key and state cloning functionality
+107/-0 
unmarshal.go
Add pool unmarshaling for ekubo-v3 types                                 

pkg/liquidity-source/ekubo/v3/unmarshal.go

  • Implements unmarshaling logic for different pool types (FullRange,
    Stableswap, Concentrated)
  • Handles multiple extension types (Base, Oracle, Twamm, MevCapture)
  • Provides type-safe pool instantiation from serialized data
+100/-0 
mev_capture.go
Add MEV capture pool implementation for ekubo-v3                 

pkg/liquidity-source/ekubo/v3/pools/mev_capture.go

  • Implements MevCapturePool extending BasePool with MEV capture fee
    logic
  • Calculates additional fees based on tick movement and pool
    configuration
  • Handles both exact input and exact output swap scenarios
+86/-0   
sqrt_ratio.go
Add TWAMM sqrt ratio calculation logic                                     

pkg/liquidity-source/ekubo/v3/math/twamm/sqrt_ratio.go

  • Implements CalculateNextSqrtRatio() for TWAMM pools with time-weighted
    calculations
  • Computes sale ratio and applies exponential decay based on time
    elapsed
  • Handles precision adjustments for different bit lengths
+71/-0   
constants.go
Add ekubo-v3 mathematical constants                                           

pkg/liquidity-source/ekubo/v3/math/constants.go

  • Defines mathematical constants for ekubo-v3 including tick masks and
    log base
  • Provides pre-computed tick mask values for efficient ratio
    calculations
+39/-0   
pool_tracker_test.go
Refactor ekubo pool tracker test utilities                             

pkg/liquidity-source/ekubo/pool_tracker_test.go

  • Replaced manual CI environment check with test.SkipCI() helper
    function
  • Updated address conversion to use valueobject.ZeroToWrappedLower()
    instead of FromEkuboAddress()
  • Removed unused imports (os and types)
+6/-6     
tick.go
Add tick-to-ratio conversion functions for ekubo-v3           

pkg/liquidity-source/ekubo/v3/math/tick.go

  • Implements ToSqrtRatio() to convert tick numbers to sqrt ratio values
  • Implements ApproximateNumberOfTickSpacingsCrossed() for tick spacing
    calculations
  • Implements ApproximateSqrtRatioToTick() for inverse conversion
+65/-0   
delta.go
Add amount delta calculations for ekubo-v3                             

pkg/liquidity-source/ekubo/v3/math/delta.go

  • Implements Amount0Delta() and Amount1Delta() for calculating token
    amount changes
  • Handles rounding up/down and overflow detection
  • Provides core math for liquidity calculations
+60/-0   
pool_tracker.go
Refactor log sorting in ekubo pool tracker                             

pkg/liquidity-source/ekubo/pool_tracker.go

  • Replaced manual log sorting with eth.SortLogs() utility function
  • Removed unused imports (slices and types)
  • Simplified log ordering logic
+2/-8     
pools_list_updater.go
Update address conversion in ekubo pool list updater         

pkg/liquidity-source/ekubo/pools_list_updater.go

  • Updated address conversion to use valueobject.ZeroToWrappedLower()
    instead of FromEkuboAddress()
  • Applied change to both token0 and token1 address conversions
+3/-2     
oracle.go
Add oracle pool implementation for ekubo-v3                           

pkg/liquidity-source/ekubo/v3/pools/oracle.go

  • Implements OraclePool extending FullRangePool with oracle snapshot gas
    costs
  • Tracks whether pool has been swapped in current block
  • Adds gas overhead for oracle updates
+48/-0   
type.go
Add ekubo-v3 core type definitions                                             

pkg/liquidity-source/ekubo/v3/type.go

  • Defines core type interfaces for ekubo-v3 pools
  • Specifies Pool interface with quote, balance, and state management
    methods
  • Defines StaticExtra and Meta structures for pool metadata
+44/-0   
config.go
Add ekubo-v3 configuration structure                                         

pkg/liquidity-source/ekubo/v3/config.go

  • Defines Config struct with DEX configuration parameters
  • Implements SupportedExtensions() method for extension type mapping
  • Includes addresses for Core, Oracle, Twamm, and MevCapture contracts
+34/-0   
abis.go
Add ABI initialization for ekubo-v3 contracts                       

pkg/liquidity-source/ekubo/v3/abis/abis.go

  • Initializes ABI objects for Core, Twamm, QuoteDataFetcher, and
    TwammDataFetcher contracts
  • Extracts event definitions for PositionUpdated and OrderUpdated
+40/-0   
muldiv.go
Add multiplication and division utilities for ekubo-v3     

pkg/liquidity-source/ekubo/v3/math/muldiv.go

  • Implements MulDivOverflow() for safe multiplication and division with
    rounding
  • Implements div() helper for division with optional rounding up
+28/-0   
quote.go
Add quote and swap info types for ekubo-v3                             

pkg/liquidity-source/ekubo/v3/quoting/quote.go

  • Defines Quote struct containing swap results and gas costs
  • Defines SwapInfo struct with swap state and routing information
+27/-0   
gas.go
Add gas cost constants for ekubo-v3 operations                     

pkg/liquidity-source/ekubo/v3/quoting/gas.go

  • Defines gas cost constants for various pool operations
  • Includes base costs for different pool types and additional fees
+18/-0   
errors.go
Add error definitions for ekubo-v3 math                                   

pkg/liquidity-source/ekubo/v3/math/errors.go

  • Defines error types for mathematical operations and calculations
  • Includes overflow, underflow, and division errors
+14/-0   
constants.go
Add ekubo-v3 constants and error definitions                         

pkg/liquidity-source/ekubo/v3/constants.go

  • Defines DexType constant for ekubo-v3
  • Defines error constants for zero amount and reorg detection
+14/-0   
exchange.go
Add ekubo-v3 exchange type constant                                           

pkg/valueobject/exchange.go

  • Added ExchangeEkuboV3 constant with value "ekubo-v3"
+1/-0     
uint.go
Add uint256 to float conversion utility                                   

pkg/liquidity-source/ekubo/v3/math/uint.go

  • Implements U256ToFloatBaseX128() for converting uint256 to float64
    with X128 scaling
+9/-0     
extension_type.go
Add extension type enumeration for ekubo-v3                           

pkg/liquidity-source/ekubo/v3/extension_type.go

  • Defines ExtensionType enum with Base, Oracle, Twamm, and MevCapture
    variants
+10/-0   
Formatting
1 files
event_parser_test.go
Refactor CI skip condition to use utility function             

pkg/liquidity-source/ekubo/event_parser_test.go

  • Refactored test skip condition to use test.SkipCI utility function
    instead of manual environment variable check
  • Improves code consistency and maintainability
+3/-4     
Bug fix
2 files
pool_simulator_test.go
Update address conversion utility usage                                   

pkg/liquidity-source/ekubo/pool_simulator_test.go

  • Updates token address conversion to use valueobject.ZeroToWrappedLower
    instead of FromEkuboAddress
  • Maintains consistency with address normalization across the codebase
+3/-2     
delta.go
Fix zero value cloning in ekubo delta calculations             

pkg/liquidity-source/ekubo/math/delta.go

  • Fixed Amount0Delta() to return cloned zero value instead of shared
    reference
  • Fixed Amount1Delta() to return cloned zero value instead of shared
    reference
+2/-2     
Configuration changes
7 files
register_pool_types.gen.go
Register ekubo-v3 pool simulator for msgpack                         

pkg/msgpack/register_pool_types.gen.go

  • Added import for pkg_liquiditysource_ekubo_v3 package
  • Registered ekubov3.PoolSimulator as a concrete msgpack type
+2/-0     
pooltypes.go
Register ekubo-v3 DEX type in pool types                                 

pkg/pooltypes/pooltypes.go

  • Added import for ekubov3 package
  • Added EkuboV3 field to Types struct
  • Registered ekubov3.DexType in default types initialization
+3/-0     
embed.go
Embed ekubo-v3 contract ABI files                                               

pkg/liquidity-source/ekubo/v3/abis/embed.go

  • Embeds ABI JSON files for Core, Twamm, QuoteDataFetcher, and
    TwammDataFetcher contracts
+17/-0   
Core.json
Add Core contract ABI for ekubo-v3                                             

pkg/liquidity-source/ekubo/v3/abis/Core.json

  • Embedded ABI specification for ekubo-v3 Core contract
  • Includes function signatures and event definitions
+797/-0 
Twamm.json
Add TWAMM contract ABI for ekubo-v3                                           

pkg/liquidity-source/ekubo/v3/abis/Twamm.json

  • Embedded ABI specification for ekubo-v3 TWAMM extension contract
  • Includes lifecycle hooks and order management functions
+613/-0 
TwammDataFetcher.json
Add TWAMM data fetcher ABI for ekubo-v3                                   

pkg/liquidity-source/ekubo/v3/abis/TwammDataFetcher.json

  • Embedded ABI specification for TWAMM data fetcher contract
  • Includes pool state and virtual order execution functions
+216/-0 
QuoteDataFetcher.json
Add quote data fetcher ABI for ekubo-v3                                   

pkg/liquidity-source/ekubo/v3/abis/QuoteDataFetcher.json

  • Embedded ABI specification for quote data fetcher contract
  • Includes functions for retrieving initialized ticks and quote data
+161/-0 
Additional files
1 files
utils.go +0/-14   

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Jan 12, 2026

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Nil pointer DoS

Description: The new exp2 function returns nil when x exceeds exponentLimit, which can lead to a nil
dereference panic (DoS) in production code if any caller uses the returned *uint256.Int
without an explicit nil check.
exp2.go [278-293]

Referred Code
func exp2(x *uint256.Int) *uint256.Int {
	if !x.Lt(exponentLimit) {
		return nil
	}

	result := big256.U2Pow127.Clone()
	var helper uint256.Int

	for _, maskAndFactor := range masksAndFactors {
		if !helper.And(x, maskAndFactor.mask).IsZero() {
			result.Rsh(result.Mul(result, maskAndFactor.factor), 128)
		}
	}

	return result.Rsh(result, 63-uint(helper.Rsh(x, 64).Uint64()))
}
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Nil on overflow: The new exp2 helper returns nil when x exceeds exponentLimit, which may lead to downstream
nil dereferences if callers do not explicitly handle the nil case.

Referred Code
func exp2(x *uint256.Int) *uint256.Int {
	if !x.Lt(exponentLimit) {
		return nil
	}

	result := big256.U2Pow127.Clone()
	var helper uint256.Int

	for _, maskAndFactor := range masksAndFactors {
		if !helper.And(x, maskAndFactor.mask).IsZero() {
			result.Rsh(result.Mul(result, maskAndFactor.factor), 128)
		}
	}

	return result.Rsh(result, 63-uint(helper.Rsh(x, 64).Uint64()))

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Missing nil guards: StableswapPool.Quote clones and dereferences inputs/state (amount.Clone(),
p.SqrtRatio.Clone()) without nil checks, which could panic if externally constructed
pool/state or parameters are nil.

Referred Code
func (p *StableswapPool) Quote(amount *uint256.Int, isToken1 bool) (*quoting.Quote, error) {
	sqrtRatio := p.SqrtRatio.Clone()

	isIncreasing := math.IsPriceIncreasing(amount, isToken1)

	sqrtRatioLimit := lo.Ternary(isIncreasing, math.MaxSqrtRatio, math.MinSqrtRatio)

	var calculatedAmount, feesPaid uint256.Int
	amountRemaining := amount.Clone()
	var initializedTicksCrossed uint32 = 0

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Jan 12, 2026

PR Code Suggestions ✨

Latest suggestions up to 84242eb

CategorySuggestion                                                                                                                                    Impact
Possible issue
Recompute active tick index
Suggestion Impact:The commit sets ActiveTickIndex to -1 initially and then recomputes it using NearestInitializedTickIndex() after AddLiquidityCutoffs(), using the mutated state.SortedTicks and state.ActiveTick.

code diff:

@@ -208,13 +208,14 @@
 		BasePoolSwapState: &pools.BasePoolSwapState{
 			SqrtRatio:       math.FloatSqrtRatioToFixed(big256.FromBig(data.SqrtRatioFloat)),
 			Liquidity:       big256.FromBig(data.Liquidity),
-			ActiveTickIndex: pools.NearestInitializedTickIndex(ticks, data.Tick),
+			ActiveTickIndex: -1,
 		},
 		ActiveTick:  data.Tick,
 		SortedTicks: ticks,
 		TickBounds:  [2]int32{data.MinTick, data.MaxTick},
 	}
 	state.AddLiquidityCutoffs()
+	state.BasePoolSwapState.ActiveTickIndex = pools.NearestInitializedTickIndex(state.SortedTicks, state.ActiveTick)

Recompute the ActiveTickIndex after calling AddLiquidityCutoffs() to ensure it
reflects the mutated SortedTicks array.

pkg/liquidity-source/ekubo/v3/data_fetchers.go [207-217]

 state := pools.BasePoolState{
 	BasePoolSwapState: &pools.BasePoolSwapState{
 		SqrtRatio:       math.FloatSqrtRatioToFixed(big256.FromBig(data.SqrtRatioFloat)),
 		Liquidity:       big256.FromBig(data.Liquidity),
-		ActiveTickIndex: pools.NearestInitializedTickIndex(ticks, data.Tick),
+		ActiveTickIndex: -1,
 	},
 	ActiveTick:  data.Tick,
 	SortedTicks: ticks,
 	TickBounds:  [2]int32{data.MinTick, data.MaxTick},
 }
 state.AddLiquidityCutoffs()
+state.BasePoolSwapState.ActiveTickIndex = pools.NearestInitializedTickIndex(state.SortedTicks, state.ActiveTick)

[Suggestion processed]

Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies that AddLiquidityCutoffs() modifies SortedTicks, which can invalidate the pre-calculated ActiveTickIndex. This is a subtle but important bug that could lead to incorrect swap calculations.

Medium
Apply signed deltas safely

Correctly handle signed liquidity deltas in BasePool.ApplyEvent by using
sign-aware addition/subtraction instead of casting, which can cause incorrect
liquidity updates.

pkg/liquidity-source/ekubo/v3/pools/events.go [70-72]

 if p.ActiveTick >= lower && p.ActiveTick < upper {
-	p.Liquidity.Add(p.Liquidity, (*uint256.Int)(liquidityDelta))
+	var abs uint256.Int
+	abs.Abs((*uint256.Int)(liquidityDelta))
+
+	if liquidityDelta.Sign() >= 0 {
+		p.Liquidity.Add(p.Liquidity, &abs)
+	} else {
+		next, underflow := new(uint256.Int).SubOverflow(p.Liquidity, &abs)
+		if underflow {
+			return fmt.Errorf("liquidity underflow applying delta")
+		}
+		p.Liquidity = next
+	}
 }
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: This suggestion correctly identifies a critical bug where casting a negative int256 to uint256 causes it to wrap, leading to incorrect liquidity calculations. The proposed fix correctly handles both positive and negative deltas.

Medium
Deep-clone pool numeric state

Implement a deep copy in CloneState for the FullRangePoolState and its nested
fields. This prevents state corruption across different pool instances during
simulation by ensuring that mutable fields like SqrtRatio and Liquidity are not
shared.

pkg/liquidity-source/ekubo/v3/pools/full_range.go [36-42]

 func (p *FullRangePool) CloneState() any {
 	cloned := *p
 	cloned.key = p.key.CloneState()
+
 	clonedFullRangePoolState := *p.FullRangePoolState
+	if p.FullRangePoolState != nil {
+		if p.FullRangePoolState.FullRangePoolSwapState != nil {
+			clonedSwap := *p.FullRangePoolState.FullRangePoolSwapState
+			if p.FullRangePoolState.FullRangePoolSwapState.SqrtRatio != nil {
+				clonedSwap.SqrtRatio = p.FullRangePoolState.FullRangePoolSwapState.SqrtRatio.Clone()
+			}
+			clonedFullRangePoolState.FullRangePoolSwapState = &clonedSwap
+		}
+
+		if p.FullRangePoolState.Liquidity != nil {
+			clonedFullRangePoolState.Liquidity = new(uint256.Int).Set(p.FullRangePoolState.Liquidity)
+		}
+	}
+
 	cloned.FullRangePoolState = &clonedFullRangePoolState
 	return &cloned
 }
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies a critical bug where CloneState performs a shallow copy of *uint256.Int fields, which can lead to state corruption during simulation as these objects are mutable.

Medium
Avoid float precision in fees

Refactor the fee calculation in MevCapturePool.Quote to use integer arithmetic
instead of float64. This will prevent potential precision loss and overflow
issues when dealing with large fixed-point fee values, ensuring accurate quote
amounts.

pkg/liquidity-source/ekubo/v3/pools/mev_capture.go [42-47]

 tickAfterSwap := ekubomath.ApproximateSqrtRatioToTick(quote.SwapInfo.SwapStateAfter.(*BasePoolSwapState).SqrtRatio)
 
 poolConfig := &p.key.Config
-approximateFeeMultiplier := math.Abs(float64(tickAfterSwap-p.lastTick)) / float64(poolConfig.TypeConfig.TickSpacing)
+tickDelta := tickAfterSwap - p.lastTick
+if tickDelta < 0 {
+	tickDelta = -tickDelta
+}
 
-fixedPointAdditionalFee := uint64(min(math.Round(approximateFeeMultiplier*float64(poolConfig.Fee)), math.MaxUint64))
+// Integer math to avoid float64 precision loss on Q64 fees.
+var fixedPointAdditionalFee uint64
+if poolConfig.TypeConfig.TickSpacing > 0 && tickDelta > 0 {
+	var num uint256.Int
+	num.Mul(uint256.NewInt(uint64(poolConfig.Fee)), uint256.NewInt(uint64(tickDelta)))
 
+	den := uint256.NewInt(uint64(poolConfig.TypeConfig.TickSpacing))
+	q, _ := new(uint256.Int).DivMod(&num, den, new(uint256.Int))
+
+	if q.BitLen() >= 64 {
+		fixedPointAdditionalFee = math.MaxUint64
+	} else {
+		fixedPointAdditionalFee = q.Uint64()
+	}
+}
+
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly points out that using float64 for fee calculations involving Q64 fixed-point numbers can lead to precision loss and incorrect results, which is a significant issue for financial calculations.

Medium
Prevent panics on short data
Suggestion Impact:The commit added an early guard `if len(data) < 116 { return nil, nil }` before slicing the data buffer, preventing panics on malformed/short event data.

code diff:

 func parseSwappedEventIfMatching(data []byte, poolKey IPoolKey) (*swappedEvent, error) {
+	if len(data) < 116 {
+		return nil, nil
+	}
+

Add a length check on the data slice in parseSwappedEventIfMatching and similar
functions to prevent panics from malformed log data.

pkg/liquidity-source/ekubo/v3/pools/events.go [241-256]

 func parseSwappedEventIfMatching(data []byte, poolKey IPoolKey) (*swappedEvent, error) {
+	// Minimum bytes accessed below: data[100:116]
+	if len(data) < 116 {
+		return nil, nil
+	}
+
 	poolId := data[20:52]
 	expectedPoolId, err := poolKey.NumId()
 	if err != nil {
 		return nil, fmt.Errorf("computing expected pool id: %w", err)
 	}
 	if !bytes.Equal(poolId, expectedPoolId) {
 		return nil, nil
 	}
 
 	return &swappedEvent{
 		sqrtRatioAfter: math.FloatSqrtRatioToFixed(new(uint256.Int).SetBytes(data[84:96])),
 		tickAfter:      int32(binary.BigEndian.Uint32(data[96:100])),
 		liquidityAfter: new(uint256.Int).SetBytes(data[100:116]),
 	}, nil
 }

[Suggestion processed]

Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that slicing the data byte array without a length check can lead to a panic, and the proposed fix improves the code's robustness against malformed inputs.

Medium
Handle empty tick list

In BasePoolState.UpdateTick, add a check to handle the case where s.SortedTicks
is empty to prevent a panic from out-of-bounds slice access.

pkg/liquidity-source/ekubo/v3/pools/base.go [84-103]

 if newTickReferenced {
+	if len(ticks) == 0 {
+		s.SortedTicks = []Tick{{
+			Number:         updatedTickNumber,
+			LiquidityDelta: liquidityDelta,
+		}}
+
+		if s.ActiveTick >= updatedTickNumber {
+			s.ActiveTickIndex = 0
+		} else {
+			s.ActiveTickIndex = -1
+		}
+		return
+	}
+
 	if !forceInsert && nearestTickIndex == -1 {
 		delta := ticks[0].LiquidityDelta
 		delta.Add(delta, liquidityDelta)
 	} else if !forceInsert && nearestTickIndex == len(ticks)-1 {
 		delta := ticks[len(ticks)-1].LiquidityDelta
 		delta.Add(delta, liquidityDelta)
 	} else {
 		insertIdx := nearestTickIndex + 1
 
 		s.SortedTicks = slices.Insert(ticks, insertIdx, Tick{
 			Number:         updatedTickNumber,
 			LiquidityDelta: liquidityDelta,
 		})
 
 		if s.ActiveTick >= updatedTickNumber {
 			s.ActiveTickIndex++
 		}
 	}
 } else {
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies a potential panic when s.SortedTicks is empty, as ticks[0] would be an out-of-bounds access. The proposed fix adds a necessary guard to handle this edge case.

Medium
Sort time-ordered delta events

Sort the VirtualOrderDeltas by Time to ensure they are processed in the correct
chronological order during simulation.

pkg/liquidity-source/ekubo/v3/data_fetchers.go [250-267]

-return &pools.TwammPoolState{
+state := &pools.TwammPoolState{
 	FullRangePoolState: &pools.FullRangePoolState{
 		FullRangePoolSwapState: &pools.FullRangePoolSwapState{
 			SqrtRatio: math.FloatSqrtRatioToFixed(big256.FromBig(data.SqrtRatio)),
 		},
 		Liquidity: big256.FromBig(data.Liquidity),
 	},
 	Token0SaleRate:    big256.FromBig(data.SaleRateToken0),
 	Token1SaleRate:    big256.FromBig(data.SaleRateToken1),
 	LastExecutionTime: data.LastVirtualOrderExecutionTime,
 	VirtualOrderDeltas: lo.Map(data.SaleRateDeltas, func(srd TimeSaleRateInfo, _ int) pools.TwammSaleRateDelta {
 		return pools.TwammSaleRateDelta{
 			Time:           srd.Time,
 			SaleRateDelta0: big256.SFromBig(srd.SaleRateDelta0),
 			SaleRateDelta1: big256.SFromBig(srd.SaleRateDelta1),
 		}
 	}),
 }
 
+slices.SortFunc(state.VirtualOrderDeltas, func(a, b pools.TwammSaleRateDelta) int {
+	switch {
+	case a.Time < b.Time:
+		return -1
+	case a.Time > b.Time:
+		return 1
+	default:
+		return 0
+	}
+})
+
+return state
+
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: The suggestion correctly points out that VirtualOrderDeltas should be sorted by time for correct simulation. While the contract is expected to return them sorted, adding an explicit sort is a good defensive measure against potential issues.

Low
Guard swap-state type assertions

Add a type assertion check in SetSwapState to safely handle incorrect or nil
swap state types. This prevents potential panics and makes the function more
robust by providing a clear error message.

pkg/liquidity-source/ekubo/v3/pools/full_range.go [44-46]

 func (p *FullRangePool) SetSwapState(state quoting.SwapState) {
-	p.FullRangePoolSwapState = state.(*FullRangePoolSwapState)
+	s, ok := state.(*FullRangePoolSwapState)
+	if !ok || s == nil {
+		panic("invalid swap state type for full range pool")
+	}
+	p.FullRangePoolSwapState = s
 }
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: The suggestion correctly identifies a potential panic from an unchecked type assertion, improving code robustness by adding a safe check. However, the likelihood of this specific error is low within the existing codebase structure.

Low
Incremental [*]
Make liquidity deltas explicitly signed

Explicitly calculate the signed liquidity delta for the lower cutoff tick
instead of relying on uint256 wraparound arithmetic. This improves code clarity
and safety by handling positive and negative deltas explicitly.

pkg/liquidity-source/ekubo/v3/pools/base.go [146-147]

-s.UpdateTick(s.TickBounds[0], u256.SInt256(&liquidityDeltaMin), false, true)
-s.UpdateTick(s.TickBounds[1], u256.SInt256(&currentLiquidity), true, true)
+var lowerCutoffDelta int256.Int
+if currentLiquidity.Cmp(s.Liquidity) > 0 {
+	lowerCutoffDelta.Neg(u256.SInt256(new(uint256.Int).Sub(&currentLiquidity, s.Liquidity)))
+} else {
+	lowerCutoffDelta.Set(u256.SInt256(new(uint256.Int).Sub(s.Liquidity, &currentLiquidity)))
+}
+s.UpdateTick(s.TickBounds[0], &lowerCutoffDelta, false, true)
 
+s.UpdateTick(s.TickBounds[1], u256.SInt256(new(uint256.Int).Set(&currentLiquidity)), true, true)
+
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that relying on uint256 wraparound for signed arithmetic is risky and unclear. The proposed change makes the calculation of liquidityDeltaMin explicit and safer by using int256 for signed operations, which improves code clarity and robustness against potential misinterpretations of two's complement representation.

Medium
  • Update

Previous suggestions

Suggestions up to commit 22d65dd
CategorySuggestion                                                                                                                                    Impact
Possible issue
Deep-clone swap state pointers

Deep-clone the BasePoolSwapState and its pointer fields (SqrtRatio, Liquidity)
within BasePoolState.CloneState() to prevent state corruption between cloned
pool instances.

pkg/liquidity-source/ekubo/v3/pools/base.go [56-60]

 func (s *BasePoolState) CloneState() *BasePoolState {
 	cloned := *s
 	cloned.SortedTicks = slices.Clone(s.SortedTicks)
+
+	if s.BasePoolSwapState != nil {
+		clonedSwap := *s.BasePoolSwapState
+		if s.BasePoolSwapState.SqrtRatio != nil {
+			clonedSwap.SqrtRatio = s.BasePoolSwapState.SqrtRatio.Clone()
+		}
+		if s.BasePoolSwapState.Liquidity != nil {
+			clonedSwap.Liquidity = new(uint256.Int).Set(s.BasePoolSwapState.Liquidity)
+		}
+		cloned.BasePoolSwapState = &clonedSwap
+	}
+
 	return &cloned
 }
Suggestion importance[1-10]: 9

__

Why: This suggestion correctly identifies a critical bug where a shallow copy of *BasePoolSwapState would cause state corruption between concurrent simulations, leading to incorrect quotes. The fix is crucial for the correctness of the pool simulator.

High
Deep-copy TWAMM mutable fields

Deep-clone the token0SaleRate, token1SaleRate, and virtualOrderDeltas fields in
TwammPool.CloneState() to prevent shared state and data corruption between pool
simulations.

pkg/liquidity-source/ekubo/v3/pools/twamm.go [74-78]

 func (p *TwammPool) CloneState() any {
 	cloned := *p
 	cloned.FullRangePool = p.FullRangePool.CloneState().(*FullRangePool)
+
+	if p.token0SaleRate != nil {
+		cloned.token0SaleRate = new(uint256.Int).Set(p.token0SaleRate)
+	}
+	if p.token1SaleRate != nil {
+		cloned.token1SaleRate = new(uint256.Int).Set(p.token1SaleRate)
+	}
+
+	cloned.virtualOrderDeltas = slices.Clone(p.virtualOrderDeltas)
+	for i := range cloned.virtualOrderDeltas {
+		if cloned.virtualOrderDeltas[i].SaleRateDelta0 != nil {
+			cloned.virtualOrderDeltas[i].SaleRateDelta0 = cloned.virtualOrderDeltas[i].SaleRateDelta0.Clone()
+		}
+		if cloned.virtualOrderDeltas[i].SaleRateDelta1 != nil {
+			cloned.virtualOrderDeltas[i].SaleRateDelta1 = cloned.virtualOrderDeltas[i].SaleRateDelta1.Clone()
+		}
+	}
+
 	return &cloned
 }
Suggestion importance[1-10]: 9

__

Why: This suggestion correctly points out a critical bug where TwammPool.CloneState performs a shallow copy of mutable fields, which would lead to state corruption across different simulations. The proposed deep copy is essential for simulation correctness.

High
Apply signed liquidity deltas safely

Safely apply signed liquidity deltas in CalcBalances by using int256 arithmetic
to prevent incorrect wrapping of negative values, and add a check to ensure
liquidity does not become negative.

pkg/liquidity-source/ekubo/v3/pools/balances.go [13-44]

 func (s *BasePoolState) CalcBalances() ([]uint256.Int, error) {
 	stateSqrtRatio := s.SqrtRatio
 
 	balances := make([]uint256.Int, 2)
 	var liquidity, sqrtRatio, minAmount1SqrtRatio, maxAmount0SqrtRatio uint256.Int
 	sqrtRatio.Set(math.MinSqrtRatio)
 
 	for _, tick := range s.SortedTicks {
 		...
 		sqrtRatio.Set(tickSqrtRatio)
-		liquidity.Add(&liquidity, (*uint256.Int)(tick.LiquidityDelta))
+
+		// Apply signed liquidity delta safely.
+		var liqI int256.Int
+		liqI.SetFromBig(liquidity.ToBig())
+
+		liqI.Add(&liqI, tick.LiquidityDelta)
+		if liqI.Sign() < 0 {
+			return nil, fmt.Errorf("negative liquidity after applying tick delta")
+		}
+
+		liquidity.SetFromBig(liqI.ToBig())
 	}
 
 	return balances, nil
 }
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a critical bug where a direct pointer cast from a signed to an unsigned integer type can lead to incorrect liquidity calculations and potential overflows.

High
Guard TWAMM ratio division-by-zero

Prevent a potential division-by-zero panic in computeSqrtSaleRatioX128 by adding
checks for zero saleRateToken0. Return a sensible ratio for one-sided or zero
sale rates.

pkg/liquidity-source/ekubo/v3/math/twamm/sqrt_ratio.go [11-27]

 func computeSqrtSaleRatioX128(saleRateToken0, saleRateToken1 *uint256.Int) *uint256.Int {
+	// Avoid division-by-zero: handle one-sided / empty sale rates.
+	if saleRateToken0.IsZero() {
+		if saleRateToken1.IsZero() {
+			return big256.U0.Clone()
+		}
+		// token0 rate is 0 while token1 > 0 => ratio tends to +inf; cap to max uint.
+		return big256.UMax.Clone()
+	}
+
 	var saleRatio uint256.Int
 	saleRatio.Div(
 		saleRatio.Lsh(saleRateToken1, 128),
 		saleRateToken0,
 	)
 
 	if bitLen := saleRatio.BitLen(); bitLen <= 128 {
-		// Full precision
 		return saleRatio.Sqrt(saleRatio.Lsh(&saleRatio, 128))
 	} else if bitLen <= 192 {
-		// We know it only has 192 bits, so we can shift it 64 before rooting to get more precision
 		return saleRatio.Lsh(saleRatio.Sqrt(saleRatio.Lsh(&saleRatio, 64)), 32)
 	}
 
 	return saleRatio.Lsh(saleRatio.Sqrt(saleRatio.Lsh(&saleRatio, 16)), 56)
 }
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies a potential division-by-zero panic and proposes a robust fix by handling edge cases where sale rates can be zero, which is a valid scenario in TWAMM pools.

Medium
Prevent NaN/Inf tick conversions

Add checks in ApproximateNumberOfTickSpacingsCrossed and
ApproximateSqrtRatioToTick to handle non-finite float values (NaN, Inf) that can
result from math.Log on edge-case inputs, preventing undefined behavior.

pkg/liquidity-source/ekubo/v3/math/tick.go [52-65]

 func ApproximateNumberOfTickSpacingsCrossed(startingSqrtRatio, endingSqrtRatio *uint256.Int, tickSpacing uint32) uint32 {
 	if tickSpacing == 0 {
 		return 0
 	}
 
 	start, end := U256ToFloatBaseX128(startingSqrtRatio), U256ToFloatBaseX128(endingSqrtRatio)
-	ticksCrossed := uint32(math.Abs(math.Log(start/end)) / logBaseSqrtTickSize)
+	if start <= 0 || end <= 0 || math.IsNaN(start) || math.IsNaN(end) || math.IsInf(start, 0) || math.IsInf(end, 0) {
+		return 0
+	}
 
-	return ticksCrossed / tickSpacing
+	v := math.Abs(math.Log(start/end)) / logBaseSqrtTickSize
+	if math.IsNaN(v) || math.IsInf(v, 0) || v < 0 {
+		return 0
+	}
+
+	ticksCrossed := uint64(v)
+	return uint32(ticksCrossed / uint64(tickSpacing))
 }
 
 func ApproximateSqrtRatioToTick(sqrtRatio *uint256.Int) int32 {
-	return int32(math.Round(math.Log(U256ToFloatBaseX128(sqrtRatio)) / logBaseSqrtTickSize))
+	x := U256ToFloatBaseX128(sqrtRatio)
+	if x <= 0 || math.IsNaN(x) || math.IsInf(x, 0) {
+		return 0
+	}
+
+	t := int64(math.Round(math.Log(x) / logBaseSqrtTickSize))
+	if t < int64(MinTick) {
+		return MinTick
+	}
+	if t > int64(MaxTick) {
+		return MaxTick
+	}
+	return int32(t)
 }
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly points out that converting uint256 to float64 for logarithmic calculations can lead to NaN/Inf values in edge cases, causing undefined behavior. The proposed checks make the approximations more robust.

Medium
Avoid returning nil sentinel

Modify the exp2 function to return a safe, deterministic value or an explicit
error instead of nil for out-of-range inputs to prevent potential nil pointer
dereferences.

pkg/liquidity-source/ekubo/v3/math/twamm/exp2.go [278-293]

 func exp2(x *uint256.Int) *uint256.Int {
 	if !x.Lt(exponentLimit) {
-		return nil
+		return new(uint256.Int) // 0, explicit safe value
 	}
 
 	result := big256.U2Pow127.Clone()
 	var helper uint256.Int
 
 	for _, maskAndFactor := range masksAndFactors {
 		if !helper.And(x, maskAndFactor.mask).IsZero() {
 			result.Rsh(result.Mul(result, maskAndFactor.factor), 128)
 		}
 	}
 
 	return result.Rsh(result, 63-uint(helper.Rsh(x, 64).Uint64()))
 }
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that returning nil can lead to panics and proposes safer alternatives, which improves the robustness of the math utility function.

Medium
Use the subtest handle consistently

*Use the subtest's testing.T handle consistently within subtests instead of the
parent's handle to ensure correct error reporting.

pkg/liquidity-source/ekubo/v3/pool_tracker_test.go [46-91]

 func (ts *PoolTrackerTestSuite) run(cases []*testcase) {
-	t := ts.T()
+	for _, tc := range cases {
+		tc := tc
+		ts.Run(tc.name, func() {
+			t := ts.T()
 
-	for _, tc := range cases {
-		ts.Run(tc.name, func() {
 			extraJson, err := json.Marshal(tc.stateBefore)
 			require.NoError(t, err)
 
 			staticExtra := StaticExtra{
 				Core:          common.HexToAddress("0x00000000000014aA86C5d3c41765bb24e11bd701"),
 				ExtensionType: tc.extensionType,
 				PoolKey:       tc.poolKey,
 			}
 
 			staticExtraJson, err := json.Marshal(&staticExtra)
 			require.NoError(t, err)
 
 			p := entity.Pool{
 				Tokens: []*entity.PoolToken{
 					{Address: valueobject.ZeroToWrappedLower(tc.poolKey.Token0.String(), MainnetConfig.ChainId)},
 					{Address: valueobject.ZeroToWrappedLower(tc.poolKey.Token1.String(), MainnetConfig.ChainId)},
 				},
 				Extra:       string(extraJson),
 				StaticExtra: string(staticExtraJson),
 			}
 
 			blockNumber, logs := ts.getTxLogs(t, tc.txHash)
 			newPoolState, err := ts.tracker.GetNewPoolState(
 				context.Background(),
 				p,
 				pool.GetNewPoolStateParams{
 					Logs: logs,
 					BlockHeaders: map[uint64]entity.BlockHeader{
 						blockNumber: {Timestamp: tc.blockTimestamp},
 					},
 				},
 			)
 			require.NoError(t, err)
 
 			poolAfter, err := unmarshalPool([]byte(newPoolState.Extra), &staticExtra)
-			require.NoError(ts.T(), err, "Failed to unmarshal pool")
+			require.NoError(t, err, "Failed to unmarshal pool")
 
 			require.Equal(t, tc.expectedStateAfter, poolAfter.GetState())
 		})
 	}
 }
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies an issue where the parent test's *testing.T is used within subtests, which can lead to incorrect test failure reporting.

Low
General
Make subtest names unique

Make subtest names unique by including more test case details to improve test
output clarity and aid in debugging failures.

pkg/liquidity-source/ekubo/v3/pool_simulator_test.go [449-471]

 for _, tc := range testCases {
-	ts.T().Run(tc.pool, func(t *testing.T) {
+	tc := tc
+	ts.T().Run(tc.pool+"_"+tc.tokenIn+"_"+tc.tokenOut+"_"+tc.amountIn, func(t *testing.T) {
 		sim := ts.sims[tc.pool]
 
 		res, err := sim.CalcAmountOut(pool.CalcAmountOutParams{
 			TokenAmountIn: pool.TokenAmount{
 				Token:  tc.tokenIn,
 				Amount: bignum.NewBig(tc.amountIn),
 			},
 			TokenOut: tc.tokenOut,
 		})
 
 		if tc.expectedErr == nil {
 			require.NotNil(t, res)
 			require.Equal(t, tc.expectedAmountOut, res.TokenAmountOut.Amount.String())
 
 			swapInfo := res.SwapInfo.(quoting.SwapInfo)
 			require.Equal(t, tc.expectedTickSpacingsCrossed, swapInfo.TickSpacingsCrossed)
 		} else {
 			require.ErrorContains(t, err, tc.expectedErr.Error())
 		}
 	})
 }
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly points out that non-unique subtest names make debugging difficult and proposes a valid solution to improve test clarity and maintainability.

Medium
✅ Suggestions up to commit 5345172
CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix unsafe type cast bug
Suggestion Impact:The commit removed the unsafe pointer casts and replaced them with a dedicated conversion helper (u256.SInt256), which safely converts the uint256 values to int256 before calling UpdateTick. An import for the conversion utility was also added.

code diff:

+	u256 "github.com/KyberNetwork/kyberswap-dex-lib/pkg/util/big256"
 )
 
 const invalidTickNumber int32 = math.MinInt32
@@ -142,8 +143,8 @@
 
 	s.ActiveTickIndex = activeTickIndex
 
-	s.UpdateTick(s.TickBounds[0], (*int256.Int)(&liquidityDeltaMin), false, true)
-	s.UpdateTick(s.TickBounds[1], (*int256.Int)(&currentLiquidity), true, true)
+	s.UpdateTick(s.TickBounds[0], u256.SInt256(&liquidityDeltaMin), false, true)
+	s.UpdateTick(s.TickBounds[1], u256.SInt256(&currentLiquidity), true, true)

**Fix an unsafe type cast from uint256.Int to int256.Int by using proper
conversion methods to avoid incorrect value interpretation and bugs in liquidity
calculations.

pkg/liquidity-source/ekubo/v3/pools/base.go [145-146]

 	s.ActiveTickIndex = activeTickIndex
 
-	s.UpdateTick(s.TickBounds[0], (*int256.Int)(&liquidityDeltaMin), false, true)
-	s.UpdateTick(s.TickBounds[1], (*int256.Int)(&currentLiquidity), true, true)
+	liquidityDeltaMinInt256 := new(int256.Int).SetFromBig(liquidityDeltaMin.ToBig())
+	currentLiquidityInt256 := new(int256.Int).SetFromBig(currentLiquidity.ToBig())
 
+	s.UpdateTick(s.TickBounds[0], liquidityDeltaMinInt256, false, true)
+	s.UpdateTick(s.TickBounds[1], currentLiquidityInt256, true, true)
+
Suggestion importance[1-10]: 10

__

Why: The suggestion identifies a critical bug due to an unsafe type cast between *uint256.Int and *int256.Int, which would cause incorrect liquidity calculations and potentially corrupt pool state.

High
Fix incorrect liquidity update logic

Fix a bug in UpdateTick by removing incorrect special handling for boundary
ticks and ensuring a new tick is always inserted if it does not exist.

pkg/liquidity-source/ekubo/v3/pools/base.go [62-102]

 func (s *BasePoolState) UpdateTick(updatedTickNumber int32, liquidityDelta *int256.Int, upper, forceInsert bool) {
 	ticks := s.SortedTicks
 
 	liquidityDelta = liquidityDelta.Clone()
 	if upper {
 		liquidityDelta.Neg(liquidityDelta)
 	}
 
 	nearestTickIndex := NearestInitializedTickIndex(ticks, updatedTickNumber)
 
 	var (
 		nearestTick       *Tick
 		nearestTickNumber = invalidTickNumber
 	)
 
-	if nearestTickIndex != -1 {
+	if nearestTickIndex != -1 && nearestTickIndex < len(ticks) {
 		nearestTick = &ticks[nearestTickIndex]
 		nearestTickNumber = nearestTick.Number
 	}
 
 	newTickReferenced := nearestTickNumber != updatedTickNumber || nearestTick == nil
 	if newTickReferenced {
-		if !forceInsert && nearestTickIndex == -1 {
-			delta := ticks[0].LiquidityDelta
-			delta.Add(delta, liquidityDelta)
-		} else if !forceInsert && nearestTickIndex == len(ticks)-1 {
-			delta := ticks[len(ticks)-1].LiquidityDelta
-			delta.Add(delta, liquidityDelta)
-		} else {
-			insertIdx := nearestTickIndex + 1
+		insertIdx := nearestTickIndex + 1
 
-			s.SortedTicks = slices.Insert(ticks, insertIdx, Tick{
-				Number:         updatedTickNumber,
-				LiquidityDelta: liquidityDelta,
-			})
+		s.SortedTicks = slices.Insert(ticks, insertIdx, Tick{
+			Number:         updatedTickNumber,
+			LiquidityDelta: liquidityDelta,
+		})
 
-			if s.ActiveTick >= updatedTickNumber {
-				s.ActiveTickIndex++
-			}
+		if s.ActiveTick >= updatedTickNumber {
+			s.ActiveTickIndex++
 		}
 	} else {
 ...
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a critical bug in the UpdateTick function where liquidity for new ticks outside the existing range is misattributed to boundary ticks, leading to incorrect liquidity accounting.

High
Fix incorrect sqrt ratio calculation

Correct the logic in nextSqrtRatioFromAmount1 to ensure sqrtRatio is updated
correctly based on the sign of amount1 (add for exact-in, subtract for
exact-out).

pkg/liquidity-source/ekubo/v3/math/sqrt_ratio.go [87-116]

 func nextSqrtRatioFromAmount1(sqrtRatio, liquidity, amount1 *uint256.Int) (*uint256.Int, error) {
 	if amount1.IsZero() {
 		return sqrtRatio.Clone(), nil
 	} else if liquidity.IsZero() {
 		return nil, ErrNoLiquidity
 	}
 
 	var tmp uint256.Int
 	amount1Abs := tmp.Abs(amount1)
+	// for exact-in, amount1 is positive, roundUp is false.
+	// for exact-out, amount1 is negative, roundUp is true.
 	roundUp := amount1.Sign() < 0
 
 	quotient, err := MulDivOverflow(amount1Abs, big256.U2Pow128, liquidity, roundUp)
 	if err != nil {
 		return nil, err
 	}
 
-	if roundUp {
-		res, overflow := quotient.SubOverflow(sqrtRatio, quotient)
-		if overflow {
-			return nil, ErrUnderflow
-		}
-		return res, nil
-	} else {
+	if amount1.Sign() > 0 { // exact-in, add to current sqrtRatio
 		res, overflow := quotient.AddOverflow(sqrtRatio, quotient)
 		if overflow {
 			return nil, ErrOverflow
 		}
 		return res, nil
+	} else { // exact-out, subtract from current sqrtRatio
+		res, overflow := sqrtRatio.SubOverflow(sqrtRatio, quotient)
+		if overflow {
+			return nil, ErrUnderflow
+		}
+		return res, nil
 	}
 }
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a logic error in the nextSqrtRatioFromAmount1 function where the sqrtRatio is updated in the wrong direction for one of the swap cases, leading to incorrect price calculations.

High
Fix incorrect offset for pool ID

Fix the parsing of the anonymous Swapped event by extracting the poolId from the
correct offset (log.Data[0:32]) and adjusting the data length check accordingly.

pkg/liquidity-source/ekubo/v3/event_parser.go [59-68]

 func (e *EventParser) handleCoreLog(log types.Log) (string, error) {
 	if len(log.Topics) == 0 {
-		if len(log.Data) < 52 {
+		// This is for the anonymous Swapped event.
+		// The first field in the data is the poolId (bytes32).
+		if len(log.Data) < 32 {
 			return "", fmt.Errorf("invalid data length for Swapped event")
 		}
 
-		return "0x" + common.Bytes2Hex(log.Data[20:52]), nil
+		return "0x" + common.Bytes2Hex(log.Data[0:32]), nil
 	}
 
 	if log.Topics[0] == abis.PositionUpdatedEvent.ID {
 ...
Suggestion importance[1-10]: 9

__

Why: This suggestion correctly identifies that the poolId for an anonymous Swapped event is being parsed with an incorrect offset. The proposed fix aligns the parsing logic with how other anonymous events are handled in the codebase, ensuring correct pool identification from logs, which is critical for the event parser's functionality.

High
Fix swapped FilterReject assignments

Correct the variable assignment for the lo.FilterReject return values. The
current code swaps twammPoolKeys and basicPoolKeys, leading to incorrect data
fetching logic.

pkg/liquidity-source/ekubo/v3/data_fetchers.go [60-191]

-func (f *dataFetchers) fetchPools(
-	ctx context.Context,
-	poolKeys []*pools.PoolKey[pools.PoolTypeConfig],
-	overrides map[common.Address]gethclient.OverrideAccount,
-) ([]*PoolWithBlockNumber, error) {
+func (f *dataFetchers) fetchPools(...) ([]*PoolWithBlockNumber, error) {
 	...
-	twammPoolKeys, basicPoolKeys := lo.FilterReject(poolKeys, func(key *pools.PoolKey[pools.PoolTypeConfig], _ int) bool {
-		extensionType := f.config.SupportedExtensions()[key.Extension()]
-		return extensionType == ExtensionTypeTwamm
+	// FilterReject returns (filtered, rejected): filtered are non-TWAMM, rejected are TWAMM
+	basicPoolKeys, twammPoolKeys := lo.FilterReject(poolKeys, func(key *pools.PoolKey[pools.PoolTypeConfig], _ int) bool {
+		return f.config.SupportedExtensions()[key.Extension()] == ExtensionTypeTwamm
 	})
 
-	poolStates := make([]*PoolWithBlockNumber, 0, len(poolKeys))
-
+	// basicPoolKeys now non-TWAMM => use basic data fetcher
 	for startIdx := 0; startIdx < len(basicPoolKeys); startIdx += maxBatchSize {
 		...
 	}
-
+	// twammPoolKeys now TWAMM => use TWAMM data fetcher
 	for startIdx := 0; startIdx < len(twammPoolKeys); startIdx += maxBatchSize {
 		...
 	}
 	return poolStates, nil
 }
Suggestion importance[1-10]: 8

__

Why: This suggestion correctly identifies a critical bug where lo.FilterReject return values are assigned to the wrong variables, causing pools to be processed by the incorrect data fetcher. Fixing this is essential for the function's correctness.

Medium
Prevent division by zero in fee calculation

Prevent a potential division-by-zero panic in the MEV capture fee calculation by
adding a check to ensure poolConfig.TypeConfig.TickSpacing is not zero before
the division.

pkg/liquidity-source/ekubo/v3/pools/mev_capture.go [45-47]

-	approximateFeeMultiplier := math.Abs(float64(tickAfterSwap-p.lastTick)) / float64(poolConfig.TypeConfig.TickSpacing)
+	var approximateFeeMultiplier float64
+	if poolConfig.TypeConfig.TickSpacing > 0 {
+		approximateFeeMultiplier = math.Abs(float64(tickAfterSwap-p.lastTick)) / float64(poolConfig.TypeConfig.TickSpacing)
+	}
 
 	fixedPointAdditionalFee := uint64(min(math.Round(approximateFeeMultiplier*float64(poolConfig.Fee)), math.MaxUint64))
Suggestion importance[1-10]: 8

__

Why: This suggestion correctly identifies a potential division-by-zero panic if TickSpacing is 0. Adding a guard clause makes the fee calculation more robust and prevents a runtime crash, which is an important improvement for error handling.

Medium
Prevent potential division by zero panics

Add checks to prevent potential division-by-zero panics in the TWAMM sqrt_ratio
calculation. Specifically, handle cases where the denominators in the c and
final ratio calculations could be zero.

pkg/liquidity-source/ekubo/v3/math/twamm/sqrt_ratio.go [62-70]

-	c, _ := num.MulDivOverflow(num, big256.U2Pow128, saleRate.Add(sqrtSaleRatio, sqrtRatio))
+	denominator := saleRate.Add(sqrtSaleRatio, sqrtRatio)
+	if denominator.IsZero() {
+		return sqrtSaleRatio
+	}
+	c, _ := num.MulDivOverflow(num, big256.U2Pow128, denominator)
 	term1, term2 := saleRate.Sub(twoPowExponentX128, c), twoPowExponentX128.Add(twoPowExponentX128, c)
+
+	if term1.IsZero() {
+		return sqrtSaleRatio
+	}
 
 	if sign {
 		sqrtSaleRatio.MulDivOverflow(sqrtSaleRatio, term2, term1)
 	} else {
 		sqrtSaleRatio.MulDivOverflow(sqrtSaleRatio, term1, term2)
 	}
 	return sqrtSaleRatio
Suggestion importance[1-10]: 8

__

Why: This suggestion correctly points out two potential division-by-zero panics in the TWAMM sqrt_ratio calculation. The proposed checks for zero denominators make the mathematical operation safer and prevent runtime crashes, which is a critical improvement for the reliability of the logic.

Medium
Guard data slice bounds
Suggestion Impact:The commit added a guard clause checking `len(data) < 116` before slicing `data[20:52]`, preventing a potential out-of-bounds panic. It returns `nil, nil` instead of an error and uses a different minimum length than suggested.

code diff:

+	if len(data) < 116 {
+		return nil, nil
+	}
+
 	poolId := data[20:52]

Add a boundary check before slicing the data byte array to prevent a potential
panic if the slice is shorter than expected.

pkg/liquidity-source/ekubo/v3/pools/events.go [242]

+if len(data) < 100 {
+    return nil, fmt.Errorf("invalid swapped event data length: %d", len(data))
+}
 poolId := data[20:52]
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies a potential panic from slicing data without a length check, which is a good defensive programming practice to improve robustness.

Medium
Prevent mutating helper in exp2 loop

In the exp2 function, use separate temporary variables for bit-testing and the
final shift calculation instead of reusing the helper variable to avoid mutation
and improve clarity.

pkg/liquidity-source/ekubo/v3/math/twamm/exp2.go [278-293]

 func exp2(x *uint256.Int) *uint256.Int {
 	if !x.Lt(exponentLimit) {
 		return nil
 	}
 
 	result := big256.U2Pow127.Clone()
-	var helper uint256.Int
 
-	for _, maskAndFactor := range masksAndFactors {
-		if !helper.And(x, maskAndFactor.mask).IsZero() {
-			result.Rsh(result.Mul(result, maskAndFactor.factor), 128)
+	// apply mask‐factor multipliers without mutating x
+	for _, mf := range masksAndFactors {
+		tmp := new(uint256.Int).And(x, mf.mask)
+		if !tmp.IsZero() {
+			result = new(uint256.Int).Rsh(new(uint256.Int).Mul(result, mf.factor), 128)
 		}
 	}
 
-	return result.Rsh(result, 63-uint(helper.Rsh(x, 64).Uint64()))
+	// extract the high bits for final right shift
+	highBits := new(uint256.Int).Rsh(x.Clone(), 64).Uint64()
+	shift := 63 - uint(highBits)
+	return new(uint256.Int).Rsh(result, shift)
 }
Suggestion importance[1-10]: 3

__

Why: The suggestion correctly identifies that reusing the helper variable can be confusing, although the original code is not buggy. The proposed change improves readability and makes the code's intent clearer by using separate variables, which is a good practice.

Low
General
set snapshot flag after first quote

In the OraclePool.Quote method, set p.swappedThisBlock = true after adding the
oracle snapshot gas cost to prevent it from being added to subsequent quotes
within the same block.

pkg/liquidity-source/ekubo/v3/pools/oracle.go [30-41]

 func (p *OraclePool) Quote(amount *uint256.Int, isToken1 bool) (*quoting.Quote, error) {
 	quote, err := p.FullRangePool.Quote(amount, isToken1)
 	if err != nil {
 		return nil, err
 	}
 
 	if !p.swappedThisBlock {
 		quote.Gas += quoting.GasUpdatingOracleSnapshot
+		p.swappedThisBlock = true
 	}
 
 	return quote, nil
 }
Suggestion importance[1-10]: 7

__

Why: This suggestion correctly identifies a logic error where a flag is not updated, leading to incorrect gas cost calculations for subsequent swaps. The fix is simple but important for ensuring the gas estimation for oracle pools is accurate.

Medium
Replace debug print
Suggestion Impact:The debug fmt.Println call was removed from pools_list_updater.go, eliminating unwanted console output (no structured logger was added).

code diff:

 	req.Var("extensions", []common.Address{{}, u.config.Oracle, u.config.Twamm, u.config.MevCapture})
 	req.Var("startBlockNumber", u.startBlockNumber)
 
-	fmt.Println(u.config.Oracle, u.config.Twamm, u.config.MevCapture)
-

Remove a debug fmt.Println call and replace it with structured logging to
prevent unwanted console output.

pkg/liquidity-source/ekubo/v3/pools_list_updater.go [73]

-fmt.Println(u.config.Oracle, u.config.Twamm, u.config.MevCapture)
+// Replace debug print with logger:
+logger.WithFields(logger.Fields{
+    "oracle":     u.config.Oracle,
+    "twamm":      u.config.Twamm,
+    "mevCapture": u.config.MevCapture,
+}).Debug("pool list updater configuration")
Suggestion importance[1-10]: 3

__

Why: The suggestion correctly points out a debug fmt.Println statement that should be removed or replaced with a proper logger to avoid polluting logs in a production environment.

Low

@qodo-code-review
Copy link
Contributor

Persistent suggestions updated to latest commit 22d65dd

@kyber-ci-bot
Copy link

kyber-ci-bot commented Jan 13, 2026

Test coverage changes:
Package Before After Diff
github.com/KyberNetwork/kyberswap-dex-lib/pkg/entity 18.50% 18.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/aave-v3 3.90% 3.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/algebra/integral 36.50% 36.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/algebra/v1 13.30% 13.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/ambient 17.60% 17.60% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/angle-transmuter 38.10% 38.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/arbera/den 41.10% 41.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/arbera/zap 44.60% 44.60% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/arena-bc 64.10% 64.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/balancer/v1 42.90% 42.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/balancer/v2/composable-stable 46.30% 46.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/balancer/v2/math 36.90% 36.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/balancer/v2/stable 26.80% 26.80% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/balancer/v2/weighted 26.50% 26.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/balancer/v3/eclp 27.20% 27.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/balancer/v3/math 29.90% 29.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/balancer/v3/quant-amm 34.10% 34.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/balancer/v3/reclamm 27.10% 27.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/balancer/v3/stable 20.20% 20.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/balancer/v3/vault 13.90% 13.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/balancer/v3/weighted 25.60% 25.60% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/bancor-v21 31.60% 31.60% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/bancor-v3 52.00% 52.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/bedrock/unibtc 22.20% 22.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/bedrock/unieth 18.30% 18.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/beets-ss 26.10% 26.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/brownfi 16.00% 16.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/brownfi/v2 36.50% 36.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/clear 20.00% 20.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/clipper 49.40% 49.40% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/compound/v2 4.20% 4.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/compound/v3 3.50% 3.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/curve/llamma 70.10% 70.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/curve/plain 60.30% 60.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/curve/stable-meta-ng 56.10% 56.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/curve/stable-ng 39.90% 39.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/curve/tricrypto-ng 62.00% 62.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/curve/twocrypto-ng 64.90% 64.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/dai-usds 21.90% 21.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/deltaswap-v1 46.40% 46.40% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/dexalot 44.30% 44.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/dodo/classical 57.80% 57.80% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/dodo/dpp 37.80% 37.80% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/dodo/dsp 40.30% 40.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/dodo/dvm 47.50% 47.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/dodo/libv1 73.30% 73.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/dodo/libv2 38.40% 38.40% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/ekubo 16.90% 16.60%
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/ekubo/math 74.10% 74.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/ekubo/math/twamm 97.20% 97.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/ekubo/pools 48.00% 48.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/ekubo/v3 0.00% 14.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/ekubo/v3/math 0.00% 74.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/ekubo/v3/math/twamm 0.00% 97.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/ekubo/v3/pools 0.00% 44.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/erc4626 45.00% 45.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/ethena/susde 27.90% 27.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/ether-vista 2.30% 2.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/etherfi/ebtc 36.40% 36.40% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/etherfi/eeth 16.00% 16.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/etherfi/vampire 27.10% 27.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/etherfi/weeth 12.10% 12.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/euler-swap/v1 50.30% 50.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/euler-swap/v2 24.10% 24.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/fluid/dex-lite 66.20% 66.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/fluid/dex-t1 71.50% 71.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/fluid/dex-v2 2.70% 2.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/fluid/vault-t1 17.90% 17.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/frax/sfrxeth 18.00% 18.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/frax/sfrxeth-convertor 37.50% 37.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/generic-arm 24.10% 24.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/generic-simple-rate 32.90% 32.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/gsm-4626 48.70% 48.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/gyroscope/2clp 42.50% 42.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/gyroscope/3clp 43.40% 43.40% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/gyroscope/eclp 58.90% 58.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/gyroscope/math 2.50% 2.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/hashflow-v3 63.90% 63.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/honey 5.20% 5.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/hyeth 38.80% 38.80% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/infinifi/gateway 52.00% 52.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/integral 37.40% 37.40% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/kelp/rseth 11.70% 11.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/kelp/rseth-l2 16.30% 16.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/kuru-ob 3.10% 3.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/lgl-clob 48.40% 48.40% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/lo1inch 64.20% 64.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/lo1inch/helper 66.90% 66.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/maker/savingsdai 30.50% 30.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/maker/sky-psm 46.60% 46.60% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/mantle/meth 28.10% 28.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/maverick/v1 66.50% 66.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/maverick/v2 48.60% 48.60% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/midas 50.00% 50.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/mkr-sky 29.20% 29.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/nabla 36.30% 36.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/nad-fun 3.70% 3.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/nomiswap/nomiswapstable 83.10% 83.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/ondo-usdy 23.90% 23.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/order-book 83.20% 83.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/overnight-usdp 29.20% 29.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/pancake/infinity/bin 36.30% 36.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/pancake/infinity/cl 16.20% 16.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/pancake/v3 14.80% 14.80% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/puffer/pufeth 22.80% 22.80% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/renzo/ezeth 30.10% 30.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/ringswap 10.60% 10.60% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/rocketpool/reth 25.50% 25.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/smardex 47.70% 47.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/solidly-v2 32.70% 32.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/staderethx 28.00% 28.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/swell/rsweth 6.20% 6.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/swell/sweth 6.20% 6.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/syncswapv2/aqua 24.00% 24.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/syncswapv2/classic 41.10% 41.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/syncswapv2/stable 48.60% 48.60% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/tessera 3.70% 3.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/uniswap/lo 51.20% 51.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/uniswap/v1 12.70% 12.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/uniswap/v2 8.40% 8.40% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/uniswap/v3 14.70% 14.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/uniswap/v4 10.90% 10.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/uniswap/v4/hooks/bunni-v2 48.90% 48.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/uniswap/v4/hooks/bunni-v2/hooklet 16.10% 16.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/uniswap/v4/hooks/clanker 17.10% 17.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/uniswap/v4/hooks/deli 89.40% 89.40% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/uniswap/v4/hooks/flaunch 75.00% 75.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/uniswap/v4/hooks/idle 100.00% 100.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/uniswap/v4/hooks/renzo 62.50% 62.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/usd0pp 27.30% 27.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/velocore-v2/cpmm 54.50% 54.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/velocore-v2/math 16.80% 16.80% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/velocore-v2/math/sd59x18 51.90% 51.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/velocore-v2/wombat-stable 30.60% 30.60% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/velodrome-v1 32.80% 32.80% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/velodrome-v2 40.60% 40.60% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/virtual-fun 39.20% 39.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/wildcat 16.30% 16.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/woofi-v2 52.30% 52.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/woofi-v21 55.60% 55.60% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/camelot 40.30% 40.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/curve/aave 66.20% 66.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/curve/base 43.50% 43.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/curve/compound 75.40% 75.40% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/curve/meta 85.50% 85.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/curve/plain-oracle 38.50% 38.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/curve/tricrypto 70.30% 70.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/curve/two 29.20% 29.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/dmm 30.80% 30.80% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/equalizer 29.00% 29.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/fraxswap 25.20% 25.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/fulcrom 31.10% 31.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/fxdx 20.70% 20.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/gmx 27.70% 27.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/gmx-glp 26.10% 26.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/iziswap 25.70% 25.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/iziswap/swap 64.20% 64.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/kokonut-crypto 55.60% 55.60% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/lido 22.80% 22.80% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/lido-steth 33.30% 33.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/limitorder 51.30% 51.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/liquiditybookv20 25.90% 25.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/liquiditybookv21 38.80% 38.80% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/madmex 24.90% 24.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/makerpsm 38.40% 38.40% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/mantisswap 53.10% 53.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/metavault 28.10% 28.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/nuriv2 13.30% 13.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/platypus 26.00% 26.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/pol-matic 19.20% 19.20% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/pool 26.70% 26.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/quickperps 23.70% 23.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/ramsesv2 15.70% 15.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/saddle 63.80% 63.80% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/slipstream 17.60% 17.60% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/solidly-v3 20.70% 20.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/swapbased-perp 31.10% 31.10% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/syncswap/syncswapclassic 67.40% 67.40% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/syncswap/syncswapstable 81.40% 81.40% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/synthetix 37.90% 37.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/uniswap 16.50% 16.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/usdfi 45.00% 45.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/velocimeter 46.90% 46.90% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/vooi 37.30% 37.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/wombat/wombatlsd 55.30% 55.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/wombat/wombatmain 56.50% 56.50% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/util 3.40% 3.40% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/util/abi 80.00% 80.00% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/util/big256 21.70% 21.70% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/util/bignumber 13.30% 13.30% ✔️
github.com/KyberNetwork/kyberswap-dex-lib/pkg/util/graphql 56.20% 56.20% ✔️

Co-authored-by: qodo-code-review[bot] <151058649+qodo-code-review[bot]@users.noreply.github.com>
Signed-off-by: Minh Nhat Hoang <nhat.hm@outlook.com>
@minhnhathoang minhnhathoang merged commit 73da96f into main Jan 17, 2026
8 checks passed
@minhnhathoang minhnhathoang deleted the ekubo-v3 branch January 17, 2026 12:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants