From cb88d5a304cbffeaa0916d0dbc87d523657898e2 Mon Sep 17 00:00:00 2001 From: ahsan-javaiid Date: Thu, 19 Feb 2026 19:03:10 +0500 Subject: [PATCH 1/5] feat: add rootstock chain --- Settings.yaml | 2 ++ crates/chain_primitives/src/token_id.rs | 1 + crates/coingecko/src/mapper.rs | 2 ++ crates/gem_evm/src/multicall3.rs | 1 + crates/gem_evm/src/rpc/ankr/model.rs | 1 + crates/gem_evm/src/uniswap/deployment/mod.rs | 1 + crates/gem_evm/src/uniswap/deployment/v3.rs | 5 ++++ crates/gem_evm/src/uniswap/path.rs | 3 +++ .../prices_dex/src/providers/pyth/mapper.rs | 1 + crates/primitives/src/asset.rs | 1 + crates/primitives/src/block_explorer.rs | 1 + crates/primitives/src/chain.rs | 1 + crates/primitives/src/chain_config.rs | 23 +++++++++++++++++++ crates/primitives/src/chain_evm.rs | 1 + crates/primitives/src/explorers/blockscout.rs | 4 ++++ crates/primitives/src/explorers/etherscan.rs | 1 + crates/primitives/src/node_config.rs | 4 ++++ crates/settings/src/lib.rs | 1 + crates/settings_chain/src/lib.rs | 2 ++ gemstone/src/gateway/mod.rs | 3 ++- 20 files changed, 58 insertions(+), 1 deletion(-) diff --git a/Settings.yaml b/Settings.yaml index fa2f2adc4..23254a091 100644 --- a/Settings.yaml +++ b/Settings.yaml @@ -192,6 +192,8 @@ chains: url: https://rpc.xlayer.tech stable: url: https://rpc.stable.xyz + rootstock: + url: https://public-node.rsk.co swap: jupiter: diff --git a/crates/chain_primitives/src/token_id.rs b/crates/chain_primitives/src/token_id.rs index 4c4596ef5..71d94b77b 100644 --- a/crates/chain_primitives/src/token_id.rs +++ b/crates/chain_primitives/src/token_id.rs @@ -32,6 +32,7 @@ pub fn format_token_id(chain: Chain, token_id: String) -> Option { | Chain::Monad | Chain::XLayer | Chain::Stable => Address::from_str(&token_id).ok().map(|address| address.to_checksum(None)), + | Chain::Rootstock => Address::from_str(&token_id).ok().map(|address| address.to_checksum(None)), Chain::Solana | Chain::Ton | Chain::Near => Some(token_id), Chain::Tron => (token_id.len() == 34 && token_id.starts_with('T')).then_some(token_id), Chain::Xrp => { diff --git a/crates/coingecko/src/mapper.rs b/crates/coingecko/src/mapper.rs index 582b80db6..a6d66801f 100644 --- a/crates/coingecko/src/mapper.rs +++ b/crates/coingecko/src/mapper.rs @@ -50,6 +50,7 @@ pub fn get_chain_for_coingecko_platform_id(id: &str) -> Option { "plasma" => Some(Chain::Plasma), "monad" => Some(Chain::Monad), "stable-2" => Some(Chain::Stable), + "rootstock" => Some(Chain::Rootstock), _ => None, } } @@ -106,5 +107,6 @@ pub fn get_coingecko_market_id_for_chain(chain: Chain) -> &'static str { Chain::Plasma => "plasma", Chain::XLayer => "okb", Chain::Stable => "tether", // gUSDT is the native gas token + Chain::Rootstock => "rootstock" } } diff --git a/crates/gem_evm/src/multicall3.rs b/crates/gem_evm/src/multicall3.rs index 89e4a9a8e..b9abd7679 100644 --- a/crates/gem_evm/src/multicall3.rs +++ b/crates/gem_evm/src/multicall3.rs @@ -90,6 +90,7 @@ pub fn deployment_by_chain(chain: &EVMChain) -> &'static str { | EVMChain::Monad | EVMChain::XLayer | EVMChain::Plasma + | EVMChain::Rootstock | EVMChain::Stable => "0xcA11bde05977b3631167028862bE2a173976CA11", EVMChain::ZkSync | EVMChain::Abstract => "0xF9cda624FBC7e059355ce98a31693d299FACd963", } diff --git a/crates/gem_evm/src/rpc/ankr/model.rs b/crates/gem_evm/src/rpc/ankr/model.rs index de6dc7c4c..d490857d9 100644 --- a/crates/gem_evm/src/rpc/ankr/model.rs +++ b/crates/gem_evm/src/rpc/ankr/model.rs @@ -60,5 +60,6 @@ pub fn ankr_chain(chain: EVMChain) -> Option { EVMChain::Monad => None, EVMChain::XLayer => None, EVMChain::Stable => None, + EVMChain::Rootstock => None, } } diff --git a/crates/gem_evm/src/uniswap/deployment/mod.rs b/crates/gem_evm/src/uniswap/deployment/mod.rs index 66044c353..d3fc22220 100644 --- a/crates/gem_evm/src/uniswap/deployment/mod.rs +++ b/crates/gem_evm/src/uniswap/deployment/mod.rs @@ -25,6 +25,7 @@ pub fn get_uniswap_permit2_by_chain(chain: &Chain) -> Option<&'static str> { | Chain::Ink | Chain::Monad | Chain::Stable => Some("0x000000000022D473030F116dDEE9F6B43aC78BA3"), + | Chain::Rootstock => Some("0xfcf5986450e4a014ffe7ad4ae24921b589d039b5"), Chain::ZkSync | Chain::Abstract => Some("0x0000000000225e31d15943971f47ad3022f714fa"), _ => None, } diff --git a/crates/gem_evm/src/uniswap/deployment/v3.rs b/crates/gem_evm/src/uniswap/deployment/v3.rs index 89642245e..5b02fbb30 100644 --- a/crates/gem_evm/src/uniswap/deployment/v3.rs +++ b/crates/gem_evm/src/uniswap/deployment/v3.rs @@ -98,6 +98,11 @@ pub fn get_uniswap_router_deployment_by_chain(chain: &Chain) -> Option Some(V3Deployment { + quoter_v2: "0xb51727c996c68e60f598a923a5006853cd2feb31", + permit2: "0xfcf5986450e4a014ffe7ad4ae24921b589d039b5", + universal_router: "0x244f68e77357f86a8522323ebf80b5fc2f814d3e", + }), _ => None, } } diff --git a/crates/gem_evm/src/uniswap/path.rs b/crates/gem_evm/src/uniswap/path.rs index 51ceda5e0..90baceec3 100644 --- a/crates/gem_evm/src/uniswap/path.rs +++ b/crates/gem_evm/src/uniswap/path.rs @@ -92,6 +92,7 @@ pub fn get_base_pair(chain: &EVMChain, weth_as_native: bool) -> Option EVMChain::World => "0x03C7054BCB39f7b2e5B2c7AcB37583e32D70Cfa3", EVMChain::Sonic => "0x0555E30da8f98308EdB960aa94C0Db47230d2B9c", EVMChain::Linea => "0x3aAB2285ddcDdaD8edf438C1bAB47e1a9D05a9b4", + EVMChain::Rootstock => "0x542fda317318ebf1d3deaf76e0b632741a7e677d", // wrbtc _ => "", // None }; @@ -118,6 +119,7 @@ pub fn get_base_pair(chain: &EVMChain, weth_as_native: bool) -> Option EVMChain::Monad => "0x754704Bc059F8C67012fEd69BC8A327a5aafb603", EVMChain::OpBNB | EVMChain::Plasma => "", EVMChain::Stable => "0x8a2b28364102bea189d99a475c494330ef2bdd0b", // USDC.e (Stargate) + EVMChain::Rootstock => "0x74c9f2b00581f1b11aa7ff05aa9f608b7389de67", // USDC.e (Stargate) _ => panic!("USDC is not configured for this chain"), }; @@ -143,6 +145,7 @@ pub fn get_base_pair(chain: &EVMChain, weth_as_native: bool) -> Option EVMChain::Plasma => "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb", // USDT0 EVMChain::Monad => "0xe7cd86e13AC4309349F30B3435a9d337750fC82D", // USDT0 EVMChain::Stable => "0x779Ded0c9e1022225f8E0630b35a9b54bE713736", // USDT0 + EVMChain::Rootstock => "0x779ded0c9e1022225f8e0630b35a9b54be713736", // USDT0 EVMChain::Blast | EVMChain::World => "", // None _ => panic!("USDT is not configured for this chain"), }; diff --git a/crates/prices_dex/src/providers/pyth/mapper.rs b/crates/prices_dex/src/providers/pyth/mapper.rs index a3fd1d530..2f588508d 100644 --- a/crates/prices_dex/src/providers/pyth/mapper.rs +++ b/crates/prices_dex/src/providers/pyth/mapper.rs @@ -60,5 +60,6 @@ pub fn price_feed_id_for_chain(chain: Chain) -> &'static str { Chain::Monad => "ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace", Chain::XLayer => "d6f83dfeaff95d596ddec26af2ee32f391c206a183b161b7980821860eeef2f5", Chain::Stable => "2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b", + Chain::Rootstock => "", // pyth not supported yet } } diff --git a/crates/primitives/src/asset.rs b/crates/primitives/src/asset.rs index 5204933f8..55a0e1199 100644 --- a/crates/primitives/src/asset.rs +++ b/crates/primitives/src/asset.rs @@ -113,6 +113,7 @@ impl Asset { Chain::Monad => chain.new_asset("Monad".to_string(), "MON".to_string(), 18, AssetType::NATIVE), Chain::XLayer => chain.new_asset("X Layer".to_string(), "OKB".to_string(), 18, AssetType::NATIVE), Chain::Stable => chain.new_asset("Stable".to_string(), "gUSDT".to_string(), 18, AssetType::NATIVE), + Chain::Rootstock => chain.new_asset("RBTC".to_string(), "rbtc".to_string(), 18, AssetType::NATIVE), } } } diff --git a/crates/primitives/src/block_explorer.rs b/crates/primitives/src/block_explorer.rs index 231291031..4bd463633 100644 --- a/crates/primitives/src/block_explorer.rs +++ b/crates/primitives/src/block_explorer.rs @@ -66,6 +66,7 @@ pub fn get_block_explorers(chain: Chain) -> Vec> { Chain::Blast => vec![EtherScan::boxed(EVMChain::Blast)], Chain::Linea => vec![EtherScan::boxed(EVMChain::Linea), blockchair::new_linea()], Chain::Celo => vec![BlockScout::new_celo(), EtherScan::boxed(EVMChain::Celo)], + Chain::Rootstock => vec![BlockScout::new_rootstock(), EtherScan::boxed(EVMChain::Rootstock)], Chain::ZkSync => vec![ZkSync::boxed(), EtherScan::boxed(EVMChain::ZkSync)], Chain::World => vec![EtherScan::boxed(EVMChain::World)], Chain::Plasma => vec![EtherScan::boxed(EVMChain::Plasma)], diff --git a/crates/primitives/src/chain.rs b/crates/primitives/src/chain.rs index 8c0845910..74e948265 100644 --- a/crates/primitives/src/chain.rs +++ b/crates/primitives/src/chain.rs @@ -63,6 +63,7 @@ pub enum Chain { Monad, XLayer, Stable, + Rootstock, } impl fmt::Display for Chain { diff --git a/crates/primitives/src/chain_config.rs b/crates/primitives/src/chain_config.rs index eefe3c52c..e63e0880f 100644 --- a/crates/primitives/src/chain_config.rs +++ b/crates/primitives/src/chain_config.rs @@ -1209,6 +1209,29 @@ static CHAIN_CONFIGS: &[ChainConfig] = &[ }), stake: None, }, + ChainConfig { + chain: Chain::Rootstock, + network_id: "30", + denom: None, + slip44: 137, + chain_type: ChainType::Ethereum, + default_asset_type: Some(AssetType::ERC20), + account_activation_fee: None, + token_activation_fee: None, + minimum_account_balance: None, + block_time: 25_000, + rank: 31, + is_swap_supported: false, + is_nft_supported: false, + is_utxo: false, + evm: Some(EvmChainConfig { + min_priority_fee: 0, + chain_stack: ChainStack::Native, + is_ethereum_layer2: false, + weth_contract: Some("0x3b3dd26c5cd371c707cc64b864f11d44692c505d"), + }), + stake: None, + }, ]; pub fn get_chain_config(chain: Chain) -> &'static ChainConfig { diff --git a/crates/primitives/src/chain_evm.rs b/crates/primitives/src/chain_evm.rs index 919599296..d39cd876e 100644 --- a/crates/primitives/src/chain_evm.rs +++ b/crates/primitives/src/chain_evm.rs @@ -41,6 +41,7 @@ pub enum EVMChain { Monad, XLayer, Stable, + Rootstock, } impl EVMChain { diff --git a/crates/primitives/src/explorers/blockscout.rs b/crates/primitives/src/explorers/blockscout.rs index 59597f652..f9f72f99a 100644 --- a/crates/primitives/src/explorers/blockscout.rs +++ b/crates/primitives/src/explorers/blockscout.rs @@ -8,6 +8,10 @@ impl BlockScout { Explorer::boxed(Metadata::with_token("BlockScout", "https://celo.blockscout.com")) } + pub fn new_rootstock() -> Box { + Explorer::boxed(Metadata::with_token("BlockScout", "https://rootstock.blockscout.com")) + } + pub fn new_manta() -> Box { Explorer::boxed(Metadata::with_token("Pacific Explorer", "https://pacific-explorer.manta.network")) } diff --git a/crates/primitives/src/explorers/etherscan.rs b/crates/primitives/src/explorers/etherscan.rs index 5d3165ff4..024fce49f 100644 --- a/crates/primitives/src/explorers/etherscan.rs +++ b/crates/primitives/src/explorers/etherscan.rs @@ -32,6 +32,7 @@ impl EtherScan { EVMChain::Monad => Explorer::boxed(Metadata::with_token("Monadscan", "https://monadscan.com")), EVMChain::Hyperliquid => Explorer::boxed(Metadata::with_token("HyperEvmScan", "https://hyperevmscan.io")), EVMChain::Stable => Explorer::boxed(Metadata::with_token("Stablescan", "https://stablescan.xyz")), + EVMChain::Rootstock => Explorer::boxed(Metadata::with_token("Rootstock", "https://explorer.rootstock.io")), _ => todo!(), } } diff --git a/crates/primitives/src/node_config.rs b/crates/primitives/src/node_config.rs index 1eceef13d..b5291efd5 100644 --- a/crates/primitives/src/node_config.rs +++ b/crates/primitives/src/node_config.rs @@ -163,5 +163,9 @@ pub fn get_nodes_for_chain(chain: Chain) -> Vec { Node::new("https://xlayerrpc.okx.com", NodePriority::High), ], Chain::Stable => vec![Node::new("https://rpc.stable.xyz", NodePriority::High)], + Chain::Rootstock => vec![ + Node::new("https://public-node.rsk.co", NodePriority::High), + Node::new("https://mycrypto.rsk.co", NodePriority::High), + ], } } diff --git a/crates/settings/src/lib.rs b/crates/settings/src/lib.rs index 482d9e47a..036268460 100644 --- a/crates/settings/src/lib.rs +++ b/crates/settings/src/lib.rs @@ -236,6 +236,7 @@ pub struct Chains { pub monad: Chain, pub xlayer: Chain, pub stable: Chain, + pub rootstock: Chain, } #[derive(Debug, Deserialize, Clone)] diff --git a/crates/settings_chain/src/lib.rs b/crates/settings_chain/src/lib.rs index 68a812eab..cf21a20b1 100644 --- a/crates/settings_chain/src/lib.rs +++ b/crates/settings_chain/src/lib.rs @@ -105,6 +105,7 @@ impl ProviderFactory { | Chain::Hyperliquid | Chain::Monad | Chain::XLayer + | Chain::Rootstock | Chain::Stable => { let chain = EVMChain::from_chain(chain).unwrap(); let client = gem_client.clone(); @@ -190,6 +191,7 @@ impl ProviderFactory { Chain::Monad => &settings.chains.monad, Chain::XLayer => &settings.chains.xlayer, Chain::Stable => &settings.chains.stable, + Chain::Rootstock => &settings.chains.rootstock, } } diff --git a/gemstone/src/gateway/mod.rs b/gemstone/src/gateway/mod.rs index f4a02e518..0eae26ed9 100644 --- a/gemstone/src/gateway/mod.rs +++ b/gemstone/src/gateway/mod.rs @@ -130,7 +130,8 @@ impl GemGateway { | Chain::Plasma | Chain::Monad | Chain::XLayer - | Chain::Stable => Ok(Arc::new(EthereumClient::new(JsonRpcClient::new(alien_client), EVMChain::from_chain(chain).unwrap()))), + | Chain::Stable + | Chain::Rootstock => Ok(Arc::new(EthereumClient::new(JsonRpcClient::new(alien_client), EVMChain::from_chain(chain).unwrap()))), } } } From f7ca3a197f65a0a5bc032b575d6750771045c9b8 Mon Sep 17 00:00:00 2001 From: gemcoder21 <104884878+gemcoder21@users.noreply.github.com> Date: Thu, 19 Feb 2026 22:15:04 +0000 Subject: [PATCH 2/5] Update crates/primitives/src/chain_config.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- crates/primitives/src/chain_config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/primitives/src/chain_config.rs b/crates/primitives/src/chain_config.rs index e63e0880f..45dbef6bb 100644 --- a/crates/primitives/src/chain_config.rs +++ b/crates/primitives/src/chain_config.rs @@ -1228,7 +1228,7 @@ static CHAIN_CONFIGS: &[ChainConfig] = &[ min_priority_fee: 0, chain_stack: ChainStack::Native, is_ethereum_layer2: false, - weth_contract: Some("0x3b3dd26c5cd371c707cc64b864f11d44692c505d"), + weth_contract: Some("0x3B3dD26C5cD371c707ce64B864f11d44692c505d"), }), stake: None, }, From 3dd67bddbc0a4fa44203c6c2435a16e7e98b33cf Mon Sep 17 00:00:00 2001 From: gemcoder21 <104884878+gemcoder21@users.noreply.github.com> Date: Thu, 19 Feb 2026 22:15:17 +0000 Subject: [PATCH 3/5] Update crates/primitives/src/asset.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- crates/primitives/src/asset.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/primitives/src/asset.rs b/crates/primitives/src/asset.rs index 55a0e1199..66d71df93 100644 --- a/crates/primitives/src/asset.rs +++ b/crates/primitives/src/asset.rs @@ -113,7 +113,7 @@ impl Asset { Chain::Monad => chain.new_asset("Monad".to_string(), "MON".to_string(), 18, AssetType::NATIVE), Chain::XLayer => chain.new_asset("X Layer".to_string(), "OKB".to_string(), 18, AssetType::NATIVE), Chain::Stable => chain.new_asset("Stable".to_string(), "gUSDT".to_string(), 18, AssetType::NATIVE), - Chain::Rootstock => chain.new_asset("RBTC".to_string(), "rbtc".to_string(), 18, AssetType::NATIVE), + Chain::Rootstock => chain.new_asset("Rootstock".to_string(), "RBTC".to_string(), 18, AssetType::NATIVE), } } } From a1dc395f105d17d558f20e94d649053cf92e6265 Mon Sep 17 00:00:00 2001 From: gemcoder21 <104884878+gemcoder21@users.noreply.github.com> Date: Thu, 19 Feb 2026 22:15:43 +0000 Subject: [PATCH 4/5] Update crates/chain_primitives/src/token_id.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- crates/chain_primitives/src/token_id.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/chain_primitives/src/token_id.rs b/crates/chain_primitives/src/token_id.rs index 71d94b77b..75cad1467 100644 --- a/crates/chain_primitives/src/token_id.rs +++ b/crates/chain_primitives/src/token_id.rs @@ -31,7 +31,7 @@ pub fn format_token_id(chain: Chain, token_id: String) -> Option { | Chain::Plasma | Chain::Monad | Chain::XLayer - | Chain::Stable => Address::from_str(&token_id).ok().map(|address| address.to_checksum(None)), + | Chain::Stable | Chain::Rootstock => Address::from_str(&token_id).ok().map(|address| address.to_checksum(None)), Chain::Solana | Chain::Ton | Chain::Near => Some(token_id), Chain::Tron => (token_id.len() == 34 && token_id.starts_with('T')).then_some(token_id), From 1207ff285f01611b9ace25722ca5ad67fcd587f9 Mon Sep 17 00:00:00 2001 From: gemcoder21 <104884878+gemcoder21@users.noreply.github.com> Date: Thu, 19 Feb 2026 22:15:51 +0000 Subject: [PATCH 5/5] Update crates/primitives/src/chain_config.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- crates/primitives/src/chain_config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/primitives/src/chain_config.rs b/crates/primitives/src/chain_config.rs index 45dbef6bb..3028d8143 100644 --- a/crates/primitives/src/chain_config.rs +++ b/crates/primitives/src/chain_config.rs @@ -1221,7 +1221,7 @@ static CHAIN_CONFIGS: &[ChainConfig] = &[ minimum_account_balance: None, block_time: 25_000, rank: 31, - is_swap_supported: false, + is_swap_supported: true, is_nft_supported: false, is_utxo: false, evm: Some(EvmChainConfig {