hopr_chain_types/
lib.rs

1//! This crate contains various on-chain related modules and types.
2use alloy::{
3    contract::Result as ContractResult, network::TransactionBuilder, primitives, rpc::types::TransactionRequest,
4};
5use constants::{ERC_1820_DEPLOYER, ERC_1820_REGISTRY_DEPLOY_CODE, ETH_VALUE_FOR_ERC1820_DEPLOYER};
6use hopr_bindings::{
7    hoprannouncements::HoprAnnouncements::{self, HoprAnnouncementsInstance},
8    hoprchannels::HoprChannels::{self, HoprChannelsInstance},
9    hoprdummyproxyfornetworkregistry::HoprDummyProxyForNetworkRegistry::{
10        self, HoprDummyProxyForNetworkRegistryInstance,
11    },
12    hoprnetworkregistry::HoprNetworkRegistry::{self, HoprNetworkRegistryInstance},
13    hoprnodemanagementmodule::HoprNodeManagementModule::{self, HoprNodeManagementModuleInstance},
14    hoprnodesaferegistry::HoprNodeSafeRegistry::{self, HoprNodeSafeRegistryInstance},
15    hoprnodestakefactory::HoprNodeStakeFactory::{self, HoprNodeStakeFactoryInstance},
16    hoprsafeproxyfornetworkregistry::HoprSafeProxyForNetworkRegistry::{self, HoprSafeProxyForNetworkRegistryInstance},
17    hoprticketpriceoracle::HoprTicketPriceOracle::{self, HoprTicketPriceOracleInstance},
18    hoprtoken::HoprToken::{self, HoprTokenInstance},
19    hoprwinningprobabilityoracle::HoprWinningProbabilityOracle::{self, HoprWinningProbabilityOracleInstance},
20};
21use hopr_crypto_types::keypairs::{ChainKeypair, Keypair};
22use hopr_primitive_types::primitives::Address;
23use serde::{Deserialize, Serialize};
24
25pub mod actions;
26pub mod chain_events;
27pub mod constants;
28pub mod errors;
29// Various (mostly testing related) utility functions
30pub mod utils;
31
32/// Holds addresses of all smart contracts.
33#[serde_with::serde_as]
34#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
35pub struct ContractAddresses {
36    /// Token contract
37    #[serde_as(as = "serde_with::DisplayFromStr")]
38    pub token: Address,
39    /// Channels contract
40    #[serde_as(as = "serde_with::DisplayFromStr")]
41    pub channels: Address,
42    /// Announcements contract
43    #[serde_as(as = "serde_with::DisplayFromStr")]
44    pub announcements: Address,
45    /// Network registry contract
46    #[serde_as(as = "serde_with::DisplayFromStr")]
47    pub network_registry: Address,
48    /// Network registry proxy contract
49    #[serde_as(as = "serde_with::DisplayFromStr")]
50    pub network_registry_proxy: Address,
51    /// Safe registry contract
52    #[serde_as(as = "serde_with::DisplayFromStr")]
53    pub node_safe_registry: Address,
54    /// Price oracle contract
55    #[serde_as(as = "serde_with::DisplayFromStr")]
56    pub ticket_price_oracle: Address,
57    /// Minimum ticket winning probability contract
58    #[serde_as(as = "serde_with::DisplayFromStr")]
59    pub winning_probability_oracle: Address,
60    /// Stake factory contract
61    #[serde_as(as = "serde_with::DisplayFromStr")]
62    pub node_stake_v2_factory: Address,
63    /// Node management module contract (can be zero if safe is not used)
64    #[serde_as(as = "serde_with::DisplayFromStr")]
65    pub module_implementation: Address,
66}
67
68#[derive(Debug, Clone)]
69pub enum NetworkRegistryProxy<P> {
70    Dummy(HoprDummyProxyForNetworkRegistryInstance<P>),
71    Safe(HoprSafeProxyForNetworkRegistryInstance<P>),
72}
73
74impl<P> NetworkRegistryProxy<P>
75where
76    P: alloy::providers::Provider + Clone,
77{
78    pub fn address(&self) -> Address {
79        match self {
80            NetworkRegistryProxy::Dummy(c) => Into::<Address>::into(*c.address()),
81            NetworkRegistryProxy::Safe(c) => Into::<Address>::into(*c.address()),
82        }
83    }
84}
85
86/// Holds instances to contracts.
87#[derive(Debug)]
88pub struct ContractInstances<P> {
89    pub token: HoprTokenInstance<P>,
90    pub channels: HoprChannelsInstance<P>,
91    pub announcements: HoprAnnouncementsInstance<P>,
92    pub network_registry: HoprNetworkRegistryInstance<P>,
93    pub network_registry_proxy: NetworkRegistryProxy<P>,
94    pub safe_registry: HoprNodeSafeRegistryInstance<P>,
95    pub price_oracle: HoprTicketPriceOracleInstance<P>,
96    pub win_prob_oracle: HoprWinningProbabilityOracleInstance<P>,
97    pub stake_factory: HoprNodeStakeFactoryInstance<P>,
98    pub module_implementation: HoprNodeManagementModuleInstance<P>,
99}
100
101impl<P> ContractInstances<P>
102where
103    P: alloy::providers::Provider + Clone,
104{
105    pub fn new(contract_addresses: &ContractAddresses, provider: P, use_dummy_nr: bool) -> Self {
106        Self {
107            token: HoprTokenInstance::new(contract_addresses.token.into(), provider.clone()),
108            channels: HoprChannelsInstance::new(contract_addresses.channels.into(), provider.clone()),
109            announcements: HoprAnnouncementsInstance::new(contract_addresses.announcements.into(), provider.clone()),
110            network_registry: HoprNetworkRegistryInstance::new(
111                contract_addresses.network_registry.into(),
112                provider.clone(),
113            ),
114            network_registry_proxy: if use_dummy_nr {
115                NetworkRegistryProxy::Dummy(HoprDummyProxyForNetworkRegistryInstance::new(
116                    contract_addresses.network_registry_proxy.into(),
117                    provider.clone(),
118                ))
119            } else {
120                NetworkRegistryProxy::Safe(HoprSafeProxyForNetworkRegistryInstance::new(
121                    contract_addresses.network_registry_proxy.into(),
122                    provider.clone(),
123                ))
124            },
125            safe_registry: HoprNodeSafeRegistryInstance::new(
126                contract_addresses.node_safe_registry.into(),
127                provider.clone(),
128            ),
129            price_oracle: HoprTicketPriceOracleInstance::new(
130                contract_addresses.ticket_price_oracle.into(),
131                provider.clone(),
132            ),
133            win_prob_oracle: HoprWinningProbabilityOracleInstance::new(
134                contract_addresses.winning_probability_oracle.into(),
135                provider.clone(),
136            ),
137            stake_factory: HoprNodeStakeFactoryInstance::new(
138                contract_addresses.node_stake_v2_factory.into(),
139                provider.clone(),
140            ),
141            module_implementation: HoprNodeManagementModuleInstance::new(
142                contract_addresses.module_implementation.into(),
143                provider.clone(),
144            ),
145        }
146    }
147
148    /// Deploys testing environment (with dummy network registry proxy) via the given provider.
149    async fn inner_deploy_common_contracts_for_testing(provider: P, deployer: &ChainKeypair) -> ContractResult<Self> {
150        {
151            // Fund 1820 deployer and deploy ERC1820Registry
152            let tx = TransactionRequest::default()
153                .with_to(ERC_1820_DEPLOYER)
154                .with_value(ETH_VALUE_FOR_ERC1820_DEPLOYER);
155
156            // Sequentially executing the following transactions:
157            // 1. Fund the deployer wallet
158            provider.send_transaction(tx.clone()).await?.watch().await?;
159            // 2. Use the fundedd deployer wallet to deploy ERC1820Registry with a signed txn
160            provider
161                .send_raw_transaction(&ERC_1820_REGISTRY_DEPLOY_CODE)
162                .await?
163                .watch()
164                .await?;
165        }
166
167        // Get deployer address
168        let self_address = deployer.public().to_address().into();
169
170        let stake_factory = HoprNodeStakeFactory::deploy(provider.clone()).await?;
171        let module_implementation = HoprNodeManagementModule::deploy(provider.clone()).await?;
172        let safe_registry = HoprNodeSafeRegistry::deploy(provider.clone()).await?;
173        let price_oracle = HoprTicketPriceOracle::deploy(
174            provider.clone(),
175            self_address,
176            primitives::U256::from(100000000000000000_u128), // U256::from(100000000000000000_u128),
177        )
178        .await?;
179        let win_prob_oracle = HoprWinningProbabilityOracle::deploy(
180            provider.clone(),
181            self_address,
182            primitives::aliases::U56::from(0xFFFFFFFFFFFFFF_u64), /* 0xFFFFFFFFFFFFFF in hex or 72057594037927935 in
183                                                                   * decimal values */
184        )
185        .await?;
186        let token = HoprToken::deploy(provider.clone()).await?;
187        let zero_network_registry_proxy =
188            HoprDummyProxyForNetworkRegistryInstance::new(primitives::Address::ZERO, provider.clone());
189        let channels = HoprChannels::deploy(
190            provider.clone(),
191            primitives::Address::from(token.address().as_ref()),
192            1_u32,
193            primitives::Address::from(safe_registry.address().as_ref()),
194        )
195        .await?;
196        let announcements = HoprAnnouncements::deploy(
197            provider.clone(),
198            primitives::Address::from(safe_registry.address().as_ref()),
199        )
200        .await?;
201        let network_registry = HoprNetworkRegistryInstance::new(primitives::Address::ZERO, provider.clone());
202
203        Ok(Self {
204            token,
205            channels,
206            announcements,
207            network_registry,
208            network_registry_proxy: NetworkRegistryProxy::Dummy(zero_network_registry_proxy),
209            safe_registry,
210            price_oracle,
211            win_prob_oracle,
212            stake_factory,
213            module_implementation,
214        })
215    }
216
217    /// Deploys testing environment (with dummy network registry proxy) via the given provider.
218    pub async fn deploy_for_testing(provider: P, deployer: &ChainKeypair) -> ContractResult<Self> {
219        let instances = Self::inner_deploy_common_contracts_for_testing(provider.clone(), deployer).await?;
220
221        // Get deployer address
222        let self_address = deployer.public().to_address().into();
223        // Deploy network registry proxy
224        let network_registry_proxy = HoprDummyProxyForNetworkRegistry::deploy(provider.clone(), self_address).await?;
225        let network_registry = HoprNetworkRegistry::deploy(
226            provider.clone(),
227            primitives::Address::from(network_registry_proxy.address().as_ref()),
228            self_address,
229            self_address,
230        )
231        .await?;
232
233        // Disable network registry in local environment and wait for its confirmation
234        network_registry.disableRegistry().send().await?.watch().await?;
235
236        Ok(Self {
237            network_registry,
238            network_registry_proxy: NetworkRegistryProxy::Dummy(network_registry_proxy),
239            ..instances
240        })
241    }
242
243    /// Deploys testing environment (with dummy network registry proxy) via the given provider.
244    pub async fn deploy_for_testing_with_staking_proxy(provider: P, deployer: &ChainKeypair) -> ContractResult<Self> {
245        let instances = Self::inner_deploy_common_contracts_for_testing(provider.clone(), deployer).await?;
246
247        // Get deployer address
248        let self_address = deployer.public().to_address().into();
249        // Deploy network registry proxy
250        // TODO:
251        let network_registry_proxy = HoprSafeProxyForNetworkRegistry::deploy(
252            provider.clone(),
253            self_address,
254            self_address,
255            primitives::Uint::ZERO,
256            provider.get_block_number().await?.into(),
257            primitives::Address::from(instances.token.address().as_ref()),
258            primitives::Address::from(instances.safe_registry.address().as_ref()),
259        )
260        .await?;
261        let network_registry = HoprNetworkRegistry::deploy(
262            provider.clone(),
263            primitives::Address::from(network_registry_proxy.address().as_ref()),
264            self_address,
265            self_address,
266        )
267        .await?;
268
269        // Disable network registry in local environment and wait for its confirmation
270        network_registry.disableRegistry().send().await?.watch().await?;
271
272        Ok(Self {
273            network_registry,
274            network_registry_proxy: NetworkRegistryProxy::Safe(network_registry_proxy),
275            ..instances
276        })
277    }
278}
279
280impl<P> From<&ContractInstances<P>> for ContractAddresses
281where
282    P: alloy::providers::Provider + Clone,
283{
284    fn from(instances: &ContractInstances<P>) -> Self {
285        Self {
286            token: Into::<Address>::into(*instances.token.address()),
287            channels: Into::<Address>::into(*instances.channels.address()),
288            announcements: Into::<Address>::into(*instances.announcements.address()),
289            network_registry: Into::<Address>::into(*instances.network_registry.address()),
290            network_registry_proxy: instances.network_registry_proxy.address(),
291            node_safe_registry: Into::<Address>::into(*instances.safe_registry.address()),
292            ticket_price_oracle: Into::<Address>::into(*instances.price_oracle.address()),
293            winning_probability_oracle: Into::<Address>::into(*instances.win_prob_oracle.address()),
294            node_stake_v2_factory: Into::<Address>::into(*instances.stake_factory.address()),
295            module_implementation: Into::<Address>::into(*instances.module_implementation.address()),
296        }
297    }
298}