Skip to main content

libid_contracts/bindings/
mod.rs

1//! Hand-written `alloy::sol!` bindings, kept in lockstep with the Solidity
2//! sources in `solidity/contracts`. One module per contract directory.
3
4pub mod ceremony;
5pub mod circuits;
6pub mod ens;
7pub mod escrow;
8pub mod factory;
9pub mod identity;
10pub mod proxy;
11
12/// The drift check the hand-written bindings are held to.
13#[cfg(test)]
14pub(crate) mod drift {
15    use std::collections::BTreeMap;
16
17    use alloy::json_abi::{
18        Event,
19        Function,
20        JsonAbi,
21    };
22
23    use crate::Artifacts;
24
25    /// A function as the check compares it: its selector's signature, its
26    /// output types and its state mutability. A selector alone would miss a
27    /// binding that decodes the wrong return.
28    fn function(f: &Function) -> (String, String) {
29        (
30            format!(
31                "function {} {}",
32                f.signature_with_outputs(),
33                f.state_mutability.as_json_str()
34            ),
35            format!("function {}", f.signature()),
36        )
37    }
38
39    /// An event with which of its parameters are indexed: the topic hash
40    /// alone would miss a binding that decodes an indexed field from data.
41    fn event(e: &Event) -> (String, String) {
42        let params: Vec<String> = e
43            .inputs
44            .iter()
45            .map(|p| {
46                if p.indexed {
47                    format!("{} indexed", p.ty)
48                } else {
49                    p.ty.clone()
50                }
51            })
52            .collect();
53        (
54            format!("event {}({})", e.name, params.join(",")),
55            format!("event {}", e.signature()),
56        )
57    }
58
59    /// Every item of an ABI, keyed by what the check compares, with the
60    /// plain signature `omitted` names it by.
61    fn items(abi: &JsonAbi) -> BTreeMap<String, String> {
62        abi.functions()
63            .map(function)
64            .chain(abi.events().map(event))
65            .chain(abi.errors().map(|e| {
66                (
67                    format!("error {}", e.signature()),
68                    format!("error {}", e.signature()),
69                )
70            }))
71            .collect()
72    }
73
74    /// Every item in the vendored artifact ABI is bound identically (inputs,
75    /// outputs, mutability, indexing) or listed in `omitted`, and the binding
76    /// has nothing extra.
77    pub(crate) fn assert_binding_matches_artifact(
78        file: &str,
79        contract: &str,
80        bound: &JsonAbi,
81        omitted: &[&str],
82    ) {
83        // The crate embeds no ABI; the check reads forge's build output.
84        let out = concat!(env!("CARGO_MANIFEST_DIR"), "/../../solidity/out");
85        let json = Artifacts::from_dir(out)
86            .raw(file, contract)
87            .expect("no forge build output; run `forge build` in solidity/");
88        let compiled: JsonAbi = serde_json::from_value(json["abi"].clone())
89            .expect("the forge artifact has no ABI");
90        let compiled = items(&compiled);
91        let bound = items(bound);
92
93        let mut unbound: Vec<&str> = compiled
94            .iter()
95            .filter(|(full, _)| !bound.contains_key(*full))
96            .map(|(_, short)| short.as_str())
97            .collect();
98        unbound.sort_unstable();
99        unbound.dedup();
100        let mut omitted = omitted.to_vec();
101        omitted.sort_unstable();
102        assert_eq!(
103            unbound, omitted,
104            "{contract}: the artifact has items the binding does not bind as compiled, or the \
105             omitted list is stale"
106        );
107
108        let extra: Vec<&str> = bound
109            .keys()
110            .filter(|full| !compiled.contains_key(*full))
111            .map(String::as_str)
112            .collect();
113        assert!(
114            extra.is_empty(),
115            "{contract}: the binding has items the contract does not: {extra:?}"
116        );
117    }
118}