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