feat: Rust testing SDK - implement get_amount_out simulation

This commit is contained in:
TAMARA LIPOWSKI
2025-09-04 00:39:40 -04:00
committed by Tamara
parent 5f8dccb729
commit f5bcd31d66
3 changed files with 54 additions and 12 deletions

View File

@@ -5429,6 +5429,8 @@ dependencies = [
"glob",
"hex",
"miette",
"num-bigint",
"num-traits",
"postgres",
"serde",
"serde_json",

View File

@@ -14,6 +14,8 @@ tycho-client = "0.82.0"
tycho-simulation = { git = "https://github.com/propeller-heads/tycho-simulation.git", tag = "0.156.0", features = ["evm"] }
## TODO: for local development
#tycho-simulation = { path = "../../tycho-simulation" }
num-bigint = "0.4"
num-traits = "0.2"
# EVM dependencies
alloy = { version = "1.0.27", features = ["arbitrary", "json", "dyn-abi", "sol-types", "contract", "provider-http"] }
tokio = { version = "1", features = ["full"] }

View File

@@ -6,6 +6,8 @@ use figment::{
Figment,
};
use miette::{miette, IntoDiagnostic, WrapErr};
use num_bigint::BigUint;
use num_traits::Zero;
use postgres::{Client, Error, NoTls};
use tokio::runtime::Runtime;
use tracing::{debug, error, info};
@@ -406,18 +408,54 @@ fn validate_state(
.map(|price| info!("Spot price {:?}: {:?}", formatted_token_str, price))
.map_err(|e| info!("Error calculating spot price for Pool {:?}: {:?}", id, e))
.ok();
// let amount_in =
// BigUint::from(1u32) * BigUint::from(10u32).pow(tokens[0].decimals as u32);
// state
// .get_amount_out(amount_in, &tokens[0], &tokens[1])
// .map(|result| {
// println!(
// "Amount out for trading 1 {:?} -> {:?}: {:?} (takes {:?} gas)",
// &tokens[0].symbol, &tokens[1].symbol, result.amount, result.gas
// )
// })
// .map_err(|e| eprintln!("Error calculating amount out for Pool {:?}: {:?}", id,
// e)) .ok();
// Test get_amount_out with different percentages of limits. The reserves or limits are
// relevant because we need to know how much to test with. We dont know if a pool is
// going to revert with 10 or 10 million USDC, for example, so by using the limits we
// can use “safe values” where the sim shouldnt break.
let percentages = [0.001, 0.01, 0.1];
for percentage in &percentages {
// Get limits for this token pair
let limits = state
.get_limits(tokens[0].address.clone(), tokens[1].address.clone())
.map_err(|e| info!("Error getting limits for Pool {:?}: {:?}", id, e))
.ok();
if let Some((max_input, _max_output)) = limits {
// Calculate test amount as percentage of max input
let percentage_biguint = BigUint::from((percentage * 1000.0) as u32);
let thousand = BigUint::from(1000u32);
let amount_in = (&max_input * &percentage_biguint) / &thousand;
// Skip if amount is zero
if amount_in.is_zero() {
continue;
}
state
.get_amount_out(amount_in.clone(), &tokens[0], &tokens[1])
.map(|result| {
info!(
"Amount out for trading {:.1}% of max ({} -> {}): {} {} (gas: {})",
percentage * 100.0,
&tokens[0].symbol,
&tokens[1].symbol,
result.amount,
&tokens[1].symbol,
result.gas
)
})
.map_err(|e| {
info!(
"Error calculating amount out for Pool {:?} at {:.1}%: {:?}",
id,
percentage * 100.0,
e
)
})
.ok();
}
}
}
}