eigenlayer_contract_deployer/
slashing_registry_coordinator.rs

1#![allow(
2    non_camel_case_types,
3    non_snake_case,
4    clippy::pub_underscore_fields,
5    clippy::missing_errors_doc,
6    clippy::too_many_arguments,
7    clippy::used_underscore_binding,
8    clippy::cast_possible_truncation
9)]
10use std::collections::BTreeMap;
11
12use alloy_provider::Network;
13
14use crate::bindings::SlashingRegistryCoordinator::constructorCall;
15use crate::bindings::core::{
16    quorum_bitmap_history_lib, signature_checker_lib, slashing_registry_coordinator,
17};
18
19pub const ARTIFACT: &str =
20    include_str!("artifacts/eigenlayer-middleware-1.3.1/SlashingRegistryCoordinator.json");
21
22fn artifact() -> std::io::Result<serde_json::Value> {
23    serde_json::from_str(ARTIFACT).map_err(std::io::Error::other)
24}
25
26fn contract_bytecode()
27-> std::io::Result<(String, serde_json::value::Map<String, serde_json::Value>)> {
28    let artifact = artifact()?;
29    // Use CREATION bytecode for deployment, not deployed/runtime bytecode.
30    // Using runtime bytecode as init code results in an empty code deployment.
31    let bytecode = artifact["bytecode"]["object"]
32        .as_str()
33        .ok_or_else(|| std::io::Error::other("No deployed bytecode found"))?;
34    // Link against the creation bytecode link references
35    let link_references = artifact["bytecode"]["linkReferences"]
36        .as_object()
37        .cloned()
38        .unwrap_or_default();
39    Ok((bytecode.to_string(), link_references))
40}
41
42fn link_all_fully_qualified(
43    bytecode: &str,
44    link_references: &serde_json::Map<String, serde_json::Value>,
45    libs: &BTreeMap<&str, alloy_sol_types::private::Address>,
46) -> String {
47    let mut replacements = Vec::new();
48
49    // Iterate over link references
50    for (file_name, references) in link_references {
51        // Check if we have a corresponding library address
52        if let Some(&lib_address) = libs.get(file_name.as_str()) {
53            // Get the references object for this file
54            if let Some(refs_obj) = references.as_object() {
55                // Iterate through each contract's references in this file
56                for (_contract_name, positions) in refs_obj {
57                    if let Some(positions_array) = positions.as_array() {
58                        // Process each position
59                        for position in positions_array {
60                            if let (Some(start), Some(length)) =
61                                (position["start"].as_u64(), position["length"].as_u64())
62                            {
63                                // 1 bytes = 2 characters. then convert to usize
64                                let char_length = (length * 2) as usize;
65                                // Convert address to hex string and prepare replacement
66                                let addr_hex = format!("{:x}", lib_address);
67                                let addr_hex = addr_hex.strip_prefix("0x").unwrap_or(&addr_hex);
68
69                                // Pad with zeros or trim to match required length
70                                let replacement = if addr_hex.len() < char_length {
71                                    format!("{:0>width$}", addr_hex, width = char_length)
72                                } else {
73                                    addr_hex[..char_length].to_string()
74                                };
75
76                                replacements.push((
77                                    ((start + 1) * 2) as usize,
78                                    char_length,
79                                    replacement,
80                                ));
81                            }
82                        }
83                    }
84                }
85            }
86        }
87    }
88
89    // Apply replacements to the bytecode
90    let mut result = bytecode.to_string();
91    for (start, length, replacement) in replacements {
92        if start + length <= result.len() {
93            result.replace_range(start..start + length, &replacement);
94        }
95    }
96
97    result
98}
99
100#[allow(clippy::missing_panics_doc)]
101pub async fn deploy_builder<P: alloy_contract::private::Provider<N> + Clone, N: Network>(
102    provider: P,
103    _stakeRegistry: alloy::sol_types::private::Address,
104    _blsApkRegistry: alloy::sol_types::private::Address,
105    _indexRegistry: alloy::sol_types::private::Address,
106    _socketRegistry: alloy::sol_types::private::Address,
107    _allocationManager: alloy::sol_types::private::Address,
108    _pauserRegistry: alloy::sol_types::private::Address,
109    _version: alloy::sol_types::private::String,
110) -> alloy_contract::Result<alloy_contract::RawCallBuilder<P, N>> {
111    let (bytecode, link_references) = contract_bytecode().expect("Failed to get contract bytecode");
112    // Deploy library contracts if needed.
113    let quourm_bitmap_history_lib =
114        quorum_bitmap_history_lib::QuorumBitmapHistoryLib::deploy(provider.clone()).await?;
115    let signature_checker_lib =
116        signature_checker_lib::SignatureCheckerLib::deploy(provider.clone()).await?;
117    let libs = BTreeMap::from([
118        (
119            "src/libraries/QuorumBitmapHistoryLib.sol",
120            *quourm_bitmap_history_lib.address(),
121        ),
122        (
123            "src/libraries/SignatureCheckerLib.sol",
124            *signature_checker_lib.address(),
125        ),
126    ]);
127    let linked_bytecode = link_all_fully_qualified(&bytecode, &link_references, &libs);
128    let linked_bytecode =
129        alloy::hex::decode(linked_bytecode).expect("Failed to decode linked bytecode");
130    Ok(alloy_contract::RawCallBuilder::<P, N>::new_raw_deploy(
131        provider,
132        [
133            &linked_bytecode[..],
134            &alloy_sol_types::SolConstructor::abi_encode(&constructorCall {
135                _stakeRegistry,
136                _blsApkRegistry,
137                _indexRegistry,
138                _socketRegistry,
139                _allocationManager,
140                _pauserRegistry,
141                _version,
142            })[..],
143        ]
144        .concat()
145        .into(),
146    ))
147}
148
149pub async fn deploy<P: alloy_contract::private::Provider<N> + Clone, N: Network>(
150    provider: P,
151    _stakeRegistry: alloy::sol_types::private::Address,
152    _blsApkRegistry: alloy::sol_types::private::Address,
153    _indexRegistry: alloy::sol_types::private::Address,
154    _socketRegistry: alloy::sol_types::private::Address,
155    _allocationManager: alloy::sol_types::private::Address,
156    _pauserRegistry: alloy::sol_types::private::Address,
157    _version: alloy::sol_types::private::String,
158) -> alloy_contract::Result<
159    slashing_registry_coordinator::SlashingRegistryCoordinator::SlashingRegistryCoordinatorInstance<
160        P,
161        N,
162    >,
163> {
164    let builder = deploy_builder(
165        provider.clone(),
166        _stakeRegistry,
167        _blsApkRegistry,
168        _indexRegistry,
169        _socketRegistry,
170        _allocationManager,
171        _pauserRegistry,
172        _version,
173    )
174    .await?;
175    let deployed = builder.deploy().await?;
176
177    // ContractNotDeployed
178    Ok(slashing_registry_coordinator::SlashingRegistryCoordinator::new(deployed, provider))
179}
180
181#[cfg(test)]
182pub mod test {
183    use super::*;
184
185    #[test]
186    fn test_link_all_fully_qualified() {
187        let (bytecode, link_references) =
188            contract_bytecode().expect("Failed to get contract bytecode");
189        // Deploy library contracts if needed.
190        let quourm_bitmap_history_lib = alloy_primitives::Address::ZERO;
191        let signature_checker_lib = alloy_primitives::Address::ZERO;
192        let libs = BTreeMap::from([
193            (
194                "src/libraries/QuorumBitmapHistoryLib.sol",
195                quourm_bitmap_history_lib,
196            ),
197            (
198                "src/libraries/SignatureCheckerLib.sol",
199                signature_checker_lib,
200            ),
201        ]);
202        let linked_bytecode = link_all_fully_qualified(&bytecode, &link_references, &libs);
203        let linked_bytecode =
204            alloy::hex::decode(linked_bytecode).expect("Failed to decode linked bytecode");
205        println!("linked_bytecode: {:?}", linked_bytecode);
206    }
207}