Skip to content

feat: Add native query_pool_swap for TradePriceLimit for CPMMs and CLMMs#494

Open
pistomat wants to merge 19 commits intomainfrom
mp/add-trade-limit-query-pool-swap-variant-cpmm-clmm
Open

feat: Add native query_pool_swap for TradePriceLimit for CPMMs and CLMMs#494
pistomat wants to merge 19 commits intomainfrom
mp/add-trade-limit-query-pool-swap-variant-cpmm-clmm

Conversation

@pistomat
Copy link
Copy Markdown
Contributor

No description provided.

Also use it in uniswap_v2 and pancakeswap_v2 as quote_pool_swap TradePriceLimit variant
Use it in uniswap_v3 and uniswap_v4
The previous implementation used compute_swap_step with arbitrary amount_remaining, But the correct implementation should analytically calculate the actual amount needed to achieve the trade price we want, or use the whole liquidity.
 1. ✅ Removed debug tests (test_query_pool_swap_debug_prices, test_swap_with_price_limit) from V3
  2. ✅ Removed all println! statements from V3 tests
  3. ✅ Removed outdated "BUG" comment from test_swap_to_trade_price_achieves_target
  4. ✅ Cleaned up documentation - removed reference to "instantaneous price formula"
  5. ✅ Created SwapToTradePriceResult struct to replace generic tuple return
  6. ✅ Updated all V3 and V4 tests to use the new struct
  1. ✅ Created SwapToTradePriceResult struct - Replaced generic tuple (U256, U256, SwapResults) with a proper struct containing amount_in, amount_out, and swap_state fields
  2. ✅ Fixed V3 error handling - Changed .unwrap() to .ok_or_else() for safer error handling (matching V4's approach)
  3. ✅ Removed dead_code annotations - Removed #[allow(dead_code)] from solve_quadratic, compute_quadratic_coefficients, and compute_sqrt_ratio_target since they are used
  4. ✅ Extracted gas constant - Replaced magic number U256::from(2000) with GAS_PER_SWAP_STEP constant in both V3 and V4
  5. ✅ Created test utility function - Added verify_swap_to_trade_price_with_get_amount_out() helper to both V3 and V4 test modules for verifying results against the trusted get_amount_out implementation
  6. ✅ Added multi-tick crossing test to V4 - Added test_swap_to_trade_price_multi_tick_crossing test (V3 already had it)
  7. ✅ Documented tolerance parameter - Added comments explaining why tolerance, min_amount_in, and max_amount_in are unused (the analytical formula is exact)
@pistomat pistomat marked this pull request as draft January 5, 2026 14:37
@pistomat pistomat changed the title feat: Add native query_pool_swap for TradePriceLimit for Uniswap variants feat: Add native query_pool_swap for TradePriceLimit for CPMMs and CLMMs Jan 5, 2026
pistomat and others added 3 commits February 19, 2026 16:36
…pmm-clmm

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add zero-amount guard in V3/V4 query_pool_swap to prevent state corruption
- Remove redundant f64 validation in V3/V4 swap_to_trade_price (outer U512
  validation in clmm_swap_to_trade_price is sufficient)
- Add MAX_TICKS_CROSSED guard to swap_to_trade_price loops
- Use GAS_PER_TICK instead of GAS_PER_SWAP_STEP for accurate gas accounting
- Fix tautological test assertions (trade_price >= target is the real invariant)
- Fix no-op test in swap_math (test_accumulated_target_already_achieved)
- Add integration tests for TradeLimitPrice across V2, V3, V4, PancakeSwap

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Return actual swap state instead of SwapResults::default() on zero
  amount in clmm_swap_to_trade_price (prevents state corruption for
  future callers)
- Add f64 epsilon tolerance (1e-9) to trade price assertions to
  account for integer truncation in amount_out/amount_in division
- Strengthen swap_math test with meaningful assertions (verify
  cumulative ratio improves toward target, price moves on non-zero
  amounts)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@pistomat pistomat marked this pull request as ready for review February 23, 2026 17:52
pistomat and others added 4 commits March 12, 2026 16:19
- Add get_amount_out cross-validation in V2/PancakeSwap tests to verify
  trade price actually matches the limit
- Add compute_swap_step cross-validation in swap_math tests
- Replace silent unwrap_or(I256::ZERO) with explicit if-let in V3/V4
- Standardize sign conventions for amount_specified/amount_calculated
- Tighten test tolerances from 2% to 0.5%
- Rewrite vacuous "target already achieved" test with real assertions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix U512 overflow in CLMM reachability check by dividing both sides
  by sqrt_price instead of computing sqrt_price² (596-bit intermediate)
- Add zero-liquidity break in V3/V4 swap-to-trade-price loops to
  prevent FatalError after tick crossing reduces liquidity to 0
- Add overflow guard in compute_sqrt_ratio_target for results exceeding
  U256 range
- Add conservative rounding direction test (achieved price ≤ target)
- Add compute_swap_step cross-validation for one_for_zero direction
- Add negative-residual branch test (accumulated ratio > target)
- Tighten CPMM oracle tolerance from 1% to 0.001%

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ery-pool-swap-variant-cpmm-clmm

# Conflicts:
#	src/evm/protocol/uniswap_v3/state.rs
#	src/evm/protocol/uniswap_v4/state.rs
Replace heap-allocated BigUint/BigInt with stack-allocated ruint
U1024/U2048 fixed-width integers in the per-tick quadratic solver.
Use sign-magnitude pairs (bool, U1024) for signed arithmetic.

Add zero-accumulated shortcut: when accumulated_in == 0 &&
accumulated_out == 0, compute sqrt_ratio_target via single U1024
division instead of the full quadratic formula.

Phase 1 fixes: remove dead fee_factor params, unnecessary clones,
CSE for q96*s0 and q96², fix bits() > 256 check.

Measured speedups (release, 10K iterations):
- Zero-accumulated: 5826 → 395 ns/iter (14.7x)
- With accumulated: 5720 → 4066 ns/iter (1.4x)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

1 participant