diff --git a/ethers-providers/src/rpc/provider.rs b/ethers-providers/src/rpc/provider.rs index 1889761e47..e8ea084fd3 100644 --- a/ethers-providers/src/rpc/provider.rs +++ b/ethers-providers/src/rpc/provider.rs @@ -767,7 +767,29 @@ impl Middleware for Provider

{ } async fn node_info(&self) -> Result { - self.request("admin_nodeInfo", ()).await + let mut raw: String = self.request("admin_nodeInfo", ()).await?; + // The ethereum mainnet TTD is 58750000000000000000000, and geth serializes this + // without quotes, because that is how golang `big.Int`s marshal in JSON. Numbers + // are arbitrary precision in JSON, so this is valid JSON. This number is also + // greater than a `u64`. + // + // Unfortunately, serde_json only supports parsing up to `u64`, resorting to `f64` + // once `u64` overflows: + // + // + // + // + // serde_json does have an arbitrary precision feature, but this breaks untagged + // enums in serde: + // + // + // + // To solve this, we surround the mainnet TTD with quotes, which our custom Visitor + // accepts. + if raw.contains(":58750000000000000000000") { + raw = raw.replacen(":58750000000000000000000", ":\"58750000000000000000000\"", 1); + } + serde_json::from_str(&raw).map_err(Into::into) } async fn peers(&self) -> Result, Self::Error> {