diff --git a/ethers-core/src/utils/solc.rs b/ethers-core/src/utils/solc.rs index 5beecaa9..05f0f6e3 100644 --- a/ethers-core/src/utils/solc.rs +++ b/ethers-core/src/utils/solc.rs @@ -1,13 +1,12 @@ -use std::{collections::HashMap, fmt, io::BufRead, path::PathBuf, process::Command}; +use std::{collections::HashMap, fmt, io::BufRead, path::PathBuf, process::Command, str::FromStr}; use glob::glob; -use serde::{Deserialize, Serialize}; +use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize, Serializer}; use thiserror::Error; use crate::{abi::Abi, types::Bytes}; use once_cell::sync::Lazy; use semver::Version; -use std::str::FromStr; /// The name of the `solc` binary on the system const SOLC: &str = "solc"; @@ -418,6 +417,156 @@ fn normalize_evm_version(version: &Version, evm_version: EvmVersion) -> Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Evm { + pub bytecode: Bytecode, + pub deployed_bytecode: Bytecode, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Bytecode { + #[serde(deserialize_with = "deserialize_bytes")] + pub object: Bytes, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Metadata { + pub compiler: Compiler, + pub language: String, + pub output: Output, + pub settings: Settings, + pub sources: Sources, + pub version: i64, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Compiler { + pub version: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Output { + pub abi: Vec, + pub devdoc: Option, + pub userdoc: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SolcAbi { + pub inputs: Vec, + #[serde(rename = "stateMutability")] + pub state_mutability: Option, + #[serde(rename = "type")] + pub abi_type: String, + pub name: Option, + pub outputs: Option>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Item { + #[serde(rename = "internalType")] + pub internal_type: String, + pub name: String, + #[serde(rename = "type")] + pub put_type: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Doc { + pub kind: String, + pub methods: Libraries, + pub version: u32, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Libraries { + #[serde(flatten)] + pub libs: HashMap, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Settings { + #[serde(rename = "compilationTarget")] + pub compilation_target: CompilationTarget, + #[serde(rename = "evmVersion")] + pub evm_version: String, + pub libraries: Libraries, + pub metadata: MetadataClass, + pub optimizer: Optimizer, + pub remappings: Vec>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CompilationTarget { + #[serde(flatten)] + pub inner: HashMap, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MetadataClass { + #[serde(rename = "bytecodeHash")] + pub bytecode_hash: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Optimizer { + pub enabled: bool, + pub runs: u32, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Sources { + #[serde(flatten)] + pub inner: HashMap, +} + +pub fn deserialize_bytes<'de, D>(d: D) -> std::result::Result +where + D: Deserializer<'de>, +{ + let value = String::deserialize(d)?; + + Ok(hex::decode(&value) + .map_err(|e| serde::de::Error::custom(e.to_string()))? + .into()) +} + +fn de_from_json_opt<'de, D, T>(deserializer: D) -> std::result::Result, D::Error> +where + D: Deserializer<'de>, + T: DeserializeOwned, +{ + if let Some(val) = >::deserialize(deserializer)? { + serde_json::from_str(&val).map_err(serde::de::Error::custom) + } else { + Ok(None) + } +} + +fn ser_to_inner_json(val: &T, s: S) -> std::result::Result +where + S: Serializer, + T: Serialize, +{ + let val = serde_json::to_string(val).map_err(serde::ser::Error::custom)?; + s.serialize_str(&val) +} + #[cfg(test)] mod tests { use super::*;