From 12e6e48a78e336ec03b62511f855265408db8bd4 Mon Sep 17 00:00:00 2001 From: TAMARA LIPOWSKI Date: Fri, 19 Sep 2025 01:35:21 -0400 Subject: [PATCH] feat: Add test for UniswapV2 - Used a random post-Shanghai-created USV2 pool state with enough liquidity for the test Necessary fixes: - Don't hardcode to EVMPoolState - Don't expect adapter to always be set. - UniswapV2 names its module differently for some reason... this seems like a special case so instead of updating all integration test yamls, I'm just hardcoding it in test_runner.rs. Perhaps not the best decision? - Log the static attributes if not found. - Get the substreams yaml path from config instead of hardcoding it. --- protocol-testing/src/config.rs | 6 +-- protocol-testing/src/test_runner.rs | 71 +++++++++++++++++++--------- protocol-testing/src/tycho_runner.rs | 8 +++- 3 files changed, 58 insertions(+), 27 deletions(-) diff --git a/protocol-testing/src/config.rs b/protocol-testing/src/config.rs index ff4e52d..f5338b9 100644 --- a/protocol-testing/src/config.rs +++ b/protocol-testing/src/config.rs @@ -66,8 +66,8 @@ impl ProtocolComponentExpectation { } None => { diffs.push(format!( - "Field 'static_attributes' mismatch for {}: Key '{}' not found", - self.id, key + "Field 'static_attributes' mismatch for {}: Key '{}' not found. Available attributes: {:?}", + self.id, key, other.static_attributes, )); } } @@ -136,7 +136,7 @@ pub struct IntegrationTest { #[derive(Debug, Clone, Deserialize, Serialize)] pub struct IntegrationTestsConfig { pub substreams_yaml_path: String, - pub adapter_contract: String, + pub adapter_contract: Option, pub adapter_build_signature: Option, pub adapter_build_args: Option, pub initialized_accounts: Option>, diff --git a/protocol-testing/src/test_runner.rs b/protocol-testing/src/test_runner.rs index e859fcc..c3e556b 100644 --- a/protocol-testing/src/test_runner.rs +++ b/protocol-testing/src/test_runner.rs @@ -22,7 +22,10 @@ use tycho_simulation::{ evm::{ decoder::TychoStreamDecoder, engine_db::tycho_db::PreCachedDB, - protocol::{u256_num::bytes_to_u256, vm::state::EVMPoolState}, + protocol::{ + u256_num::bytes_to_u256, uniswap_v2::state::UniswapV2State, + uniswap_v3::state::UniswapV3State, vm::state::EVMPoolState, + }, }, protocol::models::DecoderContext, tycho_client::feed::{ @@ -84,13 +87,6 @@ impl TestRunner { ); return Ok(()); } - let substreams_yaml_path = self - .substreams_path - .join("substreams.yaml"); - if !substreams_yaml_path.exists() { - warn!("substreams.yaml file not found at {}", self.substreams_path.display()); - return Ok(()); - } let config = match Self::parse_config(&config_yaml_path) { Ok(cfg) => cfg, @@ -100,6 +96,14 @@ impl TestRunner { } }; + let substreams_yaml_path = self + .substreams_path + .join(&config.substreams_yaml_path); + if !substreams_yaml_path.exists() { + warn!("substreams.yaml file not found at {}", substreams_yaml_path.display()); + return Ok(()); + } + let tests = match &self.match_test { Some(filter) => config .tests @@ -340,9 +344,15 @@ fn validate_state( return Ok(()); } - // Build/find the adapter contract - let adapter_contract_path = - match adapter_contract_builder.find_contract(&config.adapter_contract) { + let adapter_contract_path; + let mut adapter_contract_path_str: Option<&str> = None; + + // Adapter contract will only be configured for VM protocols, not natively implemented + // protocols. + if let Some(adapter_contract_name) = &config.adapter_contract { + // Build/find the adapter contract + adapter_contract_path = match adapter_contract_builder.find_contract(adapter_contract_name) + { Ok(path) => { info!("Found adapter contract at: {}", path.display()); path @@ -351,7 +361,7 @@ fn validate_state( info!("Adapter contract not found, building it..."); adapter_contract_builder .build_target( - &config.adapter_contract, + adapter_contract_name, config .adapter_build_signature .as_deref(), @@ -361,21 +371,36 @@ fn validate_state( } }; - info!("Using adapter contract: {}", adapter_contract_path.display()); - let adapter_contract_path_str: &str = adapter_contract_path.to_str().unwrap(); + info!("Using adapter contract: {}", adapter_contract_path.display()); + adapter_contract_path_str = Some(adapter_contract_path.to_str().unwrap()); + } // Clear the shared database state to ensure test isolation // This prevents state from previous tests from affecting the current test tycho_simulation::evm::engine_db::SHARED_TYCHO_DB.clear(); let mut decoder = TychoStreamDecoder::new(); - let decoder_context = DecoderContext::new() - .vm_adapter_path(adapter_contract_path_str) - .vm_traces(vm_traces); - decoder.register_decoder_with_context::>( - protocol_system, - decoder_context, - ); + let mut decoder_context = DecoderContext::new().vm_traces(vm_traces); + + if let Some(vm_adapter_path) = adapter_contract_path_str { + decoder_context = decoder_context.vm_adapter_path(vm_adapter_path); + } + match protocol_system.as_str() { + "uniswap_v2" | "sushiswap_v2" => { + decoder + .register_decoder_with_context::(protocol_system, decoder_context); + } + "uniswap_v3" | "pancakeswap_v3" => { + decoder + .register_decoder_with_context::(protocol_system, decoder_context); + } + _ => { + decoder.register_decoder_with_context::>( + protocol_system, + decoder_context, + ); + } + } // Mock a stream message, with only a Snapshot and no deltas let mut states: HashMap = HashMap::new(); @@ -398,8 +423,8 @@ fn validate_state( state, component: component.clone(), component_tvl: None, - entrypoints: vec![], - }; // TODO + entrypoints: vec![], // UniswapV4 is not supported for SDK testing at the moment + }; states.insert(component_id.clone(), component_with_state); } // Convert vm_storages to a HashMap - match Python behavior exactly diff --git a/protocol-testing/src/tycho_runner.rs b/protocol-testing/src/tycho_runner.rs index c35eeed..9cccd3e 100644 --- a/protocol-testing/src/tycho_runner.rs +++ b/protocol-testing/src/tycho_runner.rs @@ -39,6 +39,12 @@ impl TychoRunner { let all_accounts = self.initialized_accounts.clone(); + // Determine the correct module name based on protocol system + let module_name = match protocol_system { + "uniswap_v2" => "map_pool_events", + _ => "map_protocol_changes", + }; + cmd.args([ "--database-url", self.db_url.as_str(), @@ -46,7 +52,7 @@ impl TychoRunner { "--spkg", spkg_path, "--module", - "map_protocol_changes", + module_name, "--protocol-type-names", &protocol_type_names.join(","), "--protocol-system",