From 910448dd36b5dae1db319d56a3193095d5ceddbe Mon Sep 17 00:00:00 2001 From: 0xh3rman <119309671+0xh3rman@users.noreply.github.com> Date: Mon, 13 Jan 2025 11:04:39 +0900 Subject: [PATCH 1/5] match enabled assets with swapper, add cross chain check to universal router --- crates/gem_evm/src/across/deployment.rs | 77 +++----------------- gemstone/src/swapper/universal_router/mod.rs | 5 +- 2 files changed, 13 insertions(+), 69 deletions(-) diff --git a/crates/gem_evm/src/across/deployment.rs b/crates/gem_evm/src/across/deployment.rs index 6a7d8c9e..06c66858 100644 --- a/crates/gem_evm/src/across/deployment.rs +++ b/crates/gem_evm/src/across/deployment.rs @@ -78,81 +78,22 @@ impl AcrossDeployment { HashMap::from([ ( Chain::Ethereum, - vec![ - ACX_ETH_ASSET_ID.into(), - DAI_ETH_ASSET_ID.into(), - USDC_ETH_ASSET_ID.into(), - USDT_ETH_ASSET_ID.into(), - USDC_E_ETH_ASSET_ID.into(), - WBTC_ETH_ASSET_ID.into(), - WETH_ETH_ASSET_ID.into(), - ], - ), - ( - Chain::Optimism, - vec![ - ACX_OP_ASSET_ID.into(), - DAI_OP_ASSET_ID.into(), - USDT_OP_ASSET_ID.into(), - USDC_OP_ASSET_ID.into(), - USDC_E_OP_ASSET_ID.into(), - WBTC_OP_ASSET_ID.into(), - WETH_OP_ASSET_ID.into(), - ], + vec![USDC_ETH_ASSET_ID.into(), USDT_ETH_ASSET_ID.into(), WETH_ETH_ASSET_ID.into()], ), + (Chain::Optimism, vec![USDT_OP_ASSET_ID.into(), USDC_OP_ASSET_ID.into(), WETH_OP_ASSET_ID.into()]), ( Chain::Polygon, - vec![ - ACX_POLYGON_ASSET_ID.into(), - DAI_POLYGON_ASSET_ID.into(), - USDC_POLYGON_ASSET_ID.into(), - USDC_E_POLYGON_ASSET_ID.into(), - USDT_POLYGON_ASSET_ID.into(), - WBTC_POLYGON_ASSET_ID.into(), - WETH_POLYGON_ASSET_ID.into(), - ], + vec![USDC_POLYGON_ASSET_ID.into(), USDT_POLYGON_ASSET_ID.into(), WETH_POLYGON_ASSET_ID.into()], ), ( Chain::Arbitrum, - vec![ - ACX_ARB_ASSET_ID.into(), - DAI_ARB_ASSET_ID.into(), - USDT_ARB_ASSET_ID.into(), - USDC_ARB_ASSET_ID.into(), - USDC_E_ARB_ASSET_ID.into(), - WBTC_ARB_ASSET_ID.into(), - WETH_ARB_ASSET_ID.into(), - ], - ), - ( - Chain::Base, - vec![WETH_BASE_ASSET_ID.into(), USDC_BASE_ASSET_ID.into(), USDC_E_BASE_ASSET_ID.into()], - ), - ( - Chain::Linea, - vec![ - DAI_LINEA_ASSET_ID.into(), - USDC_E_LINEA_ASSET_ID.into(), - USDT_LINEA_ASSET_ID.into(), - WBTC_LINEA_ASSET_ID.into(), - WETH_LINEA_ASSET_ID.into(), - ], - ), - ( - Chain::ZkSync, - vec![ - DAI_ZKSYNC_ASSET_ID.into(), - WBTC_ZKSYNC_ASSET_ID.into(), - WETH_ZKSYNC_ASSET_ID.into(), - USDC_E_ZKSYNC_ASSET_ID.into(), - USDT_ZKSYNC_ASSET_ID.into(), - ], - ), - ( - Chain::World, - vec![WBTC_WORLD_ASSET_ID.into(), WETH_WORLD_ASSET_ID.into(), USDC_E_WORLD_ASSET_ID.into()], + vec![USDT_ARB_ASSET_ID.into(), USDC_ARB_ASSET_ID.into(), WETH_ARB_ASSET_ID.into()], ), - (Chain::Blast, vec![WBTC_BLAST_ASSET_ID.into(), WETH_BLAST_ASSET_ID.into()]), + (Chain::Base, vec![WETH_BASE_ASSET_ID.into(), USDC_BASE_ASSET_ID.into()]), + (Chain::Linea, vec![USDT_LINEA_ASSET_ID.into(), WETH_LINEA_ASSET_ID.into()]), + (Chain::ZkSync, vec![WETH_ZKSYNC_ASSET_ID.into(), USDT_ZKSYNC_ASSET_ID.into()]), + (Chain::World, vec![WETH_WORLD_ASSET_ID.into()]), + (Chain::Blast, vec![WETH_BLAST_ASSET_ID.into()]), ]) } diff --git a/gemstone/src/swapper/universal_router/mod.rs b/gemstone/src/swapper/universal_router/mod.rs index 24c0587d..8145600e 100644 --- a/gemstone/src/swapper/universal_router/mod.rs +++ b/gemstone/src/swapper/universal_router/mod.rs @@ -324,11 +324,14 @@ impl GemSwapProvider for UniswapV3 { } async fn fetch_quote(&self, request: &SwapQuoteRequest, provider: Arc) -> Result { + // Prevent cross chain swaps + if request.from_asset.chain != request.to_asset.chain { + return Err(SwapperError::NotSupportedPair); + } // Prevent swaps on unsupported chains if !self.support_chain(&request.from_asset.chain) { return Err(SwapperError::NotSupportedChain); } - let wallet_address: Address = request.wallet_address.as_str().parse().map_err(SwapperError::from)?; // Check deployment and weth contract From 1d576692de26d6b5557dfeca6326785250620a3f Mon Sep 17 00:00:00 2001 From: 0xh3rman <119309671+0xh3rman@users.noreply.github.com> Date: Mon, 13 Jan 2025 11:16:33 +0900 Subject: [PATCH 2/5] Fix lint --- apps/daemon/src/pricer/price_updater.rs | 2 +- crates/gem_chain_rpc/src/polkadot/client.rs | 28 ++++++++++----------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/apps/daemon/src/pricer/price_updater.rs b/apps/daemon/src/pricer/price_updater.rs index 82b8d697..1c76dbd5 100644 --- a/apps/daemon/src/pricer/price_updater.rs +++ b/apps/daemon/src/pricer/price_updater.rs @@ -24,7 +24,7 @@ impl PriceUpdater { } pub async fn get_coin_list(&mut self) -> Result, Box> { - Ok(self.coin_gecko_client.get_coin_list().await?) + self.coin_gecko_client.get_coin_list().await } pub async fn update_prices_assets(&mut self) -> Result> { diff --git a/crates/gem_chain_rpc/src/polkadot/client.rs b/crates/gem_chain_rpc/src/polkadot/client.rs index d49ee195..e2560926 100644 --- a/crates/gem_chain_rpc/src/polkadot/client.rs +++ b/crates/gem_chain_rpc/src/polkadot/client.rs @@ -69,21 +69,19 @@ impl PolkadotClient { transfer.value.clone(), )] } - ExtrinsicArguments::Transfers(transfers) => { - return transfers - .calls - .iter() - .map(|x| { - self.map_transfer( - block.clone(), - transaction.clone(), - x.method.method.clone(), - x.args.dest.id.clone(), - x.args.value.clone(), - ) - }) - .collect() - } + ExtrinsicArguments::Transfers(transfers) => transfers + .calls + .iter() + .map(|x| { + self.map_transfer( + block.clone(), + transaction.clone(), + x.method.method.clone(), + x.args.dest.id.clone(), + x.args.value.clone(), + ) + }) + .collect(), _ => vec![], } } From 81ec9285758b7a0cd33eef44280bf59c1f9faae2 Mon Sep 17 00:00:00 2001 From: 0xh3rman <119309671+0xh3rman@users.noreply.github.com> Date: Tue, 14 Jan 2025 11:03:01 +0900 Subject: [PATCH 3/5] try appending id --- gemstone/src/swapper/across/mod.rs | 1 + gemstone/src/swapper/across/provider.rs | 20 +++++++++++--------- gemstone/src/swapper/universal_router/mod.rs | 4 ---- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/gemstone/src/swapper/across/mod.rs b/gemstone/src/swapper/across/mod.rs index e326a40f..e2c2ff14 100644 --- a/gemstone/src/swapper/across/mod.rs +++ b/gemstone/src/swapper/across/mod.rs @@ -5,3 +5,4 @@ pub mod config_store; pub mod hubpool; const DEFAULT_FILL_TIMEOUT: u32 = 60 * 60 * 6; // 6 hours +const GEM_IDENTIFIER: [u8; 5] = [0x1d, 0xc0, 0xde, 0x00, 0x60]; diff --git a/gemstone/src/swapper/across/provider.rs b/gemstone/src/swapper/across/provider.rs index d874e463..e5d59109 100644 --- a/gemstone/src/swapper/across/provider.rs +++ b/gemstone/src/swapper/across/provider.rs @@ -2,7 +2,7 @@ use super::{ api::AcrossApi, config_store::{ConfigStoreClient, TokenConfig}, hubpool::HubPoolClient, - DEFAULT_FILL_TIMEOUT, + DEFAULT_FILL_TIMEOUT, GEM_IDENTIFIER, }; use crate::{ config::swap_config::SwapReferralFee, @@ -50,14 +50,9 @@ impl Across { pub fn is_supported_pair(from_asset: &AssetId, to_asset: &AssetId) -> bool { let from = weth_address::normalize_asset(from_asset).unwrap(); let to = weth_address::normalize_asset(to_asset).unwrap(); - debug_println!("from: {:?}, to: {:?}", from, to); let asset_mappings = AcrossDeployment::asset_mappings(); - for mapping in asset_mappings.iter() { - if mapping.set.contains(&from) && mapping.set.contains(&to) { - return true; - } - } - false + + asset_mappings.into_iter().any(|x| x.set.contains(&from) && x.set.contains(&to)) } pub fn get_rate_model(from_asset: &AssetId, to_asset: &AssetId, token_config: &TokenConfig) -> RateModel { @@ -250,6 +245,12 @@ impl GemSwapProvider for Across { SwapChainAsset::Assets(Chain::Ethereum, vec![ETHEREUM_USDC.id.clone()]), SwapChainAsset::Assets(Chain::Base, vec![BASE_USDC.id.clone()]), SwapChainAsset::Assets(Chain::Optimism, vec![OPTIMISM_USDC.id.clone()]), + // USDT + SwapChainAsset::Assets(Chain::Arbitrum, vec![ARBITRUM_USDT.id.clone()]), + SwapChainAsset::Assets(Chain::Ethereum, vec![ETHEREUM_USDT.id.clone()]), + SwapChainAsset::Assets(Chain::Linea, vec![LINEA_USDT.id.clone()]), + SwapChainAsset::Assets(Chain::Optimism, vec![OPTIMISM_USDT.id.clone()]), + SwapChainAsset::Assets(Chain::ZkSync, vec![ZKSYNC_USDT.id.clone()]), ] } @@ -453,7 +454,7 @@ impl GemSwapProvider for Across { let route_data = HexDecode(&route.route_data)?; let v3_relay_data = V3RelayData::abi_decode(&route_data, true).map_err(|_| SwapperError::InvalidRoute)?; - let deposit_v3_call = V3SpokePoolInterface::depositV3Call { + let mut deposit_v3_call = V3SpokePoolInterface::depositV3Call { depositor: v3_relay_data.depositor, recipient: v3_relay_data.recipient, inputToken: v3_relay_data.inputToken, @@ -468,6 +469,7 @@ impl GemSwapProvider for Across { message: v3_relay_data.message, } .abi_encode(); + deposit_v3_call.extend_from_slice(&GEM_IDENTIFIER); let value: &str = if quote.request.from_asset.is_native() { "e.from_value } else { "0" }; diff --git a/gemstone/src/swapper/universal_router/mod.rs b/gemstone/src/swapper/universal_router/mod.rs index 8145600e..419fa270 100644 --- a/gemstone/src/swapper/universal_router/mod.rs +++ b/gemstone/src/swapper/universal_router/mod.rs @@ -324,10 +324,6 @@ impl GemSwapProvider for UniswapV3 { } async fn fetch_quote(&self, request: &SwapQuoteRequest, provider: Arc) -> Result { - // Prevent cross chain swaps - if request.from_asset.chain != request.to_asset.chain { - return Err(SwapperError::NotSupportedPair); - } // Prevent swaps on unsupported chains if !self.support_chain(&request.from_asset.chain) { return Err(SwapperError::NotSupportedChain); From 76a9dc1d7d2285172ffdc619e722f2ef5ff9d61e Mon Sep 17 00:00:00 2001 From: 0xh3rman <119309671+0xh3rman@users.noreply.github.com> Date: Tue, 14 Jan 2025 13:00:12 +0900 Subject: [PATCH 4/5] should be handle in app side --- gemstone/src/swapper/across/mod.rs | 1 - gemstone/src/swapper/across/provider.rs | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/gemstone/src/swapper/across/mod.rs b/gemstone/src/swapper/across/mod.rs index e2c2ff14..e326a40f 100644 --- a/gemstone/src/swapper/across/mod.rs +++ b/gemstone/src/swapper/across/mod.rs @@ -5,4 +5,3 @@ pub mod config_store; pub mod hubpool; const DEFAULT_FILL_TIMEOUT: u32 = 60 * 60 * 6; // 6 hours -const GEM_IDENTIFIER: [u8; 5] = [0x1d, 0xc0, 0xde, 0x00, 0x60]; diff --git a/gemstone/src/swapper/across/provider.rs b/gemstone/src/swapper/across/provider.rs index e5d59109..f01a42ee 100644 --- a/gemstone/src/swapper/across/provider.rs +++ b/gemstone/src/swapper/across/provider.rs @@ -2,7 +2,7 @@ use super::{ api::AcrossApi, config_store::{ConfigStoreClient, TokenConfig}, hubpool::HubPoolClient, - DEFAULT_FILL_TIMEOUT, GEM_IDENTIFIER, + DEFAULT_FILL_TIMEOUT, }; use crate::{ config::swap_config::SwapReferralFee, @@ -454,7 +454,7 @@ impl GemSwapProvider for Across { let route_data = HexDecode(&route.route_data)?; let v3_relay_data = V3RelayData::abi_decode(&route_data, true).map_err(|_| SwapperError::InvalidRoute)?; - let mut deposit_v3_call = V3SpokePoolInterface::depositV3Call { + let deposit_v3_call = V3SpokePoolInterface::depositV3Call { depositor: v3_relay_data.depositor, recipient: v3_relay_data.recipient, inputToken: v3_relay_data.inputToken, @@ -469,7 +469,6 @@ impl GemSwapProvider for Across { message: v3_relay_data.message, } .abi_encode(); - deposit_v3_call.extend_from_slice(&GEM_IDENTIFIER); let value: &str = if quote.request.from_asset.is_native() { "e.from_value } else { "0" }; From 6bb8c22798e10eb2231192aa865eb22529fdf8c6 Mon Sep 17 00:00:00 2001 From: 0xh3rman <119309671+0xh3rman@users.noreply.github.com> Date: Tue, 14 Jan 2025 16:15:52 +0900 Subject: [PATCH 5/5] Update provider.rs --- gemstone/src/swapper/across/provider.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gemstone/src/swapper/across/provider.rs b/gemstone/src/swapper/across/provider.rs index f01a42ee..5a226467 100644 --- a/gemstone/src/swapper/across/provider.rs +++ b/gemstone/src/swapper/across/provider.rs @@ -50,9 +50,10 @@ impl Across { pub fn is_supported_pair(from_asset: &AssetId, to_asset: &AssetId) -> bool { let from = weth_address::normalize_asset(from_asset).unwrap(); let to = weth_address::normalize_asset(to_asset).unwrap(); - let asset_mappings = AcrossDeployment::asset_mappings(); - asset_mappings.into_iter().any(|x| x.set.contains(&from) && x.set.contains(&to)) + AcrossDeployment::asset_mappings() + .into_iter() + .any(|x| x.set.contains(&from) && x.set.contains(&to)) } pub fn get_rate_model(from_asset: &AssetId, to_asset: &AssetId, token_config: &TokenConfig) -> RateModel {