feat: add per-pool slippage, utilization, and execution risk to /simulate response#50
Open
0xcentur1on wants to merge 14 commits intomasterfrom
Open
feat: add per-pool slippage, utilization, and execution risk to /simulate response#500xcentur1on wants to merge 14 commits intomasterfrom
0xcentur1on wants to merge 14 commits intomasterfrom
Conversation
…esponse Each AmountOutResponse now includes: - slippage_bps: per-ladder-step slippage in basis points, computed from the pool's spot_price() (marginal rate) vs the actual amount_out/amount_in ratio. - pool_utilization_bps: fraction of the pool's get_limits() max_in consumed by the largest requested amount, in basis points (10_000 = 100%). Inside simulate_pool() one spot_price() call is made per pool after the ladder completes. spot_price and max_in are threaded through PoolQuoteResult and the computation is done in get_amounts_out() before building AmountOutResponse.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Compute a composite execution-risk score for each pool returned by /simulate, derived from slippage (price sensitivity), pool utilization (capacity pressure), bonding curve convexity, and partial-ladder detection. The score and a qualitative label (low/medium/high/very_high/ unknown) are surfaced as execution_risk on each AmountOutResponse. Block-lag staleness is intentionally excluded from the server-side score; clients add that penalty using block_number vs. the current chain head. Adds 14 new unit tests covering score thresholds, the partial-ladder penalty, convexity amplification, division-by-zero guards, and serialization of the new types.
…server into feat/per-pool-slippage
- Add pool_type: PoolType::Volatile to all AmountOutRequest initializers in sim_analysis/mod.rs (encode-hop-1, encode-hop-2, simulate_request) - Add pool_type: PoolType::Volatile to the make_amount_out_request test helper in services/quotes.rs - Import PoolType in sim_analysis/mod.rs and at the top level of quotes.rs - Fix compute_execution_risk: remove incomplete match pool_type block left from partial feature work, lift weight constants back to function scope, and pass Some(self.request.pool_type) at the production call site - Add None as the 4th argument to all compute_execution_risk test call sites - All 182 unit tests pass
- Differentiate risk score weights by PoolType: - Stablecoin: higher utilization weight (0.55) to reflect peg sensitivity - BlueChip: balanced utilization weight (0.45) for deep-liquidity pools - Volatile (default): original weights unchanged (slippage 0.35, utilization 0.35) - Rename _pool_type to pool_type now that the parameter is fully consumed - Fix missing pool_type field in integration test AmountOutRequest fixture - Minor formatting cleanup in quotes.rs import block and requested_max_in chain
- stablecoin: w1 0.25→0.10, w2 0.55→0.70 (utilization is dominant signal) - blue_chip: w1 0.25→0.35, w2 0.45→0.55 (both signals meaningful) - volatile: w1 0.35→0.45 (slippage is primary risk indicator)
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.
Summary
Enriches each pool entry in the
/simulateresponse with three new fields that give callers a complete, server-side view of execution risk before sending a transaction on-chain:slippage_bps— per-ladder-step price impact in basis points (positive = cost to trader)pool_utilization_bps— fraction of the pool's reportedmax_inconsumed by the largest requested amount (10 000 = 100 %)execution_risk— composite risk score and qualitative label (low/medium/high/very_high/unknown) derived from slippage, utilization, curve convexity, and ladder completenessA new
pool_typefield (blue_chip|stablecoin|volatile, defaults tovolatile) on the request lets callers pass pool-class context so the service can apply pool-type-aware weights when computing the risk score.Changed files
src/models/messages.rsPoolTypeenum,pool_typeonAmountOutRequest; addedslippage_bps,pool_utilization_bps,execution_riskonAmountOutResponse; addedExecutionRiskstruct andRiskLevelenum; addedSkippedPrecheckpool outcome kindsrc/services/quotes.rscompute_slippage_bps,compute_pool_utilization_bps, andcompute_execution_risk(pool-type-aware weights); extendedPoolQuoteResultwithspot_priceandmax_in; wires all three new fields into response constructionsrc/handlers/quote.rsSkippedPrecheckarmsrc/sim_analysis/mod.rsdocs/slippage.mddocs/pool-execution-risk.mddocs/tycho-simulation-library.mdscripts/start_server.sh.gitignoreRisk score formula
Weights differ by pool type (blue-chip pools apply tighter slippage tolerance; stablecoin pools penalise utilization more heavily). Block-lag staleness is excluded from the server-side score — callers should add that penalty using
block_numbervs. the current chain head.lowmediumhighvery_highunknownTest plan
cargo testpasses (216 tests: 182 unit + 32 integration + 2 main)slippage_bps,pool_utilization_bps, andexecution_riskappear in/simulatepool responsesexecution_riskis omitted from the response when insufficient signal is availablepool_typedefaults tovolatile; new fields skip serialisation when absentCloses #45