1#![allow(clippy::too_many_arguments)]
2use std::{ops::Add, str::FromStr, sync::Arc};
9
10use IMulticall3Extract::IMulticall3ExtractInstance;
11use SafeSingleton::{SafeSingletonInstance, execTransactionCall, removeOwnerCall, setupCall};
12use alloy::{
13 network::TransactionBuilder,
14 primitives::{Address, B256, Bytes, U256, keccak256, utils::format_units},
15 providers::{
16 CallInfoTrait, CallItem, MULTICALL3_ADDRESS, MulticallBuilder, MulticallError, Provider, WalletProvider,
17 bindings::IMulticall3::{Call3, Call3Value, aggregate3Call, aggregate3ValueCall},
18 },
19 rpc::types::TransactionRequest,
20 signers::{Signer, local::PrivateKeySigner},
21 sol,
22 sol_types::{SolCall, SolValue},
23};
24use hex_literal::hex;
25use hopr_bindings::{
26 hoprnetworkregistry::HoprNetworkRegistry::HoprNetworkRegistryInstance,
27 hoprnodemanagementmodule::HoprNodeManagementModule::{
28 HoprNodeManagementModuleInstance, addChannelsAndTokenTargetCall, includeNodeCall, removeNodeCall,
29 scopeTargetTokenCall,
30 },
31 hoprnodesaferegistry::HoprNodeSafeRegistry::{HoprNodeSafeRegistryInstance, deregisterNodeBySafeCall},
32 hoprnodestakefactory::HoprNodeStakeFactory::{HoprNodeStakeFactoryInstance, cloneCall},
33 hoprtoken::HoprToken::{HoprTokenInstance, approveCall},
34};
35use hopr_crypto_types::keypairs::{ChainKeypair, Keypair};
36use tracing::{debug, info};
37
38use crate::utils::{
39 DEFAULT_ANNOUNCEMENT_PERMISSIONS, DEFAULT_CAPABILITY_PERMISSIONS, DEFAULT_NODE_PERMISSIONS,
40 DOMAIN_SEPARATOR_TYPEHASH, HelperErrors, SAFE_COMPATIBILITYFALLBACKHANDLER_ADDRESS, SAFE_MULTISEND_ADDRESS,
41 SAFE_SAFE_ADDRESS, SAFE_SAFEPROXYFACTORY_ADDRESS, SAFE_TX_TYPEHASH, SENTINEL_OWNERS, get_create2_address,
42};
43
44sol!(
45 #![sol(abi)]
46 #![sol(rpc)]
47 contract SafeSingleton {
48 event ExecutionSuccess(bytes32 indexed txHash, uint256 payment);
49
50 function setup(address[],uint256,address,bytes,address,address,uint256,address);
51 function execTransaction(address to, uint256 value, bytes calldata data, uint8 operation, uint256 safeTxGas, uint256 baseGas, uint256 gasPrice, address gasToken, address payable refundReceiver, bytes memory signatures) public payable returns (bool);
52 function removeOwner(address prevOwner, address owner, uint256 _threshold) public;
53 function getThreshold() public view returns (uint256);
54 function getOwners() public view returns (address[] memory);
55 function nonce() public view returns (uint256);
56 function domainSeparator() public view returns (bytes32);
57 function encodeTransactionData(address to, uint256 value, bytes calldata data, uint8 operation, uint256 safeTxGas, uint256 baseGas, uint256 gasPrice, address gasToken, address refundReceiver, uint256 _nonce) public view returns (bytes memory);
58 function getTransactionHash(address to, uint256 value, bytes calldata data, uint8 operation, uint256 safeTxGas, uint256 baseGas, uint256 gasPrice, address gasToken, address refundReceiver, uint256 _nonce) public view returns (bytes32);
59 function isModuleEnabled(address module) public view returns (bool);
60 }
61);
62
63sol!(
64 #![sol(abi)]
65 #![sol(rpc)]
66 contract ModuleSingleton {
67 function isNode(address) external view returns (bool);
68 function getTargets() external view returns (uint256[] memory);
69 function owner() public view returns (address);
70 }
71);
72
73sol!(
74 #![sol(abi)]
75 #![sol(rpc)]
76 function multiSend(bytes memory transactions) public payable;
77);
78
79sol!(
80 #![sol(abi)]
81 #![sol(rpc)]
82 interface IMulticall3Extract {
83 function getEthBalance(address addr) external view returns (uint256 balance);
84 }
85);
86
87#[derive(Debug, Clone, PartialEq, Eq)]
89pub enum SafeTxOperation {
90 Call,
91 DelegateCall,
92}
93impl SafeTxOperation {
94 pub fn to_byte(&self) -> [u8; 1] {
96 match self {
97 SafeTxOperation::Call => hex!("00"),
98 SafeTxOperation::DelegateCall => hex!("01"),
99 }
100 }
101}
102
103impl From<SafeTxOperation> for u8 {
104 fn from(s: SafeTxOperation) -> u8 {
105 s as u8
106 }
107}
108
109#[derive(Debug, Clone)]
111pub struct MultisendTransaction {
112 pub encoded_data: Bytes,
114 pub tx_operation: SafeTxOperation,
116 pub to: Address,
118 pub value: U256,
120}
121
122impl MultisendTransaction {
124 fn encode_packed(&self) -> Vec<u8> {
126 let tx_operation_bytes: Bytes = self.tx_operation.to_byte().into();
127
128 let value = (
129 tx_operation_bytes, self.to, U256::from(self.value), U256::from(self.encoded_data.len()), self.encoded_data.clone(), );
135 value.abi_encode_packed()
136 }
137
138 fn build_multisend_tx(transactions: Vec<MultisendTransaction>) -> Vec<u8> {
140 let mut payload: Vec<u8> = Vec::new();
141 for transaction in transactions {
142 payload = [payload, transaction.encode_packed()].concat();
143 }
144 debug!("payload {:?}", hex::encode(&payload));
145 payload
146 }
147}
148
149fn get_domain_separator(chain_id: U256, contract_address: Address) -> [u8; 32] {
152 keccak256(
153 (
154 B256::from_str(DOMAIN_SEPARATOR_TYPEHASH)
155 .unwrap_or_else(|_| panic!("decode the DOMAIN_SEPARATOR_TYPEHASH")), chain_id, contract_address, )
159 .abi_encode(),
160 )
161 .into()
162}
163
164fn get_safe_transaction_hash(
167 to: Address,
168 value: U256,
169 data: Vec<u8>,
170 operation: SafeTxOperation,
171 refund_address: Address,
172 nonce: U256,
173 domain_separator: [u8; 32],
174) -> [u8; 32] {
175 let data_hash = keccak256(data);
177
178 let encoded = (
179 B256::from_str(SAFE_TX_TYPEHASH).unwrap_or_else(|_| panic!("failed to decode the SAFE_TX_TYPEHASH")), to, value, data_hash, U256::from(operation as u8), U256::ZERO, U256::ZERO, U256::ZERO, Address::ZERO, refund_address, nonce, )
191 .abi_encode();
192
193 let safe_hash = keccak256(encoded);
194
195 let encoded_transaction_data = (hex!("1901"), domain_separator, safe_hash).abi_encode_packed();
196
197 let transaction_hash = keccak256(encoded_transaction_data);
198 debug!("transaction_hash {:?}", hex::encode(transaction_hash));
199 transaction_hash.0
200}
201
202pub async fn send_multisend_safe_transaction_with_threshold_one<P: WalletProvider + Provider>(
207 safe: SafeSingletonInstance<Arc<P>>,
208 signer_key: ChainKeypair,
209 multisend_contract: Address,
210 multisend_txns: Vec<MultisendTransaction>,
211 chain_id: U256,
212 nonce: U256,
213) -> Result<(), HelperErrors> {
214 let signer = safe.provider().default_signer_address();
216 let wallet = PrivateKeySigner::from_slice(signer_key.secret().as_ref()).expect("failed to construct wallet");
218
219 let total_value = multisend_txns
222 .clone()
223 .into_iter()
224 .fold(U256::ZERO, |acc, cur| acc.add(cur.value));
225 let tx_payload = MultisendTransaction::build_multisend_tx(multisend_txns);
227 let multisend_payload = multiSendCall {
228 transactions: tx_payload.into(),
229 }
230 .abi_encode();
231 let domain_separator = get_domain_separator(chain_id, *safe.address());
233
234 debug!("multisend_payload {:?}", hex::encode(&multisend_payload));
235
236 let transaction_hash = get_safe_transaction_hash(
238 multisend_contract,
239 total_value,
240 multisend_payload.clone(),
241 SafeTxOperation::DelegateCall,
242 signer,
243 nonce,
244 domain_separator,
245 );
246
247 let signature = wallet
249 .sign_hash(&B256::from_slice(&transaction_hash))
250 .await
251 .unwrap_or_else(|_| panic!("failed to sign a transaction hash"));
252 debug!("signature {:?}", hex::encode(signature.as_bytes()));
253
254 let tx_receipt = safe
256 .execTransaction(
257 multisend_contract,
258 total_value,
259 multisend_payload.into(),
260 SafeTxOperation::DelegateCall.into(),
261 U256::ZERO,
262 U256::ZERO,
263 U256::ZERO,
264 Address::ZERO,
265 signer,
266 Bytes::from(signature.as_bytes()),
267 )
268 .send()
269 .await?
270 .get_receipt()
272 .await?;
273
274 tx_receipt
275 .decoded_log::<SafeSingleton::ExecutionSuccess>()
276 .ok_or(HelperErrors::MultiSendError)?;
277 Ok(())
278}
279
280pub async fn deploy_multicall3_for_testing<P: Provider>(provider: Arc<P>) -> Result<(), HelperErrors> {
282 let tx = TransactionRequest::default()
284 .with_to(Address::from_str(crate::utils::MULTICALL3_DEPLOYER).expect("failed to parse MULTICALL3_DEPLOYER"))
285 .with_value(U256::from(crate::utils::ETH_VALUE_FOR_MULTICALL3_DEPLOYER));
286
287 provider
288 .send_transaction(tx)
289 .await
290 .map_err(|e| HelperErrors::RpcError(e.into()))?
291 .watch()
292 .await?;
294
295 provider.send_raw_transaction(
296 &hex!("f90f538085174876e800830f42408080b90f00608060405234801561001057600080fd5b50610ee0806100206000396000f3fe6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bbe565b61014d610148366004610a85565b6104ef565b604051610111929190610bd8565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c60565b610690565b60405161011193929190610cba565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610ce2565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c60565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d18565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d31565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d60565b6020026020010151905087878381811061035d5761035d610d60565b905060200281019061036f9190610d8f565b6040810135958601959093506103886020850185610ce2565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dcd565b6040516103ba929190610e32565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d31565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d60565b90506020028101906105749190610e42565b92506105836020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dcd565b6040516105b4929190610e32565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d60565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d31565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d60565b6020026020010151905086868381811061074c5761074c610d60565b905060200281019061075e9190610e76565b925061076d6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dcd565b60405161079e929190610e32565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d31565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d60565b602002602001015190508686838181106108fb576108fb610d60565b905060200281019061090d9190610e42565b925061091c6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dcd565b60405161094d929190610e32565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b81811115610aff576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b84811015610bb1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9d81860183610ac7565b9a86019a9450505090830190600101610b4f565b5090979650505050505050565b602081526000610bd16020830184610b32565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c52577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c40868351610ac7565b95509284019290840190600101610c06565b509398975050505050505050565b600080600060408486031215610c7557600080fd5b83358015158114610c8557600080fd5b9250602084013567ffffffffffffffff811115610ca157600080fd5b610cad86828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd96060830184610b32565b95945050505050565b600060208284031215610cf457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bd157600080fd5b600060208284031215610d2a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dc357600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610e0257600080fd5b83018035915067ffffffffffffffff821115610e1d57600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dc357600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dc357600080fdfea2646970667358221220bb2b5c71a328032f97c676ae39a1ec2148d3e5d6f73d95e9b17910152d61f16264736f6c634300080c00331ca0edce47092c0f398cebf3ffc267f05c8e7076e3b89445e0fe50f6332273d4569ba01b0b9d000e19b24c5869b0fc3b22b0d6fa47cd63316875cbbd577d76e6fde086")
297 ).await.map_err(|e| HelperErrors::RpcError(e.into()))?
298 .watch()
299 .await?;
301 Ok(())
302}
303
304pub async fn get_chain_id_and_safe_nonce<P: Provider>(
306 safe: SafeSingletonInstance<P>,
307) -> Result<(U256, U256), HelperErrors> {
308 let provider = safe.provider();
309 let multicall = provider.multicall().get_chain_id().add(safe.nonce());
310 let (get_chain_id_return, nonce_return) = multicall.aggregate().await?;
311
312 Ok((get_chain_id_return, nonce_return))
313}
314
315pub async fn get_native_and_token_balances<P: Provider>(
317 hopr_token: HoprTokenInstance<P>,
318 addresses: Vec<Address>,
319) -> Result<(Vec<U256>, Vec<U256>), MulticallError> {
320 let provider = hopr_token.provider();
321 let multicall3_instance = IMulticall3ExtractInstance::new(MULTICALL3_ADDRESS, provider);
322
323 if addresses.is_empty() {
326 Ok((vec![], vec![]))
327 } else if addresses.len() == 1 {
328 let address = addresses[0];
329 let multicall = provider
330 .multicall()
331 .get_eth_balance(address)
332 .add(hopr_token.balanceOf(address));
333
334 let (native_balance, token_balance) = multicall.aggregate().await?;
335 Ok((vec![native_balance], vec![token_balance]))
336 } else {
337 let mut native_balances_multicall = MulticallBuilder::new_dynamic(provider);
338 let mut token_balances_multicall = MulticallBuilder::new_dynamic(provider);
339
340 for address in addresses {
341 native_balances_multicall =
342 native_balances_multicall.add_dynamic(multicall3_instance.getEthBalance(address));
343 token_balances_multicall = token_balances_multicall.add_dynamic(hopr_token.balanceOf(address));
344 }
346
347 let native_balances_return = native_balances_multicall.aggregate().await?;
348 let token_balances_return = token_balances_multicall.aggregate().await?;
349
350 Ok((native_balances_return, token_balances_return))
351 }
352}
353
354pub async fn transfer_or_mint_tokens<P: Provider + WalletProvider>(
369 hopr_token: HoprTokenInstance<Arc<P>>,
370 addresses: Vec<Address>,
371 amounts: Vec<U256>,
372) -> Result<U256, HelperErrors> {
373 let provider = hopr_token.provider();
374 let caller = hopr_token.provider().default_signer_address();
375
376 assert_eq!(
378 addresses.len(),
379 amounts.len(),
380 "addresses and amounts are of different lengths in transfer_or_mint_tokens"
381 );
382
383 if addresses.is_empty() {
385 return Ok(U256::ZERO);
386 }
387
388 let total = amounts.iter().fold(U256::ZERO, |acc, cur| acc.add(cur));
390 info!("total amount of HOPR tokens to be transferred {:?}", total.to_string());
391
392 let encoded_minter_role = keccak256(b"MINTER_ROLE");
394 let multicall = provider
395 .multicall()
396 .add(
397 hopr_token.balanceOf(caller), )
401 .add(
402 hopr_token.hasRole(encoded_minter_role, caller), );
409 let (token_balance_return, has_role_return) = multicall.aggregate().await?;
410
411 if total.gt(&token_balance_return) {
414 info!("caller does not have enough balance to transfer tokens to recipients.");
415 if has_role_return {
416 info!("caller tries to mint tokens");
417 hopr_token
418 .mint(caller, total, Bytes::default(), Bytes::default())
419 .send()
420 .await?
421 .watch()
423 .await?;
424 } else {
426 return Err(HelperErrors::NotAMinter);
427 }
428 }
429
430 if addresses.len() == 1 {
432 info!("doing direct transfer...");
433
434 hopr_token
436 .transfer(addresses[0], amounts[0])
437 .send()
438 .await?
439 .watch()
441 .await?;
442 } else {
444 info!("using multicall...");
445 hopr_token
449 .approve(MULTICALL3_ADDRESS, total)
450 .send()
451 .await?
452 .watch()
454 .await?;
455
456 let calls: Vec<Call3> = addresses
457 .clone()
458 .into_iter()
459 .enumerate()
460 .map(|(i, addr)| {
461 let calldata = hopr_token.transferFrom(caller, addr, amounts[i]);
462 let call = Call3 {
463 target: *hopr_token.address(),
464 allowFailure: false,
465 callData: calldata.calldata().clone(),
466 };
467 call
468 })
469 .collect::<Vec<_>>();
470 let aggregate3_payload = aggregate3Call { calls }.abi_encode();
471 let tx = TransactionRequest::default()
472 .with_to(MULTICALL3_ADDRESS)
473 .with_input(aggregate3_payload);
474 provider
475 .send_transaction(tx)
476 .await
477 .map_err(|e| HelperErrors::RpcError(e.into()))?
478 .watch()
479 .await?;
480 }
481
482 Ok(total)
483}
484
485pub async fn transfer_native_tokens<P: Provider + WalletProvider>(
488 provider: Arc<P>,
489 addresses: Vec<Address>,
490 amounts: Vec<U256>,
491) -> Result<U256, HelperErrors> {
492 assert_eq!(
494 addresses.len(),
495 amounts.len(),
496 "addresses and amounts are of different lengths in transfer_native_tokens"
497 );
498 let total = amounts.iter().fold(U256::ZERO, |acc, cur| acc.add(cur));
500 info!(
501 "total amount of native tokens to be transferred {:?}",
502 total.to_string()
503 );
504
505 let calls: Vec<Call3Value> = addresses
506 .clone()
507 .into_iter()
508 .enumerate()
509 .map(|(i, addr)| Call3Value {
510 target: addr,
511 allowFailure: false,
512 value: amounts[i],
513 callData: Bytes::default(),
514 })
515 .collect::<Vec<_>>();
516 let aggregate3_value_payload = aggregate3ValueCall { calls }.abi_encode();
517 let tx = TransactionRequest::default()
518 .with_to(MULTICALL3_ADDRESS)
519 .with_input(aggregate3_value_payload)
520 .with_value(total);
521 provider
522 .send_transaction(tx)
523 .await
524 .map_err(|e| HelperErrors::RpcError(e.into()))?
525 .watch()
526 .await?;
527 Ok(total)
528}
529
530pub async fn get_registered_safes_for_nodes_on_network_registry<P: Provider + WalletProvider>(
532 network_registry: HoprNetworkRegistryInstance<Arc<P>>,
533 node_addresses: Vec<Address>,
534) -> Result<Vec<Address>, MulticallError> {
535 let provider = network_registry.provider();
536
537 let mut dynamic_multicall = MulticallBuilder::new_dynamic(provider.clone());
538
539 for node in node_addresses {
540 dynamic_multicall = dynamic_multicall.add_dynamic(network_registry.nodeRegisterdToAccount(node));
541 }
542
543 let response = dynamic_multicall.aggregate().await?;
544
545 Ok(response)
546}
547
548pub async fn register_safes_and_nodes_on_network_registry<P: Provider + WalletProvider + Clone>(
558 network_registry: HoprNetworkRegistryInstance<Arc<P>>,
559 safe_addresses: Vec<Address>,
560 node_addresses: Vec<Address>,
561) -> Result<(usize, usize), HelperErrors> {
562 assert_eq!(
563 safe_addresses.len(),
564 node_addresses.len(),
565 "unmatched lengths of safes and nodes"
566 );
567
568 let registered_safes =
570 get_registered_safes_for_nodes_on_network_registry(network_registry.clone(), node_addresses.clone()).await?;
571
572 let mut nodes_to_remove: Vec<Address> = Vec::new();
573 let mut safes_to_add: Vec<Address> = Vec::new();
574 let mut nodes_to_add: Vec<Address> = Vec::new();
575
576 for (i, registered_safe) in registered_safes.iter().enumerate() {
577 if registered_safe.eq(&Address::ZERO) {
578 safes_to_add.push(safe_addresses[i]);
580 nodes_to_add.push(node_addresses[i]);
581 } else if registered_safe.ne(&safe_addresses[i]) {
582 nodes_to_remove.push(node_addresses[i]);
584 safes_to_add.push(safe_addresses[i]);
585 nodes_to_add.push(node_addresses[i]);
586 } else {
587 }
589 }
590
591 if !nodes_to_remove.is_empty() {
592 network_registry
594 .managerDeregister(nodes_to_remove.clone())
595 .send()
596 .await?
597 .watch()
598 .await?;
599 }
600
601 network_registry
602 .managerRegister(safes_to_add.clone(), nodes_to_add.clone())
603 .send()
604 .await?
605 .watch()
606 .await?;
607
608 network_registry
610 .managerForceSync(safes_to_add.clone(), vec![true; safes_to_add.len()])
611 .send()
612 .await?
613 .watch()
614 .await?;
615
616 Ok((nodes_to_remove.len(), nodes_to_add.len()))
617}
618
619pub async fn deregister_nodes_from_network_registry<P: Provider + WalletProvider + Clone>(
624 network_registry: HoprNetworkRegistryInstance<Arc<P>>,
625 node_addresses: Vec<Address>,
626) -> Result<usize, HelperErrors> {
627 let registered_safes =
629 get_registered_safes_for_nodes_on_network_registry(network_registry.clone(), node_addresses.clone()).await?;
630
631 let mut nodes_to_remove: Vec<Address> = Vec::new();
632
633 for (i, registered_safe) in registered_safes.iter().enumerate() {
634 if registered_safe.ne(&Address::ZERO) {
635 nodes_to_remove.push(node_addresses[i]);
637 }
638 }
639
640 if !nodes_to_remove.is_empty() {
641 network_registry
643 .managerDeregister(nodes_to_remove.clone())
644 .send()
645 .await?
646 .watch()
647 .await?;
648 }
649 Ok(nodes_to_remove.len())
650}
651
652pub async fn force_sync_safes_on_network_registry<P: Provider>(
654 network_registry: HoprNetworkRegistryInstance<Arc<P>>,
655 safe_addresses: Vec<Address>,
656 eligibilities: Vec<bool>,
657) -> Result<(), HelperErrors> {
658 assert_eq!(
659 safe_addresses.len(),
660 eligibilities.len(),
661 "unmatched lengths of safes and eligibilities"
662 );
663
664 network_registry
666 .managerForceSync(safe_addresses, eligibilities)
667 .send()
668 .await?
669 .watch()
670 .await?;
671
672 Ok(())
673}
674
675pub async fn toggle_network_registry_status<P: Provider>(
676 network_registry: HoprNetworkRegistryInstance<Arc<P>>,
677 status: bool,
678) -> Result<(), HelperErrors> {
679 let current_status = network_registry
680 .enabled()
681 .call()
682 .await
683 .map_err(|e| HelperErrors::RpcError(e.into()))?;
684
685 info!(
686 current_status = ?current_status,
687 desired_status = ?status,
688 "Toggling network registry status",
689 );
690
691 if current_status == status {
692 info!("Network registry is already in the desired state: {:?}", status);
693 return Ok(());
694 }
695
696 if status {
697 info!("Enabling the network registry");
698 network_registry
700 .enableRegistry()
701 .send()
702 .await?
703 .watch()
704 .await
705 .map_err(|e| HelperErrors::RpcError(e.into()))?;
706 } else {
707 info!("Disabling the network registry");
708 network_registry
710 .disableRegistry()
711 .send()
712 .await?
713 .watch()
714 .await
715 .map_err(|e| HelperErrors::RpcError(e.into()))?;
716 }
717 Ok(())
718}
719
720pub fn predict_module_address(
722 caller: Address,
723 nonce: B256,
724 factory_address: Address,
725 implementation_address: Address,
726) -> Result<Address, HelperErrors> {
727 let module_salt = keccak256((caller, nonce).abi_encode_packed());
728 debug!("module_salt {:?}", module_salt);
729
730 let module_creation_code = (
731 Bytes::copy_from_slice(&hex!("3d602d80600a3d3981f3363d3d373d3d3d363d73")),
732 implementation_address,
733 Bytes::copy_from_slice(&hex!("5af43d82803e903d91602b57fd5bf3")),
734 )
735 .abi_encode_packed();
736 debug!("module_creation_code {:?}", module_creation_code);
737
738 let predict_module_addr = get_create2_address(factory_address, module_salt, module_creation_code);
739 debug!("predict_module_addr {:?}", predict_module_addr);
740
741 Ok(predict_module_addr)
742}
743
744pub fn predict_safe_address(
746 stake_factory: Address,
747 admins: Vec<Address>,
748 nonce: B256,
749 safe_fallback: Address,
750 safe_singleton: Address,
751 safe_factory: Address,
752) -> Result<Address, HelperErrors> {
753 let mut temp_admins = admins.clone();
754 temp_admins[0] = stake_factory;
755
756 let initializer = setupCall {
757 _0: temp_admins,
758 _1: U256::ONE,
759 _2: Address::ZERO,
760 _3: Bytes::from(hex!("00")),
761 _4: safe_fallback,
762 _5: Address::ZERO,
763 _6: U256::ZERO,
764 _7: Address::ZERO,
765 }
766 .abi_encode();
767
768 let safe_salt = get_salt_from_salt_nonce(initializer, nonce)?;
769 debug!("safe_salt {:?}", hex::encode(safe_salt));
770
771 let predict_safe_addr = deploy_proxy(safe_singleton, safe_salt, safe_factory)?;
772 debug!("predict_safe_addr {:?}", hex::encode(predict_safe_addr));
773
774 Ok(predict_safe_addr)
775}
776
777fn get_salt_from_salt_nonce(initializer: Vec<u8>, salt_nonce: B256) -> Result<[u8; 32], HelperErrors> {
779 let hashed_initializer = keccak256(initializer);
780 let encoded = (hashed_initializer, salt_nonce).abi_encode_packed();
781
782 Ok(keccak256(encoded).into())
783}
784
785fn deploy_proxy(safe_singleton: Address, safe_salt: [u8; 32], safe_factory: Address) -> Result<Address, HelperErrors> {
787 let safe_creation_code = (
788 Bytes::from_static(&hex!("608060405234801561001057600080fd5b506040516101e63803806101e68339818101604052602081101561003357600080fd5b8101908080519060200190929190505050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156100ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806101c46022913960400191505060405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505060ab806101196000396000f3fe608060405273ffffffffffffffffffffffffffffffffffffffff600054167fa619486e0000000000000000000000000000000000000000000000000000000060003514156050578060005260206000f35b3660008037600080366000845af43d6000803e60008114156070573d6000fd5b3d6000f3fea264697066735822122003d1488ee65e08fa41e58e888a9865554c535f2c77126a82cb4c0f917f31441364736f6c63430007060033496e76616c69642073696e676c65746f6e20616464726573732070726f7669646564")),
789 Bytes::from_static(&hex!("000000000000000000000000")), safe_singleton,
791 ).abi_encode_packed();
792 debug!("safe_creation_code {:?}", hex::encode(safe_creation_code.clone()));
793
794 let predict_safe_addr = get_create2_address(safe_factory, safe_salt, safe_creation_code);
795 debug!("predict_safe_addr {:?}", hex::encode(predict_safe_addr));
796
797 Ok(predict_safe_addr.0.into())
798}
799
800pub fn prepare_safe_tx_multicall_payload_from_owner_contract(
801 deployed_safe: Address,
802 target: Address,
803 refund_address: Address,
804 tx_payload: Vec<u8>,
805) -> CallItem<execTransactionCall> {
806 let approval_hash_sig = (
807 Bytes::from_static(&hex!("000000000000000000000000")),
808 MULTICALL3_ADDRESS,
809 Bytes::from_static(&hex!(
810 "0000000000000000000000000000000000000000000000000000000000000000"
811 )),
812 Bytes::from_static(&hex!("01")),
813 )
814 .abi_encode_packed();
815
816 let input = execTransactionCall {
817 to: target,
818 value: U256::ZERO,
819 data: Bytes::from(tx_payload),
820 operation: 0u8,
821 safeTxGas: U256::ZERO,
822 baseGas: U256::ZERO,
823 gasPrice: U256::ZERO,
824 gasToken: Address::ZERO,
825 refundReceiver: refund_address,
826 signatures: Bytes::from(approval_hash_sig),
827 }
828 .abi_encode();
829
830 CallItem::<execTransactionCall>::new(deployed_safe, input.into())
831}
832
833#[allow(clippy::too_many_arguments)]
845pub async fn deploy_safe_module_with_targets_and_nodes<P: WalletProvider + Provider>(
846 hopr_node_stake_factory: HoprNodeStakeFactoryInstance<Arc<P>>,
847 hopr_token_address: Address,
848 hopr_channels_address: Address,
849 hopr_module_implementation_address: Address,
850 hopr_announcement_address: Address,
851 allowance: U256,
852 node_addresses: Option<Vec<Address>>,
853 admins: Vec<Address>,
854 threshold: U256,
855) -> Result<(SafeSingletonInstance<Arc<P>>, HoprNodeManagementModuleInstance<Arc<P>>), HelperErrors> {
856 let caller = hopr_node_stake_factory.provider().default_signer_address();
857 let provider = hopr_node_stake_factory.provider();
858
859 assert!(!admins.is_empty(), "safe must have valid admin(s)");
861 assert!(
862 threshold.ge(&U256::ONE) && threshold.le(&U256::from(admins.len())),
863 "safe threshold must be at least one and not greater than the total number of admins"
864 );
865 assert!(
866 !admins.contains(&MULTICALL3_ADDRESS),
867 "multicall contract cannot be an admin"
868 );
869
870 let mut temporary_admins: Vec<Address> = admins.clone();
872 temporary_admins.insert(0, MULTICALL3_ADDRESS);
873 info!(
874 "temporary_admins expends from admin from {:?} addresses to {:?}",
875 admins.len(),
876 temporary_admins.len()
877 );
878
879 let default_target =
881 U256::from_str(format!("{:?}{}", hopr_channels_address, DEFAULT_CAPABILITY_PERMISSIONS).as_str())
883 .unwrap();
884 debug!("default target {:?}", default_target);
885 let curr_nonce = provider
887 .get_transaction_count(caller)
888 .pending()
889 .await
890 .map_err(|e| HelperErrors::MiddlewareError(e.to_string()))?;
891 let nonce = keccak256((caller, U256::from(curr_nonce)).abi_encode_packed());
892
893 debug!("curr_nonce {} and nonce {:?}", curr_nonce, nonce);
894
895 let module_address = predict_module_address(
897 MULTICALL3_ADDRESS,
898 nonce,
899 *hopr_node_stake_factory.address(),
900 hopr_module_implementation_address,
901 )?;
902 info!("predicted module address {:?}", module_address.to_string());
903
904 let safe_address = predict_safe_address(
905 *hopr_node_stake_factory.address(),
906 temporary_admins.clone(),
907 nonce,
908 Address::from_str(SAFE_COMPATIBILITYFALLBACKHANDLER_ADDRESS).unwrap(),
909 Address::from_str(SAFE_SAFE_ADDRESS).unwrap(),
910 Address::from_str(SAFE_SAFEPROXYFACTORY_ADDRESS).unwrap(),
911 )?;
912 info!("predicted safe address {:?}", safe_address.to_string());
913
914 let deployed_module = HoprNodeManagementModuleInstance::new(module_address, provider.clone());
915 let deployed_safe = SafeSingleton::new(safe_address, provider.clone());
916
917 let mut multicall_payloads: Vec<Call3> = vec![];
919 let safe_address = *deployed_safe.address();
920 multicall_payloads.push(Call3 {
921 target: *hopr_node_stake_factory.address(),
922 allowFailure: false,
923 callData: cloneCall {
924 moduleSingletonAddress: hopr_module_implementation_address,
925 admins: temporary_admins,
926 nonce: nonce.into(),
927 defaultTarget: default_target.into(),
928 }
929 .abi_encode()
930 .into(),
931 });
932 info!("Safe and module deployment multicall payload is created");
933
934 let announcement_target =
936 U256::from_str(format!("{:?}{}", hopr_announcement_address, DEFAULT_ANNOUNCEMENT_PERMISSIONS).as_str())
937 .unwrap();
938 let scope_announcement_tx_payload = scopeTargetTokenCall {
939 defaultTarget: announcement_target,
940 }
941 .abi_encode();
942
943 let multicall_payload_2 = prepare_safe_tx_multicall_payload_from_owner_contract(
944 safe_address,
946 module_address,
947 caller,
948 scope_announcement_tx_payload,
949 );
950 multicall_payloads.push(multicall_payload_2.to_call3());
952 info!("Announcement contract scoping multicall payload is created");
953
954 let approve_tx_payload = approveCall {
956 spender: hopr_channels_address,
957 value: allowance,
958 }
959 .abi_encode();
960
961 let multicall_payload_3 = prepare_safe_tx_multicall_payload_from_owner_contract(
962 safe_address,
963 hopr_token_address,
964 caller,
965 approve_tx_payload,
966 );
967 multicall_payloads.push(multicall_payload_3.to_call3());
969
970 info!("Token transfer approval multicall payload is created");
971
972 if let Some(nodes) = node_addresses {
974 for node in nodes {
975 let node_target =
976 U256::from_str(&format!("{node:?}{DEFAULT_NODE_PERMISSIONS}")).expect("Invalid node_target format");
977
978 let encoded_call = includeNodeCall {
979 nodeDefaultTarget: node_target,
980 }
981 .abi_encode();
982
983 let payload = prepare_safe_tx_multicall_payload_from_owner_contract(
984 safe_address,
985 module_address,
986 caller,
987 encoded_call,
988 );
989
990 multicall_payloads.push(payload.to_call3());
991 }
992
993 info!("Nodes inclusion multicall payload is created");
994 } else {
995 info!("No node has been provided. Skip node inclusion action for multicall payload generation");
996 }
997
998 let remove_owner_tx_payload = removeOwnerCall {
1000 prevOwner: Address::from_str(SENTINEL_OWNERS).unwrap(),
1001 owner: MULTICALL3_ADDRESS,
1002 _threshold: threshold,
1003 }
1004 .abi_encode();
1005
1006 let multicall_payload_5 = prepare_safe_tx_multicall_payload_from_owner_contract(
1007 safe_address,
1008 safe_address,
1009 caller,
1010 remove_owner_tx_payload,
1011 );
1012 multicall_payloads.push(multicall_payload_5.to_call3());
1015 info!("Admins and threshold setting multicall payload is created");
1016
1017 let aggregate3_payload = aggregate3Call {
1019 calls: multicall_payloads,
1020 }
1021 .abi_encode();
1022 let tx = TransactionRequest::default()
1023 .with_to(MULTICALL3_ADDRESS)
1024 .with_input(aggregate3_payload);
1025 let tx_receipt = provider
1026 .send_transaction(tx)
1027 .await
1028 .map_err(|e| HelperErrors::RpcError(e.into()))?
1029 .get_receipt()
1030 .await?;
1031 info!("multicall is sent {:?}", tx_receipt.transaction_hash.to_string());
1032
1033 let safe_address_from_log = tx_receipt
1034 .decoded_log::<hopr_bindings::hoprnodestakefactory::HoprNodeStakeFactory::NewHoprNodeStakeSafe>()
1035 .ok_or_else(|| HelperErrors::ContractNotDeployed("cannot find safe from log".into()))?
1036 .instance;
1037 let module_address_from_log = tx_receipt
1038 .decoded_log::<hopr_bindings::hoprnodestakefactory::HoprNodeStakeFactory::NewHoprNodeStakeModule>()
1039 .ok_or_else(|| HelperErrors::ContractNotDeployed("cannot find module from log".into()))?
1040 .instance;
1041
1042 assert_eq!(
1043 safe_address,
1044 safe_address_from_log,
1045 "safe address mismatch: predicted {:?} actual {:?}",
1046 safe_address.to_string(),
1047 safe_address_from_log.to_string(),
1048 );
1049 assert_eq!(
1050 module_address,
1051 module_address_from_log,
1052 "module address mismatch: predicted {:?} actual {:?}",
1053 module_address.to_string(),
1054 module_address_from_log.to_string(),
1055 );
1056 Ok((deployed_safe, deployed_module))
1057}
1058
1059pub async fn get_registered_safes_for_nodes_on_node_safe_registry<P: Provider>(
1061 node_safe_registry: HoprNodeSafeRegistryInstance<P>,
1062 node_addresses: Vec<Address>,
1063) -> Result<Vec<Address>, MulticallError> {
1064 let provider = node_safe_registry.provider();
1065 let mut dyn_multicall = MulticallBuilder::new_dynamic(provider);
1066
1067 for node in node_addresses {
1068 dyn_multicall = dyn_multicall.add_dynamic(node_safe_registry.nodeToSafe(node));
1069 }
1070
1071 let native_balances_return = dyn_multicall.aggregate().await?;
1072
1073 Ok(native_balances_return)
1074}
1075
1076pub async fn deregister_nodes_from_node_safe_registry_and_remove_from_module<P: WalletProvider + Provider>(
1083 node_safe_registry: HoprNodeSafeRegistryInstance<Arc<P>>,
1084 node_addresses: Vec<Address>,
1085 module_addresses: Vec<Address>,
1086 owner_chain_key: ChainKeypair,
1087) -> Result<u32, HelperErrors> {
1088 let provider = node_safe_registry.provider();
1089 let registered_safes =
1091 get_registered_safes_for_nodes_on_node_safe_registry(node_safe_registry.clone(), node_addresses.clone())
1092 .await
1093 .unwrap();
1094
1095 let mut nodes_to_remove_counter = 0u32;
1096
1097 for (i, registered_safe) in registered_safes.iter().enumerate() {
1098 if registered_safe.ne(&Address::ZERO) {
1099 let safe = SafeSingleton::new(registered_safe.to_owned(), provider.clone());
1101 nodes_to_remove_counter += 1;
1103 let (chain_id, safe_nonce) = get_chain_id_and_safe_nonce(safe.clone()).await?;
1105
1106 let multisend_txns: Vec<MultisendTransaction> = vec![
1108 MultisendTransaction {
1109 encoded_data: deregisterNodeBySafeCall {
1111 nodeAddr: node_addresses[i],
1112 }
1113 .abi_encode()
1114 .into(),
1115 tx_operation: SafeTxOperation::Call,
1116 to: *node_safe_registry.address(),
1117 value: U256::ZERO,
1118 },
1119 MultisendTransaction {
1120 encoded_data: removeNodeCall {
1122 nodeAddress: node_addresses[i],
1123 }
1124 .abi_encode()
1125 .into(),
1126 tx_operation: SafeTxOperation::Call,
1127 to: module_addresses[i],
1128 value: U256::ZERO,
1129 },
1130 ];
1131
1132 send_multisend_safe_transaction_with_threshold_one(
1134 safe,
1135 owner_chain_key.clone(),
1136 Address::from_str(SAFE_MULTISEND_ADDRESS).unwrap(),
1137 multisend_txns,
1138 chain_id,
1139 safe_nonce,
1140 )
1141 .await?;
1142 }
1143 }
1144
1145 Ok(nodes_to_remove_counter)
1146}
1147
1148pub async fn include_nodes_to_module<P: WalletProvider + Provider>(
1150 safe: SafeSingletonInstance<Arc<P>>,
1151 node_addresses: Vec<Address>,
1152 module_address: Address,
1153 owner_chain_key: ChainKeypair,
1154) -> Result<(), HelperErrors> {
1155 let (chain_id, safe_nonce) = get_chain_id_and_safe_nonce(safe.clone()).await?;
1157
1158 let mut multisend_txns: Vec<MultisendTransaction> = Vec::new();
1160 for node_address in node_addresses {
1161 let node_target = U256::from_str(format!("{:?}{}", node_address, DEFAULT_NODE_PERMISSIONS).as_str()).unwrap();
1162 multisend_txns.push(MultisendTransaction {
1163 encoded_data: includeNodeCall {
1164 nodeDefaultTarget: node_target,
1165 }
1166 .abi_encode()
1167 .into(),
1168 tx_operation: SafeTxOperation::Call,
1169 to: module_address,
1170 value: U256::ZERO,
1171 });
1172 }
1173
1174 send_multisend_safe_transaction_with_threshold_one(
1176 safe,
1177 owner_chain_key.clone(),
1178 Address::from_str(SAFE_MULTISEND_ADDRESS).unwrap(),
1179 multisend_txns,
1180 chain_id,
1181 safe_nonce,
1182 )
1183 .await?;
1184
1185 Ok(())
1186}
1187
1188pub async fn migrate_nodes<P: WalletProvider + Provider>(
1193 safe: SafeSingletonInstance<Arc<P>>,
1194 module_addresses: Address,
1195 channels_address: Address,
1196 token_address: Address,
1197 announcement_address: Address,
1198 allowance: U256,
1199 owner_chain_key: ChainKeypair,
1200) -> Result<(), HelperErrors> {
1201 let (chain_id, safe_nonce) = get_chain_id_and_safe_nonce(safe.clone()).await?;
1202
1203 let mut multisend_txns: Vec<MultisendTransaction> = Vec::new();
1204
1205 let default_target =
1207 U256::from_str(format!("{:?}{}", channels_address, DEFAULT_CAPABILITY_PERMISSIONS).as_str()).unwrap();
1208 debug!("default target {:?}", default_target);
1209
1210 multisend_txns.push(MultisendTransaction {
1211 encoded_data: addChannelsAndTokenTargetCall {
1213 defaultTarget: default_target,
1214 }
1215 .abi_encode()
1216 .into(),
1217 tx_operation: SafeTxOperation::Call,
1218 to: module_addresses,
1219 value: U256::ZERO,
1220 });
1221
1222 let announcement_target =
1224 U256::from_str(format!("{:?}{}", announcement_address, DEFAULT_ANNOUNCEMENT_PERMISSIONS).as_str()).unwrap();
1225
1226 multisend_txns.push(MultisendTransaction {
1227 encoded_data: scopeTargetTokenCall {
1229 defaultTarget: announcement_target,
1230 }
1231 .abi_encode()
1232 .into(),
1233 tx_operation: SafeTxOperation::Call,
1234 to: module_addresses,
1235 value: U256::ZERO,
1236 });
1237
1238 multisend_txns.push(MultisendTransaction {
1240 encoded_data: approveCall {
1242 spender: channels_address,
1243 value: allowance,
1244 }
1245 .abi_encode()
1246 .into(),
1247 tx_operation: SafeTxOperation::Call,
1248 to: token_address,
1249 value: U256::ZERO,
1250 });
1251
1252 send_multisend_safe_transaction_with_threshold_one(
1254 safe,
1255 owner_chain_key.clone(),
1256 Address::from_str(SAFE_MULTISEND_ADDRESS).unwrap(),
1257 multisend_txns,
1258 chain_id,
1259 safe_nonce,
1260 )
1261 .await?;
1262
1263 Ok(())
1264}
1265
1266pub async fn debug_node_safe_module_setup_on_balance_and_registries<P: Provider>(
1271 network_registry: HoprNetworkRegistryInstance<Arc<P>>,
1272 node_safe_registry: HoprNodeSafeRegistryInstance<Arc<P>>,
1273 node_address: &Address,
1274) -> Result<Address, MulticallError> {
1275 let provider = network_registry.provider();
1276 info!("checking for node {:?}", node_address);
1281 let multicall = provider
1282 .multicall()
1283 .get_eth_balance(*node_address)
1285 .add(network_registry.nodeRegisterdToAccount(*node_address))
1287 .add(node_safe_registry.nodeToSafe(*node_address));
1289
1290 let (node_native_balance, safe_in_network_registry, safe_in_nodesafe_registry) = multicall.aggregate().await?;
1291
1292 info!(
1293 "node does{:?} have xDAI balance {:?}",
1294 if node_native_balance.ge(
1295 &U256::from_str("100000000000000000").unwrap() ) {
1297 ""
1298 } else {
1299 " NOT"
1300 },
1301 format_units(node_native_balance, "ether").unwrap_or("Unknown balance".into())
1302 );
1303
1304 if safe_in_network_registry.eq(&Address::ZERO) {
1305 info!("Please register the node to the network registry");
1306 } else {
1307 info!("safe in network registry {:?}", safe_in_network_registry);
1308 }
1309
1310 if safe_in_nodesafe_registry.eq(&Address::ZERO) {
1311 info!("Please start the node. It will auto-register to node-safe registry");
1312 } else {
1313 info!("safe in node-safe registry {:?}", safe_in_nodesafe_registry);
1314 }
1315 info!(
1316 "Safes in both registies should match: {:?}",
1317 safe_in_network_registry.eq(&safe_in_nodesafe_registry)
1318 );
1319
1320 Ok(safe_in_network_registry)
1321}
1322
1323pub async fn debug_node_safe_module_setup_main<P: Provider>(
1331 hopr_token: HoprTokenInstance<Arc<P>>,
1332 module_address: &Address,
1333 node_address: &Address,
1334 safe_address: &Address,
1335 channel_address: &Address,
1336 announce_address: &Address,
1337) -> Result<(), MulticallError> {
1338 let provider = hopr_token.provider();
1339
1340 let safe = SafeSingleton::new(safe_address.to_owned(), provider.clone());
1341 let module = ModuleSingleton::new(module_address.to_owned(), provider.clone());
1342
1343 info!("checking for safe {:?} module {:?}", safe_address, module_address);
1344 let multicall = provider
1345 .multicall()
1346 .add(safe.getOwners())
1348 .add(hopr_token.balanceOf(*safe_address))
1350 .add(hopr_token.allowance(*safe_address, *channel_address))
1352 .add(safe.isModuleEnabled(*module_address))
1354 .add(module.isNode(*node_address))
1356 .add(module.getTargets())
1358 .add(module.owner());
1360
1361 let (
1362 safe_owners,
1363 safe_wxhopr_balance,
1364 safe_wxhopr_allownace,
1365 is_module_enabled,
1366 is_node_included,
1367 module_targets,
1368 module_owner,
1369 ) = multicall.aggregate().await?;
1370
1371 info!("safe has owners: {:?}", safe_owners);
1372 info!(
1373 "safe has wxHOPR balance: {:?}",
1374 format_units(safe_wxhopr_balance, "ether").unwrap_or("Unknown balance".into())
1375 );
1376 info!(
1377 "safe has wxHOPR allowance: {:?}",
1378 format_units(safe_wxhopr_allownace, "ether").unwrap_or("Unknown balance".into())
1379 );
1380 info!("module is enabled: {:?}", is_module_enabled);
1381 info!("node is included in the module: {:?}", is_node_included);
1382 info!("module has targets:");
1383 for target in module_targets {
1384 let target_address = format!("{:#x}", target);
1385 let has_channels = target_address.contains(&format!("{:#x}", channel_address));
1386 let has_announcement = target_address.contains(&format!("{:#x}", announce_address));
1387 info!(
1389 "Target {:?} has channels {:?} has announcement {:?}",
1390 target_address, has_channels, has_announcement
1391 );
1392 }
1393
1394 info!(
1395 "module owner: {:?} same as safe address: {:?}",
1396 module_owner,
1397 module_owner.eq(safe_address)
1398 );
1399 Ok(())
1400}
1401
1402#[cfg(test)]
1403mod tests {
1404 use std::vec;
1405
1406 use alloy::{
1407 contract::Result as ContractResult, network::TransactionBuilder, primitives::address,
1408 rpc::types::TransactionRequest, sol_types::SolValue,
1409 };
1410 use hopr_bindings::{
1411 hoprannouncements::HoprAnnouncements, hoprchannels::HoprChannels, hoprnetworkregistry::HoprNetworkRegistry,
1412 hoprnodesaferegistry::HoprNodeSafeRegistry, hoprnodestakefactory::HoprNodeStakeFactory, hoprtoken::HoprToken,
1413 };
1414 use hopr_chain_rpc::client::create_rpc_client_to_anvil;
1415 use hopr_chain_types::ContractInstances;
1416 use hopr_crypto_types::keypairs::{ChainKeypair, Keypair};
1417 use hopr_primitive_types::prelude::BytesRepresentable;
1418
1419 use super::*;
1420
1421 fn get_random_address_for_testing() -> Address {
1422 Address::new(hopr_crypto_random::random_bytes::<
1424 { hopr_primitive_types::primitives::Address::SIZE },
1425 >())
1426 }
1427
1428 async fn deploy_safe_suites<P: Provider>(provider: Arc<P>) -> ContractResult<()> {
1429 let code = provider
1431 .get_code_at(address!("0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7"))
1432 .await?;
1433 if code.is_empty() {
1437 debug!("deploying safe code");
1438 let safe_diamond_proxy_address = {
1440 let tx = TransactionRequest::default()
1442 .with_to(address!("E1CB04A0fA36DdD16a06ea828007E35e1a3cBC37"))
1443 .with_value(U256::from(10000000000000000u128));
1444
1445 provider.send_transaction(tx).await?.watch().await?;
1446
1447 let tx = provider.send_raw_transaction(
1448 &hex!("f8a78085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf382f4f5a00dc4d1d21b308094a30f5f93da35e4d72e99115378f135f2295bea47301a3165a0636b822daad40aa8c52dd5132f378c0c0e6d83b4898228c7e21c84e631a0b891")
1449 ).await?.get_receipt()
1450 .await?;
1451 tx.contract_address.unwrap()
1453 };
1454 debug!("Safe diamond proxy singleton {:?}", safe_diamond_proxy_address);
1455
1456 let _tx_safe_proxy_factory = TransactionRequest::default().with_to(safe_diamond_proxy_address).with_input(
1459 hex!("0000000000000000000000000000000000000000000000000000000000000000608060405234801561001057600080fd5b50610bee806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80631688f0b91461005c5780633408e4701461016b57806353e5d93514610189578063d18af54d1461020c578063ec9e80bb1461033b575b600080fd5b61013f6004803603606081101561007257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001906401000000008111156100af57600080fd5b8201836020820111156100c157600080fd5b803590602001918460018302840111640100000000831117156100e357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019092919050505061044a565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101736104fe565b6040518082815260200191505060405180910390f35b61019161050b565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101d15780820151818401526020810190506101b6565b50505050905090810190601f1680156101fe5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61030f6004803603608081101561022257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561025f57600080fd5b82018360208201111561027157600080fd5b8035906020019184600183028401116401000000008311171561029357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610536565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61041e6004803603606081101561035157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561038e57600080fd5b8201836020820111156103a057600080fd5b803590602001918460018302840111640100000000831117156103c257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803590602001909291905050506106e5565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008083805190602001208360405160200180838152602001828152602001925050506040516020818303038152906040528051906020012090506104908585836107a8565b91508173ffffffffffffffffffffffffffffffffffffffff167f4f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e23586604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a2509392505050565b6000804690508091505090565b60606040518060200161051d906109c5565b6020820181038252601f19601f82011660405250905090565b6000808383604051602001808381526020018273ffffffffffffffffffffffffffffffffffffffff1660601b8152601401925050506040516020818303038152906040528051906020012060001c905061059186868361044a565b9150600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146106dc578273ffffffffffffffffffffffffffffffffffffffff16631e52b518838888886040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015610674578082015181840152602081019050610659565b50505050905090810190601f1680156106a15780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b1580156106c357600080fd5b505af11580156106d7573d6000803e3d6000fd5b505050505b50949350505050565b6000808380519060200120836106f96104fe565b60405160200180848152602001838152602001828152602001935050505060405160208183030381529060405280519060200120905061073a8585836107a8565b91508173ffffffffffffffffffffffffffffffffffffffff167f4f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e23586604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a2509392505050565b60006107b3846109b2565b610825576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f53696e676c65746f6e20636f6e7472616374206e6f74206465706c6f7965640081525060200191505060405180910390fd5b600060405180602001610837906109c5565b6020820181038252601f19601f820116604052508573ffffffffffffffffffffffffffffffffffffffff166040516020018083805190602001908083835b602083106108985780518252602082019150602081019050602083039250610875565b6001836020036101000a038019825116818451168082178552505050505050905001828152602001925050506040516020818303038152906040529050828151826020016000f59150600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610984576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f437265617465322063616c6c206661696c65640000000000000000000000000081525060200191505060405180910390fd5b6000845111156109aa5760008060008651602088016000875af114156109a957600080fd5b5b509392505050565b600080823b905060008111915050919050565b6101e6806109d38339019056fe608060405234801561001057600080fd5b506040516101e63803806101e68339818101604052602081101561003357600080fd5b8101908080519060200190929190505050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156100ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806101c46022913960400191505060405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505060ab806101196000396000f3fe608060405273ffffffffffffffffffffffffffffffffffffffff600054167fa619486e0000000000000000000000000000000000000000000000000000000060003514156050578060005260206000f35b3660008037600080366000845af43d6000803e60008114156070573d6000fd5b3d6000f3fea264697066735822122003d1488ee65e08fa41e58e888a9865554c535f2c77126a82cb4c0f917f31441364736f6c63430007060033496e76616c69642073696e676c65746f6e20616464726573732070726f7669646564a26469706673582212200fd975ca8e62d9bf08aa3d09c74b9bdc9d7acba7621835be4187989ddd0e54b164736f6c63430007060033")
1460 );
1461 let _tx_safe_compatibility_fallback_handler = TransactionRequest::default().with_to(safe_diamond_proxy_address).with_input(
1463 hex!("0000000000000000000000000000000000000000000000000000000000000000608060405234801561001057600080fd5b5061073f806100206000396000f3fe608060405234801561001057600080fd5b50600436106100565760003560e01c806223de291461005b57806301ffc9a714610193578063150b7a02146101f6578063bc197c81146102ec578063f23a6e6114610482575b600080fd5b610191600480360360c081101561007157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156100f857600080fd5b82018360208201111561010a57600080fd5b8035906020019184600183028401116401000000008311171561012c57600080fd5b90919293919293908035906020019064010000000081111561014d57600080fd5b82018360208201111561015f57600080fd5b8035906020019184600183028401116401000000008311171561018157600080fd5b9091929391929390505050610582565b005b6101de600480360360208110156101a957600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061058c565b60405180821515815260200191505060405180910390f35b6102b76004803603608081101561020c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561027357600080fd5b82018360208201111561028557600080fd5b803590602001918460018302840111640100000000831117156102a757600080fd5b90919293919293905050506106c6565b60405180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b61044d600480360360a081101561030257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561035f57600080fd5b82018360208201111561037157600080fd5b8035906020019184602083028401116401000000008311171561039357600080fd5b9091929391929390803590602001906401000000008111156103b457600080fd5b8201836020820111156103c657600080fd5b803590602001918460208302840111640100000000831117156103e857600080fd5b90919293919293908035906020019064010000000081111561040957600080fd5b82018360208201111561041b57600080fd5b8035906020019184600183028401116401000000008311171561043d57600080fd5b90919293919293905050506106db565b60405180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b61054d600480360360a081101561049857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291908035906020019064010000000081111561050957600080fd5b82018360208201111561051b57600080fd5b8035906020019184600183028401116401000000008311171561053d57600080fd5b90919293919293905050506106f3565b60405180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b5050505050505050565b60007f4e2312e0000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061065757507f150b7a02000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806106bf57507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b600063150b7a0260e01b905095945050505050565b600063bc197c8160e01b905098975050505050505050565b600063f23a6e6160e01b9050969550505050505056fea2646970667358221220f62cd059f3672bb04062df149e7ae71534a8512cca0172e695d98a43cff0c53564736f6c63430007060033")
1464 );
1465 let _tx_safe_multisend_call_only = TransactionRequest::default().with_to(safe_diamond_proxy_address).with_input(
1467 hex!("0000000000000000000000000000000000000000000000000000000000000000608060405234801561001057600080fd5b5061019a806100206000396000f3fe60806040526004361061001e5760003560e01c80638d80ff0a14610023575b600080fd5b6100dc6004803603602081101561003957600080fd5b810190808035906020019064010000000081111561005657600080fd5b82018360208201111561006857600080fd5b8035906020019184600183028401116401000000008311171561008a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506100de565b005b805160205b8181101561015f578083015160f81c6001820184015160601c60158301850151603584018601516055850187016000856000811461012857600181146101385761013d565b6000808585888a5af1915061013d565b600080fd5b50600081141561014c57600080fd5b82605501870196505050505050506100e3565b50505056fea26469706673582212208d297bb003abee230b5dfb38774688f37a6fbb97a82a21728e8049b2acb9b73564736f6c63430007060033")
1468 );
1469 let _tx_safe_singleton = TransactionRequest::default().with_to(safe_diamond_proxy_address).with_input(
1471 hex!("0000000000000000000000000000000000000000000000000000000000000000608060405234801561001057600080fd5b506001600481905550615c1b80620000296000396000f3fe6080604052600436106101d15760003560e01c8063affed0e0116100f7578063e19a9dd911610095578063f08a032311610064578063f08a03231461156b578063f698da25146115bc578063f8dc5dd9146115e7578063ffa1ad741461166257610226565b8063e19a9dd9146112bf578063e318b52b14611310578063e75235b8146113a1578063e86637db146113cc57610226565b8063cc2f8452116100d1578063cc2f84521461100c578063d4d9bdcd146110d9578063d8d11f7814611114578063e009cfde1461124e57610226565b8063affed0e014610d89578063b4faba0914610db4578063b63e800d14610e9c57610226565b80635624b25b1161016f5780636a7612021161013e5780636a761202146109895780637d83297414610b45578063934f3a1114610bb4578063a0e67e2b14610d1d57610226565b80635624b25b146107f05780635ae6bd37146108ae578063610b5925146108fd578063694e80c31461094e57610226565b80632f54bf6e116101ab5780632f54bf6e146104c85780633408e4701461052f578063468721a71461055a5780635229073f1461066f57610226565b80630d582f131461029357806312fb68e0146102ee5780632d9ad53d1461046157610226565b36610226573373ffffffffffffffffffffffffffffffffffffffff167f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d346040518082815260200191505060405180910390a2005b34801561023257600080fd5b5060007f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d560001b905080548061026757600080f35b36600080373360601b365260008060143601600080855af13d6000803e8061028e573d6000fd5b3d6000f35b34801561029f57600080fd5b506102ec600480360360408110156102b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506116f2565b005b3480156102fa57600080fd5b5061045f6004803603608081101561031157600080fd5b81019080803590602001909291908035906020019064010000000081111561033857600080fd5b82018360208201111561034a57600080fd5b8035906020019184600183028401116401000000008311171561036c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803590602001906401000000008111156103cf57600080fd5b8201836020820111156103e157600080fd5b8035906020019184600183028401116401000000008311171561040357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190929190505050611ad8565b005b34801561046d57600080fd5b506104b06004803603602081101561048457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506123d6565b60405180821515815260200191505060405180910390f35b3480156104d457600080fd5b50610517600480360360208110156104eb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506124a8565b60405180821515815260200191505060405180910390f35b34801561053b57600080fd5b5061054461257a565b6040518082815260200191505060405180910390f35b34801561056657600080fd5b506106576004803603608081101561057d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156105c457600080fd5b8201836020820111156105d657600080fd5b803590602001918460018302840111640100000000831117156105f857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff169060200190929190505050612587565b60405180821515815260200191505060405180910390f35b34801561067b57600080fd5b5061076c6004803603608081101561069257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156106d957600080fd5b8201836020820111156106eb57600080fd5b8035906020019184600183028401116401000000008311171561070d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff16906020019092919050505061278d565b60405180831515815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107b4578082015181840152602081019050610799565b50505050905090810190601f1680156107e15780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b3480156107fc57600080fd5b506108336004803603604081101561081357600080fd5b8101908080359060200190929190803590602001909291905050506127c3565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610873578082015181840152602081019050610858565b50505050905090810190601f1680156108a05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156108ba57600080fd5b506108e7600480360360208110156108d157600080fd5b810190808035906020019092919050505061284a565b6040518082815260200191505060405180910390f35b34801561090957600080fd5b5061094c6004803603602081101561092057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612862565b005b34801561095a57600080fd5b506109876004803603602081101561097157600080fd5b8101908080359060200190929190505050612bea565b005b610b2d60048036036101408110156109a057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156109e757600080fd5b8201836020820111156109f957600080fd5b80359060200191846001830284011164010000000083111715610a1b57600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610aa757600080fd5b820183602082011115610ab957600080fd5b80359060200191846001830284011164010000000083111715610adb57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612d24565b60405180821515815260200191505060405180910390f35b348015610b5157600080fd5b50610b9e60048036036040811015610b6857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613253565b6040518082815260200191505060405180910390f35b348015610bc057600080fd5b50610d1b60048036036060811015610bd757600080fd5b810190808035906020019092919080359060200190640100000000811115610bfe57600080fd5b820183602082011115610c1057600080fd5b80359060200191846001830284011164010000000083111715610c3257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190640100000000811115610c9557600080fd5b820183602082011115610ca757600080fd5b80359060200191846001830284011164010000000083111715610cc957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050613278565b005b348015610d2957600080fd5b50610d32613307565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610d75578082015181840152602081019050610d5a565b505050509050019250505060405180910390f35b348015610d9557600080fd5b50610d9e6134b0565b6040518082815260200191505060405180910390f35b348015610dc057600080fd5b50610e9a60048036036040811015610dd757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610e1457600080fd5b820183602082011115610e2657600080fd5b80359060200191846001830284011164010000000083111715610e4857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506134b6565b005b348015610ea857600080fd5b5061100a6004803603610100811015610ec057600080fd5b8101908080359060200190640100000000811115610edd57600080fd5b820183602082011115610eef57600080fd5b80359060200191846020830284011164010000000083111715610f1157600080fd5b909192939192939080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610f5c57600080fd5b820183602082011115610f6e57600080fd5b80359060200191846001830284011164010000000083111715610f9057600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506134d8565b005b34801561101857600080fd5b506110656004803603604081101561102f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613696565b60405180806020018373ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019060200280838360005b838110156110c45780820151818401526020810190506110a9565b50505050905001935050505060405180910390f35b3480156110e557600080fd5b50611112600480360360208110156110fc57600080fd5b81019080803590602001909291905050506139f9565b005b34801561112057600080fd5b50611238600480360361014081101561113857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561117f57600080fd5b82018360208201111561119157600080fd5b803590602001918460018302840111640100000000831117156111b357600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613b98565b6040518082815260200191505060405180910390f35b34801561125a57600080fd5b506112bd6004803603604081101561127157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613bc5565b005b3480156112cb57600080fd5b5061130e600480360360208110156112e257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613f4c565b005b34801561131c57600080fd5b5061139f6004803603606081101561133357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614138565b005b3480156113ad57600080fd5b506113b6614796565b6040518082815260200191505060405180910390f35b3480156113d857600080fd5b506114f060048036036101408110156113f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561143757600080fd5b82018360208201111561144957600080fd5b8035906020019184600183028401116401000000008311171561146b57600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506147a0565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015611530578082015181840152602081019050611515565b50505050905090810190601f16801561155d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561157757600080fd5b506115ba6004803603602081101561158e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614948565b005b3480156115c857600080fd5b506115d161499f565b6040518082815260200191505060405180910390f35b3480156115f357600080fd5b506116606004803603606081101561160a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050614a1d565b005b34801561166e57600080fd5b50611677614e46565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156116b757808201518184015260208101905061169c565b50505050905090810190601f1680156116e45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6116fa614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156117645750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b801561179c57503073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b61180e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461190f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506003600081548092919060010191905055508173ffffffffffffffffffffffffffffffffffffffff167f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2660405160405180910390a28060045414611ad457611ad381612bea565b5b5050565b611aec604182614f2290919063ffffffff16565b82511015611b62576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000808060008060005b868110156123ca57611b7e8882614f5c565b80945081955082965050505060008460ff1614156120035789898051906020012014611c12576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323700000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8260001c9450611c2c604188614f2290919063ffffffff16565b8260001c1015611ca4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8751611cbd60208460001c614f8b90919063ffffffff16565b1115611d31576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006020838a01015190508851611d6782611d5960208760001c614f8b90919063ffffffff16565b614f8b90919063ffffffff16565b1115611ddb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60606020848b010190506320c13b0b60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168773ffffffffffffffffffffffffffffffffffffffff166320c13b0b8d846040518363ffffffff1660e01b8152600401808060200180602001838103835285818151815260200191508051906020019080838360005b83811015611e7d578082015181840152602081019050611e62565b50505050905090810190601f168015611eaa5780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015611ee3578082015181840152602081019050611ec8565b50505050905090810190601f168015611f105780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015611f2f57600080fd5b505afa158015611f43573d6000803e3d6000fd5b505050506040513d6020811015611f5957600080fd5b81019080805190602001909291905050507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611ffc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5050612248565b60018460ff161415612117578260001c94508473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806120a057506000600860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008c81526020019081526020016000205414155b612112576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b612247565b601e8460ff1611156121df5760018a60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c018281526020019150506040516020818303038152906040528051906020012060048603858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156121ce573d6000803e3d6000fd5b505050602060405103519450612246565b60018a85858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612239573d6000803e3d6000fd5b5050506020604051035194505b5b5b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1611801561230f5750600073ffffffffffffffffffffffffffffffffffffffff16600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b80156123485750600173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b6123ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323600000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8495508080600101915050611b6c565b50505050505050505050565b60008173ffffffffffffffffffffffffffffffffffffffff16600173ffffffffffffffffffffffffffffffffffffffff16141580156124a15750600073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b6000600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156125735750600073ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b6000804690508091505090565b6000600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156126525750600073ffffffffffffffffffffffffffffffffffffffff16600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b6126c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6126f1858585857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff614faa565b90508015612741573373ffffffffffffffffffffffffffffffffffffffff167f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb860405160405180910390a2612785565b3373ffffffffffffffffffffffffffffffffffffffff167facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37560405160405180910390a25b949350505050565b6000606061279d86868686612587565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b606060006020830267ffffffffffffffff811180156127e157600080fd5b506040519080825280601f01601f1916602001820160405280156128145781602001600182028036833780820191505090505b50905060005b8381101561283f5780850154806020830260208501015250808060010191505061281a565b508091505092915050565b60076020528060005260406000206000915090505481565b61286a614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156128d45750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b612946576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612a47576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844060405160405180910390a250565b612bf2614e7f565b600354811115612c6a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001811015612ce1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b806004819055507f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c936004546040518082815260200191505060405180910390a150565b6000806000612d3e8e8e8e8e8e8e8e8e8e8e6005546147a0565b905060056000815480929190600101919050555080805190602001209150612d67828286613278565b506000612d72614ff6565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612f58578073ffffffffffffffffffffffffffffffffffffffff166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b8152600401808d73ffffffffffffffffffffffffffffffffffffffff1681526020018c8152602001806020018a6001811115612e1557fe5b81526020018981526020018881526020018781526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff168152602001806020018473ffffffffffffffffffffffffffffffffffffffff16815260200183810383528d8d82818152602001925080828437600081840152601f19601f820116905080830192505050838103825285818151815260200191508051906020019080838360005b83811015612ee7578082015181840152602081019050612ecc565b50505050905090810190601f168015612f145780820380516001836020036101000a031916815260200191505b509e505050505050505050505050505050600060405180830381600087803b158015612f3f57600080fd5b505af1158015612f53573d6000803e3d6000fd5b505050505b6101f4612f7f6109c48b01603f60408d0281612f7057fe5b0461502790919063ffffffff16565b015a1015612ff5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60005a905061305e8f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e60008d14613053578e613059565b6109c45a035b614faa565b93506130735a8261504190919063ffffffff16565b90508380613082575060008a14155b8061308e575060008814155b613100576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60008089111561311a57613117828b8b8b8b615061565b90505b841561315d57837f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e826040518082815260200191505060405180910390a2613196565b837f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d23826040518082815260200191505060405180910390a25b5050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614613242578073ffffffffffffffffffffffffffffffffffffffff16639327136883856040518363ffffffff1660e01b815260040180838152602001821515815260200192505050600060405180830381600087803b15801561322957600080fd5b505af115801561323d573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b6008602052816000526040600020602052806000526040600020600091509150505481565b60006004549050600081116132f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b61330184848484611ad8565b50505050565b6060600060035467ffffffffffffffff8111801561332457600080fd5b506040519080825280602002602001820160405280156133535781602001602082028036833780820191505090505b50905060008060026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146134a757808383815181106133fe57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081806001019250506133bd565b82935050505090565b60055481565b600080825160208401855af4806000523d6020523d600060403e60403d016000fd5b6135238a8a80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505089615267565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146135615761356084615767565b5b6135af8787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050615838565b60008211156135c9576135c782600060018685615061565b505b3373ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b8960405180806020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281038252878782818152602001925060200280828437600081840152601f19601f820116905080830192505050965050505050505060405180910390a250505050505050505050565b60606000600173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806136da57506136d9846123d6565b5b61374c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600083116137c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303600000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8267ffffffffffffffff811180156137d957600080fd5b506040519080825280602002602001820160405280156138085781602001602082028036833780820191505090505b5091506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156138da5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b80156138e557508381105b156139a057818382815181106138f757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508080600101915050613870565b600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146139ee578260018203815181106139e357fe5b602002602001015191505b808352509250929050565b600073ffffffffffffffffffffffffffffffffffffffff16600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415613afb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330333000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff16817ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c60405160405180910390a350565b6000613bad8c8c8c8c8c8c8c8c8c8c8c6147a0565b8051906020012090509b9a5050505050505050505050565b613bcd614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015613c375750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b613ca9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614613da9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427660405160405180910390a25050565b613f54614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146140c6578073ffffffffffffffffffffffffffffffffffffffff166301ffc9a77fe6d7a83a000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b15801561401857600080fd5b505afa15801561402c573d6000803e3d6000fd5b505050506040513d602081101561404257600080fd5b81019080805190602001909291905050506140c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475333303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b60007f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c860001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa260405160405180910390a25050565b614140614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156141aa5750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156141e257503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b614254576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614355576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156143bf5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b614431576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614531576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf60405160405180910390a28073ffffffffffffffffffffffffffffffffffffffff167f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2660405160405180910390a2505050565b6000600454905090565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d60405180838380828437808301925050509250505060405180910390208c8c8c8c8c8c8c604051602001808c81526020018b73ffffffffffffffffffffffffffffffffffffffff1681526020018a815260200189815260200188600181111561483157fe5b81526020018781526020018681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019b505050505050505050505050604051602081830303815290604052805190602001209050601960f81b600160f81b6148bd61499f565b8360405160200180857effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152600101847effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526001018381526020018281526020019450505050506040516020818303038152906040529150509b9a5050505050505050505050565b614950614e7f565b61495981615767565b8073ffffffffffffffffffffffffffffffffffffffff167f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b060405160405180910390a250565b60007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a7946921860001b6149cd61257a565b30604051602001808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405160208183030381529060405280519060200120905090565b614a25614e7f565b806001600354031015614aa0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015614b0a5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b614b7c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614c7c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600360008154809291906001900391905055508173ffffffffffffffffffffffffffffffffffffffff167ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf60405160405180910390a28060045414614e4157614e4081612bea565b5b505050565b6040518060400160405280600581526020017f312e342e3100000000000000000000000000000000000000000000000000000081525081565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614614f20576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330333100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b565b600080831415614f355760009050614f56565b6000828402905082848281614f4657fe5b0414614f5157600080fd5b809150505b92915050565b60008060008360410260208101860151925060408101860151915060ff60418201870151169350509250925092565b600080828401905083811015614fa057600080fd5b8091505092915050565b6000600180811115614fb857fe5b836001811115614fc457fe5b1415614fdd576000808551602087018986f49050614fed565b600080855160208701888a87f190505b95945050505050565b6000807f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c860001b9050805491505090565b6000818310156150375781615039565b825b905092915050565b60008282111561505057600080fd5b600082840390508091505092915050565b600080600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461509e57826150a0565b325b9050600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156151b85761510a3a86106150e7573a6150e9565b855b6150fc888a614f8b90919063ffffffff16565b614f2290919063ffffffff16565b91508073ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050506151b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b61525d565b6151dd856151cf888a614f8b90919063ffffffff16565b614f2290919063ffffffff16565b91506151ea848284615b0e565b61525c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b5095945050505050565b6000600454146152df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8151811115615356576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60018110156153cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006001905060005b83518110156156d35760008482815181106153ed57fe5b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156154615750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b801561549957503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156154d157508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b615543576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614615644576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b80600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508092505080806001019150506153d6565b506001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550825160038190555081600481905550505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415615809576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475334303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60007f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d560001b90508181555050565b600073ffffffffffffffffffffffffffffffffffffffff1660016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461593a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001806000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614615b0a576159f682615bd2565b615a68576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b615a978260008360017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff614faa565b615b09576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b5050565b60008063a9059cbb8484604051602401808373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001925050506040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050602060008251602084016000896127105a03f13d60008114615bb55760208114615bbd5760009350615bc8565b819350615bc8565b600051158215171593505b5050509392505050565b600080823b90506000811191505091905056fea264697066735822122057398fa72884cf9a6cb78aab2fb58a6b927f0e9d97d75b015daaee0959a153bf64736f6c63430007060033")
1472 );
1473 let _tx_safe_multisend = TransactionRequest::default().with_to(safe_diamond_proxy_address).with_input(
1475 hex!("000000000000000000000000000000000000000000000000000000000000000060a060405234801561001057600080fd5b503073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b8152505060805160601c6102756100646000398060e052506102756000f3fe60806040526004361061001e5760003560e01c80638d80ff0a14610023575b600080fd5b6100dc6004803603602081101561003957600080fd5b810190808035906020019064010000000081111561005657600080fd5b82018360208201111561006857600080fd5b8035906020019184600183028401116401000000008311171561008a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506100de565b005b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161415610183576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260308152602001806102106030913960400191505060405180910390fd5b805160205b8181101561020a578083015160f81c6001820184015160601c6015830185015160358401860151605585018701600085600081146101cd57600181146101dd576101e8565b6000808585888a5af191506101e8565b6000808585895af491505b5060008114156101f757600080fd5b8260550187019650505050505050610188565b50505056fe4d756c746953656e642073686f756c64206f6e6c792062652063616c6c6564207669612064656c656761746563616c6ca264697066735822122021102e6d5bc1da75411b41fe2792a1748bf5c49c794e51e81405ccd2399da13564736f6c63430007060033")
1476 );
1477 provider.send_transaction(_tx_safe_proxy_factory).await?.watch().await?;
1480 provider
1481 .send_transaction(_tx_safe_compatibility_fallback_handler)
1482 .await?
1483 .watch()
1484 .await?;
1485 provider
1486 .send_transaction(_tx_safe_multisend_call_only)
1487 .await?
1488 .watch()
1489 .await?;
1490 provider.send_transaction(_tx_safe_singleton).await?.watch().await?;
1491 provider.send_transaction(_tx_safe_multisend).await?.watch().await?;
1492 }
1493 Ok(())
1494 }
1495
1496 #[tokio::test]
1497 async fn test_native_and_token_balances_in_anvil_with_multicall() -> anyhow::Result<()> {
1498 let kp = ChainKeypair::random();
1500 let kp_address = Address::from(&kp.public().to_address().into());
1501
1502 let anvil = hopr_chain_types::utils::create_anvil(None);
1504 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1505 let client = create_rpc_client_to_anvil(&anvil, &contract_deployer);
1506 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1508 .await
1509 .expect("failed to deploy");
1510 deploy_multicall3_for_testing(client.clone()).await?;
1512
1513 let (native_balance, token_balance) = get_native_and_token_balances(instances.token, vec![kp_address]).await?;
1515 assert_eq!(native_balance.len(), 1, "invalid native balance lens");
1516 assert_eq!(token_balance.len(), 1, "invalid token balance lens");
1517 assert_eq!(native_balance[0].to::<u64>(), 0u64, "wrong native balance");
1518 assert_eq!(token_balance[0].to::<u64>(), 0u64, "wrong token balance");
1519 drop(anvil);
1520 Ok(())
1521 }
1522
1523 #[tokio::test]
1524 async fn test_transfer_or_mint_tokens_in_anvil_with_multicall() -> anyhow::Result<()> {
1525 let _ = env_logger::builder().is_test(true).try_init();
1526
1527 let mut addresses: Vec<Address> = Vec::new();
1528 for _ in 0..4 {
1529 addresses.push(get_random_address_for_testing());
1530 }
1531 let desired_amount = vec![U256::from(1), U256::from(2), U256::from(3), U256::from(4)];
1532
1533 let anvil = hopr_chain_types::utils::create_anvil(None);
1535 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1536 let client = create_rpc_client_to_anvil(&anvil, &contract_deployer);
1537 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1539 .await
1540 .expect("failed to deploy");
1541
1542 deploy_multicall3_for_testing(client.clone()).await?;
1544 let encoded_minter_role = keccak256(b"MINTER_ROLE");
1546 instances
1547 .token
1548 .grantRole(encoded_minter_role, contract_deployer.public().to_address().into())
1549 .send()
1550 .await?
1551 .watch()
1552 .await?;
1553
1554 let check_minter_role = instances
1556 .token
1557 .hasRole(encoded_minter_role, contract_deployer.public().to_address().into())
1558 .call()
1559 .await?;
1560 assert!(check_minter_role, "deployer does not have minter role yet");
1561
1562 let total_transferred_amount =
1564 transfer_or_mint_tokens(instances.token.clone(), addresses.clone(), desired_amount.clone()).await?;
1565
1566 let (native_balance, token_balance) = get_native_and_token_balances(instances.token, addresses.clone()).await?;
1568
1569 assert_eq!(native_balance.len(), 4, "invalid native balance lens");
1570 assert_eq!(token_balance.len(), 4, "invalid token balance lens");
1571 for (i, amount) in desired_amount.iter().enumerate() {
1572 assert_eq!(&token_balance[i], amount, "token balance unmatch");
1573 }
1574
1575 assert_eq!(
1576 total_transferred_amount,
1577 U256::from(10),
1578 "amount transferred does not equal to the desired amount"
1579 );
1580 Ok(())
1581 }
1582
1583 #[tokio::test]
1584 async fn test_transfer_or_mint_tokens_in_anvil_with_one_recipient() -> anyhow::Result<()> {
1585 let addresses: Vec<Address> = vec![get_random_address_for_testing()];
1586 let desired_amount = vec![U256::from(42)];
1587
1588 let anvil = hopr_chain_types::utils::create_anvil(None);
1590 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1591 let client = create_rpc_client_to_anvil(&anvil, &contract_deployer);
1592 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1594 .await
1595 .expect("failed to deploy");
1596
1597 deploy_multicall3_for_testing(client.clone()).await?;
1599 let encoded_minter_role = keccak256(b"MINTER_ROLE");
1601 instances
1602 .token
1603 .grantRole(encoded_minter_role, contract_deployer.public().to_address().into())
1604 .send()
1605 .await?
1606 .watch()
1607 .await?;
1608
1609 let check_minter_role = instances
1611 .token
1612 .hasRole(encoded_minter_role, contract_deployer.public().to_address().into())
1613 .call()
1614 .await?;
1615 assert!(check_minter_role, "deployer does not have minter role yet");
1616
1617 let total_transferred_amount =
1619 transfer_or_mint_tokens(instances.token.clone(), addresses.clone(), desired_amount.clone()).await?;
1620
1621 let (native_balance, token_balance) = get_native_and_token_balances(instances.token, addresses.clone()).await?;
1623 assert_eq!(native_balance.len(), 1, "invalid native balance lens");
1624 assert_eq!(token_balance.len(), 1, "invalid token balance lens");
1625 for (i, amount) in desired_amount.iter().enumerate() {
1626 assert_eq!(&token_balance[i], amount, "token balance unmatch");
1627 }
1628
1629 assert_eq!(
1630 total_transferred_amount, desired_amount[0],
1631 "amount transferred does not equal to the desired amount"
1632 );
1633 Ok(())
1634 }
1635
1636 #[tokio::test]
1637 async fn test_transfer_or_mint_tokens_in_anvil_without_recipient() -> anyhow::Result<()> {
1638 let addresses: Vec<Address> = Vec::new();
1639 let desired_amount: Vec<U256> = Vec::new();
1640
1641 let anvil = hopr_chain_types::utils::create_anvil(None);
1643 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1644 let client = create_rpc_client_to_anvil(&anvil, &contract_deployer);
1645 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1647 .await
1648 .expect("failed to deploy");
1649
1650 deploy_multicall3_for_testing(client.clone()).await?;
1652
1653 let total_transferred_amount =
1655 transfer_or_mint_tokens(instances.token.clone(), addresses.clone(), desired_amount.clone()).await?;
1656
1657 let (native_balance, token_balance) = get_native_and_token_balances(instances.token, addresses.clone()).await?;
1659 assert_eq!(native_balance.len(), 0, "invalid native balance lens");
1660 assert_eq!(token_balance.len(), 0, "invalid token balance lens");
1661 assert_eq!(
1666 total_transferred_amount,
1667 U256::from(0),
1668 "amount transferred does not equal to the desired amount"
1669 );
1670 Ok(())
1671 }
1672
1673 #[tokio::test]
1674 async fn test_transfer_native_tokens_in_anvil_with_multicall() -> anyhow::Result<()> {
1675 let mut addresses: Vec<Address> = Vec::new();
1676 for _ in 0..4 {
1677 addresses.push(get_random_address_for_testing());
1678 }
1679 let desired_amount = vec![U256::from(1), U256::from(2), U256::from(3), U256::from(4)];
1680
1681 let anvil = hopr_chain_types::utils::create_anvil(None);
1683 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1684 let client = create_rpc_client_to_anvil(&anvil, &contract_deployer);
1685 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1686 .await
1687 .expect("failed to deploy");
1688
1689 deploy_multicall3_for_testing(client.clone()).await?;
1691
1692 let total_transferred_amount =
1694 transfer_native_tokens(client.clone(), addresses.clone(), desired_amount.clone()).await?;
1695
1696 let (native_balance, token_balance) = get_native_and_token_balances(instances.token, addresses.clone()).await?;
1698 assert_eq!(native_balance.len(), 4, "invalid native balance lens");
1699 assert_eq!(token_balance.len(), 4, "invalid token balance lens");
1700 for (i, amount) in desired_amount.iter().enumerate() {
1701 assert_eq!(&native_balance[i], amount, "native balance unmatch");
1702 }
1703
1704 assert_eq!(
1705 total_transferred_amount,
1706 U256::from(10),
1707 "amount transferred does not equal to the desired amount"
1708 );
1709 Ok(())
1710 }
1711
1712 #[tokio::test]
1713 async fn test_register_safes_and_nodes_then_deregister_nodes_in_anvil_with_multicall() -> anyhow::Result<()> {
1714 let mut safe_addresses: Vec<Address> = Vec::new();
1715 let mut node_addresses: Vec<Address> = Vec::new();
1716 for _ in 0..4 {
1717 safe_addresses.push(get_random_address_for_testing());
1718 node_addresses.push(get_random_address_for_testing());
1719 }
1720
1721 let anvil = hopr_chain_types::utils::create_anvil(None);
1723 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1724 let client = create_rpc_client_to_anvil(&anvil, &contract_deployer);
1725 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1726 .await
1727 .expect("failed to deploy");
1728 deploy_multicall3_for_testing(client.clone()).await?;
1730
1731 let (removed_amt, added_amt) = register_safes_and_nodes_on_network_registry(
1733 instances.network_registry.clone(),
1734 safe_addresses.clone(),
1735 node_addresses.clone(),
1736 )
1737 .await?;
1738
1739 assert_eq!(removed_amt, 0, "should not remove any safe");
1740 assert_eq!(added_amt, 4, "there should be 4 additions");
1741
1742 let registered_safes = get_registered_safes_for_nodes_on_network_registry(
1744 instances.network_registry.clone(),
1745 node_addresses.clone(),
1746 )
1747 .await?;
1748
1749 assert_eq!(safe_addresses.len(), registered_safes.len(), "returned length unmatch");
1750 for (i, safe_addr) in safe_addresses.iter().enumerate() {
1751 assert_eq!(safe_addr, ®istered_safes[i], "registered safe addresses unmatch");
1752 }
1753
1754 let deregisterd_nodes = deregister_nodes_from_network_registry(
1756 instances.network_registry.clone(),
1757 node_addresses.split_at(3).0.to_vec(),
1758 )
1759 .await?;
1760 assert_eq!(deregisterd_nodes, 3, "cannot deregister all the nodes");
1761
1762 let (removed_amt_2, added_amt_2) = register_safes_and_nodes_on_network_registry(
1764 instances.network_registry.clone(),
1765 safe_addresses.clone(),
1766 node_addresses.clone(),
1767 )
1768 .await?;
1769
1770 assert_eq!(removed_amt_2, 0, "should not remove any safe");
1771 assert_eq!(added_amt_2, 3, "there should be 3 additions");
1772 Ok(())
1773 }
1774
1775 #[tokio::test]
1776 async fn test_deploy_proxy() -> anyhow::Result<()> {
1777 let prediction = deploy_proxy(
1778 address!("41675c099f32341bf84bfc5382af534df5c7461a"),
1779 hex!("09e458584ce79e57b65cb303dc136c5d53e17b676599b9b7bc03815e0eef5172"),
1780 Address::from_str(SAFE_SAFEPROXYFACTORY_ADDRESS)?,
1781 )?;
1782
1783 assert_eq!(
1784 prediction,
1785 address!("ec5c8d045dfa1f93785125c26e187e9439f67105"),
1786 "cannot reproduce proxy"
1787 );
1788 Ok(())
1789 }
1790 #[tokio::test]
1791 async fn test_get_salt_from_salt_nonce() -> anyhow::Result<()> {
1792 let salt = get_salt_from_salt_nonce(
1793 hex!("b63e800d00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000002a15de4410d4c8af0a7b6c12803120f43c42b8200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000098b275485c406573d042848d66eb9d63fca311c00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000").into(),
1794 B256::from_str("E5EAFDE6416CCB48925026B6313D62A98C0997E03591E29EB4CF1EA968D6BC8F")?)?;
1796
1797 assert_eq!(
1798 salt.to_vec(),
1799 Bytes::from_str("09e458584ce79e57b65cb303dc136c5d53e17b676599b9b7bc03815e0eef5172")?,
1800 "cannot reproduce salt"
1801 );
1802 Ok(())
1803 }
1804
1805 #[tokio::test]
1806 async fn test_safe_and_module_address_prediction() -> anyhow::Result<()> {
1807 let _ = env_logger::builder().is_test(true).try_init();
1809
1810 let mut admin_addresses: Vec<Address> = Vec::new();
1812 for _ in 0..2 {
1813 admin_addresses.push(get_random_address_for_testing());
1814 }
1815
1816 let anvil = hopr_chain_types::utils::create_anvil(None);
1818 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1819 let client = create_rpc_client_to_anvil(&anvil, &contract_deployer);
1820 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1821 .await
1822 .expect("failed to deploy");
1823 deploy_multicall3_for_testing(client.clone()).await?;
1825 deploy_safe_suites(client.clone()).await?;
1827
1828 let caller = client.default_signer_address();
1829
1830 let default_target = format!("{:?}{}", instances.channels.address(), DEFAULT_CAPABILITY_PERMISSIONS);
1832 debug!("default target {:?}", default_target);
1833 let curr_nonce = client.get_transaction_count(caller).pending().await?;
1835 let nonce = keccak256((caller, U256::from(curr_nonce)).abi_encode_packed());
1836
1837 let module_address = predict_module_address(
1838 caller,
1839 nonce,
1840 *instances.stake_factory.address(),
1841 *instances.module_implementation.address(),
1842 )?;
1843 debug!("predict_module_addr {:?}", module_address);
1844
1845 let safe_address = predict_safe_address(
1846 *instances.stake_factory.address(),
1847 vec![address!("9062a96b9e947b2b57283e705c97b871f5eb6561")],
1848 nonce,
1849 Address::from_str(SAFE_COMPATIBILITYFALLBACKHANDLER_ADDRESS)?,
1850 Address::from_str(SAFE_SAFE_ADDRESS)?,
1851 Address::from_str(SAFE_SAFEPROXYFACTORY_ADDRESS)?,
1852 )?;
1853
1854 debug!("predict_safe_address {:?}", safe_address);
1855
1856 let deployment_receipt = instances
1858 .stake_factory
1859 .clone(
1860 *instances.module_implementation.address(),
1861 vec![caller],
1862 nonce.into(),
1863 U256::from_str(&default_target)?.into(),
1864 )
1865 .send()
1866 .await?
1867 .get_receipt()
1868 .await?;
1869
1870 let module_log = deployment_receipt
1872 .decoded_log::<HoprNodeStakeFactory::NewHoprNodeStakeModule>()
1873 .ok_or_else(|| anyhow::anyhow!("Module log not found"))?;
1874
1875 let safe_log = deployment_receipt
1876 .decoded_log::<HoprNodeStakeFactory::NewHoprNodeStakeSafe>()
1877 .ok_or_else(|| anyhow::anyhow!("Module log not found"))?;
1878
1879 let module_addr = module_log.instance;
1880 let safe_addr = safe_log.instance;
1881
1882 assert_eq!(module_addr, module_address, "module prediction does not match");
1883 assert_eq!(safe_addr, safe_address, "safe prediction does not match");
1884 Ok(())
1885 }
1886
1887 #[tokio::test]
1888 async fn test_deploy_safe_and_module() -> anyhow::Result<()> {
1889 let _ = env_logger::builder().is_test(true).try_init();
1890
1891 let mut admin_addresses: Vec<Address> = Vec::new();
1893 for _ in 0..2 {
1894 admin_addresses.push(get_random_address_for_testing());
1895 }
1896 let mut node_addresses: Vec<Address> = Vec::new();
1897 for _ in 0..2 {
1898 node_addresses.push(get_random_address_for_testing());
1899 }
1900
1901 let anvil = hopr_chain_types::utils::create_anvil(None);
1903 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1904 let client = create_rpc_client_to_anvil(&anvil, &contract_deployer);
1905 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1906 .await
1907 .expect("failed to deploy");
1908 deploy_multicall3_for_testing(client.clone()).await?;
1910 deploy_safe_suites(client.clone()).await?;
1912
1913 let (safe, node_module) = deploy_safe_module_with_targets_and_nodes(
1915 instances.stake_factory,
1916 *instances.token.address(),
1917 *instances.channels.address(),
1918 *instances.module_implementation.address(),
1919 *instances.announcements.address(),
1920 U256::MAX,
1921 Some(node_addresses.clone()),
1922 admin_addresses.clone(),
1923 U256::from(2),
1924 )
1925 .await?;
1926
1927 let try_get_announcement_target = node_module
1929 .tryGetTarget(*instances.announcements.address())
1930 .call()
1931 .await?;
1932
1933 assert!(try_get_announcement_target._0, "announcement is not a target");
1934
1935 let allowance = instances
1937 .token
1938 .allowance(*safe.address(), *instances.channels.address())
1939 .call()
1940 .await?;
1941
1942 assert_eq!(allowance, U256::MAX, "allowance is not set");
1943
1944 for node_address in node_addresses {
1946 let is_node_included = node_module.isNode(node_address).call().await?;
1947 assert!(is_node_included, "failed to include a node");
1948 }
1949
1950 let owners = safe.getOwners().call().await?;
1952 let thresold = safe.getThreshold().call().await?;
1953
1954 assert_eq!(owners.len(), 2, "should have 2 owners");
1955 for (i, owner) in owners.iter().enumerate() {
1956 assert_eq!(owner, &admin_addresses[i], "admin is wrong");
1957 }
1958 assert_eq!(thresold, U256::from(2), "threshold should be two");
1959 Ok(())
1960 }
1961
1962 #[tokio::test]
1963 async fn test_safe_tx_via_multisend() -> anyhow::Result<()> {
1964 let _ = env_logger::builder().is_test(true).try_init();
1966
1967 let desired_amount = vec![U256::from(1), U256::from(2), U256::from(3), U256::from(4)];
1969
1970 let anvil = hopr_chain_types::utils::create_anvil(None);
1972 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1973 let client = create_rpc_client_to_anvil(&anvil, &contract_deployer);
1974 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1975 .await
1976 .expect("failed to deploy");
1977 deploy_multicall3_for_testing(client.clone()).await?;
1979 deploy_safe_suites(client.clone()).await?;
1981
1982 let (safe, _node_module) = deploy_safe_module_with_targets_and_nodes(
1984 instances.stake_factory,
1985 *instances.token.address(),
1986 *instances.channels.address(),
1987 *instances.module_implementation.address(),
1988 *instances.announcements.address(),
1989 U256::MAX,
1990 None,
1991 vec![contract_deployer.public().to_address().into()],
1992 U256::from(1),
1993 )
1994 .await?;
1995
1996 let is_owner = safe.getOwners().call().await?;
1998 assert_eq!(is_owner.len(), 1, "safe has too many owners");
1999 assert_eq!(
2000 is_owner[0].0.0,
2001 contract_deployer.public().to_address().as_ref(),
2002 "safe wrong owner"
2003 );
2004
2005 let allowance = instances
2007 .token
2008 .allowance(*safe.address(), *instances.channels.address())
2009 .call()
2010 .await?;
2011
2012 assert_eq!(allowance, U256::MAX, "allowance initiation is wrong");
2013
2014 let mut multisend_txns: Vec<MultisendTransaction> = Vec::new();
2015 for val in desired_amount {
2016 multisend_txns.push(MultisendTransaction {
2017 encoded_data: approveCall {
2019 spender: *instances.channels.address(),
2020 value: val,
2021 }
2022 .abi_encode()
2023 .into(),
2024 tx_operation: SafeTxOperation::Call,
2025 to: *instances.token.address(),
2026 value: U256::ZERO,
2027 });
2028 }
2029
2030 let chain_id = client.get_chain_id().await?;
2032 let safe_nonce = safe.nonce().call().await?;
2033 debug!("safe address {:?}", safe.address());
2034 debug!("chain_id {:?}", chain_id);
2035 debug!("safe_nonce {:?}", safe_nonce);
2036
2037 send_multisend_safe_transaction_with_threshold_one(
2039 safe.clone(),
2040 contract_deployer,
2041 Address::from_str(SAFE_MULTISEND_ADDRESS)?,
2042 multisend_txns,
2043 U256::from(chain_id),
2044 safe_nonce,
2045 )
2046 .await?;
2047
2048 let new_allowance = instances
2050 .token
2051 .allowance(*safe.address(), *instances.channels.address())
2052 .call()
2053 .await?;
2054
2055 assert_eq!(new_allowance, U256::from(4), "final allowance is not desired");
2056 Ok(())
2057 }
2058
2059 #[tokio::test]
2060 async fn test_register_nodes_to_node_safe_registry() -> anyhow::Result<()> {
2061 let _ = env_logger::builder().is_test(true).try_init();
2063
2064 let anvil = hopr_chain_types::utils::create_anvil(None);
2066 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
2067 let client = create_rpc_client_to_anvil(&anvil, &contract_deployer);
2068 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
2069 .await
2070 .expect("failed to deploy");
2071 deploy_multicall3_for_testing(client.clone()).await?;
2073 deploy_safe_suites(client.clone()).await?;
2075
2076 let deployer_vec: Vec<Address> = vec![contract_deployer.public().to_address().into()];
2077
2078 let (safe, node_module) = deploy_safe_module_with_targets_and_nodes(
2080 instances.stake_factory,
2081 *instances.token.address(),
2082 *instances.channels.address(),
2083 *instances.module_implementation.address(),
2084 *instances.announcements.address(),
2085 U256::MAX,
2086 Some(deployer_vec.clone()),
2087 deployer_vec.clone(),
2088 U256::from(1),
2089 )
2090 .await?;
2091
2092 instances
2094 .safe_registry
2095 .registerSafeByNode(*safe.address())
2096 .send()
2097 .await?
2098 .watch()
2099 .await?;
2100
2101 let get_registered_safe =
2103 get_registered_safes_for_nodes_on_node_safe_registry(instances.safe_registry.clone(), deployer_vec.clone())
2104 .await?;
2105
2106 assert_eq!(get_registered_safe.len(), 1, "cannot read registered safe");
2107 assert_eq!(&get_registered_safe[0], safe.address(), "registered safe is wrong");
2108
2109 deregister_nodes_from_node_safe_registry_and_remove_from_module(
2111 instances.safe_registry.clone(),
2112 deployer_vec.clone(),
2113 vec![*node_module.address()],
2114 contract_deployer.clone(),
2115 )
2116 .await?;
2117
2118 let get_registered_safe =
2120 get_registered_safes_for_nodes_on_node_safe_registry(instances.safe_registry.clone(), deployer_vec.clone())
2121 .await?;
2122
2123 assert_eq!(get_registered_safe.len(), 1, "cannot read registered safe");
2124 assert_eq!(get_registered_safe[0], Address::ZERO, "node is still registered");
2125
2126 let is_removed = node_module
2128 .isNode(contract_deployer.public().to_address().into())
2129 .call()
2130 .await?;
2131 assert!(!is_removed, "node is not removed");
2132 Ok(())
2133 }
2134
2135 #[tokio::test]
2136 async fn test_include_nodes_to_module() -> anyhow::Result<()> {
2137 let _ = env_logger::builder().is_test(true).try_init();
2139
2140 let mut node_addresses: Vec<Address> = Vec::new();
2141 for _ in 0..2 {
2142 node_addresses.push(get_random_address_for_testing());
2143 }
2144
2145 let anvil = hopr_chain_types::utils::create_anvil(None);
2147 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
2148 let client = create_rpc_client_to_anvil(&anvil, &contract_deployer);
2149 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
2150 .await
2151 .expect("failed to deploy");
2152 deploy_multicall3_for_testing(client.clone()).await?;
2154 deploy_safe_suites(client.clone()).await?;
2156
2157 let deployer_vec: Vec<Address> = vec![contract_deployer.public().to_address().into()];
2158
2159 let (safe, node_module) = deploy_safe_module_with_targets_and_nodes(
2161 instances.stake_factory,
2162 *instances.token.address(),
2163 *instances.channels.address(),
2164 *instances.module_implementation.address(),
2165 *instances.announcements.address(),
2166 U256::MAX,
2167 None,
2168 deployer_vec.clone(),
2169 U256::from(1),
2170 )
2171 .await?;
2172
2173 for node_addr in node_addresses.clone() {
2175 let node_is_not_included = node_module.isNode(node_addr).call().await?;
2177 assert!(!node_is_not_included, "node should not be included");
2178 }
2179
2180 include_nodes_to_module(safe, node_addresses.clone(), *node_module.address(), contract_deployer).await?;
2182
2183 for node_addr in node_addresses {
2186 let node_is_included = node_module.isNode(node_addr).call().await?;
2188 assert!(node_is_included, "node should be included");
2189 }
2190 Ok(())
2191 }
2192
2193 #[tokio::test]
2194 async fn test_migrate_nodes_to_new_network() -> anyhow::Result<()> {
2195 let _ = env_logger::builder().is_test(true).try_init();
2197
2198 let mut node_addresses: Vec<Address> = Vec::new();
2199 for _ in 0..2 {
2200 node_addresses.push(get_random_address_for_testing());
2201 }
2202
2203 let anvil = hopr_chain_types::utils::create_anvil(None);
2205 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
2206 let self_address: Address = contract_deployer.public().to_address().into();
2207 let client = create_rpc_client_to_anvil(&anvil, &contract_deployer);
2208 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
2209 .await
2210 .expect("failed to deploy");
2211 deploy_multicall3_for_testing(client.clone()).await?;
2213 deploy_safe_suites(client.clone()).await?;
2215
2216 let new_safe_registry = HoprNodeSafeRegistry::deploy(client.clone()).await?;
2218 let new_token = HoprToken::deploy(client.clone()).await?;
2219 let new_channels = HoprChannels::deploy(
2220 client.clone(),
2221 *new_token.address(),
2222 1_u32,
2223 *new_safe_registry.address(),
2224 )
2225 .await?;
2226 let new_announcements = HoprAnnouncements::deploy(client.clone(), *new_safe_registry.address()).await?;
2227 let _new_network_registry = HoprNetworkRegistry::deploy(
2228 client.clone(),
2229 instances.network_registry_proxy.address().into(),
2230 self_address,
2231 self_address,
2232 )
2233 .await?;
2234
2235 let deployer_vec: Vec<Address> = vec![self_address];
2236
2237 let (safe, node_module) = deploy_safe_module_with_targets_and_nodes(
2239 instances.stake_factory,
2240 *instances.token.address(),
2241 *instances.channels.address(),
2242 *instances.module_implementation.address(),
2243 *instances.announcements.address(),
2244 U256::MAX,
2245 None,
2246 deployer_vec.clone(),
2247 U256::from(1),
2248 )
2249 .await?;
2250
2251 let old_channels_inclusion = node_module.tryGetTarget(*instances.channels.address()).call().await?;
2253 assert!(old_channels_inclusion._0, "old channel should be included");
2254 let new_channels_inclusion = node_module.tryGetTarget(*new_channels.address()).call().await?;
2255 assert!(!new_channels_inclusion._0, "new channel should not be included");
2256
2257 migrate_nodes(
2259 safe,
2260 *node_module.address(),
2261 *new_channels.address(),
2262 *new_token.address(),
2263 *new_announcements.address(),
2264 U256::MAX,
2265 contract_deployer,
2266 )
2267 .await?;
2268
2269 let old_channels_inclusion = node_module.tryGetTarget(*instances.channels.address()).call().await?;
2271 assert!(old_channels_inclusion._0, "old channel should still be included");
2272 let new_channels_inclusion = node_module.tryGetTarget(*new_channels.address()).call().await?;
2273 assert!(new_channels_inclusion._0, "new channel should now be included");
2274 Ok(())
2275 }
2276
2277 #[tokio::test]
2278 async fn test_debug_node_safe_module_setup_on_balance_and_registries() -> anyhow::Result<()> {
2279 let _ = env_logger::builder().is_test(true).try_init();
2281
2282 let mut node_addresses: Vec<Address> = Vec::new();
2283 for _ in 0..2 {
2284 node_addresses.push(get_random_address_for_testing());
2285 }
2286
2287 let anvil = hopr_chain_types::utils::create_anvil(None);
2289 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
2290 let client = create_rpc_client_to_anvil(&anvil, &contract_deployer);
2291 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
2292 .await
2293 .expect("failed to deploy");
2294 deploy_multicall3_for_testing(client.clone()).await?;
2296 deploy_safe_suites(client.clone()).await?;
2298
2299 let deployer_vec: Vec<Address> = vec![contract_deployer.public().to_address().into()];
2300
2301 let (safe, _) = deploy_safe_module_with_targets_and_nodes(
2303 instances.stake_factory,
2304 *instances.token.address(),
2305 *instances.channels.address(),
2306 *instances.module_implementation.address(),
2307 *instances.announcements.address(),
2308 U256::MAX,
2309 None,
2310 deployer_vec.clone(),
2311 U256::from(1),
2312 )
2313 .await?;
2314 let registered_safe_before_registration = debug_node_safe_module_setup_on_balance_and_registries(
2315 instances.network_registry.clone(),
2316 instances.safe_registry.clone(),
2317 &node_addresses[0],
2318 )
2319 .await?;
2320
2321 assert_eq!(
2322 registered_safe_before_registration,
2323 Address::ZERO,
2324 "safe is already registered"
2325 );
2326
2327 let (..) = register_safes_and_nodes_on_network_registry(
2329 instances.network_registry.clone(),
2330 vec![*safe.address()],
2331 vec![node_addresses[0]],
2332 )
2333 .await?;
2334
2335 let registered_safe_after_registration = debug_node_safe_module_setup_on_balance_and_registries(
2336 instances.network_registry.clone(),
2337 instances.safe_registry.clone(),
2338 &node_addresses[0],
2339 )
2340 .await?;
2341
2342 assert_eq!(
2343 ®istered_safe_after_registration,
2344 safe.address(),
2345 "safe is not registered"
2346 );
2347 Ok(())
2348 }
2349
2350 #[tokio::test]
2351 async fn test_debug_node_safe_module_setup_main() -> anyhow::Result<()> {
2352 let _ = env_logger::builder().is_test(true).try_init();
2354
2355 let mut node_addresses: Vec<Address> = Vec::new();
2356 for _ in 0..2 {
2357 node_addresses.push(get_random_address_for_testing());
2358 }
2359
2360 let anvil = hopr_chain_types::utils::create_anvil(None);
2362 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
2363 let client = create_rpc_client_to_anvil(&anvil, &contract_deployer);
2364 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
2365 .await
2366 .expect("failed to deploy");
2367 deploy_multicall3_for_testing(client.clone()).await?;
2369 deploy_safe_suites(client.clone()).await?;
2371
2372 let deployer_vec: Vec<Address> = vec![contract_deployer.public().to_address().into()];
2373
2374 let (safe, node_module) = deploy_safe_module_with_targets_and_nodes(
2376 instances.stake_factory,
2377 *instances.token.address(),
2378 *instances.channels.address(),
2379 *instances.module_implementation.address(),
2380 *instances.announcements.address(),
2381 U256::MAX,
2382 None,
2383 deployer_vec.clone(),
2384 U256::from(1),
2385 )
2386 .await?;
2387
2388 let (..) = register_safes_and_nodes_on_network_registry(
2390 instances.network_registry.clone(),
2391 vec![*safe.address()],
2392 vec![node_addresses[0]],
2393 )
2394 .await?;
2395
2396 debug_node_safe_module_setup_main(
2397 instances.token.clone(),
2398 node_module.address(),
2399 &node_addresses[0],
2400 safe.address(),
2401 instances.channels.address(),
2402 instances.announcements.address(),
2403 )
2404 .await?;
2405 Ok(())
2406 }
2407}