diff --git a/ethers-providers/src/transports/retry.rs b/ethers-providers/src/transports/retry.rs index 5c496045..72b823de 100644 --- a/ethers-providers/src/transports/retry.rs +++ b/ethers-providers/src/transports/retry.rs @@ -5,7 +5,6 @@ use super::{common::JsonRpcError, http::ClientError}; use crate::{provider::ProviderError, JsonRpcClient}; use std::{ - clone::Clone, fmt::Debug, sync::atomic::{AtomicU32, Ordering}, time::Duration, @@ -135,10 +134,23 @@ where A: std::fmt::Debug + Serialize + Send + Sync, R: DeserializeOwned, { - let ahead_in_queue = self.requests_enqueued.fetch_add(1, Ordering::SeqCst) as u64; + // Helper type that caches the `params` value across several retries + // This is necessary because the wrapper provider is supposed to skip he `params` if it's of + // size 0, see `crate::transports::common::Request` + enum RetryParams { + Value(Params), + Zst(()), + } - let params = - serde_json::to_value(params).map_err(|err| RetryClientError::SerdeJson(err))?; + let params = if std::mem::size_of::() == 0 { + RetryParams::Zst(()) + } else { + let params = + serde_json::to_value(params).map_err(|err| RetryClientError::SerdeJson(err))?; + RetryParams::Value(params) + }; + + let ahead_in_queue = self.requests_enqueued.fetch_add(1, Ordering::SeqCst) as u64; let mut retry_number: u32 = 0; @@ -148,7 +160,11 @@ where // hack to not hold `R` across an await in the sleep future and prevent requiring // R: Send + Sync { - match self.inner.request(method, params.clone()).await { + let resp = match params { + RetryParams::Value(ref params) => self.inner.request(method, params).await, + RetryParams::Zst(unit) => self.inner.request(method, unit).await, + }; + match resp { Ok(ret) => { self.requests_enqueued.fetch_sub(1, Ordering::SeqCst); return Ok(ret) diff --git a/ethers-providers/tests/provider.rs b/ethers-providers/tests/provider.rs index 666de8e7..b1da9db7 100644 --- a/ethers-providers/tests/provider.rs +++ b/ethers-providers/tests/provider.rs @@ -91,6 +91,28 @@ mod eth_tests { let (_max_fee_per_gas, _max_priority_fee_per_gas) = provider.estimate_eip1559_fees(None).await.unwrap(); } + + #[tokio::test] + #[ignore] + async fn test_hardhat_compatibility() { + use ethers_providers::RetryClient; + + async fn send_zst_requests(provider: M) { + let _ = provider.get_chainid().await.unwrap(); + let _ = provider.get_block_number().await.unwrap(); + let _ = provider.get_gas_price().await.unwrap(); + let _ = provider.get_accounts().await.unwrap(); + let _ = provider.get_net_version().await.unwrap(); + } + + let provider = Provider::::try_from("http://localhost:8545").unwrap(); + send_zst_requests(provider).await; + + let provider = + Provider::>::new_client("http://localhost:8545", 10, 200).unwrap(); + + send_zst_requests(provider).await; + } } #[cfg(feature = "celo")]