tycho_simulation/price_level_stream/config.rs
1use std::str::FromStr;
2
3use num_bigint::BigUint;
4use tycho_common::Bytes;
5
6/// Protocol system family name of components sourced from the pAMM price level stream.
7///
8/// The full protocol system of a component is `pricelevelstream:{pamm}`, where `{pamm}` is the
9/// configured venue name (e.g. `pricelevelstream:fermiswap`) or, for auto-detected venues, the
10/// venue address (e.g. `pricelevelstream:0x5979…`); see the [module documentation](super) for
11/// details.
12pub const PRICE_LEVEL_STREAM_FAMILY: &str = "pricelevelstream";
13
14/// Protocol system family of components executed through Tycho's `TychoFallbackRouter`, which
15/// retries a reverted pAMM swap on the fallback pool the solver names in the swap's `user_data`.
16///
17/// Must match `tycho-execution`'s `FALLBACK_KEY`.
18pub const FALLBACK_FAMILY: &str = "fallback";
19
20/// Configuration of a single pAMM to be served from the price level stream.
21#[derive(Debug, Clone)]
22pub struct PriceLevelStreamConfig {
23 /// Bare pAMM name (e.g. `fermiswap`); the emitted components carry
24 /// `pricelevelstream:{protocol}` as their protocol system.
25 pub protocol: String,
26 /// The pAMM venue address under which Titan streams its quotes.
27 pub address: Bytes,
28 /// Constant per-swap gas cost estimate reported for every quote of this pAMM.
29 pub gas_cost: BigUint,
30}
31
32impl PriceLevelStreamConfig {
33 pub fn new(protocol: impl Into<String>, address: Bytes, gas_cost: BigUint) -> Self {
34 Self { protocol: protocol.into(), address, gas_cost }
35 }
36
37 /// The configuration an auto-detected pAMM (streamed by Titan but not otherwise configured)
38 /// is served under: named by its full lowercase hex address, with the given per-swap gas
39 /// cost.
40 pub(super) fn auto_detected(address: Bytes, gas_cost: BigUint) -> Self {
41 let protocol = address.to_string();
42 Self::new(protocol, address, gas_cost)
43 }
44
45 /// The protocol system identifier of components emitted for this pAMM.
46 pub fn protocol_system(&self) -> String {
47 format!("{PRICE_LEVEL_STREAM_FAMILY}:{}", self.protocol)
48 }
49
50 /// The protocol system identifier when this pAMM executes through `TychoFallbackRouter`.
51 pub fn fallback_protocol_system(&self) -> String {
52 format!("{FALLBACK_FAMILY}:{}", self.protocol)
53 }
54}
55
56/// Per-swap gas estimate for auto-detected pAMMs whose venue has not been measured: the maximum
57/// over the known venue profiles (see [`default_served_pamms`]), as the conservative choice.
58/// Overridable per stream via
59/// [`auto_detected_gas_cost`](super::stream::PriceLevelStreamBuilder::auto_detected_gas_cost).
60pub const DEFAULT_AUTO_DETECTED_GAS_COST: u64 = 335_000;
61
62/// The pAMMs known to be served by the Titan price level stream (as of 2026-09-11): FermiSwap,
63/// Kipseli, Metric, Bebop, TaurusFi, and Tempest.
64///
65/// Registered on a builder via
66/// [`with_known_pamms`](super::stream::PriceLevelStreamBuilder::with_known_pamms), so their
67/// components carry the venue name instead of the raw address; an
68/// [`add_pamm`](super::stream::PriceLevelStreamBuilder::add_pamm) call for one of these
69/// addresses overrides the corresponding entry.
70///
71/// Only the venues' router addresses are registered — the keys the price level stream has been
72/// observed to use — because the streamed key doubles as the execution target
73/// ([`PAMM_ADDRESS_ATTRIBUTE`](super::stream::PAMM_ADDRESS_ATTRIBUTE)): unlike the state-override
74/// stream, which also publishes frames under non-executable oracle aliases, an entry here must
75/// be an address a swap can be sent to.
76pub fn default_served_pamms() -> Vec<PriceLevelStreamConfig> {
77 // The venues' `IPropAMM::swap` gas, calibrated by replaying real fills on the live venues at
78 // fresh-oracle blocks via `debug_traceCall`, plus a small headroom. Deliberately excludes
79 // router-level overhead (user/input/fee transfers): tycho-execution's gas estimator accounts
80 // for those on top of this per-swap value.
81 let pamms = [
82 // The FermiSwapper router. Measured ~177k-182k (2026-08-18).
83 ("fermiswap", "0x5979458912f80b96d30d4220af8e2e4925a33320", 185_000u64),
84 // The KipseliPropAMMWrapper router. Measured ~308k-329k (2026-08-18). Titan's venue docs
85 // list a newer Kipseli router (0x342b8458…), but the stream still keys Kipseli
86 // quotes by this address and the newer one has no activity.
87 ("kipseli", "0x71e790dd841c8a9061487cb3e78c288e75ce0b3d", 335_000u64),
88 // The Metric router (unverified; identified via its pools' pricing reads of the Metric
89 // oracle 0x28d9cced…). Measured ~225k (2026-08-18).
90 ("metric", "0xe715dc29d2c273d0fc5a03e5cca9ccb0abb1dcdb", 230_000u64),
91 // The BopAMM (Bebop) router, per Titan's venue docs. Measured ~133k-136k (2026-08-18).
92 ("bebop", "0xb09aaa5614916d7aeb59c295c52c92ca82addd76", 140_000u64),
93 // The TaurusFi router, per Titan's venue docs. Measured ~105k (2026-08-18).
94 ("taurusfi", "0x217d58931a8549ca539426aa8152e33dafc3d95a", 110_000u64),
95 // The Tempest router (unverified), per Titan's venue docs. Measured ~120k-155k
96 // (2026-09-11).
97 ("tempest", "0x00000003f1ec2379e79f58e12ec6c4f51ee92149", 160_000u64),
98 ];
99 pamms
100 .into_iter()
101 .map(|(protocol, address, gas_cost)| {
102 PriceLevelStreamConfig::new(
103 protocol,
104 Bytes::from_str(address).expect("hardcoded pAMM address must parse"),
105 BigUint::from(gas_cost),
106 )
107 })
108 .collect()
109}
110
111/// The streamed venues known NOT to be executable through the generic executor, excluded from
112/// auto-detection via
113/// [`with_known_pamms`](super::stream::PriceLevelStreamBuilder::with_known_pamms): quoting them
114/// would advertise liquidity every routed swap reverts on. An
115/// [`add_pamm`](super::stream::PriceLevelStreamBuilder::add_pamm) entry for one of these
116/// addresses overrides the denial.
117pub fn default_denied_pamms() -> Vec<Bytes> {
118 // No streamed venue is currently known to reject the executor's swap. This is where one
119 // goes that gates settlement — on a taker allowlist, say — or otherwise reverts a swap sent
120 // by an arbitrary caller.
121 Vec::new()
122}