diff --git a/.env.bak b/.env.bak deleted file mode 100644 index 09d987a..0000000 --- a/.env.bak +++ /dev/null @@ -1,14 +0,0 @@ -# INFRA -MONGO_URL=mongodb://127.0.0.1:27017 -REDIS_URL=redis://localhost:6379 - -# API_KEYS -BUNGEE_API_KEY= -COVALENT_API_KEY= -COINGECKO_API_KEY= - -# RPC_URLS -ETHEREUM_RPC_URL=https://rpc.ankr.com/eth -ARBITRUM_RPC_URL=https://arbitrum.llamarpc.com -OPTIMISM_RPC_URL=https://mainnet.optimism.io -BASE_RPC_URL=https://mainnet.base.org diff --git a/Cargo.lock b/Cargo.lock index a6eba82..4cb8538 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3158,10 +3158,12 @@ dependencies = [ "clap", "config", "dotenv", + "futures-util", "log", "routing-engine", "simple_logger", "storage", + "thiserror", "tokio", "tower-http", ] diff --git a/bin/reflux/Cargo.toml b/bin/reflux/Cargo.toml index 7a3fdb9..4a3c8d2 100644 --- a/bin/reflux/Cargo.toml +++ b/bin/reflux/Cargo.toml @@ -11,6 +11,7 @@ log = "0.4.21" simple_logger = "5.0.0" clap = { version = "4.5.7", features = ["derive"] } dotenv = "0.15.0" +futures-util = "0.3.30" # workspace dependencies account-aggregation = { workspace = true } @@ -18,3 +19,4 @@ storage = { workspace = true } config = { workspace = true } routing-engine = { workspace = true } api = { workspace = true } +thiserror = "1.0.61" diff --git a/bin/reflux/src/main.rs b/bin/reflux/src/main.rs index 6dfedb5..d3d0b42 100644 --- a/bin/reflux/src/main.rs +++ b/bin/reflux/src/main.rs @@ -1,11 +1,14 @@ use std::collections::HashMap; +use std::fmt::Debug; use std::sync::Arc; use std::time::Duration; use axum::http::Method; use clap::Parser; use dotenv::dotenv; +use futures_util::future::join_all; use log::{debug, error, info}; +use tokio::join; use tokio::sync::Mutex; use tower_http::cors::{Any, CorsLayer}; @@ -19,6 +22,10 @@ use routing_engine::settlement_engine::{generate_erc20_instance_map, SettlementE use storage::{ControlFlow, MessageQueue, RedisClient}; use storage::mongodb_client::MongoDBClient; +use crate::utils::find_lowest_transfer_amount_usd; + +mod utils; + #[derive(Parser, Debug)] struct Args { /// Run the Solver (default) @@ -29,6 +36,10 @@ struct Args { #[arg(short, long)] indexer: bool, + /// Run the utility to find the lowest transfer amount in USD for all possible token pairs + #[arg(short, long)] + find_lowest_transfer_amounts_usd: bool, + /// Config file path #[arg(short, long, default_value = "config.yaml")] config: String, @@ -48,11 +59,6 @@ async fn main() { panic!("Cannot run both indexer and solver at the same time"); } - if !args.indexer && !args.solver { - args.solver = true; - debug!("Running Solver by default"); - } - // Load configuration from yaml let config = Arc::new(Config::build_from_file(&args.config).expect("Failed to load config file")); @@ -61,6 +67,11 @@ async fn main() { run_indexer(config).await; } else if args.solver { run_solver(config).await; + } else if args.find_lowest_transfer_amounts_usd { + run_find_lowest_transfer_amount_usd(config).await; + } else { + info!("Running Solver by default"); + run_solver(config).await; } } @@ -228,4 +239,66 @@ async fn run_indexer(config: Arc) { Ok(_) => info!("Indexer Job Completed"), Err(e) => error!("Indexer Job Failed: {}", e), }; -} \ No newline at end of file +} + +async fn run_find_lowest_transfer_amount_usd(config: Arc) { + let redis_client = RedisClient::build(&config.infra.redis_url).await.unwrap(); + let bungee_client = BungeeClient::new(&config.bungee.base_url, &config.bungee.api_key) + .expect("Failed to Instantiate Bungee Client"); + let token_price_provider = Arc::new(Mutex::new(CoingeckoClient::new( + config.coingecko.base_url.clone(), + config.coingecko.api_key.clone(), + redis_client.clone(), + Duration::from_secs(config.coingecko.expiry_sec), + ))); + + let mut results = Vec::new(); + + // Intentionally not running these concurrently to avoid rate limiting + for (_, token_a) in config.tokens.iter() { + for (chain_a, _) in token_a.by_chain.iter() { + for (_, token_b) in config.tokens.iter() { + for (chain_b, _) in token_b.by_chain.iter() { + if token_a.symbol != token_b.symbol || chain_a != chain_b { + results.push(( + ( + *chain_a, + *chain_b, + token_a.symbol.clone(), + token_b.symbol.clone(), + false, + ), + find_lowest_transfer_amount_usd( + &config, + *chain_a, + *chain_b, + &token_a.symbol, + &token_b.symbol, + false, + &bungee_client, + Arc::clone(&token_price_provider), + ) + .await, + )) + } + } + } + } + } + + for result in results { + let (route, amount_result) = result; + + match amount_result { + Ok(amount) => { + info!( + "Found lowest transfer amount in USD for token {} on chain {} to token {} on chain {}: {}", + route.2, route.0, route.3, route.1, amount + ); + } + Err(e) => { + error!("Failed to find lowest transfer amount in USD: {}", e); + } + } + } +} diff --git a/bin/reflux/src/utils.rs b/bin/reflux/src/utils.rs new file mode 100644 index 0000000..eadd370 --- /dev/null +++ b/bin/reflux/src/utils.rs @@ -0,0 +1,95 @@ +use std::sync::Arc; + +use log::{debug, info}; +use thiserror::Error; +use tokio::sync::Mutex; + +use config::Config; +use routing_engine::{CostType, Route, token_price}; +use routing_engine::source::RouteSource; +use routing_engine::token_price::TokenPriceProvider; +use routing_engine::token_price::utils::Errors; + +const TOKEN_AMOUNT_USD_LOWER_BOUND: f64 = 0.0; +const TOKEN_AMOUNT_USD_UPPER_BOUND: f64 = 25.0; +const DIFFERENCE_THRESHOLD_USD: f64 = 0.5; + +pub async fn find_lowest_transfer_amount_usd< + Source: RouteSource, + PriceProvider: TokenPriceProvider, +>( + config: &Config, + from_chain_id: u32, + to_chain_id: u32, + from_token_id: &String, + to_token_id: &String, + is_smart_contract_deposit: bool, + source: &Source, + token_price_provider: Arc>, +) -> Result> { + debug!( + "Finding lowest transfer amount in USD for token {} on chain {} to token {} on chain {}", + from_token_id, from_chain_id, to_token_id, to_chain_id + ); + + let mut low = TOKEN_AMOUNT_USD_LOWER_BOUND; + let mut high = TOKEN_AMOUNT_USD_UPPER_BOUND; + + loop { + let route = Route::build( + config, + &from_chain_id, + &to_chain_id, + from_token_id, + to_token_id, + is_smart_contract_deposit, + )?; + + if high - low < DIFFERENCE_THRESHOLD_USD { + info!("Found lowest transfer amount in USD: {} for route {}", high, route); + break Ok(high); + } + + debug!("Trying with low: {} and high: {} for route {}", low, high, route); + + let mid = (low + high) / 2.0; + + let from_token_amount_in_wei = token_price::utils::get_token_amount_from_value_in_usd( + &config, + &token_price_provider.lock().await, + from_token_id, + from_chain_id, + &mid, + ) + .await + .map_err(FindLowestTransferAmountErr::GetTokenAmountFromValueInUsdErr)?; + + let result = source + .fetch_least_cost_route_and_cost_in_usd( + &route, + &from_token_amount_in_wei, + None, + None, + &CostType::Fee, + ) + .await; + + if result.is_err() { + low = mid; + } else { + high = mid; + } + } +} + +#[derive(Error, Debug)] +pub enum FindLowestTransferAmountErr { + #[error("Failed to build route")] + RouteBuildErr(#[from] routing_engine::RouteError), + + #[error("Failed to fetch route cost")] + FetchRouteCostErr(T::FetchRouteCostError), + + #[error("Failed to get token amount from value in usd")] + GetTokenAmountFromValueInUsdErr(Errors), +} diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..1ed7b26 --- /dev/null +++ b/config.yaml @@ -0,0 +1,2603 @@ +chains: + - id: 42161 + name: Arbitrum + covalent_name: arbitrum-mainnet + is_enabled: true + rpc_url_env_name: ARBITRUM_RPC_URL + - id: 10 + name: Optimism + is_enabled: true + covalent_name: optimism-mainnet + rpc_url_env_name: OPTIMISM_RPC_URL + - id: 8453 + name: Base + is_enabled: true + covalent_name: base-mainnet + rpc_url_env_name: BASE_RPC_URL +tokens: + - symbol: USDC + is_enabled: true + coingecko_symbol: usd-coin + by_chain: + "42161": + is_enabled: true + decimals: 6 + address: "0xaf88d065e77c8cc2239327c5edb3a432268e5831" + "10": + is_enabled: true + decimals: 6 + address: "0x7f5c764cbc14f9669b88837ca1490cca17c31607" + "8453": + is_enabled: true + decimals: 6 + address: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913" + - symbol: USDT + is_enabled: true + coingecko_symbol: tether + by_chain: + "42161": + is_enabled: true + decimals: 6 + address: "0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9" + "10": + is_enabled: true + decimals: 6 + address: "0x94b008aa00579c1307b0ef2c499ad98a8ce58e58" + "8453": + is_enabled: true + decimals: 6 + address: "0xfde4c96c8593536e31f229ea8f37b2ada2699bb2" + - symbol: ETH + is_enabled: true + coingecko_symbol: ethereum + by_chain: + "42161": + is_enabled: true + decimals: 18 + address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + "10": + is_enabled: true + decimals: 18 + address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + "8453": + is_enabled: true + decimals: 18 + address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" +buckets: + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 42161 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 10 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 42161 + to_chain_id: 8453 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 42161 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 10 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 10 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 10 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 10 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 10 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 10 + to_chain_id: 8453 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 42161 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDC + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDT + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 10 + from_token: ETH + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDC + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDC + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDT + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: USDT + to_token: ETH + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: ETH + to_token: USDC + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 3 + token_amount_to_usd: 10 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10 + token_amount_to_usd: 100 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 100 + token_amount_to_usd: 1000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 1000 + token_amount_to_usd: 10000 + - from_chain_id: 8453 + to_chain_id: 8453 + from_token: ETH + to_token: USDT + is_smart_contract_deposit_supported: false + token_amount_from_usd: 10000 + token_amount_to_usd: 100000 +bungee: + base_url: https://api.socket.tech/v2 +covalent: + base_url: "https://api.covalenthq.com" +coingecko: + base_url: "https://api.coingecko.com/api/v3" + expiry_sec: 300 +server: + port: 8080 + host: "localhost" +indexer_config: + indexer_update_topic: indexer_update + indexer_update_message: message + points_per_bucket: 4 +solver_config: + x_value: 2.0 + y_value: 1.0 diff --git a/crates/config/src/config.rs b/crates/config/src/config.rs index a53b927..16463d1 100644 --- a/crates/config/src/config.rs +++ b/crates/config/src/config.rs @@ -1,5 +1,5 @@ +use std::{cmp, env}; use std::collections::HashMap; -use std::env; use std::hash::{DefaultHasher, Hash, Hasher}; use std::num::ParseIntError; use std::ops::Deref; @@ -428,6 +428,43 @@ impl Deref for TokenConfigByChainConfigs { } } +#[derive(Debug, Clone, Deserialize)] +#[serde(try_from = "String")] +pub struct TokenAddress(String); + +impl PartialEq for TokenAddress { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl cmp::Eq for TokenAddress {} + +impl Hash for TokenAddress { + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} + +impl Display for TokenAddress { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl TryFrom for TokenAddress { + type Error = String; + + fn try_from(value: String) -> Result { + let pattern = r"0x[a-fA-F0-9]{40}"; + if regex::Regex::new(pattern).unwrap().is_match(&value) { + Ok(TokenAddress(value.to_lowercase())) + } else { + Err(format!("Invalid Token Address: {}", value)) + } + } +} + #[derive(Debug, Deserialize, Validate, Clone)] pub struct ChainSpecificTokenConfig { // The number of decimals the token has @@ -435,8 +472,7 @@ pub struct ChainSpecificTokenConfig { #[validate(maximum = 18)] pub decimals: u8, // The token address on the chain - #[validate(pattern = r"0x[a-fA-F0-9]{40}")] - pub address: String, + pub address: TokenAddress, // Whether the token is supported on this chain pub is_enabled: bool, } diff --git a/crates/routing-engine/src/indexer.rs b/crates/routing-engine/src/indexer.rs index 1362cf1..114565c 100644 --- a/crates/routing-engine/src/indexer.rs +++ b/crates/routing-engine/src/indexer.rs @@ -395,7 +395,7 @@ mod tests { let mut config = get_sample_config(); config.buckets = vec![ Arc::new(config::BucketConfig { - from_chain_id: 1, + from_chain_id: 10, to_chain_id: 42161, from_token: "USDC".to_string(), to_token: "USDC".to_string(), @@ -404,7 +404,7 @@ mod tests { token_amount_to_usd: 100.0, }), Arc::new(config::BucketConfig { - from_chain_id: 1, + from_chain_id: 10, to_chain_id: 42161, from_token: "USDC".to_string(), to_token: "USDC".to_string(), diff --git a/crates/routing-engine/src/lib.rs b/crates/routing-engine/src/lib.rs index 9316496..4aed5b5 100644 --- a/crates/routing-engine/src/lib.rs +++ b/crates/routing-engine/src/lib.rs @@ -5,8 +5,8 @@ pub use alloy::transports::Transport; use derive_more::Display; use thiserror::Error; -use config::{ChainConfig, TokenConfig}; use config::config::{BucketConfig, Config}; +use config::{ChainConfig, TokenConfig}; pub use indexer::Indexer; pub use source::bungee::BungeeClient; pub use token_price::CoingeckoClient; @@ -26,7 +26,7 @@ pub enum CostType { // BridgingTime, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Route { from_chain: Arc, to_chain: Arc, @@ -35,6 +35,20 @@ pub struct Route { is_smart_contract_deposit: bool, } +impl Display for Route { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "Route: chain: {} -> {}, token: {} -> {}, is_smart_contract_deposit: {}", + self.from_chain.id, + self.to_chain.id, + self.from_token.symbol, + self.to_token.symbol, + self.is_smart_contract_deposit + ) + } +} + impl Route { pub fn build( config: &Config, @@ -102,6 +116,29 @@ pub struct BridgeResult { to_address: String, } +impl Display for BridgeResult { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "BridgeResult: route: {}, source_amount_in_usd: {}, from_address: {}, to_address: {}", + self.route, self.source_amount_in_usd, self.from_address, self.to_address + ) + } +} + +pub struct BridgeResultVecWrapper<'a>(&'a Vec); + +impl Display for BridgeResultVecWrapper<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "[")?; + for bridge_result in self.0 { + write!(f, "{}, ", bridge_result)?; + } + write!(f, "]")?; + Ok(()) + } +} + impl BridgeResult { pub fn build( config: &Config, @@ -141,7 +178,7 @@ mod test { let config = get_sample_config(); let route = super::Route::build( &config, - &1, + &10, &42161, &"USDC".to_string(), &"USDT".to_string(), @@ -157,7 +194,7 @@ mod test { let config = get_sample_config(); let bridge_result = super::BridgeResult::build( &config, - &1, + &10, &42161, &"USDC".to_string(), &"USDT".to_string(), diff --git a/crates/routing-engine/src/routing_engine.rs b/crates/routing-engine/src/routing_engine.rs index 08ae098..712ea71 100644 --- a/crates/routing-engine/src/routing_engine.rs +++ b/crates/routing-engine/src/routing_engine.rs @@ -1,3 +1,4 @@ +use std::cmp; use std::collections::HashMap; use std::sync::Arc; @@ -12,7 +13,7 @@ use storage::{KeyValueStore, RedisClient, RedisClientError}; use crate::{ BridgeResult, - estimator::{Estimator, LinearRegressionEstimator}, Route, + BridgeResultVecWrapper, estimator::{Estimator, LinearRegressionEstimator}, Route, }; /// (from_chain, to_chain, from_token, to_token) @@ -130,7 +131,7 @@ impl RoutingEngine { total_cost += swap_total_cost; } - debug!("Selected assets: {:?}", selected_routes); + debug!("Selected assets: {}", BridgeResultVecWrapper(&selected_routes)); info!( "Total cost for user: {} on chain {} to token {} is {}", account, to_chain, to_token, total_cost @@ -153,9 +154,10 @@ impl RoutingEngine { let mut assets_sorted_by_bridging_cost: Vec<(TokenWithBalance, f64)> = stream::iter(assets.into_iter()) .then(|balance| async move { + let balance_taken = cmp::min_by(to_value_usd, balance.amount_in_usd, |a, b| a.partial_cmp(b).unwrap_or_else(|| cmp::Ordering::Less)); let fee_cost = self .estimate_bridging_cost( - balance.amount_in_usd, + balance_taken, PathQuery( balance.chain_id, to_chain, @@ -193,10 +195,10 @@ impl RoutingEngine { if total_amount_needed <= 0.0 { break; } - let amount_to_take = if balance.amount >= total_amount_needed { + let amount_to_take = if balance.amount_in_usd >= total_amount_needed { total_amount_needed } else { - balance.amount + balance.amount_in_usd }; total_amount_needed -= amount_to_take; total_cost += fee; @@ -245,7 +247,7 @@ impl RoutingEngine { let cache = self.cache.read().await; let value = cache .get(&key) - .ok_or_else(|| RoutingEngineError::CacheError("No cached value found".to_string()))?; + .ok_or_else(|| RoutingEngineError::CacheError(format!("No cached value found for {}", key)))?; let estimator: LinearRegressionEstimator = serde_json::from_str(value)?; Ok(estimator.estimate(target_amount_in_usd)) @@ -359,7 +361,7 @@ mod tests { DataPoint { x: 1.0, y: 1.0 }, DataPoint { x: 2.0, y: 2.0 }, ]) - .unwrap(); + .unwrap(); let serialized_estimator = serde_json::to_string(&dummy_estimator)?; // Create a cache with a dummy bucket @@ -374,8 +376,8 @@ mod tests { "test".to_string(), true, ) - .await - .unwrap(); + .await + .unwrap(); let aas_client = Arc::new(AccountAggregationService::new( user_db_provider.clone(), @@ -424,8 +426,8 @@ mod tests { "test".to_string(), true, ) - .await - .unwrap(); + .await + .unwrap(); let aas_client = Arc::new(AccountAggregationService::new( user_db_provider.clone(), user_db_provider.clone(), @@ -460,7 +462,7 @@ mod tests { DataPoint { x: 1.0, y: 1.0 }, DataPoint { x: 2.0, y: 2.0 }, ]) - .unwrap(); + .unwrap(); let serialized_estimator = serde_json::to_string(&dummy_estimator)?; // Create a cache with a dummy bucket let key1 = buckets[0].get_hash().to_string(); diff --git a/crates/routing-engine/src/settlement_engine.rs b/crates/routing-engine/src/settlement_engine.rs index ce98cc2..805b8aa 100644 --- a/crates/routing-engine/src/settlement_engine.rs +++ b/crates/routing-engine/src/settlement_engine.rs @@ -12,9 +12,9 @@ use serde::Serialize; use thiserror::Error; use tokio::sync::Mutex; -use config::Config; +use config::{Config, TokenAddress}; -use crate::{blockchain, BridgeResult}; +use crate::{blockchain, BridgeResult, BridgeResultVecWrapper}; use crate::blockchain::erc20::IERC20::IERC20Instance; use crate::source::{EthereumTransaction, RequiredApprovalDetails, RouteSource}; use crate::token_price::TokenPriceProvider; @@ -25,7 +25,7 @@ pub struct SettlementEngine, price_provider: Arc>, // (chain_id, token_address) -> contract - erc20_instance_map: HashMap<(u32, String), blockchain::ERC20Contract>, + erc20_instance_map: HashMap<(u32, TokenAddress), blockchain::ERC20Contract>, } #[derive(Debug, PartialEq, Serialize)] @@ -49,7 +49,7 @@ impl config: Arc, source: Source, price_provider: Arc>, - erc20_instance_map: HashMap<(u32, String), blockchain::ERC20Contract>, + erc20_instance_map: HashMap<(u32, TokenAddress), blockchain::ERC20Contract>, ) -> Self { SettlementEngine { source, config, price_provider, erc20_instance_map } } @@ -58,7 +58,7 @@ impl &self, routes: Vec, ) -> Result, SettlementEngineErrors> { - info!("Generating transactions for routes: {:?}", routes); + info!("Generating transactions for routes: {}", BridgeResultVecWrapper(&routes)); let (results, failed): ( Vec< @@ -70,7 +70,7 @@ impl _, ) = futures::stream::iter(routes.into_iter()) .map(|route| async move { - info!("Generating transactions for route: {:?}", route.route); + info!("Generating transactions for route: {}", route.route); let token_amount = get_token_amount_from_value_in_usd( &self.config, @@ -82,7 +82,7 @@ impl .await .map_err(|err| SettlementEngineErrors::GetTokenAmountFromValueInUsdError(err))?; - info!("Token amount: {:?} for route {:?}", token_amount, route); + info!("Token amount: {:?} for route {}", token_amount, route); let (ethereum_transactions, required_approval_details) = self .source @@ -95,7 +95,7 @@ impl .await .map_err(|err| SettlementEngineErrors::GenerateTransactionsError(err))?; - info!("Generated transactions: {:?} for route {:?}", ethereum_transactions, route); + info!("Generated transactions: {:?} for route {}", ethereum_transactions, route); Ok::<_, SettlementEngineErrors<_, _>>(( ethereum_transactions, @@ -108,9 +108,10 @@ impl .into_iter() .partition(Result::is_ok); - let failed: Vec<_> = failed.into_iter().map(Result::unwrap_err).collect(); + let mut failed: Vec<_> = failed.into_iter().map(Result::unwrap_err).collect(); if !failed.is_empty() { error!("Failed to generate transactions: {:?}", failed); + return Err(failed.remove(0)); } if results.is_empty() { @@ -200,7 +201,8 @@ impl Ok(Some(TransactionWithType { transaction: EthereumTransaction { - from: required_approval_details.owner.clone(), + from_address: required_approval_details.owner.clone(), + from_chain: required_approval_details.chain_id, to: token_instance.address().to_string(), value: Uint::ZERO, calldata, @@ -217,7 +219,7 @@ impl // Group the approvals and combine them based on chain_id, token_address, spender and target let mut approvals_grouped = - HashMap::<(u32, &String, &String, &String), Vec<&RequiredApprovalDetails>>::new(); + HashMap::<(u32, &TokenAddress, &String, &String), Vec<&RequiredApprovalDetails>>::new(); for approval in approvals { let key = (approval.chain_id, &approval.token_address, &approval.owner, &approval.target); @@ -307,7 +309,7 @@ pub enum SettlementEngineErrors Result, Vec> -{ +) -> Result< + HashMap<(u32, TokenAddress), blockchain::ERC20Contract>, + Vec, +> { let (result, failed): (Vec<_>, _) = config .tokens .iter() @@ -329,7 +333,10 @@ pub fn generate_erc20_instance_map( .iter() .map( |(chain_id, chain_specific_config)| -> Result< - ((u32, String), IERC20Instance, RootProvider>>), + ( + (u32, TokenAddress), + IERC20Instance, RootProvider>>, + ), GenerateERC20InstanceMapErrors, > { let rpc_url = &config @@ -345,15 +352,17 @@ pub fn generate_erc20_instance_map( |_| GenerateERC20InstanceMapErrors::InvalidRPCUrl(rpc_url.clone()), )?); - let token_address = - chain_specific_config.address.clone().parse().map_err(|err| { + let token_address = chain_specific_config.address.clone(); + + let token = blockchain::ERC20Contract::new( + token_address.to_string().parse().map_err(|err| { GenerateERC20InstanceMapErrors::InvalidAddressError( - chain_specific_config.address.clone(), + token_address.clone().to_string(), err, ) - })?; - - let token = blockchain::ERC20Contract::new(token_address, provider); + })?, + provider, + ); Ok(((*chain_id, chain_specific_config.address.clone()), token)) }, @@ -489,7 +498,7 @@ mod tests { let required_approval_data = RequiredApprovalDetails { chain_id: 42161, - token_address: TOKEN_ADDRESS_USDC_42161.to_string(), + token_address: TOKEN_ADDRESS_USDC_42161.to_string().try_into().unwrap(), owner: TEST_OWNER_WALLET.to_string(), target: TARGET_NO_APPROVAL_BY_OWNER_ON_42161_FOR_USDC.to_string(), amount: U256::from(100), @@ -529,7 +538,7 @@ mod tests { let required_approval_data = RequiredApprovalDetails { chain_id: 42161, - token_address: TOKEN_ADDRESS_USDC_42161.to_string(), + token_address: TOKEN_ADDRESS_USDC_42161.to_string().try_into().unwrap(), owner: TEST_OWNER_WALLET.to_string(), target: TARGET_100_USDC_APPROVAL_BY_OWNER_ON_42161_FOR_USDC.to_string(), amount: U256::from(150), @@ -570,14 +579,14 @@ mod tests { let required_approval_datas = vec![ RequiredApprovalDetails { chain_id: 42161, - token_address: TOKEN_ADDRESS_USDC_42161.to_string(), + token_address: TOKEN_ADDRESS_USDC_42161.to_string().try_into().unwrap(), owner: TEST_OWNER_WALLET.to_string(), target: TARGET_NO_APPROVAL_BY_OWNER_ON_42161_FOR_USDC.to_string(), amount: U256::from(100), }, RequiredApprovalDetails { chain_id: 42161, - token_address: TOKEN_ADDRESS_USDC_42161.to_string(), + token_address: TOKEN_ADDRESS_USDC_42161.to_string().try_into().unwrap(), owner: TEST_OWNER_WALLET.to_string(), target: TARGET_100_USDC_APPROVAL_BY_OWNER_ON_42161_FOR_USDC.to_string(), amount: U256::from(150), @@ -644,14 +653,14 @@ mod tests { let required_approval_datas = vec![ RequiredApprovalDetails { chain_id: 42161, - token_address: TOKEN_ADDRESS_USDC_42161.to_string(), + token_address: TOKEN_ADDRESS_USDC_42161.to_string().try_into().unwrap(), owner: TEST_OWNER_WALLET.to_string(), target: TARGET_NO_APPROVAL_BY_OWNER_ON_42161_FOR_USDC.to_string(), amount: U256::from(100), }, RequiredApprovalDetails { chain_id: 42161, - token_address: TOKEN_ADDRESS_USDC_42161.to_string(), + token_address: TOKEN_ADDRESS_USDC_42161.to_string().try_into().unwrap(), owner: TEST_OWNER_WALLET.to_string(), target: TARGET_NO_APPROVAL_BY_OWNER_ON_42161_FOR_USDC.to_string(), amount: U256::from(150), @@ -693,12 +702,12 @@ mod tests { let bridge_result = BridgeResult::build( &config, - &1, &42161, + &10, &"USDC".to_string(), &"USDC".to_string(), false, - 100.0, + 1000.0, TEST_OWNER_WALLET.to_string(), TEST_OWNER_WALLET.to_string(), ) @@ -721,12 +730,12 @@ mod tests { let bridge_result = BridgeResult::build( &config, - &1, - &1, + &42161, + &10, &"USDC".to_string(), &"USDT".to_string(), false, - 100.0, + 1000.0, TEST_OWNER_WALLET.to_string(), TEST_OWNER_WALLET.to_string(), ) diff --git a/crates/routing-engine/src/source/bungee/mod.rs b/crates/routing-engine/src/source/bungee/mod.rs index 2328123..efa0310 100644 --- a/crates/routing-engine/src/source/bungee/mod.rs +++ b/crates/routing-engine/src/source/bungee/mod.rs @@ -19,7 +19,7 @@ use crate::source::{EthereumTransaction, RequiredApprovalDetails, RouteSource}; mod types; -const BUNGEE_API_RATE_LIMIT: u32 = 2; +const BUNGEE_API_RATE_LIMIT: u32 = 3; #[derive(Debug)] pub struct BungeeClient { @@ -126,6 +126,9 @@ pub enum GenerateRouteTransactionsError { #[error("Error while parsing U256: {0}")] InvalidU256Error(String), + + #[error("Error while parsing Address: {0}")] + InvalidAddressError(String), } #[async_trait] @@ -170,14 +173,15 @@ impl RouteSource for BungeeClient { let request = GetQuoteRequest { from_chain_id: route.from_chain.id, - from_token_address: from_token.address.clone(), + from_token_address: from_token.address.to_string(), to_chain_id: route.to_chain.id, - to_token_address: to_token.address.clone(), + to_token_address: to_token.address.to_string(), from_amount: from_token_amount.to_string(), user_address: sender_address.unwrap_or(&ADDRESS_ZERO.to_string()).clone(), recipient: recipient_address.unwrap_or(&ADDRESS_ZERO.to_string()).clone(), - unique_routes_per_bridge: false, + unique_routes_per_bridge: true, is_contract_call: route.is_smart_contract_deposit, + single_tx_only: true, }; // Get quote @@ -219,7 +223,10 @@ impl RouteSource for BungeeClient { } if route_costs_in_usd.len() == 0 { - error!("No valid routes returned by Bungee API for route {:?}", route); + error!( + "No valid routes returned by Bungee API for route {} and from_token_amount {}", + route, from_token_amount + ); return Err(BungeeFetchRouteCostError::NoValidRouteError()); } @@ -246,10 +253,7 @@ impl RouteSource for BungeeClient { (Vec, Vec), Self::GenerateRouteTransactionsError, > { - info!( - "Generating cheapest route transactions for route {:?} with amount {}", - route, amount - ); + info!("Generating cheapest route transactions for route {} with amount {}", route, amount); let (bungee_route, _) = self .fetch_least_cost_route_and_cost_in_usd( @@ -261,7 +265,7 @@ impl RouteSource for BungeeClient { ) .await?; - info!("Retrieved bungee route {:?} for route {:?}", bungee_route, route); + info!("Retrieved bungee route {} for route {}", bungee_route, route); let tx = self.build_tx(BuildTxRequest { route: bungee_route }).await?; if !tx.success { @@ -276,7 +280,8 @@ impl RouteSource for BungeeClient { info!("Returned transaction from bungee {:?}", tx); let transactions = vec![EthereumTransaction { - from: sender_address.clone(), + from_address: sender_address.clone(), + from_chain: route.to_chain.id, to: tx.tx_target, value: Uint::from_str(&tx.value).map_err(|err| { error!("Error while parsing tx data: {}", err); @@ -287,18 +292,24 @@ impl RouteSource for BungeeClient { info!("Generated transactions {:?}", transactions); - let approvals = vec![RequiredApprovalDetails { - chain_id: tx.chain_id, - token_address: tx.approval_data.approval_token_address, - owner: tx.approval_data.owner, - target: tx.approval_data.allowance_target, - amount: Uint::from_str(&tx.approval_data.minimum_approval_amount).map_err(|err| { - error!("Error while parsing approval data: {}", err); - GenerateRouteTransactionsError::InvalidU256Error( - tx.approval_data.minimum_approval_amount, - ) - })?, - }]; + let approvals = match tx.approval_data { + Some(approval_data) => vec![RequiredApprovalDetails { + chain_id: tx.chain_id, + token_address: approval_data + .approval_token_address + .try_into() + .map_err(GenerateRouteTransactionsError::InvalidAddressError)?, + owner: approval_data.owner, + target: approval_data.allowance_target, + amount: Uint::from_str(&approval_data.minimum_approval_amount).map_err(|err| { + error!("Error while parsing approval data: {}", err); + GenerateRouteTransactionsError::InvalidU256Error( + approval_data.minimum_approval_amount, + ) + })?, + }], + None => vec![], + }; info!("Generated approvals {:?}", approvals); @@ -346,6 +357,7 @@ mod tests { recipient: "0x0000000000000000000000000000000000000000".to_string(), is_contract_call: false, unique_routes_per_bridge: false, + single_tx_only: true, }) .await .unwrap(); @@ -359,9 +371,9 @@ mod tests { let (config, client) = setup(); let route = - Route::build(&config, &1, &42161, &"USDC".to_string(), &"USDC".to_string(), false) + Route::build(&config, &10, &42161, &"USDC".to_string(), &"USDC".to_string(), false) .unwrap(); - let (_, least_route_cost) = client + let result = client .fetch_least_cost_route_and_cost_in_usd( &route, &Uint::from(100000000), @@ -369,10 +381,9 @@ mod tests { None, &CostType::Fee, ) - .await - .unwrap(); + .await; - assert_eq!(least_route_cost > 0.0, true); + assert!(result.is_ok()); } #[tokio::test] @@ -380,7 +391,7 @@ mod tests { let (config, client) = setup(); let route = - Route::build(&config, &1, &42161, &"USDC".to_string(), &"USDC".to_string(), false) + Route::build(&config, &10, &42161, &"USDC".to_string(), &"USDC".to_string(), false) .unwrap(); let address = "0x90f05C1E52FAfB4577A4f5F869b804318d56A1ee".to_string(); diff --git a/crates/routing-engine/src/source/bungee/types.rs b/crates/routing-engine/src/source/bungee/types.rs index e4a71ca..ad32604 100644 --- a/crates/routing-engine/src/source/bungee/types.rs +++ b/crates/routing-engine/src/source/bungee/types.rs @@ -19,6 +19,7 @@ pub struct GetQuoteRequest { pub recipient: String, pub is_contract_call: bool, pub unique_routes_per_bridge: bool, + pub single_tx_only: bool, } #[derive(Serialize, Deserialize, Debug, Clone, Default)] @@ -85,7 +86,7 @@ pub struct BuildTxResponse { pub tx_type: String, pub value: String, pub total_user_tx: Option, - pub approval_data: BuildTxResponseApprovalData, + pub approval_data: Option, } #[derive(Serialize, Deserialize, Debug)] diff --git a/crates/routing-engine/src/source/mod.rs b/crates/routing-engine/src/source/mod.rs index 2bfeead..2cf0e5c 100644 --- a/crates/routing-engine/src/source/mod.rs +++ b/crates/routing-engine/src/source/mod.rs @@ -5,13 +5,16 @@ use async_trait::async_trait; use ruint::aliases::U256; use serde::Serialize; +use config::TokenAddress; + use crate::{CostType, Route}; pub mod bungee; #[derive(Debug, Serialize)] pub struct EthereumTransaction { - pub from: String, + pub from_address: String, + pub from_chain: u32, pub to: String, pub value: U256, pub calldata: String, @@ -20,7 +23,7 @@ pub struct EthereumTransaction { #[derive(Debug, Clone)] pub struct RequiredApprovalDetails { pub chain_id: u32, - pub token_address: String, + pub token_address: TokenAddress, pub owner: String, pub target: String, pub amount: U256, diff --git a/crates/routing-engine/src/token_price/utils.rs b/crates/routing-engine/src/token_price/utils.rs index ca2bca8..232fc6a 100644 --- a/crates/routing-engine/src/token_price/utils.rs +++ b/crates/routing-engine/src/token_price/utils.rs @@ -103,7 +103,7 @@ mod tests { let token_price_provider = Arc::new(Mutex::new(TokenPriceProviderStub {})); let token_symbol = String::from("USDC"); - let chain_id = 1; + let chain_id = 10; let value_in_usd = 10.0; let result = super::get_token_amount_from_value_in_usd(