Skip to content

feat: MEVCapture v2.1 exact model and parity (EKU-1577) - #41

Draft
moodysalem wants to merge 2 commits into
mainfrom
eku-1577-mevcapture-v21
Draft

moodysalem wants to merge 2 commits into
mainfrom
eku-1577-mevcapture-v21

Conversation

@moodysalem

@moodysalem moodysalem commented Oct 11, 2026 •

Copy link
Copy Markdown
Member

Board origin and outcome

  • Board origin: EKU-946, ancestor EKU-928.
  • Integration parent: EKU-1023.
  • Delivery owner/task: EKU-1577.
  • User outcome: exact MEVCapture v2.1 quotes, with v1 behavior unchanged.
  • Contract authority: da368348238a46857d39b6db57bdb2b432c979df, design rev6 ad3e6585-8135-431e-82af-7a177d7f5282.

What this adds

src/quoting/pools/mev_capture_v21.rs is a separate module. The v1 mev_capture.rs is unchanged. Base is rust-sdk 32af207, and no launchpad or auction work is included.

  • Typed inputs. MevCaptureV21Config is the exact getConfig tuple and is validated against the constructor. MevCaptureV21Anchor holds all seven getAnchor fields. MevCaptureV21PoolKey carries the contract Q0.16 fee and tick_spacing_exp.
  • MevCaptureV21Pool::new(key, config, state, sorted_ticks). Implements Pool (Meta = BlockTimestamp).
  • simulate_swap(state, MevCaptureV21SwapParams { is_token1, amount, sqrt_ratio_limit, min_fee, skip_ahead }, now). Returns:
    • the gate result
    • one record per Core call: kind (pass-through, toward or away k), limit, minFee, remaining amount, deltas, state after, steps and ticks crossed
    • checked int128 sums, the final pool and anchor state, and resources (Core calls and steps, ticks crossed, anchor updates, state writes)
  • Contract semantics covered:
    • first-touch gate and Q1 restore
    • toward call at the user minFee, ending at floor or ceil of the anchor
    • N1 sliver
    • absolute-grid and doubling away segments, with membership decided by sqrt ratio
    • per-call fee of max(segmentFee, userMinFee); Core also takes the max with the pool fee
    • user limit, early stop and the maxSegments budget
    • post-swap refresh, suppressed when a position changed in the same timestamp
  • Core step loop emulation. The v2.1 Core step loop is emulated: initialized ticks, 256-spacing word ends, skipAhead and Core's stored tick. Every step rounds its fee separately, so this matters for exact amounts. Step math is the SDK's compute_step::<Evm> with fee << 48.

Evidence (zero differences, inputs only)

  • swaps.json (merged contract): 32 swaps / 152 Core calls. Each swap checks gate, every call (limit, minFee, remaining amount, in order), both deltas, pool sqrt ratio/tick/liquidity and all seven anchor fields. Pool::quote is also checked against the same result.
  • New vectors generated from the unmodified merged contract: the generator is in tests/data/mevcapture-v21/generator, and in the same environment the merged generator reproduced swaps.json byte for byte.
    • swapsSupplement.json (9 / 61) covers word-boundary step splits with liquidity, user minFee on away segments, and the refresh raise and its suppression.
    • swapsNondefault.json (6 / 10) covers a nondefault config, decay clamp, capped segments and a pass-through swap.
  • Earlier replays still pass: 120 anchor updates, 24 scenarios / 1785 gate steps, 288 schedules, nondefault model test, construction and revert checks.
  • Mutation checks: each of these mutants fails the replay: removed sqrt-ratio skip, ignored minFee (Core or away), removed refresh, no word-end stops, toward call without early stop, ignored pool fee. Two survivors are equivalent or unreachable: the maxSegments budget clause (fee reaches maxFee first, by the constructor's budget lemma) and the int128 output clamp at 2^127.
  • Commands: cargo test --features evm,starknet,serde (193 lib + 8 v2.1 tests); cargo fmt --check; CI clippy with and without no_std, -D warnings; no_std,evm build. The existing 9 v1 tests pass.
  • Representation: contract fees are Q0.16 and fee_q16_to_q64 is lossless. Sqrt ratios are 64.128 fixed values that are exactly representable as compressed SqrtRatio, and the replay checks the round trip.

Known limits

  • Quotes are exact for the initialized ticks supplied. If a swap reaches ticks outside the fetched range, those ticks are needed too.
  • Pool::quote uses minFee 0 and skipAhead 0. Use simulate_swap for other values.

No publish, deployment, migration, activation, extension address or monitoring claim. CTO owns ordinary review and merge, and launch and deployment holds remain.

Origin: EKU-946; delivery: EKU-1577 under EKU-1023. Checkpoint only: executable swap parity remains pending.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Adds MevCaptureV21Pool (Pool impl + simulate_swap with per-call records and
resources): first-touch gate, toward call, away segments with sqrt-ratio
membership, N1, user minFee, call budget, checked int128 sums, post-swap
refresh, and an emulation of the v2.1 Core step loop (bitmap word ends,
skipAhead, Core tick). Replays swaps.json (32 swaps / 152 calls) plus
contract-generated supplement (9/61) and nondefault-config (6/10) vectors
with zero differences.

Origin: EKU-946; delivery: EKU-1577 under EKU-1023. No publish or deployment.

Co-Authored-By: Paperclip <noreply@paperclip.ing>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants