diff --git a/ethers-etherscan/src/contract.rs b/ethers-etherscan/src/contract.rs index 55aa0a521..ebf24018b 100644 --- a/ethers-etherscan/src/contract.rs +++ b/ethers-etherscan/src/contract.rs @@ -48,6 +48,8 @@ pub enum SourceCodeMetadata { #[serde(default, skip_serializing_if = "Option::is_none")] settings: Option, }, + /// Contains just mapped source code. + Sources(HashMap), /// Contains only the source code. SourceCode(String), } @@ -57,7 +59,10 @@ impl SourceCodeMetadata { match self { Self::Metadata { sources, .. } => { sources.values().map(|s| s.content.clone()).collect::>().join("\n") - } + }, + Self::Sources(sources) => { + sources.values().map(|s| s.content.clone()).collect::>().join("\n") + }, Self::SourceCode(s) => s.clone(), } } @@ -65,6 +70,7 @@ impl SourceCodeMetadata { pub fn language(&self) -> Option { match self { Self::Metadata { language, .. } => language.clone(), + Self::Sources(_)=> None, Self::SourceCode(_) => None, } } @@ -72,6 +78,7 @@ impl SourceCodeMetadata { pub fn sources(&self) -> HashMap { match self { Self::Metadata { sources, .. } => sources.clone(), + Self::Sources(sources) => sources.clone(), Self::SourceCode(s) => HashMap::from([("Contract".into(), s.into())]), } } @@ -89,6 +96,7 @@ impl SourceCodeMetadata { } None => Ok(None), }, + Self::Sources(_) => Ok(None), Self::SourceCode(_) => Ok(None), } } @@ -97,6 +105,7 @@ impl SourceCodeMetadata { pub fn settings(&self) -> Option<&serde_json::Value> { match self { Self::Metadata { settings, .. } => settings.as_ref(), + Self::Sources(_) => None, Self::SourceCode(_) => None, } } diff --git a/ethers-etherscan/tests/it/contract.rs b/ethers-etherscan/tests/it/contract.rs index a0ff3cd35..a3972af74 100644 --- a/ethers-etherscan/tests/it/contract.rs +++ b/ethers-etherscan/tests/it/contract.rs @@ -97,3 +97,19 @@ async fn can_fetch_contract_source_tree_for_multi_entry_contract() { }) .await } + +/// Query a contract that has a plain source code mapping instead of tagged structures. +#[tokio::test] +#[serial] +async fn can_fetch_contract_source_tree_for_plain_source_code_mapping() { + run_with_client(Chain::Mainnet, |client| async move { + let meta = client + .contract_source_code("0x68b26dcf21180d2a8de5a303f8cc5b14c8d99c4c".parse().unwrap()) + .await + .unwrap(); + + assert_eq!(meta.items.len(), 1); + assert!(matches!(meta.items[0].source_code, SourceCodeMetadata::Sources(_))); + }) + .await +}