Skip to main content

rain_metadata/solc/
mod.rs

1use serde_json::Value;
2use strum::EnumString;
3use crate::error::Error;
4
5/// Represent section of a solidity artifact to extract
6#[derive(Copy, Clone, EnumString, strum::Display)]
7#[strum(serialize_all = "kebab-case")]
8pub enum ArtifactComponent {
9    Abi,
10    Bytecode,
11    DeployedBytecode,
12}
13
14/// extracts the given section of a solidity artifact as [Value]
15///
16/// does not perform any checks on the returned [Value] such as if
17/// it is null or not.
18/// The given data should be utf8 encoded json string bytes
19pub fn extract_artifact_component_json(
20    component: ArtifactComponent,
21    data: &[u8],
22) -> Result<Value, Error> {
23    let json = serde_json::from_str::<Value>(std::str::from_utf8(data)?)?;
24    match component {
25        ArtifactComponent::Abi => Ok(json["abi"].clone()),
26        ArtifactComponent::Bytecode => Ok(json["bytecode"].clone()),
27        ArtifactComponent::DeployedBytecode => Ok(json["deployedBytecode"].clone()),
28    }
29}
30
31#[cfg(all(test, not(target_family = "wasm")))]
32mod tests {
33    use super::*;
34
35    fn artifact_json() -> Vec<u8> {
36        serde_json::json!({
37            "abi": [{ "type": "function", "name": "foo" }],
38            "bytecode": { "object": "0x6001" },
39            "deployedBytecode": { "object": "0x6002" }
40        })
41        .to_string()
42        .into_bytes()
43    }
44
45    /// Each component arm extracts exactly its own key.
46    #[test]
47    fn test_extract_each_component() {
48        let data = artifact_json();
49        assert_eq!(
50            extract_artifact_component_json(ArtifactComponent::Abi, &data).unwrap(),
51            serde_json::json!([{ "type": "function", "name": "foo" }])
52        );
53        assert_eq!(
54            extract_artifact_component_json(ArtifactComponent::Bytecode, &data).unwrap(),
55            serde_json::json!({ "object": "0x6001" })
56        );
57        assert_eq!(
58            extract_artifact_component_json(ArtifactComponent::DeployedBytecode, &data).unwrap(),
59            serde_json::json!({ "object": "0x6002" })
60        );
61    }
62
63    /// Documented: no null check is performed — a missing component is
64    /// returned as JSON null, not an error.
65    #[test]
66    fn test_missing_component_returns_null() {
67        assert_eq!(
68            extract_artifact_component_json(ArtifactComponent::Abi, b"{}").unwrap(),
69            serde_json::Value::Null
70        );
71    }
72
73    /// Non-utf8 and non-json inputs error.
74    #[test]
75    fn test_invalid_input_errors() {
76        assert!(extract_artifact_component_json(ArtifactComponent::Abi, &[0xff, 0xfe]).is_err());
77        assert!(extract_artifact_component_json(ArtifactComponent::Abi, b"not json").is_err());
78    }
79}