hardening(tier-1): doc-truth & offline-completeness before v0.1.0 - #28
Merged
KaiCode2 merged 11 commits intoJul 7, 2026
Merged
Conversation
Second of the pre-release hardening PRs (P1 correctness + doc accuracy),
stacked on tier-0.
- SimError typed source: `SimError::Execution` now carries a boxed
`dyn Error + Send + Sync` (was `String`) with a `source()` impl, matching the
crate's other boxed-source facades (CacheError/DriverError). `quote_via_call`
boxes the CacheError so a consumer can downcast the underlying cause. SimError
drops Clone/PartialEq/Eq (boxed payload); affected test assertions moved to
`matches!`, and facade_typing gains a downcast-source assertion.
- V3 offline completeness: the windowed cold-start planner now warms ALL FOUR
`Tick.Info` words of each initialized tick (was {0, 3}); a tick-crossing quote
reads feeGrowthOutside{0,1}X128 (words 1/2) too, so {0,3} forced a mid-quote
lazy fetch. The reactive Mint/Burn resync (repair.rs) refreshes all four to
match (a tick flip changes feeGrowthOutside). Golden/oracle tests updated
(7→11, 6→10 slots) and the cold-start test now asserts all four are warmed.
- README doc-truth:
* headline "purely from logs / no RPC / fully offline" narrowed to the real
exact-write-vs-resync split;
* "pool's own quote entrypoint" → "protocol's canonical quote entrypoint"
(V2/V3 quote via Router/Quoter, not the pool);
* cut the "Balancer/Curve seeding … in scope … before complete" roadmap leak
(now: seeding covers V2/V3; others fetch code lazily — a latency-only diff);
* added a Solidly offline caveat (getAmountOut also reads stable/decimals +
an external factory.getFee()).
- Factory-preset comment reconciliation: the gated RPC-test headers/messages
claimed "placeholder … TODO(slice)" while the shipped presets carry the
on-chain-confirmed constants (Pancake getPool slot 2 / feeAmountTickSpacing
slot 1 + verify_derivations on + create2 pinned; Aerodrome getPool slot 5 +
SOLIDLY_AERODROME_LAYOUT). Comments now describe the tests as confirming the
shipped constants. Velodrome doc reworded (reuses Aerodrome's Base-verified
constants; unverified for Optimism). Slipstream doc: discovery-only quoting
(fee left unset → MissingMetadata).
Full gate green: tests (all/default/no-default), clippy -D warnings
(all-features + 7-way isolation + no-default), fmt, doc -D warnings,
experimental x2, heavy-dep guard, MSRV 1.88.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Part 1 of the Tier 2 polish PR (missing_docs sweep follows as its own commit). - Configurable quote sender: `SimConfig.from` (default `Address::ZERO`) + a new public `quote_via_call_from(cache, from, target, calldata)`; `quote_via_call` now delegates to it with ZERO (unchanged behavior). Every adapter's `simulate_swap` threads `config.from` so a caller can quote against a target that gates on `msg.sender`. facade_typing gains a sender-threading test. - New `docs/protocol-support-matrix.md`: a per-protocol v0.1 capability matrix (cold-start, offline-after-cold-start, exact-write vs resync, factory discovery, known limitations), linked from the README's protocol table. - README: note that the published crate excludes `tests/`, so `cargo test` on a crates.io download runs only inline unit tests (clone for the full suite). - docs/benchmarks.md: a point-in-time / reproduce note on the results (medians are one host/run; `cargo bench` emits full Criterion stats + HTML reports). Full gate green: tests (all/default/no-default), clippy -D warnings, fmt, doc. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…_docs)] Part 2 of the Tier 2 polish PR. Enable `#![warn(missing_docs)]` at the crate root (CI's `-D warnings` promotes it to an error), and document every previously-undocumented public item so the surface stays fully documented as it grows — ~300 items across types, factory, bytecode, registry, cache, traits, storage, reactive, driver, the adapter structs, and the module declarations. Docs only; no behavior change. Verified: missing_docs = 0 under all-features / no-default / experimental; clippy -D warnings (all-features + no-default + isolation), doc -D warnings, fmt, and tests all green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…onal code seed CurveColdStartPlanner now skips discovery when CurveMetadata.discovered_slots is already known (a prior discovery, a trace, or a registry): no pool-account/bytecode fetch and no cold-cache get_dy slot-faulting, just a single verify round over the known slots. This makes a known-read-set single-pool cold_start as cheap as the bundled cold_start_many storage-program path Uniswap V2/V3 use. The discover->verify path is unchanged when discovered_slots is empty. Adds optional CurveMetadata.code_seed (+ with_code_seed builder + CurveAdapter::code_seeds): a caller-supplied Vyper runtime, verified once against on-chain EXTCODEHASH (mismatch -> purged -> lazy fetch), removing the one lazy code fetch a Curve pool otherwise pays on its first simulate_swap. Additive, non-breaking. Tests: verify-only skips-discovery + unfetchable-slot repair (cold_start_adoption), code_seeds unit test (curve), positive Curve one-shot classification (bootstrap_many). Adds examples/curve_cold_start_phases.rs and updates docs (curve-adapter, README, benchmarks). 216 tests pass; clippy/doc/all-features clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Uniswap V3 `Mint`/`Burn` previously always emitted a tick-range resync (an RPC round trip). They now event-source the affected state directly wherever it is already warm, matching the exact-write posture of the V2/Solidly `Sync` path, and resync ONLY for ticks outside the warmed window. The event carries the exact liquidity delta and the boundary ticks; the current tick comes from cached `slot0`. For each warm boundary tick the adapter read-modify-writes the packed `Tick.Info` word 0 — `liquidityGross` (low 128) and `liquidityNet` (high 128, opposite signs for the lower vs upper tick) — and toggles the `tickBitmap` bit on an init/clear (Uniswap `flipTick` is an XOR); the in-range global `liquidity` slot is adjusted by `±amount`. Those are exactly the slots a `QuoterV2` swap reads; `feeGrowthOutside`/`positions` are accounting-only (they do not affect `amountOut`) and are intentionally not maintained. A cold boundary tick (word 0 not cached) cannot be read-modify-written, so its info + bitmap slots fall back to a `VerifySlots` resync — the hybrid write-where-warm / resync-cold policy. No-layout pools still degrade to a conservative whole-storage invalidation. Correctness rests on the reactive runtime applying each input's updates before the next input's decode (verified in `ingest_batch_direct`), so read-modify-write sees prior events in the batch. Bitmap flips for both ticks in a shared word are accumulated into one combined write (two full-slot writes from the same pre-event view would not compose). Tests: 9 inline unit tests (packing round-trip incl. negative net, all four mint/burn sign combos, init/clear detection, overflow rejection, bit-position vs Uniswap `position`); reactive integration tests for warm direct writes, out-of-range liquidity, burn-to-zero bitmap clear (shared word), and cold-tick resync fallback; Pancake/Slipstream layout coverage retained. `RepairAction:: V3TickRange` is retained as a reserved variant. Full gate green (tests all/default/no-default, clippy -D warnings ×2, doc, fmt, missing_docs=0). Follow-up: an env-gated RPC parity test (apply a real Mint/Burn, compare event-sourced slots to eth_getStorageAt ground truth at the post-event block) — deferred pending an archive endpoint to author it against. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ports the Curve verify-only fast path to BalancerV2ColdStartPlanner: when BalancerV2Metadata.balance_slots is already known (a prior discovery or a trace), skip the getPoolTokens discovery -- no vault-account fetch, no cold-cache faulting -- and warm exactly those slots in a single verify round, matching the bundled cold_start_many storage-program path. Config-supplied tokens are preserved (no getPoolTokens decode repopulates them). The discover->verify path is unchanged when balance_slots is empty. Adds balancer_cold_start_verify_only_skips_discovery. 217 tests pass; clippy/all-features/doc clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds tests/v3_liquidity_rpc.rs (env-gated, #[ignore]): for a real add- and remove-liquidity transaction, fetch the exact per-tx storage diff via trace_replayTransaction(stateDiff), warm the pre-tx state, apply the event through the adapter, and assert the event-sourced writes reproduce the on-chain post-tx values for every slot the adapter maintains — each boundary tick's packed Tick.Info word 0 (liquidityGross/liquidityNet, incl. a negative net in two's complement) and the in-range global liquidity. Verified live against a mainnet archive+trace endpoint: a JIT add + remove of the same liquidity on the USDC/WETH 0.05% pool — BOTH the Mint and the Burn reproduce the on-chain per-tx storage exactly (tickLower/tickUpper word0 + global liquidity). This is the RPC parity check deferred in the feature commit; it now exists and passes. serde_json added as a dev-dependency (parses the trace stateDiff JSON). Full gate green: clippy -D warnings (all-features + no-default), offline tests, fmt, doc, missing_docs=0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
feat(uniswap-v3): event-source Mint/Burn liquidity (no RPC where warm)
perf(cold-start): verify-only fast path for Curve + Balancer (+ optional Curve code seed)
hardening(tier-2): polish, ergonomics, full-surface docs, V3 liquidity, and cold-start fast paths
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tier 1 — doc-truth & offline-completeness (pre-v0.1.0 hardening)
Second of the three stacked hardening PRs. Stacked on #27 (base =
hardening/tier-0-correctness); review only the Tier 1 diff here. Retarget tomainonce #27 merges.Changes
SimError::Execution(String)→Execution(Box<dyn Error + Send + Sync>)with asource()impl, matching the crate's other boxed-source facades (CacheError/DriverError).quote_via_callboxes theCacheErrorso a consumer can downcast the real cause instead of parsing a string.SimErrordropsClone/PartialEq/Eq(boxed payload); affected asserts moved tomatches!(strictness preserved), andfacade_typinggains a downcast-source assertion.Tick.Infowords per initialized tick (was{0, 3}) — a tick-crossingQuoterV2swap readsfeeGrowthOutside{0,1}X128(words 1/2) on every cross, so{0,3}forced a mid-quote lazy fetch (correct online, not fully offline). The reactiveMint/Burnresync refreshes all four too (a tick flip changesfeeGrowthOutside), so the cold-start warm and the resync now produce identical sets, matching the one-shot full-sync program. Golden/oracle tests updated (7→11, 6→10 slots); the cold-start test now asserts all four are warmed.getAmountOutalso readsstable/decimals+ an externalfactory.getFee()).getPoolslot 2 /feeAmountTickSpacingslot 1 +verify_derivationson + create2 pinned; AerodromegetPoolslot 5 +SOLIDLY_AERODROME_LAYOUT). Comments now describe the tests as confirming the shipped constants. Velodrome doc reworded (reuses Aerodrome's Base-verified constants; unverified for Optimism). Slipstream doc: discovery-only quoting (fee left unset →MissingMetadata).Verification
Full CI-parity gate green:
cargo test(all-features / default / no-default),clippy -D warnings(all-features + 7-way isolation + no-default),fmt --check,doc -D warnings,experimental-protocols×2, heavy-dep guard, MSRV 1.88.A skeptical review agent audited the diff (verdict SHIP); its one finding — a planner struct-doc line still saying
{0, 3}— was fixed.🤖 Generated with Claude Code