From 50873fafaf30ece101d93c13e1299cbb60ffb3b3 Mon Sep 17 00:00:00 2001 From: allthatjazzleo Date: Fri, 6 Jun 2025 15:29:06 +0800 Subject: [PATCH 1/6] Add CosmosEvmDynamicFee option to ExtensionOption --- crates/relayer/src/config.rs | 13 ++++++++++++- crates/relayer/src/extension_options.rs | 7 ++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/crates/relayer/src/config.rs b/crates/relayer/src/config.rs index e53c6a0d42..2b472fd4f6 100644 --- a/crates/relayer/src/config.rs +++ b/crates/relayer/src/config.rs @@ -121,6 +121,7 @@ pub fn parse_gas_prices(prices: String) -> Vec { )] pub enum ExtensionOption { EthermintDynamicFee(String), + CosmosEvmDynamicFee(String), } impl ExtensionOption { @@ -129,7 +130,11 @@ impl ExtensionOption { Self::EthermintDynamicFee(max_priority_price) => ExtensionOptionDynamicFeeTx { max_priority_price: max_priority_price.into(), } - .to_any(), + .to_any("/ethermint.types.v1.ExtensionOptionDynamicFeeTx"), + Self::CosmosEvmDynamicFee(max_priority_price) => ExtensionOptionDynamicFeeTx { + max_priority_price: max_priority_price.into(), + } + .to_any("/cosmos.evm.types.v1.ExtensionOptionDynamicFeeTx"), } } } @@ -143,6 +148,12 @@ impl Display for ExtensionOption { "EthermintDynamicFee(max_priority_price: {max_priority_price})" ) } + Self::CosmosEvmDynamicFee(max_priority_price) => { + write!( + f, + "CosmosEvmDynamicFee(max_priority_price: {max_priority_price})" + ) + } } } } diff --git a/crates/relayer/src/extension_options.rs b/crates/relayer/src/extension_options.rs index f5eda5c08c..4695f4f9c5 100644 --- a/crates/relayer/src/extension_options.rs +++ b/crates/relayer/src/extension_options.rs @@ -4,8 +4,9 @@ use serde_derive::{Deserialize, Serialize}; use crate::error::Error; -// ExtensionOptionDynamicFeeTx is an extension option used with ethermint dynamic fee tx. +// ExtensionOptionDynamicFeeTx is an extension option used with ethermint dynamic fee tx and cosmos evm dynamic fee tx. // protobuf message: https://github.com/evmos/ethermint/blob/main/proto/ethermint/types/v1/dynamic_fee.proto +// protobuf message: https://github.com/cosmos/evm/blob/main/proto/cosmos/evm/types/v1/dynamic_fee.proto #[derive(Clone, PartialEq, Eq, Message, Serialize, Deserialize)] pub struct ExtensionOptionDynamicFeeTx { #[prost(string, tag = "1")] @@ -13,12 +14,12 @@ pub struct ExtensionOptionDynamicFeeTx { } impl ExtensionOptionDynamicFeeTx { - pub fn to_any(&self) -> Result { + pub fn to_any(&self, type_url: &str) -> Result { let mut buf = Vec::new(); Message::encode(self, &mut buf) .map_err(|e| Error::protobuf_encode("ExtensionOptionDynamicFeeTx".into(), e))?; Ok(Any { - type_url: "/ethermint.types.v1.ExtensionOptionDynamicFeeTx".to_string(), + type_url: type_url.to_string(), value: buf, }) } From c4c9209f387132cd67a6f6377a0956b0e4c401ff Mon Sep 17 00:00:00 2001 From: allthatjazzleo Date: Sat, 7 Jun 2025 20:02:37 +0800 Subject: [PATCH 2/6] Enhance dynamic gas price configuration and querying support for Cosmos EVM, Osmosis, and SkipFeeMarket --- config.toml | 14 ++- crates/relayer-cli/src/chain_registry.rs | 2 +- .../relayer/src/chain/cosmos/eip_base_fee.rs | 115 ++++++++++++++---- crates/relayer/src/chain/cosmos/gas.rs | 19 +-- crates/relayer/src/config/dynamic_gas.rs | 102 ++++++++++++++-- .../src/tests/dynamic_gas_fee.rs | 5 +- .../interchain_security/dynamic_gas_fee.rs | 3 +- tools/test-framework/src/relayer/tx.rs | 2 +- tools/test-framework/src/types/single/node.rs | 2 +- 9 files changed, 217 insertions(+), 47 deletions(-) diff --git a/config.toml b/config.toml index 224d49af7c..286c7ea30e 100644 --- a/config.toml +++ b/config.toml @@ -311,14 +311,24 @@ gas_multiplier = 1.1 # Query the current gas price from the chain instead of using the static `gas_price` from the config. # Useful for chains which have [EIP-1559][eip]-like dynamic gas price. # -# At the moment, only chains which support the `osmosis.txfees.v1beta1.Query/GetEipBaseFee` -# query or have enabled Skip's `x/feemarket` module https://github.com/skip-mev/feemarket +# At the moment, only chains which support the `/cosmos.evm.feemarket.v1.Query/BaseFee` query or +# `osmosis.txfees.v1beta1.Query/GetEipBaseFee` query or have enabled Skip's `x/feemarket` module https://github.com/skip-mev/feemarket # can be used with dynamic gas price enabled. # +# The `type` field allows you to specify which query method to use: +# - `skip_fee_market`: Use Skip's feemarket module query at `/feemarket.feemarket.v1.Query/GasPrices` +# - `osmosis`: Use Osmosis EIP-1559 query at `/osmosis.txfees.v1beta1.Query/GetEipBaseFee` +# - `cosmos_evm`: Use Cosmos EVM query at `/cosmos.evm.feemarket.v1.Query/BaseFee` +# +# If `type` is not specified, Hermes will attempt to auto-detect for backwards compatibility: +# - Chains starting with "osmosis" or "osmo-test" will use `osmosis` type +# - All other chains will default to `skip_fee_market` type +# # See this page in the Hermes guide for more information: # https://hermes.informal.systems/documentation/configuration/dynamic-gas-fees.html # # Default: { enabled = false, multiplier = 1.1, max = 0.6 } +# Example with type specified: { enabled = true, multiplier = 1.1, max = 0.6, type = 'cosmos_evm' } dynamic_gas_price = { enabled = false, multiplier = 1.1, max = 0.6 } # Specify how many IBC messages at most to include in a single transaction. diff --git a/crates/relayer-cli/src/chain_registry.rs b/crates/relayer-cli/src/chain_registry.rs index f9fdb22d1d..5a66a0a7e9 100644 --- a/crates/relayer-cli/src/chain_registry.rs +++ b/crates/relayer-cli/src/chain_registry.rs @@ -118,7 +118,7 @@ where // Use EIP-1559 dynamic gas price for Osmosis let dynamic_gas_price = if chain_data.chain_id.as_str() == "osmosis-1" { - DynamicGasPrice::unsafe_new(true, 1.1, 0.6) + DynamicGasPrice::unsafe_new(true, 1.1, 0.6, None) } else { DynamicGasPrice::disabled() }; diff --git a/crates/relayer/src/chain/cosmos/eip_base_fee.rs b/crates/relayer/src/chain/cosmos/eip_base_fee.rs index 5c91fc7ad6..da542f9085 100644 --- a/crates/relayer/src/chain/cosmos/eip_base_fee.rs +++ b/crates/relayer/src/chain/cosmos/eip_base_fee.rs @@ -10,31 +10,29 @@ use tracing::{debug, trace}; use ibc_proto::cosmos::base::v1beta1::{DecCoin, DecProto}; use ibc_relayer_types::core::ics24_host::identifier::ChainId; -use crate::error::Error; +use crate::{config::dynamic_gas::DynamicGasType, error::Error}; pub async fn query_eip_base_fee( rpc_address: &Url, gas_price_denom: &str, + dynamic_gas_type: &Option, chain_id: &ChainId, ) -> Result { - debug!("Querying Omosis EIP-1559 base fee from {rpc_address}"); - - let chain_name = chain_id.name(); - - let is_osmosis = chain_name.starts_with("osmosis") || chain_name.starts_with("osmo-test"); - - let url = if is_osmosis { - format!( - "{}abci_query?path=\"/osmosis.txfees.v1beta1.Query/GetEipBaseFee\"", - rpc_address - ) - } else { - format!( - "{}abci_query?path=\"/feemarket.feemarket.v1.Query/GasPrices\"&denom={}", - rpc_address, gas_price_denom - ) + let dynamic_gas_type = match dynamic_gas_type { + Some(dynamic_gas_type) => dynamic_gas_type, + None => { + // backward compatibility for chains that do not specify dynamic gas type + if chain_id.name().starts_with("osmosis") || chain_id.name().starts_with("osmo-test") { + &DynamicGasType::Osmosis + } else { + &DynamicGasType::SkipFeeMarket + } + } }; + debug!("Querying {dynamic_gas_type} base fee from {rpc_address}"); + + let url = dynamic_gas_type.get_url(rpc_address, gas_price_denom); let response = reqwest::get(&url).await.map_err(Error::http_request)?; if !response.status().is_success() { @@ -58,11 +56,7 @@ pub async fn query_eip_base_fee( let result: EipBaseFeeHTTPResult = response.json().await.map_err(Error::http_response_body)?; - let amount = if is_osmosis { - extract_dynamic_gas_price_osmosis(result.result.response.value)? - } else { - extract_dynamic_gas_price(result.result.response.value)? - }; + let amount = dynamic_gas_type.extract_dynamic_gas_price(result.result.response.value)?; trace!("EIP-1559 base fee: {amount}"); @@ -70,7 +64,7 @@ pub async fn query_eip_base_fee( } /// This method extracts the gas base fee from Skip's feemarket -fn extract_dynamic_gas_price(encoded: String) -> Result { +fn extract_dynamic_gas_price_fee_market(encoded: String) -> Result { let decoded = base64::decode(encoded).map_err(Error::base64_decode)?; let gas_price_response: GasPriceResponse = @@ -84,8 +78,8 @@ fn extract_dynamic_gas_price(encoded: String) -> Result { f64::from_str(dec.to_string().as_str()).map_err(Error::parse_float) } -/// This method extracts the gas base fee from Osmosis EIP-1559 -fn extract_dynamic_gas_price_osmosis(encoded: String) -> Result { +/// This method extracts the gas base fee from Osmosis EIP-1559 and Cosmos EVM EIP-1559 +fn extract_dynamic_gas_price(encoded: String) -> Result { let decoded = base64::decode(encoded).map_err(Error::base64_decode)?; let dec_proto: DecProto = prost::Message::decode(decoded.as_ref()) @@ -189,3 +183,74 @@ impl fmt::Display for Decimal { } } } + +impl DynamicGasType { + fn get_url(&self, rpc_address: &Url, gas_price_denom: &str) -> String { + match self { + DynamicGasType::SkipFeeMarket => format!( + "{}abci_query?path=\"/feemarket.feemarket.v1.Query/GasPrices\"&denom={}", + rpc_address, gas_price_denom + ), + DynamicGasType::Osmosis => format!( + "{}abci_query?path=\"/osmosis.txfees.v1beta1.Query/GetEipBaseFee\"", + rpc_address + ), + DynamicGasType::CosmosEvm => format!( + "{}abci_query?path=\"/cosmos.evm.feemarket.v1.Query/BaseFee\"", + rpc_address + ), + } + } + + fn extract_dynamic_gas_price(&self, encoded: String) -> Result { + match self { + DynamicGasType::SkipFeeMarket => extract_dynamic_gas_price_fee_market(encoded), + DynamicGasType::Osmosis => extract_dynamic_gas_price(encoded), + DynamicGasType::CosmosEvm => extract_dynamic_gas_price(encoded), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_extract_dynamic_gas_price_fee_market() { + // Test with the provided encoded value + let encoded = "ChgKA3VvbRIRMTAwMDAwMDAwMDAwMDAwMDA".to_string(); + + let result = extract_dynamic_gas_price_fee_market(encoded); + + assert!(result.is_ok()); + let gas_price = result.unwrap(); + + assert_eq!(gas_price, 0.01); + } + + #[test] + fn test_extract_dynamic_gas_price_osmosis() { + // Test with the provided encoded value + let encoded = "ChAyNTAwMDAwMDAwMDAwMDAw".to_string(); + + let result = extract_dynamic_gas_price(encoded); + + assert!(result.is_ok()); + let gas_price = result.unwrap(); + + assert_eq!(gas_price, 0.0025); + } + + #[test] + fn test_extract_dynamic_gas_price_cosmos_evm() { + // Test with the provided encoded value + let encoded = "ChExMDAwMDAwMDAwMDAwMDAwMA==".to_string(); + + let result = extract_dynamic_gas_price(encoded); + + assert!(result.is_ok()); + let gas_price = result.unwrap(); + + assert_eq!(gas_price, 0.01); + } +} diff --git a/crates/relayer/src/chain/cosmos/gas.rs b/crates/relayer/src/chain/cosmos/gas.rs index 76ad0adcb3..373e6f752a 100644 --- a/crates/relayer/src/chain/cosmos/gas.rs +++ b/crates/relayer/src/chain/cosmos/gas.rs @@ -43,13 +43,18 @@ pub async fn dynamic_gas_price( rpc_address: &Url, ) -> GasPrice { if config.dynamic_gas_price.enabled { - let dynamic_gas_price = query_eip_base_fee(rpc_address, &config.gas_price.denom, chain_id) - .await - .map(|base_fee| base_fee * config.dynamic_gas_price.multiplier) - .map(|new_price| GasPrice { - price: new_price, - denom: config.gas_price.denom.clone(), - }); + let dynamic_gas_price = query_eip_base_fee( + rpc_address, + &config.gas_price.denom, + &config.dynamic_gas_price.r#type, + chain_id, + ) + .await + .map(|base_fee| base_fee * config.dynamic_gas_price.multiplier) + .map(|new_price| GasPrice { + price: new_price, + denom: config.gas_price.denom.clone(), + }); let dynamic_gas_price = match dynamic_gas_price { Ok(dynamic_gas_price) => { diff --git a/crates/relayer/src/config/dynamic_gas.rs b/crates/relayer/src/config/dynamic_gas.rs index f18246f7eb..1574228996 100644 --- a/crates/relayer/src/config/dynamic_gas.rs +++ b/crates/relayer/src/config/dynamic_gas.rs @@ -1,3 +1,4 @@ +use core::fmt; use serde::de::Error as DeserializeError; use serde::de::Unexpected; use serde::Deserialize; @@ -15,11 +16,30 @@ flex_error::define_error! { } } +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum DynamicGasType { + SkipFeeMarket, + Osmosis, + CosmosEvm, +} + +impl fmt::Display for DynamicGasType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + DynamicGasType::SkipFeeMarket => write!(f, "SkipFeeMarket"), + DynamicGasType::Osmosis => write!(f, "Osmosis"), + DynamicGasType::CosmosEvm => write!(f, "CosmosEVM"), + } + } +} + #[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize)] pub struct DynamicGasPrice { pub enabled: bool, pub multiplier: f64, pub max: f64, + pub r#type: Option, } impl DynamicGasPrice { @@ -27,8 +47,12 @@ impl DynamicGasPrice { const DEFAULT_MAX: f64 = 0.6; const MIN_MULTIPLIER: f64 = 1.0; - pub fn enabled(multiplier: f64, max: f64) -> Result { - Self::new(true, multiplier, max) + pub fn enabled( + multiplier: f64, + max: f64, + r#type: Option, + ) -> Result { + Self::new(true, multiplier, max, r#type) } pub fn disabled() -> Self { @@ -36,10 +60,16 @@ impl DynamicGasPrice { enabled: false, multiplier: Self::DEFAULT_MULTIPLIER, max: Self::DEFAULT_MAX, + r#type: None, } } - pub fn new(enabled: bool, multiplier: f64, max: f64) -> Result { + pub fn new( + enabled: bool, + multiplier: f64, + max: f64, + r#type: Option, + ) -> Result { if multiplier < Self::MIN_MULTIPLIER { return Err(Error::multiplier_too_small(multiplier)); } @@ -48,15 +78,22 @@ impl DynamicGasPrice { enabled, multiplier, max, + r#type, }) } // Unsafe GasMultiplier used for test cases only. - pub fn unsafe_new(enabled: bool, multiplier: f64, max: f64) -> Self { + pub fn unsafe_new( + enabled: bool, + multiplier: f64, + max: f64, + r#type: Option, + ) -> Self { Self { enabled, multiplier, max, + r#type, } } } @@ -77,15 +114,17 @@ impl<'de> Deserialize<'de> for DynamicGasPrice { enabled: bool, multiplier: f64, max: f64, + r#type: Option, } let DynGas { enabled, multiplier, max, + r#type, } = DynGas::deserialize(deserializer)?; - DynamicGasPrice::new(enabled, multiplier, max).map_err(|e| match e.detail() { + DynamicGasPrice::new(enabled, multiplier, max, r#type).map_err(|e| match e.detail() { ErrorDetail::MultiplierTooSmall(_) => D::Error::invalid_value( Unexpected::Float(multiplier), &format!( @@ -126,7 +165,7 @@ mod tests { #[test] fn safe_gas_multiplier() { - let dynamic_gas = DynamicGasPrice::new(true, 0.6, 0.6); + let dynamic_gas = DynamicGasPrice::new(true, 0.6, 0.6, None); assert!( dynamic_gas.is_err(), "Gas multiplier should be an error if value is lower than 1.0: {dynamic_gas:?}" @@ -135,8 +174,57 @@ mod tests { #[test] fn unsafe_gas_multiplier() { - let dynamic_gas = DynamicGasPrice::unsafe_new(true, 0.6, 0.4); + let dynamic_gas = DynamicGasPrice::unsafe_new(true, 0.6, 0.4, None); assert_eq!(dynamic_gas.multiplier, 0.6); assert_eq!(dynamic_gas.max, 0.4); } + + #[test] + fn parse_valid_dynamic_gas_type() { + #[derive(Debug, Deserialize)] + struct DummyConfig { + dynamic_gas: DynamicGasPrice, + } + let config: DummyConfig = toml::from_str( + "dynamic_gas = { enabled = true, multiplier = 1.1, max = 0.6, type = 'skip_fee_market' }", + ) + .unwrap(); + + assert_eq!(config.dynamic_gas.multiplier, 1.1); + assert_eq!(config.dynamic_gas.max, 0.6); + assert_eq!( + config.dynamic_gas.r#type, + Some(DynamicGasType::SkipFeeMarket) + ); + } + + #[test] + fn parse_invalid_dynamic_gas_type() { + #[derive(Debug, Deserialize)] + struct DummyConfig { + dynamic_gas: DynamicGasPrice, + } + let err = toml::from_str::( + "dynamic_gas = { enabled = true, multiplier = 1.1, max = 0.6, type = 'invalid_type' }", + ) + .unwrap_err() + .to_string(); + + assert!(err.contains("unknown variant `invalid_type`, expected one of `skip_fee_market`, `osmosis`, `cosmos_evm`")); + } + + #[test] + fn parse_no_dynamic_gas_type() { + #[derive(Debug, Deserialize)] + struct DummyConfig { + dynamic_gas: DynamicGasPrice, + } + let config: DummyConfig = + toml::from_str("dynamic_gas = { enabled = true, multiplier = 1.1, max = 0.6 }") + .unwrap(); + + assert_eq!(config.dynamic_gas.multiplier, 1.1); + assert_eq!(config.dynamic_gas.max, 0.6); + assert!(config.dynamic_gas.r#type.is_none()); + } } diff --git a/tools/integration-test/src/tests/dynamic_gas_fee.rs b/tools/integration-test/src/tests/dynamic_gas_fee.rs index aa091d2efc..8dca8f3436 100644 --- a/tools/integration-test/src/tests/dynamic_gas_fee.rs +++ b/tools/integration-test/src/tests/dynamic_gas_fee.rs @@ -50,7 +50,8 @@ impl TestOverrides for DynamicGasTest { ChainConfig::CosmosSdk(chain_config_a) => { chain_config_a.gas_price = GasPrice::new(0.1, chain_config_a.gas_price.denom.clone()); - chain_config_a.dynamic_gas_price = DynamicGasPrice::unsafe_new(false, 1.1, 0.6); + chain_config_a.dynamic_gas_price = + DynamicGasPrice::unsafe_new(false, 1.1, 0.6, None); } ChainConfig::Namada(_) => {} ChainConfig::Penumbra(_) => panic!("running tests with Penumbra chain not supported"), @@ -61,7 +62,7 @@ impl TestOverrides for DynamicGasTest { chain_config_b.gas_price = GasPrice::new(0.1, chain_config_b.gas_price.denom.clone()); chain_config_b.dynamic_gas_price = - DynamicGasPrice::unsafe_new(self.dynamic_gas_enabled, 1.1, 0.6); + DynamicGasPrice::unsafe_new(self.dynamic_gas_enabled, 1.1, 0.6, None); } ChainConfig::Namada(_) => {} ChainConfig::Penumbra(_) => panic!("running tests with Penumbra chain not supported"), diff --git a/tools/integration-test/src/tests/interchain_security/dynamic_gas_fee.rs b/tools/integration-test/src/tests/interchain_security/dynamic_gas_fee.rs index 36ff4f4855..3233d1ffcb 100644 --- a/tools/integration-test/src/tests/interchain_security/dynamic_gas_fee.rs +++ b/tools/integration-test/src/tests/interchain_security/dynamic_gas_fee.rs @@ -84,7 +84,8 @@ impl TestOverrides for DynamicGasTest { chain_config_a.gas_price = GasPrice::new(0.3, chain_config_a.gas_price.denom.clone()); - chain_config_a.dynamic_gas_price = DynamicGasPrice::unsafe_new(false, 1.1, 0.6); + chain_config_a.dynamic_gas_price = + DynamicGasPrice::unsafe_new(false, 1.1, 0.6, None); } ChainConfig::Penumbra(_) => panic!("running tests with Penumbra chain not supported"), } diff --git a/tools/test-framework/src/relayer/tx.rs b/tools/test-framework/src/relayer/tx.rs index 90f62a09fb..73be604718 100644 --- a/tools/test-framework/src/relayer/tx.rs +++ b/tools/test-framework/src/relayer/tx.rs @@ -39,7 +39,7 @@ pub fn gas_config_for_test(native_token: String, chain_type: ChainType) -> GasCo }; let dynamic_gas_price = if chain_type.enable_dynamic_fee() { - DynamicGasPrice::unsafe_new(true, 1.3, 5.0) + DynamicGasPrice::unsafe_new(true, 1.3, 5.0, None) } else { DynamicGasPrice::disabled() }; diff --git a/tools/test-framework/src/types/single/node.rs b/tools/test-framework/src/types/single/node.rs index 51ab9499d3..76b34df283 100644 --- a/tools/test-framework/src/types/single/node.rs +++ b/tools/test-framework/src/types/single/node.rs @@ -158,7 +158,7 @@ impl FullNode { }; let dynamic_gas_price = if chain_type.enable_dynamic_fee() { - DynamicGasPrice::unsafe_new(true, 1.3, 5.0) + DynamicGasPrice::unsafe_new(true, 1.3, 5.0, None) } else { DynamicGasPrice::disabled() }; From cd36bcd3a4ec8c6c91f31f96224eafe7ac3b5d2e Mon Sep 17 00:00:00 2001 From: allthatjazzleo Date: Thu, 12 Jun 2025 21:37:40 +0800 Subject: [PATCH 3/6] fix: update DynamicGasPrice initialization to include optional parameter --- .../src/tests/interchain_security/dynamic_gas_fee.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/integration-test/src/tests/interchain_security/dynamic_gas_fee.rs b/tools/integration-test/src/tests/interchain_security/dynamic_gas_fee.rs index 3233d1ffcb..7056905a2a 100644 --- a/tools/integration-test/src/tests/interchain_security/dynamic_gas_fee.rs +++ b/tools/integration-test/src/tests/interchain_security/dynamic_gas_fee.rs @@ -98,7 +98,7 @@ impl TestOverrides for DynamicGasTest { chain_config_b.gas_multiplier = Some(GasMultiplier::unsafe_new(1.8)); chain_config_b.dynamic_gas_price = - DynamicGasPrice::unsafe_new(self.dynamic_gas_enabled, 1.1, 0.6); + DynamicGasPrice::unsafe_new(self.dynamic_gas_enabled, 1.1, 0.6, None); } ChainConfig::Penumbra(_) => panic!("running tests with Penumbra chain not supported"), } From 051aec60a1c9221afac104c230afae4bdff4012e Mon Sep 17 00:00:00 2001 From: allthatjazzleo Date: Tue, 5 Aug 2025 17:32:00 +0800 Subject: [PATCH 4/6] chore: add changelog entry for CosmosEvmDynamicFee support --- .changelog/unreleased/.gitkeep | 0 .changelog/unreleased/features/4369-support-cosmos-evm.md | 2 ++ 2 files changed, 2 insertions(+) delete mode 100644 .changelog/unreleased/.gitkeep create mode 100644 .changelog/unreleased/features/4369-support-cosmos-evm.md diff --git a/.changelog/unreleased/.gitkeep b/.changelog/unreleased/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/.changelog/unreleased/features/4369-support-cosmos-evm.md b/.changelog/unreleased/features/4369-support-cosmos-evm.md new file mode 100644 index 0000000000..5edf4a9a0c --- /dev/null +++ b/.changelog/unreleased/features/4369-support-cosmos-evm.md @@ -0,0 +1,2 @@ +- missing CosmosEvmDynamicFee for extension_options and dynamic gas price support for cosmos evm + ([\#4369](https://github.com/informalsystems/hermes/issues/4369)) \ No newline at end of file From 81f4c9acaf609e07256c80f71e2e3aa0bff899e0 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 17 Oct 2025 09:08:57 +0800 Subject: [PATCH 5/6] fix: unable to resolve type URL for cosmos_evm_dynamic_fee --- crates/relayer/src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/relayer/src/config.rs b/crates/relayer/src/config.rs index 5304107627..ef77903ab0 100644 --- a/crates/relayer/src/config.rs +++ b/crates/relayer/src/config.rs @@ -134,7 +134,7 @@ impl ExtensionOption { Self::CosmosEvmDynamicFee(max_priority_price) => ExtensionOptionDynamicFeeTx { max_priority_price: max_priority_price.into(), } - .to_any("/cosmos.evm.types.v1.ExtensionOptionDynamicFeeTx"), + .to_any("/cosmos.evm.ante.v1.ExtensionOptionDynamicFeeTx"), } } } From 9acd34cda57d0e33d9cd6f2fbe2c053ea264ccfd Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 17 Oct 2025 09:09:02 +0800 Subject: [PATCH 6/6] suport both with cosmos_evm_dynamic_fee_v1 --- crates/relayer/src/config.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crates/relayer/src/config.rs b/crates/relayer/src/config.rs index ef77903ab0..eeae8868a9 100644 --- a/crates/relayer/src/config.rs +++ b/crates/relayer/src/config.rs @@ -122,6 +122,7 @@ pub fn parse_gas_prices(prices: String) -> Vec { pub enum ExtensionOption { EthermintDynamicFee(String), CosmosEvmDynamicFee(String), + CosmosEvmDynamicFeeV1(String), } impl ExtensionOption { @@ -134,6 +135,10 @@ impl ExtensionOption { Self::CosmosEvmDynamicFee(max_priority_price) => ExtensionOptionDynamicFeeTx { max_priority_price: max_priority_price.into(), } + .to_any("/cosmos.evm.types.v1.ExtensionOptionDynamicFeeTx"), + Self::CosmosEvmDynamicFeeV1(max_priority_price) => ExtensionOptionDynamicFeeTx { + max_priority_price: max_priority_price.into(), + } .to_any("/cosmos.evm.ante.v1.ExtensionOptionDynamicFeeTx"), } } @@ -154,6 +159,12 @@ impl Display for ExtensionOption { "CosmosEvmDynamicFee(max_priority_price: {max_priority_price})" ) } + Self::CosmosEvmDynamicFeeV1(max_priority_price) => { + write!( + f, + "CosmosEvmDynamicFeeV1(max_priority_price: {max_priority_price})" + ) + } } } }