1use ethers::{
8 abi::AbiEncode,
9 contract::{
10 abigen,
11 multicall_contract::{Aggregate3ValueCall, Call3Value},
12 ContractError, Multicall, MulticallError, MULTICALL_ADDRESS,
13 },
14 providers::Middleware,
15 types::{Address, Bytes, Eip1559TransactionRequest, H160, H256, U256},
16 utils::{format_units, get_create2_address, keccak256, parse_units},
17};
18use hex_literal::hex;
19use std::sync::Arc;
20use std::{ops::Add, str::FromStr};
21use tracing::{debug, info};
22
23use hopr_bindings::{
24 hopr_network_registry::HoprNetworkRegistry,
25 hopr_node_management_module::{
26 AddChannelsAndTokenTargetCall, HoprNodeManagementModule, IncludeNodeCall, RemoveNodeCall, ScopeTargetTokenCall,
27 },
28 hopr_node_safe_registry::{DeregisterNodeBySafeCall, HoprNodeSafeRegistry},
29 hopr_node_stake_factory::HoprNodeStakeFactory,
30 hopr_token::{ApproveCall, HoprToken},
31};
32use hopr_chain_rpc::TypedTransaction;
33use hopr_crypto_types::keypairs::{ChainKeypair, Keypair};
34
35use crate::utils::{
36 HelperErrors, DEFAULT_ANNOUNCEMENT_PERMISSIONS, DEFAULT_CAPABILITY_PERMISSIONS, DEFAULT_NODE_PERMISSIONS,
37 DOMAIN_SEPARATOR_TYPEHASH, SAFE_COMPATIBILITYFALLBACKHANDLER_ADDRESS, SAFE_EXECUTION_SUCCESS,
38 SAFE_MULTISEND_ADDRESS, SAFE_SAFEPROXYFACTORY_ADDRESS, SAFE_SAFE_ADDRESS, SAFE_TX_TYPEHASH, SENTINEL_OWNERS,
39};
40
41abigen!(
42 SafeSingleton,
43 r"[
44 function setup(address[],uint256,address,bytes,address,address,uint256,address)
45 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)
46 function removeOwner(address prevOwner, address owner, uint256 _threshold) public
47 function getThreshold() public view returns (uint256)
48 function getOwners() public view returns (address[] memory)
49 function nonce() public view returns (uint256)
50 function domainSeparator() public view returns (bytes32)
51 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)
52 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)
53 function isModuleEnabled(address module) public view returns (bool)
54]"
55);
56abigen!(
57 ModuleSingleton,
58 r"[
59 function isNode(address) external view returns (bool)
60 function getTargets() external view returns (uint256[] memory)
61 function owner() public view returns (address)
62]"
63);
64
65abigen!(
66 MultiSend,
67 r"[
68 function multiSend(bytes memory transactions) public payable
69 ]"
70);
71
72#[derive(Debug, Clone, PartialEq, Eq)]
74pub enum SafeTxOperation {
75 Call,
76 DelegateCall,
77}
78impl SafeTxOperation {
79 pub fn to_byte(&self) -> [u8; 1] {
81 match self {
82 SafeTxOperation::Call => hex!("00"),
83 SafeTxOperation::DelegateCall => hex!("01"),
84 }
85 }
86}
87
88impl From<SafeTxOperation> for u8 {
89 fn from(s: SafeTxOperation) -> u8 {
90 s as u8
91 }
92}
93
94#[derive(Debug, Clone)]
96pub struct MultisendTransaction {
97 pub encoded_data: Bytes,
99 pub tx_operation: SafeTxOperation,
101 pub to: Address,
103 pub value: U256,
105}
106
107impl MultisendTransaction {
109 fn encode_packed(&self) -> Vec<u8> {
111 let tx_operation_bytes = self.tx_operation.to_byte();
112
113 let fixed_length_values = ethers::abi::Token::FixedArray(vec![
114 ethers::abi::Token::Uint(self.value), ethers::abi::Token::Uint(U256::from(self.encoded_data.len())), ]);
117
118 ethers::abi::encode_packed(&[
119 ethers::abi::Token::Bytes(tx_operation_bytes.to_vec()), ethers::abi::Token::Address(self.to), fixed_length_values, ethers::abi::Token::Bytes(self.encoded_data.to_vec()), ])
124 .unwrap_or_else(|_| panic!("failed to encode_packed a multisig transaction"))
125 }
126
127 fn build_multisend_tx(transactions: Vec<MultisendTransaction>) -> Vec<u8> {
129 let mut payload: Vec<u8> = Vec::new();
130 for transaction in transactions {
131 payload = [payload, transaction.encode_packed()].concat();
132 }
133 debug!("payload {:?}", hex::encode(&payload));
134 payload
135 }
136}
137
138fn get_domain_separator(chain_id: U256, contract_address: Address) -> [u8; 32] {
141 keccak256(ethers::abi::encode(&[
142 ethers::abi::Token::FixedBytes(
143 hex::decode(DOMAIN_SEPARATOR_TYPEHASH).unwrap_or_else(|_| panic!("decode the DOMAIN_SEPARATOR_TYPEHASH")),
144 ), ethers::abi::Token::Uint(chain_id), ethers::abi::Token::Address(contract_address), ]))
148}
149
150fn get_safe_transaction_hash(
153 to: Address,
154 value: U256,
155 data: Vec<u8>,
156 operation: SafeTxOperation,
157 refund_address: Address,
158 nonce: U256,
159 domain_separator: [u8; 32],
160) -> [u8; 32] {
161 let data_hash = keccak256(data);
163
164 let encoded = ethers::abi::encode(&[
165 ethers::abi::Token::FixedBytes(
166 hex::decode(SAFE_TX_TYPEHASH).unwrap_or_else(|_| panic!("failed to decode the SAFE_TX_TYPEHASH")),
167 ), ethers::abi::Token::Address(to), ethers::abi::Token::Uint(value), ethers::abi::Token::FixedBytes(data_hash.into()), ethers::abi::Token::Uint(U256::from(operation as u8)), ethers::abi::Token::Uint(U256::zero()), ethers::abi::Token::Uint(U256::zero()), ethers::abi::Token::Uint(U256::zero()), ethers::abi::Token::Address(Address::zero()), ethers::abi::Token::Address(refund_address), ethers::abi::Token::Uint(nonce), ]);
179
180 let safe_hash = keccak256(encoded);
181
182 let encoded_transaction_data = ethers::abi::encode_packed(&[
183 ethers::abi::Token::Bytes(hex!("1901").to_vec()),
184 ethers::abi::Token::FixedBytes(domain_separator.into()),
185 ethers::abi::Token::FixedBytes(safe_hash.into()),
186 ])
187 .unwrap_or_else(|_| panic!("failed to encode_packed a transaction with ethereum prefix"));
188
189 let transaction_hash = keccak256(encoded_transaction_data);
190 debug!("transaction_hash {:?}", hex::encode(transaction_hash));
191 transaction_hash
192}
193
194pub async fn send_multisend_safe_transaction_with_threshold_one<M: Middleware>(
199 safe: SafeSingleton<M>,
200 signer_key: ChainKeypair,
201 multisend_contract: Address,
202 multisend_txns: Vec<MultisendTransaction>,
203 chain_id: U256,
204 nonce: U256,
205) -> Result<(), HelperErrors> {
206 let signer = safe.client().default_sender().expect("client must have a sender");
208 let wallet =
209 ethers::signers::LocalWallet::from_bytes(signer_key.secret().as_ref()).expect("failed to construct wallet");
210
211 let total_value = multisend_txns
214 .clone()
215 .into_iter()
216 .fold(U256::zero(), |acc, cur| acc.add(cur.value));
217 let tx_payload = MultisendTransaction::build_multisend_tx(multisend_txns);
219 let multisend_payload = MultiSendCall {
220 transactions: tx_payload.into(),
221 }
222 .encode();
223 let domain_separator = get_domain_separator(chain_id, safe.address());
225
226 debug!("multisend_payload {:?}", hex::encode(&multisend_payload));
227
228 let transaction_hash = get_safe_transaction_hash(
230 multisend_contract,
231 total_value,
232 multisend_payload.clone(),
233 SafeTxOperation::DelegateCall,
234 signer,
235 nonce,
236 domain_separator,
237 );
238
239 let signature = wallet
241 .sign_hash(transaction_hash.into())
242 .unwrap_or_else(|_| panic!("failed to sign a transaction hash"));
243 debug!("signature {:?}", hex::encode(signature.to_vec()));
244
245 let tx = safe
247 .exec_transaction(
248 multisend_contract,
249 total_value,
250 multisend_payload.into(),
251 SafeTxOperation::DelegateCall.into(),
252 U256::zero(),
253 U256::zero(),
254 U256::zero(),
255 Address::zero(),
256 signer,
257 signature.to_vec().into(),
258 )
259 .send()
260 .await
261 .unwrap_or_else(|_| panic!("failed to exeute a pending transaction"))
262 .await
263 .unwrap_or_else(|_| panic!("failed to resolve a transaction receipt"))
264 .ok_or(HelperErrors::MultiSendError)?;
265
266 tx.logs
267 .iter()
268 .find(|log| log.topics[0].eq(&SAFE_EXECUTION_SUCCESS.parse::<H256>().unwrap()))
269 .ok_or(HelperErrors::MultiSendError)?;
270
271 Ok(())
272}
273
274#[allow(clippy::too_many_arguments)]
276pub async fn send_safe_transaction_with_threshold_one<M: Middleware>(
277 safe: SafeSingleton<M>,
278 signer_key: ChainKeypair,
279 target: Address,
280 tx_payload: Vec<u8>,
281 operation: SafeTxOperation,
282 total_value: U256,
283 chain_id: U256,
284 nonce: U256,
285) -> Result<(), HelperErrors> {
286 let signer = safe.client().default_sender().expect("client must have a sender");
288 let wallet =
289 ethers::signers::LocalWallet::from_bytes(signer_key.secret().as_ref()).expect("failed to construct wallet");
290
291 let domain_separator = get_domain_separator(chain_id, safe.address());
293
294 let transaction_hash = get_safe_transaction_hash(
296 target,
297 total_value,
298 tx_payload.clone(),
299 operation.clone(),
300 signer,
301 nonce,
302 domain_separator,
303 );
304
305 let signature = wallet.sign_hash(transaction_hash.into())?;
307 debug!("signature {:?}", hex::encode(signature.to_vec()));
308
309 let tx = safe
311 .exec_transaction(
312 target,
313 total_value,
314 tx_payload.into(),
315 operation.into(),
316 U256::zero(),
317 U256::zero(),
318 U256::zero(),
319 Address::zero(),
320 signer,
321 signature.to_vec().into(),
322 )
323 .send()
324 .await
325 .unwrap_or_else(|_| panic!("failed to exeute a pending transaction"))
326 .await
327 .unwrap_or_else(|_| panic!("failed to resolve a transaction receipt"))
328 .ok_or(HelperErrors::MultiSendError)?;
329
330 tx.logs
331 .iter()
332 .find(|log| log.topics[0].eq(&SAFE_EXECUTION_SUCCESS.parse::<H256>().unwrap()))
333 .ok_or(HelperErrors::MultiSendError)?;
334
335 Ok(())
336}
337
338pub async fn deploy_multicall3_for_testing<M: Middleware>(provider: Arc<M>) -> Result<(), ContractError<M>> {
340 let mut tx = Eip1559TransactionRequest::new();
342 tx = tx.to(H160::from_str(crate::utils::MULTICALL3_DEPLOYER).unwrap());
343 tx = tx.value(crate::utils::ETH_VALUE_FOR_MULTICALL3_DEPLOYER);
344
345 provider
346 .send_transaction(tx, None)
347 .await
348 .map_err(|e| ContractError::MiddlewareError { e })?
349 .await?;
350
351 provider.send_raw_transaction(
352 hex!("f90f538085174876e800830f42408080b90f00608060405234801561001057600080fd5b50610ee0806100206000396000f3fe6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bbe565b61014d610148366004610a85565b6104ef565b604051610111929190610bd8565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c60565b610690565b60405161011193929190610cba565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610ce2565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c60565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d18565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d31565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d60565b6020026020010151905087878381811061035d5761035d610d60565b905060200281019061036f9190610d8f565b6040810135958601959093506103886020850185610ce2565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dcd565b6040516103ba929190610e32565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d31565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d60565b90506020028101906105749190610e42565b92506105836020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dcd565b6040516105b4929190610e32565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d60565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d31565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d60565b6020026020010151905086868381811061074c5761074c610d60565b905060200281019061075e9190610e76565b925061076d6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dcd565b60405161079e929190610e32565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d31565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d60565b602002602001015190508686838181106108fb576108fb610d60565b905060200281019061090d9190610e42565b925061091c6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dcd565b60405161094d929190610e32565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b81811115610aff576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b84811015610bb1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9d81860183610ac7565b9a86019a9450505090830190600101610b4f565b5090979650505050505050565b602081526000610bd16020830184610b32565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c52577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c40868351610ac7565b95509284019290840190600101610c06565b509398975050505050505050565b600080600060408486031215610c7557600080fd5b83358015158114610c8557600080fd5b9250602084013567ffffffffffffffff811115610ca157600080fd5b610cad86828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd96060830184610b32565b95945050505050565b600060208284031215610cf457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bd157600080fd5b600060208284031215610d2a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dc357600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610e0257600080fd5b83018035915067ffffffffffffffff821115610e1d57600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dc357600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dc357600080fdfea2646970667358221220bb2b5c71a328032f97c676ae39a1ec2148d3e5d6f73d95e9b17910152d61f16264736f6c634300080c00331ca0edce47092c0f398cebf3ffc267f05c8e7076e3b89445e0fe50f6332273d4569ba01b0b9d000e19b24c5869b0fc3b22b0d6fa47cd63316875cbbd577d76e6fde086")
353 .into()).await.map_err(|e| ContractError::MiddlewareError {e})?.await?;
354 Ok(())
355}
356
357pub async fn get_chain_id_and_safe_nonce<M: Middleware>(safe: SafeSingleton<M>) -> Result<(U256, U256), HelperErrors> {
359 let provider = safe.client();
360 let mut multicall = Multicall::new(provider.clone(), Some(MULTICALL_ADDRESS))
361 .await
362 .expect("cannot create multicall");
363
364 multicall.add_get_chain_id().add_call(
365 safe.method::<_, U256>("nonce", ())
366 .map_err(|e| HelperErrors::MulticallError(e.to_string()))?,
367 false,
368 );
369
370 let result: (U256, U256) = multicall
371 .call()
372 .await
373 .map_err(|_| HelperErrors::MulticallError("failed in getting chain id and safe nonce".to_string()))?;
374
375 Ok(result)
376}
377
378pub async fn get_native_and_token_balances<M: Middleware>(
380 hopr_token: HoprToken<M>,
381 addresses: Vec<Address>,
382) -> Result<(Vec<U256>, Vec<U256>), MulticallError<M>> {
383 let provider = hopr_token.client();
384 let mut multicall = Multicall::new(provider.clone(), Some(MULTICALL_ADDRESS)).await?;
385
386 for address in addresses {
387 multicall.add_get_eth_balance(address, false).add_call(
388 hopr_token
389 .method::<_, U256>("balanceOf", address)
390 .map_err(|e| MulticallError::ContractError(ContractError::AbiError(e)))?,
391 false,
392 );
393 }
394
395 let response: Vec<U256> = multicall.call_array().await?;
396 let mut native_balance: Vec<U256> = vec![];
397 let mut token_balance: Vec<U256> = vec![];
398
399 for (i, &balance) in response.iter().enumerate() {
400 if i % 2 == 0 {
401 native_balance.push(balance);
402 } else {
403 token_balance.push(balance);
404 }
405 }
406
407 Ok((native_balance, token_balance))
408}
409
410pub async fn transfer_or_mint_tokens<M: Middleware>(
425 hopr_token: HoprToken<M>,
426 addresses: Vec<Address>,
427 amounts: Vec<U256>,
428) -> Result<U256, HelperErrors> {
429 let caller = hopr_token.client().default_sender().expect("client must have a sender");
430 let provider = hopr_token.client();
431 let mut multicall = Multicall::new(provider.clone(), Some(MULTICALL_ADDRESS))
432 .await
433 .expect("cannot create multicall");
434
435 assert_eq!(
437 addresses.len(),
438 amounts.len(),
439 "addresses and amounts are of different lengths in transfer_or_mint_tokens"
440 );
441
442 if addresses.is_empty() {
444 return Ok(U256::zero());
445 }
446
447 let total = amounts.iter().fold(U256::zero(), |acc, cur| acc.add(cur));
449 info!("total amount of HOPR tokens to be transferred {:?}", total.to_string());
450
451 let encoded_minter_role: [u8; 32] = keccak256(b"MINTER_ROLE");
453 multicall
454 .add_call(
455 hopr_token
456 .method::<_, U256>("balanceOf", caller)
457 .map_err(|e| HelperErrors::MulticallError(e.to_string()))?,
458 false,
459 )
460 .add_call(
461 hopr_token
462 .method::<_, bool>("hasRole", (encoded_minter_role, caller))
463 .map_err(|e| HelperErrors::MulticallError(e.to_string()))?,
464 false,
465 );
466 let result: (U256, bool) = multicall.call().await.map_err(|_| {
467 HelperErrors::MulticallError(
468 "failed in getting caller balance and its role in transfer_or_mint_tokens".to_string(),
469 )
470 })?;
471
472 if total.gt(&result.0) {
474 info!("caller does not have enough balance to transfer tokens to recipients.");
475 if result.1 {
476 info!("caller tries to mint tokens");
477 hopr_token
478 .mint(caller, total, Bytes::default(), Bytes::default())
479 .send()
480 .await
481 .unwrap_or_else(|_| panic!("failed to exeute a pending transaction"))
482 .await
483 .unwrap_or_else(|_| panic!("failed to resolve a transaction receipt"));
484 } else {
485 return Err(HelperErrors::NotAMinter);
486 }
487 }
488
489 if addresses.len() == 1 {
491 hopr_token
493 .transfer(addresses[0], amounts[0])
494 .send()
495 .await
496 .unwrap_or_else(|_| panic!("failed to exeute a pending transaction"))
497 .await
498 .unwrap_or_else(|_| panic!("failed to resolve a transaction receipt"));
499 } else {
500 hopr_token
504 .approve(MULTICALL_ADDRESS, total)
505 .send()
506 .await
507 .unwrap_or_else(|_| panic!("failed to exeute a pending transaction"))
508 .await
509 .unwrap_or_else(|_| panic!("failed to resolve a transaction receipt"));
510
511 for (i, address) in addresses.iter().enumerate() {
513 if amounts[i].gt(&U256::zero()) {
515 multicall.add_call(
516 hopr_token
517 .method::<_, bool>("transferFrom", (caller, *address, amounts[i]))
518 .map_err(|e| HelperErrors::MulticallError(e.to_string()))?,
519 false,
520 );
521 }
522 }
523
524 multicall
525 .send()
526 .await
527 .unwrap_or_else(|_| panic!("failed to exeute a pending transaction"))
528 .await
529 .unwrap_or_else(|_| panic!("failed to resolve a transaction receipt"));
530 }
531
532 Ok(total)
533}
534
535pub async fn transfer_native_tokens<M: Middleware>(
538 provider: Arc<M>,
539 addresses: Vec<Address>,
540 amounts: Vec<U256>,
541) -> Result<U256, HelperErrors> {
542 assert_eq!(
544 addresses.len(),
545 amounts.len(),
546 "addresses and amounts are of different lengths in transfer_native_tokens"
547 );
548 let total = amounts.iter().fold(U256::zero(), |acc, cur| acc.add(cur));
550 info!(
551 "total amount of native tokens to be transferred {:?}",
552 total.to_string()
553 );
554
555 let call3values: Vec<Call3Value> = addresses
556 .iter()
557 .enumerate()
558 .map(|(i, addr)| Call3Value {
559 target: *addr,
560 allow_failure: false,
561 value: amounts[i],
562 call_data: Bytes::default(),
563 })
564 .collect();
565 let mut tx = TypedTransaction::Eip1559(Eip1559TransactionRequest::new());
567 tx.set_to(MULTICALL_ADDRESS);
568 tx.set_data(Aggregate3ValueCall { calls: call3values }.encode().into());
569 tx.set_value(total);
570
571 provider
572 .send_transaction(tx, None)
573 .await
574 .map_err(|e| HelperErrors::MiddlewareError(e.to_string()))?
575 .await
576 .map_err(|e| HelperErrors::MiddlewareError(e.to_string()))?;
577
578 Ok(total)
579}
580
581pub async fn get_registered_safes_for_nodes_on_network_registry<M: Middleware>(
583 network_registry: HoprNetworkRegistry<M>,
584 node_addresses: Vec<H160>,
585) -> Result<Vec<H160>, MulticallError<M>> {
586 let provider = network_registry.client();
587 let mut multicall = Multicall::new(provider.clone(), Some(MULTICALL_ADDRESS))
588 .await
589 .expect("cannot create multicall");
590
591 for node in node_addresses {
592 multicall.add_call(
593 network_registry
594 .method::<_, Address>("nodeRegisterdToAccount", node)
595 .map_err(|e| MulticallError::ContractError(ContractError::AbiError(e)))?,
596 false,
597 );
598 }
599
600 let response: Vec<Address> = multicall.call_array().await?;
601
602 Ok(response)
603}
604
605pub async fn register_safes_and_nodes_on_network_registry<M: Middleware>(
613 network_registry: HoprNetworkRegistry<M>,
614 safe_addresses: Vec<H160>,
615 node_addresses: Vec<H160>,
616) -> Result<(usize, usize), HelperErrors> {
617 assert_eq!(
618 safe_addresses.len(),
619 node_addresses.len(),
620 "unmatched lengths of safes and nodes"
621 );
622
623 let registered_safes =
625 get_registered_safes_for_nodes_on_network_registry(network_registry.clone(), node_addresses.clone())
626 .await
627 .map_err(|e| HelperErrors::MulticallError(e.to_string()))?;
628
629 let mut nodes_to_remove: Vec<H160> = Vec::new();
630 let mut safes_to_add: Vec<H160> = Vec::new();
631 let mut nodes_to_add: Vec<H160> = Vec::new();
632
633 for (i, registered_safe) in registered_safes.iter().enumerate() {
634 if registered_safe.eq(&H160::zero()) {
635 safes_to_add.push(safe_addresses[i]);
637 nodes_to_add.push(node_addresses[i]);
638 } else if registered_safe.ne(&safe_addresses[i]) {
639 nodes_to_remove.push(node_addresses[i]);
641 safes_to_add.push(safe_addresses[i]);
642 nodes_to_add.push(node_addresses[i]);
643 } else {
644 }
646 }
647
648 if !nodes_to_remove.is_empty() {
649 network_registry
651 .manager_deregister(nodes_to_remove.clone())
652 .send()
653 .await
654 .unwrap()
655 .await
656 .unwrap();
657 }
658
659 network_registry
660 .manager_register(safes_to_add.clone(), nodes_to_add.clone())
661 .send()
662 .await
663 .unwrap_or_else(|_| panic!("failed to exeute a pending transaction"))
664 .await
665 .unwrap_or_else(|_| panic!("failed to resolve a transaction receipt"));
666
667 network_registry
669 .manager_force_sync(safes_to_add.clone(), vec![true; safes_to_add.len()])
670 .send()
671 .await
672 .unwrap_or_else(|_| panic!("failed to exeute a pending transaction"))
673 .await
674 .unwrap_or_else(|_| panic!("failed to resolve a transaction receipt"));
675
676 Ok((nodes_to_remove.len(), nodes_to_add.len()))
677}
678
679pub async fn deregister_nodes_from_network_registry<M: Middleware>(
684 network_registry: HoprNetworkRegistry<M>,
685 node_addresses: Vec<H160>,
686) -> Result<usize, HelperErrors> {
687 let registered_safes =
689 get_registered_safes_for_nodes_on_network_registry(network_registry.clone(), node_addresses.clone())
690 .await
691 .map_err(|e| HelperErrors::MulticallError(e.to_string()))?;
692
693 let mut nodes_to_remove: Vec<H160> = Vec::new();
694
695 for (i, registered_safe) in registered_safes.iter().enumerate() {
696 if registered_safe.ne(&H160::zero()) {
697 nodes_to_remove.push(node_addresses[i]);
699 }
700 }
701
702 if !nodes_to_remove.is_empty() {
703 network_registry
705 .manager_deregister(nodes_to_remove.clone())
706 .send()
707 .await
708 .unwrap_or_else(|_| panic!("failed to exeute a pending transaction"))
709 .await
710 .unwrap_or_else(|_| panic!("failed to resolve a transaction receipt"));
711 }
712 Ok(nodes_to_remove.len())
713}
714
715pub async fn force_sync_safes_on_network_registry<M: Middleware>(
717 network_registry: HoprNetworkRegistry<M>,
718 safe_addresses: Vec<H160>,
719 eligibilities: Vec<bool>,
720) -> Result<(), HelperErrors> {
721 assert_eq!(
722 safe_addresses.len(),
723 eligibilities.len(),
724 "unmatched lengths of safes and eligibilities"
725 );
726
727 network_registry
729 .manager_force_sync(safe_addresses, eligibilities)
730 .send()
731 .await
732 .unwrap_or_else(|_| panic!("failed to exeute a pending transaction"))
733 .await
734 .unwrap_or_else(|_| panic!("failed to resolve a transaction receipt"));
735
736 Ok(())
737}
738
739pub fn predict_module_address(
741 caller: Address,
742 nonce: [u8; 32],
743 factory_address: Address,
744 implementation_address: Address,
745) -> Result<Address, HelperErrors> {
746 let module_salt = keccak256(ethers::abi::encode_packed(&[
747 ethers::abi::Token::Address(caller),
748 ethers::abi::Token::Bytes(nonce.into()),
749 ])?);
750 debug!("module_salt {:?}", module_salt);
751
752 let module_creation_code = ethers::abi::encode_packed(&[
753 ethers::abi::Token::Bytes(hex!("3d602d80600a3d3981f3363d3d373d3d3d363d73").to_vec()),
754 ethers::abi::Token::Address(implementation_address),
755 ethers::abi::Token::Bytes(hex!("5af43d82803e903d91602b57fd5bf3").to_vec()),
756 ])?;
757 debug!("module_creation_code {:?}", module_creation_code);
758
759 let predict_module_addr = get_create2_address(factory_address, module_salt, module_creation_code);
760 debug!("predict_module_addr {:?}", predict_module_addr);
761
762 Ok(predict_module_addr)
763}
764
765pub fn predict_safe_address(
767 stake_factory: Address,
768 admins: Vec<Address>,
769 nonce: [u8; 32],
770 safe_fallback: Address,
771 safe_singleton: Address,
772 safe_factory: Address,
773) -> Result<Address, HelperErrors> {
774 let mut temp_admins = admins.clone();
775 temp_admins[0] = stake_factory;
776
777 let initializer = SetupCall(
778 temp_admins,
779 U256::one(),
780 Address::zero(),
781 Bytes::from(hex!("00")),
782 safe_fallback,
783 Address::zero(),
784 U256::zero(),
785 Address::zero(),
786 )
787 .encode();
788
789 let safe_salt = get_salt_from_salt_nonce(initializer, nonce)?;
790 debug!("safe_salt {:?}", hex::encode(safe_salt));
791
792 let predict_safe_addr = deploy_proxy(safe_singleton, safe_salt, safe_factory)?;
793 debug!("predict_safe_addr {:?}", hex::encode(predict_safe_addr));
794
795 Ok(predict_safe_addr)
796}
797
798fn get_salt_from_salt_nonce(initializer: Vec<u8>, salt_nonce: [u8; 32]) -> Result<[u8; 32], HelperErrors> {
800 let hashed_initializer = keccak256(initializer);
801
802 Ok(keccak256(ethers::abi::encode_packed(&[
803 ethers::abi::Token::Bytes(hashed_initializer.into()),
804 ethers::abi::Token::Bytes(salt_nonce.into()),
805 ])?))
806}
807
808fn deploy_proxy(safe_singleton: Address, safe_salt: [u8; 32], safe_factory: Address) -> Result<Address, HelperErrors> {
810 let safe_creation_code = ethers::abi::encode_packed(&[
811 ethers::abi::Token::Bytes(hex!("608060405234801561001057600080fd5b506040516101e63803806101e68339818101604052602081101561003357600080fd5b8101908080519060200190929190505050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156100ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806101c46022913960400191505060405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505060ab806101196000396000f3fe608060405273ffffffffffffffffffffffffffffffffffffffff600054167fa619486e0000000000000000000000000000000000000000000000000000000060003514156050578060005260206000f35b3660008037600080366000845af43d6000803e60008114156070573d6000fd5b3d6000f3fea264697066735822122003d1488ee65e08fa41e58e888a9865554c535f2c77126a82cb4c0f917f31441364736f6c63430007060033496e76616c69642073696e676c65746f6e20616464726573732070726f7669646564").to_vec()),
812 ethers::abi::Token::Bytes(hex!("000000000000000000000000").to_vec()), ethers::abi::Token::Address(safe_singleton),
814 ])?;
815 debug!("safe_creation_code {:?}", hex::encode(safe_creation_code.clone()));
816
817 let predict_safe_addr = get_create2_address(safe_factory, safe_salt, safe_creation_code);
818 debug!("predict_safe_addr {:?}", hex::encode(predict_safe_addr));
819
820 Ok(predict_safe_addr)
821}
822
823pub fn prepare_safe_tx_from_owner_contract<M: Middleware>(
826 mut multicall: Multicall<M>,
827 deployed_safe: SafeSingleton<M>,
828 target: Address,
829 refund_address: Address,
830 tx_payload: Vec<u8>,
831) -> Result<Multicall<M>, HelperErrors> {
832 let approval_hash_sig = ethers::abi::encode_packed(&[
833 ethers::abi::Token::Bytes(hex!("000000000000000000000000").to_vec()),
834 ethers::abi::Token::Address(MULTICALL_ADDRESS),
835 ethers::abi::Token::Bytes(hex!("0000000000000000000000000000000000000000000000000000000000000000").to_vec()),
836 ethers::abi::Token::Bytes(hex!("01").to_vec()),
837 ])?;
838
839 multicall.add_call(
840 deployed_safe
841 .method::<_, bool>(
842 "execTransaction",
843 (
844 target,
845 U256::zero(),
846 Bytes::from(tx_payload),
847 0u8,
848 U256::zero(),
849 U256::zero(),
850 U256::zero(),
851 Address::zero(),
852 refund_address,
853 Bytes::from(approval_hash_sig),
854 ),
855 )
856 .map_err(|e| HelperErrors::MulticallError(e.to_string()))?,
857 false,
858 );
859 Ok(multicall)
860}
861
862#[allow(clippy::too_many_arguments)]
874pub async fn deploy_safe_module_with_targets_and_nodes<M: Middleware>(
875 hopr_node_stake_factory: HoprNodeStakeFactory<M>,
876 hopr_token_address: Address,
877 hopr_channels_address: Address,
878 hopr_module_implementation_address: Address,
879 hopr_announcement_address: Address,
880 allowance: U256,
881 node_addresses: Option<Vec<Address>>,
882 admins: Vec<Address>,
883 threshold: U256,
884) -> Result<(SafeSingleton<M>, HoprNodeManagementModule<M>), HelperErrors> {
885 let caller = hopr_node_stake_factory
886 .client()
887 .default_sender()
888 .expect("client must have a sender");
889 let provider = hopr_node_stake_factory.client();
890 let mut multicall = Multicall::new(provider.clone(), Some(MULTICALL_ADDRESS))
891 .await
892 .expect("cannot create multicall");
893
894 assert!(!admins.is_empty(), "safe must have valid admin(s)");
896 assert!(
897 threshold.ge(&U256::one()) && threshold.le(&admins.len().into()),
898 "safe threshold must be at least one and not greater than the total number of admins"
899 );
900 assert!(
901 !admins.contains(&MULTICALL_ADDRESS),
902 "multicall contract cannot be an admin"
903 );
904
905 let mut temporary_admins: Vec<Address> = admins.clone();
907 temporary_admins.insert(0, MULTICALL_ADDRESS);
908 info!(
909 "temporary_admins expends from admin from {:?} addresses to {:?}",
910 admins.len(),
911 temporary_admins.len()
912 );
913
914 let default_target: [u8; 32] =
916 U256::from_str(format!("{:?}{}", hopr_channels_address, DEFAULT_CAPABILITY_PERMISSIONS).as_str())
917 .unwrap()
918 .into();
919 debug!("default target {:?}", default_target);
920 let curr_nonce = provider
922 .get_transaction_count(caller, Some(ethers::types::BlockNumber::Pending.into()))
923 .await
924 .map_err(|e| HelperErrors::MiddlewareError(e.to_string()))?;
925 let nonce = keccak256(ethers::abi::encode_packed(&[
926 ethers::abi::Token::Address(caller),
927 ethers::abi::Token::Uint(curr_nonce),
928 ])?);
929
930 debug!("curr_nonce {} and nonce {:?}", curr_nonce, nonce);
931
932 let module_address = predict_module_address(
934 MULTICALL_ADDRESS,
935 nonce,
936 hopr_node_stake_factory.address(),
937 hopr_module_implementation_address,
938 )?;
939 info!("predicted module address {:?}", module_address);
940
941 let safe_address = predict_safe_address(
942 hopr_node_stake_factory.address(),
943 temporary_admins.clone(),
944 nonce,
945 Address::from_str(SAFE_COMPATIBILITYFALLBACKHANDLER_ADDRESS).unwrap(),
946 Address::from_str(SAFE_SAFE_ADDRESS).unwrap(),
947 Address::from_str(SAFE_SAFEPROXYFACTORY_ADDRESS).unwrap(),
948 )?;
949 info!("predicted safe address {:?}", safe_address);
950
951 let deployed_module = HoprNodeManagementModule::new(module_address, provider.clone());
952 let deployed_safe = SafeSingleton::new(safe_address, provider.clone());
953
954 multicall.add_call(
956 hopr_node_stake_factory
957 .method::<_, (Address, Address)>(
958 "clone",
959 (
960 hopr_module_implementation_address,
961 temporary_admins,
962 U256::from(nonce),
963 default_target,
964 ),
965 )
966 .map_err(|e| HelperErrors::MulticallError(e.to_string()))?,
967 false,
968 );
969 info!("Safe and module have been deployed");
970
971 let announcement_target =
973 U256::from_str(format!("{:?}{}", hopr_announcement_address, DEFAULT_ANNOUNCEMENT_PERMISSIONS).as_str())
974 .unwrap();
975 let scope_announcement_tx_payload = ScopeTargetTokenCall {
976 default_target: announcement_target,
977 }
978 .encode();
979
980 multicall = prepare_safe_tx_from_owner_contract(
981 multicall.clone(),
982 deployed_safe.clone(),
983 module_address,
984 caller,
985 scope_announcement_tx_payload,
986 )?;
987 info!("Announcement smart contract has been scoped as target");
988
989 let approve_tx_payload = ApproveCall {
991 spender: hopr_channels_address,
992 value: allowance,
993 }
994 .encode();
995
996 multicall = prepare_safe_tx_from_owner_contract(
997 multicall.clone(),
998 deployed_safe.clone(),
999 hopr_token_address,
1000 caller,
1001 approve_tx_payload,
1002 )?;
1003 info!("Token transfer allowance has been set for channel contract");
1004
1005 if let Some(nodes) = node_addresses {
1007 for node in nodes {
1008 let node_target = U256::from_str(format!("{:?}{}", node, DEFAULT_NODE_PERMISSIONS).as_str()).unwrap();
1009 let include_node_tx_payload = IncludeNodeCall {
1010 node_default_target: node_target,
1011 }
1012 .encode();
1013 multicall = prepare_safe_tx_from_owner_contract(
1014 multicall.clone(),
1015 deployed_safe.clone(),
1016 module_address,
1017 caller,
1018 include_node_tx_payload,
1019 )?;
1020 }
1021 info!("Nodes have been included in the module");
1022 } else {
1023 info!("No node has been provided. Skip node inclusion action");
1024 }
1025
1026 let remove_owner_tx_payload = RemoveOwnerCall {
1028 prev_owner: Address::from_str(SENTINEL_OWNERS).unwrap(),
1029 owner: MULTICALL_ADDRESS,
1030 threshold,
1031 }
1032 .encode();
1033
1034 multicall = prepare_safe_tx_from_owner_contract(
1035 multicall.clone(),
1036 deployed_safe.clone(),
1037 safe_address,
1038 caller,
1039 remove_owner_tx_payload,
1040 )?;
1041 info!("Admins and threshold have been set to provided values");
1042
1043 let receipt = multicall
1044 .send()
1045 .await
1046 .map_err(|e| HelperErrors::MulticallError(e.to_string()))?
1047 .await
1048 .unwrap()
1049 .unwrap();
1050 info!("multicall receipt {:?}", receipt.transaction_hash);
1051
1052 Ok((deployed_safe, deployed_module))
1053}
1054
1055pub async fn get_registered_safes_for_nodes_on_node_safe_registry<M: Middleware>(
1057 node_safe_registry: HoprNodeSafeRegistry<M>,
1058 node_addresses: Vec<H160>,
1059) -> Result<Vec<H160>, MulticallError<M>> {
1060 let provider = node_safe_registry.client();
1061 let mut multicall = Multicall::new(provider.clone(), Some(MULTICALL_ADDRESS))
1062 .await
1063 .expect("cannot create multicall");
1064
1065 for node in node_addresses {
1066 multicall.add_call(
1067 node_safe_registry
1068 .method::<_, Address>("nodeToSafe", node)
1069 .map_err(|e| MulticallError::ContractError(ContractError::AbiError(e)))?,
1070 false,
1071 );
1072 }
1073
1074 let response: Vec<Address> = multicall.call_array().await?;
1075
1076 Ok(response)
1077}
1078
1079pub async fn deregister_nodes_from_node_safe_registry_and_remove_from_module<M: Middleware>(
1086 node_safe_registry: HoprNodeSafeRegistry<M>,
1087 node_addresses: Vec<H160>,
1088 module_addresses: Vec<H160>,
1089 owner_chain_key: ChainKeypair,
1090) -> Result<u32, HelperErrors> {
1091 let provider = node_safe_registry.client();
1092 let registered_safes =
1094 get_registered_safes_for_nodes_on_node_safe_registry(node_safe_registry.clone(), node_addresses.clone())
1095 .await
1096 .unwrap();
1097
1098 let mut nodes_to_remove_counter = 0u32;
1099
1100 for (i, registered_safe) in registered_safes.iter().enumerate() {
1101 if registered_safe.ne(&H160::zero()) {
1102 let safe = SafeSingleton::new(registered_safe.to_owned(), provider.clone());
1104 nodes_to_remove_counter += 1;
1106 let (chain_id, safe_nonce) = get_chain_id_and_safe_nonce(safe.clone()).await?;
1108
1109 let multisend_txns: Vec<MultisendTransaction> = vec![
1111 MultisendTransaction {
1112 encoded_data: DeregisterNodeBySafeCall {
1114 node_addr: node_addresses[i],
1115 }
1116 .encode()
1117 .into(),
1118 tx_operation: SafeTxOperation::Call,
1119 to: node_safe_registry.address(),
1120 value: U256::zero(),
1121 },
1122 MultisendTransaction {
1123 encoded_data: RemoveNodeCall {
1125 node_address: node_addresses[i],
1126 }
1127 .encode()
1128 .into(),
1129 tx_operation: SafeTxOperation::Call,
1130 to: module_addresses[i],
1131 value: U256::zero(),
1132 },
1133 ];
1134
1135 send_multisend_safe_transaction_with_threshold_one(
1137 safe,
1138 owner_chain_key.clone(),
1139 H160::from_str(SAFE_MULTISEND_ADDRESS).unwrap(),
1140 multisend_txns,
1141 chain_id,
1142 safe_nonce,
1143 )
1144 .await?;
1145 }
1146 }
1147
1148 Ok(nodes_to_remove_counter)
1149}
1150
1151pub async fn include_nodes_to_module<M: Middleware>(
1153 safe: SafeSingleton<M>,
1154 node_addresses: Vec<H160>,
1155 module_address: H160,
1156 owner_chain_key: ChainKeypair,
1157) -> Result<(), HelperErrors> {
1158 let (chain_id, safe_nonce) = get_chain_id_and_safe_nonce(safe.clone()).await?;
1160
1161 let mut multisend_txns: Vec<MultisendTransaction> = Vec::new();
1163 for node_address in node_addresses {
1164 let node_target = U256::from_str(format!("{:?}{}", node_address, DEFAULT_NODE_PERMISSIONS).as_str()).unwrap();
1165 multisend_txns.push(MultisendTransaction {
1166 encoded_data: IncludeNodeCall {
1167 node_default_target: node_target,
1168 }
1169 .encode()
1170 .into(),
1171 tx_operation: SafeTxOperation::Call,
1172 to: module_address,
1173 value: U256::zero(),
1174 });
1175 }
1176
1177 send_multisend_safe_transaction_with_threshold_one(
1179 safe,
1180 owner_chain_key.clone(),
1181 H160::from_str(SAFE_MULTISEND_ADDRESS).unwrap(),
1182 multisend_txns,
1183 chain_id,
1184 safe_nonce,
1185 )
1186 .await?;
1187
1188 Ok(())
1189}
1190
1191pub async fn migrate_nodes<M: Middleware>(
1196 safe: SafeSingleton<M>,
1197 module_addresses: Address,
1198 channels_address: Address,
1199 token_address: Address,
1200 announcement_address: Address,
1201 allowance: U256,
1202 owner_chain_key: ChainKeypair,
1203) -> Result<(), HelperErrors> {
1204 let (chain_id, safe_nonce) = get_chain_id_and_safe_nonce(safe.clone()).await?;
1205
1206 let mut multisend_txns: Vec<MultisendTransaction> = Vec::new();
1207
1208 let default_target =
1210 U256::from_str(format!("{:?}{}", channels_address, DEFAULT_CAPABILITY_PERMISSIONS).as_str()).unwrap();
1211 debug!("default target {:?}", default_target);
1212
1213 multisend_txns.push(MultisendTransaction {
1214 encoded_data: AddChannelsAndTokenTargetCall { default_target }.encode().into(),
1216 tx_operation: SafeTxOperation::Call,
1217 to: module_addresses,
1218 value: U256::zero(),
1219 });
1220
1221 let announcement_target =
1223 U256::from_str(format!("{:?}{}", announcement_address, DEFAULT_ANNOUNCEMENT_PERMISSIONS).as_str()).unwrap();
1224
1225 multisend_txns.push(MultisendTransaction {
1226 encoded_data: ScopeTargetTokenCall {
1228 default_target: announcement_target,
1229 }
1230 .encode()
1231 .into(),
1232 tx_operation: SafeTxOperation::Call,
1233 to: module_addresses,
1234 value: U256::zero(),
1235 });
1236
1237 multisend_txns.push(MultisendTransaction {
1239 encoded_data: ApproveCall {
1241 spender: channels_address,
1242 value: allowance,
1243 }
1244 .encode()
1245 .into(),
1246 tx_operation: SafeTxOperation::Call,
1247 to: token_address,
1248 value: U256::zero(),
1249 });
1250
1251 send_multisend_safe_transaction_with_threshold_one(
1253 safe,
1254 owner_chain_key.clone(),
1255 H160::from_str(SAFE_MULTISEND_ADDRESS).unwrap(),
1256 multisend_txns,
1257 chain_id,
1258 safe_nonce,
1259 )
1260 .await?;
1261
1262 Ok(())
1263}
1264
1265pub async fn debug_node_safe_module_setup_on_balance_and_registries<M: Middleware>(
1270 network_registry: HoprNetworkRegistry<M>,
1271 node_safe_registry: HoprNodeSafeRegistry<M>,
1272 node_address: &H160,
1273) -> Result<Address, MulticallError<M>> {
1274 let provider = network_registry.client();
1275 let mut multicall = Multicall::new(provider.clone(), Some(MULTICALL_ADDRESS))
1276 .await
1277 .expect("cannot create multicall");
1278
1279 info!("checking for node {:?}", node_address);
1280 multicall
1281 .add_get_eth_balance(*node_address, false)
1283 .add_call(
1285 network_registry
1286 .method::<_, Address>("nodeRegisterdToAccount", *node_address)
1287 .map_err(|e| MulticallError::ContractError(ContractError::AbiError(e)))?,
1288 false,
1289 )
1290 .add_call(
1292 node_safe_registry
1293 .method::<_, Address>("nodeToSafe", *node_address)
1294 .map_err(|e| MulticallError::ContractError(ContractError::AbiError(e)))?,
1295 false,
1296 );
1297
1298 let (node_native_balance, safe_in_network_registry, safe_in_nodesafe_registry): (U256, Address, Address) =
1299 multicall.call().await?;
1300
1301 info!(
1302 "node does{:?} have xDAI balance {:?}",
1303 if node_native_balance.ge(&U256::from(
1304 parse_units(0.1, "ether").unwrap_or_else(|_| panic!("cannot parse node_native_balance"))
1305 )) {
1306 ""
1307 } else {
1308 " NOT"
1309 },
1310 format_units(node_native_balance, "ether").unwrap_or("Unknown balance".into())
1311 );
1312
1313 if safe_in_network_registry.eq(&H160::zero()) {
1314 info!("Please register the node to the network registry");
1315 } else {
1316 info!("safe in network registry {:?}", safe_in_network_registry);
1317 }
1318
1319 if safe_in_nodesafe_registry.eq(&H160::zero()) {
1320 info!("Please start the node. It will auto-register to node-safe registry");
1321 } else {
1322 info!("safe in node-safe registry {:?}", safe_in_nodesafe_registry);
1323 }
1324 info!(
1325 "Safes in both registies should match: {:?}",
1326 safe_in_network_registry.eq(&safe_in_nodesafe_registry)
1327 );
1328
1329 Ok(safe_in_network_registry)
1330}
1331
1332pub async fn debug_node_safe_module_setup_main<M: Middleware>(
1340 hopr_token: HoprToken<M>,
1341 module_address: &H160,
1342 node_address: &H160,
1343 safe_address: &H160,
1344 channel_address: &H160,
1345 announce_address: &H160,
1346) -> Result<(), MulticallError<M>> {
1347 let provider = hopr_token.client();
1348 let mut multicall = Multicall::new(provider.clone(), Some(MULTICALL_ADDRESS))
1349 .await
1350 .expect("cannot create multicall");
1351
1352 let safe = SafeSingleton::new(safe_address.to_owned(), provider.clone());
1353 let module = ModuleSingleton::new(module_address.to_owned(), provider.clone());
1354
1355 info!("checking for safe {:?} module {:?}", safe_address, module_address);
1356 multicall
1357 .add_call(
1359 safe.method::<_, Vec<Address>>("getOwners", ())
1360 .map_err(|e| MulticallError::ContractError(ContractError::AbiError(e)))?,
1361 false,
1362 )
1363 .add_call(
1365 hopr_token
1366 .method::<_, U256>("balanceOf", *safe_address)
1367 .map_err(|e| MulticallError::ContractError(ContractError::AbiError(e)))?,
1368 false,
1369 )
1370 .add_call(
1372 hopr_token
1373 .method::<_, U256>("allowance", (*safe_address, *channel_address))
1374 .map_err(|e| MulticallError::ContractError(ContractError::AbiError(e)))?,
1375 false,
1376 )
1377 .add_call(
1379 safe.method::<_, bool>("isModuleEnabled", *module_address)
1380 .map_err(|e| MulticallError::ContractError(ContractError::AbiError(e)))?,
1381 false,
1382 )
1383 .add_call(
1385 module
1386 .method::<_, bool>("isNode", *node_address)
1387 .map_err(|e| MulticallError::ContractError(ContractError::AbiError(e)))?,
1388 false,
1389 )
1390 .add_call(
1392 module
1393 .method::<_, Vec<U256>>("getTargets", ())
1394 .map_err(|e| MulticallError::ContractError(ContractError::AbiError(e)))?,
1395 false,
1396 )
1397 .add_call(
1399 module
1400 .method::<_, Address>("owner", ())
1401 .map_err(|e| MulticallError::ContractError(ContractError::AbiError(e)))?,
1402 false,
1403 );
1404
1405 let (
1406 safe_owners,
1407 safe_wxhopr_balance,
1408 safe_wxhopr_allownace,
1409 is_module_enabled,
1410 is_node_included,
1411 module_targets,
1412 module_owner,
1413 ): (Vec<Address>, U256, U256, bool, bool, Vec<U256>, Address) = multicall.call().await?;
1414
1415 info!("safe has owners: {:?}", safe_owners);
1416 info!(
1417 "safe has wxHOPR balance: {:?}",
1418 format_units(safe_wxhopr_balance, "ether").unwrap_or("Unknown balance".into())
1419 );
1420 info!(
1421 "safe has wxHOPR allowance: {:?}",
1422 format_units(safe_wxhopr_allownace, "ether").unwrap_or("Unknown balance".into())
1423 );
1424 info!("module is enabled: {:?}", is_module_enabled);
1425 info!("node is included in the module: {:?}", is_node_included);
1426 info!("module has targets:");
1427 for target in module_targets {
1428 let target_address = format!("{:#x}", target);
1429 let has_channels = target_address.contains(&format!("{:#x}", channel_address));
1430 let has_announcement = target_address.contains(&format!("{:#x}", announce_address));
1431 info!(
1433 "Target {:?} has channels {:?} has announcement {:?}",
1434 target_address, has_channels, has_announcement
1435 );
1436 }
1437
1438 info!(
1439 "module owner: {:?} same as safe address: {:?}",
1440 module_owner,
1441 module_owner.eq(safe_address)
1442 );
1443 Ok(())
1444}
1445
1446#[cfg(test)]
1447mod tests {
1448 use super::*;
1449
1450 use ethers::abi::AbiDecode;
1451 use ethers::types::TransactionRequest;
1452 use std::vec;
1453
1454 use hopr_bindings::{hopr_announcements::HoprAnnouncements, hopr_channels::HoprChannels};
1455 use hopr_chain_rpc::client::{create_rpc_client_to_anvil, surf_client::SurfRequestor};
1456 use hopr_chain_types::ContractInstances;
1457 use hopr_crypto_types::keypairs::{ChainKeypair, Keypair};
1458 use hopr_primitive_types::prelude::BytesRepresentable;
1459 use hopr_primitive_types::primitives::Address;
1460
1461 use crate::utils::{NEW_HOPR_NODE_STAKE_MODULE_TOPIC, NEW_HOPR_NODE_STAKE_SAFE_TOPIC};
1462
1463 fn get_random_address_for_testing() -> Address {
1464 Address::new(&hopr_crypto_random::random_bytes::<{ Address::SIZE }>())
1466 }
1467
1468 async fn deploy_safe_suites<M: Middleware>(provider: Arc<M>) -> Result<(), ContractError<M>> {
1469 let code = provider
1471 .get_code(
1472 "0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7"
1473 .parse::<ethers::types::Address>()
1474 .unwrap(),
1475 None,
1476 )
1477 .await
1478 .map_err(|e| ContractError::MiddlewareError { e })?;
1479
1480 if code.len() == 0 {
1482 debug!("deploying safe code");
1483 let safe_diamond_proxy_address = {
1485 let mut tx = Eip1559TransactionRequest::new();
1487 tx = tx.to(H160::from_str("E1CB04A0fA36DdD16a06ea828007E35e1a3cBC37").unwrap());
1488 tx = tx.value(10000000000000000u128);
1489
1490 provider
1491 .send_transaction(tx, None)
1492 .await
1493 .map_err(|e| ContractError::MiddlewareError { e })?
1494 .await?;
1495
1496 let tx = provider.send_raw_transaction(
1497 hex!("f8a78085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf382f4f5a00dc4d1d21b308094a30f5f93da35e4d72e99115378f135f2295bea47301a3165a0636b822daad40aa8c52dd5132f378c0c0e6d83b4898228c7e21c84e631a0b891")
1498 .into()).await.map_err(|e| ContractError::MiddlewareError {e})?.await?.unwrap();
1499 tx.contract_address.unwrap()
1500 };
1501 debug!("Safe diamond proxy singleton {:?}", safe_diamond_proxy_address);
1502
1503 let _tx_safe_proxy_factory = TransactionRequest::new().to(safe_diamond_proxy_address).data::<Bytes>(
1506 hex!("0000000000000000000000000000000000000000000000000000000000000000608060405234801561001057600080fd5b50610bee806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80631688f0b91461005c5780633408e4701461016b57806353e5d93514610189578063d18af54d1461020c578063ec9e80bb1461033b575b600080fd5b61013f6004803603606081101561007257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001906401000000008111156100af57600080fd5b8201836020820111156100c157600080fd5b803590602001918460018302840111640100000000831117156100e357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019092919050505061044a565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101736104fe565b6040518082815260200191505060405180910390f35b61019161050b565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101d15780820151818401526020810190506101b6565b50505050905090810190601f1680156101fe5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61030f6004803603608081101561022257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561025f57600080fd5b82018360208201111561027157600080fd5b8035906020019184600183028401116401000000008311171561029357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610536565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61041e6004803603606081101561035157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561038e57600080fd5b8201836020820111156103a057600080fd5b803590602001918460018302840111640100000000831117156103c257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803590602001909291905050506106e5565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008083805190602001208360405160200180838152602001828152602001925050506040516020818303038152906040528051906020012090506104908585836107a8565b91508173ffffffffffffffffffffffffffffffffffffffff167f4f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e23586604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a2509392505050565b6000804690508091505090565b60606040518060200161051d906109c5565b6020820181038252601f19601f82011660405250905090565b6000808383604051602001808381526020018273ffffffffffffffffffffffffffffffffffffffff1660601b8152601401925050506040516020818303038152906040528051906020012060001c905061059186868361044a565b9150600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146106dc578273ffffffffffffffffffffffffffffffffffffffff16631e52b518838888886040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015610674578082015181840152602081019050610659565b50505050905090810190601f1680156106a15780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b1580156106c357600080fd5b505af11580156106d7573d6000803e3d6000fd5b505050505b50949350505050565b6000808380519060200120836106f96104fe565b60405160200180848152602001838152602001828152602001935050505060405160208183030381529060405280519060200120905061073a8585836107a8565b91508173ffffffffffffffffffffffffffffffffffffffff167f4f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e23586604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a2509392505050565b60006107b3846109b2565b610825576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f53696e676c65746f6e20636f6e7472616374206e6f74206465706c6f7965640081525060200191505060405180910390fd5b600060405180602001610837906109c5565b6020820181038252601f19601f820116604052508573ffffffffffffffffffffffffffffffffffffffff166040516020018083805190602001908083835b602083106108985780518252602082019150602081019050602083039250610875565b6001836020036101000a038019825116818451168082178552505050505050905001828152602001925050506040516020818303038152906040529050828151826020016000f59150600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610984576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f437265617465322063616c6c206661696c65640000000000000000000000000081525060200191505060405180910390fd5b6000845111156109aa5760008060008651602088016000875af114156109a957600080fd5b5b509392505050565b600080823b905060008111915050919050565b6101e6806109d38339019056fe608060405234801561001057600080fd5b506040516101e63803806101e68339818101604052602081101561003357600080fd5b8101908080519060200190929190505050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156100ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806101c46022913960400191505060405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505060ab806101196000396000f3fe608060405273ffffffffffffffffffffffffffffffffffffffff600054167fa619486e0000000000000000000000000000000000000000000000000000000060003514156050578060005260206000f35b3660008037600080366000845af43d6000803e60008114156070573d6000fd5b3d6000f3fea264697066735822122003d1488ee65e08fa41e58e888a9865554c535f2c77126a82cb4c0f917f31441364736f6c63430007060033496e76616c69642073696e676c65746f6e20616464726573732070726f7669646564a26469706673582212200fd975ca8e62d9bf08aa3d09c74b9bdc9d7acba7621835be4187989ddd0e54b164736f6c63430007060033").into()
1507 );
1508 let _tx_safe_compatibility_fallback_handler = TransactionRequest::new().to(safe_diamond_proxy_address).data::<Bytes>(
1510 hex!("0000000000000000000000000000000000000000000000000000000000000000608060405234801561001057600080fd5b5061073f806100206000396000f3fe608060405234801561001057600080fd5b50600436106100565760003560e01c806223de291461005b57806301ffc9a714610193578063150b7a02146101f6578063bc197c81146102ec578063f23a6e6114610482575b600080fd5b610191600480360360c081101561007157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156100f857600080fd5b82018360208201111561010a57600080fd5b8035906020019184600183028401116401000000008311171561012c57600080fd5b90919293919293908035906020019064010000000081111561014d57600080fd5b82018360208201111561015f57600080fd5b8035906020019184600183028401116401000000008311171561018157600080fd5b9091929391929390505050610582565b005b6101de600480360360208110156101a957600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061058c565b60405180821515815260200191505060405180910390f35b6102b76004803603608081101561020c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561027357600080fd5b82018360208201111561028557600080fd5b803590602001918460018302840111640100000000831117156102a757600080fd5b90919293919293905050506106c6565b60405180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b61044d600480360360a081101561030257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561035f57600080fd5b82018360208201111561037157600080fd5b8035906020019184602083028401116401000000008311171561039357600080fd5b9091929391929390803590602001906401000000008111156103b457600080fd5b8201836020820111156103c657600080fd5b803590602001918460208302840111640100000000831117156103e857600080fd5b90919293919293908035906020019064010000000081111561040957600080fd5b82018360208201111561041b57600080fd5b8035906020019184600183028401116401000000008311171561043d57600080fd5b90919293919293905050506106db565b60405180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b61054d600480360360a081101561049857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291908035906020019064010000000081111561050957600080fd5b82018360208201111561051b57600080fd5b8035906020019184600183028401116401000000008311171561053d57600080fd5b90919293919293905050506106f3565b60405180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b5050505050505050565b60007f4e2312e0000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061065757507f150b7a02000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806106bf57507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b600063150b7a0260e01b905095945050505050565b600063bc197c8160e01b905098975050505050505050565b600063f23a6e6160e01b9050969550505050505056fea2646970667358221220f62cd059f3672bb04062df149e7ae71534a8512cca0172e695d98a43cff0c53564736f6c63430007060033").into()
1511 );
1512 let _tx_safe_multisend_call_only = TransactionRequest::new().to(safe_diamond_proxy_address).data::<Bytes>(
1514 hex!("0000000000000000000000000000000000000000000000000000000000000000608060405234801561001057600080fd5b5061019a806100206000396000f3fe60806040526004361061001e5760003560e01c80638d80ff0a14610023575b600080fd5b6100dc6004803603602081101561003957600080fd5b810190808035906020019064010000000081111561005657600080fd5b82018360208201111561006857600080fd5b8035906020019184600183028401116401000000008311171561008a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506100de565b005b805160205b8181101561015f578083015160f81c6001820184015160601c60158301850151603584018601516055850187016000856000811461012857600181146101385761013d565b6000808585888a5af1915061013d565b600080fd5b50600081141561014c57600080fd5b82605501870196505050505050506100e3565b50505056fea26469706673582212208d297bb003abee230b5dfb38774688f37a6fbb97a82a21728e8049b2acb9b73564736f6c63430007060033").into()
1515 );
1516 let _tx_safe_singleton = TransactionRequest::new().to(safe_diamond_proxy_address).data::<Bytes>(
1518 hex!("0000000000000000000000000000000000000000000000000000000000000000608060405234801561001057600080fd5b506001600481905550615c1b80620000296000396000f3fe6080604052600436106101d15760003560e01c8063affed0e0116100f7578063e19a9dd911610095578063f08a032311610064578063f08a03231461156b578063f698da25146115bc578063f8dc5dd9146115e7578063ffa1ad741461166257610226565b8063e19a9dd9146112bf578063e318b52b14611310578063e75235b8146113a1578063e86637db146113cc57610226565b8063cc2f8452116100d1578063cc2f84521461100c578063d4d9bdcd146110d9578063d8d11f7814611114578063e009cfde1461124e57610226565b8063affed0e014610d89578063b4faba0914610db4578063b63e800d14610e9c57610226565b80635624b25b1161016f5780636a7612021161013e5780636a761202146109895780637d83297414610b45578063934f3a1114610bb4578063a0e67e2b14610d1d57610226565b80635624b25b146107f05780635ae6bd37146108ae578063610b5925146108fd578063694e80c31461094e57610226565b80632f54bf6e116101ab5780632f54bf6e146104c85780633408e4701461052f578063468721a71461055a5780635229073f1461066f57610226565b80630d582f131461029357806312fb68e0146102ee5780632d9ad53d1461046157610226565b36610226573373ffffffffffffffffffffffffffffffffffffffff167f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d346040518082815260200191505060405180910390a2005b34801561023257600080fd5b5060007f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d560001b905080548061026757600080f35b36600080373360601b365260008060143601600080855af13d6000803e8061028e573d6000fd5b3d6000f35b34801561029f57600080fd5b506102ec600480360360408110156102b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506116f2565b005b3480156102fa57600080fd5b5061045f6004803603608081101561031157600080fd5b81019080803590602001909291908035906020019064010000000081111561033857600080fd5b82018360208201111561034a57600080fd5b8035906020019184600183028401116401000000008311171561036c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803590602001906401000000008111156103cf57600080fd5b8201836020820111156103e157600080fd5b8035906020019184600183028401116401000000008311171561040357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190929190505050611ad8565b005b34801561046d57600080fd5b506104b06004803603602081101561048457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506123d6565b60405180821515815260200191505060405180910390f35b3480156104d457600080fd5b50610517600480360360208110156104eb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506124a8565b60405180821515815260200191505060405180910390f35b34801561053b57600080fd5b5061054461257a565b6040518082815260200191505060405180910390f35b34801561056657600080fd5b506106576004803603608081101561057d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156105c457600080fd5b8201836020820111156105d657600080fd5b803590602001918460018302840111640100000000831117156105f857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff169060200190929190505050612587565b60405180821515815260200191505060405180910390f35b34801561067b57600080fd5b5061076c6004803603608081101561069257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156106d957600080fd5b8201836020820111156106eb57600080fd5b8035906020019184600183028401116401000000008311171561070d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff16906020019092919050505061278d565b60405180831515815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107b4578082015181840152602081019050610799565b50505050905090810190601f1680156107e15780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b3480156107fc57600080fd5b506108336004803603604081101561081357600080fd5b8101908080359060200190929190803590602001909291905050506127c3565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610873578082015181840152602081019050610858565b50505050905090810190601f1680156108a05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156108ba57600080fd5b506108e7600480360360208110156108d157600080fd5b810190808035906020019092919050505061284a565b6040518082815260200191505060405180910390f35b34801561090957600080fd5b5061094c6004803603602081101561092057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612862565b005b34801561095a57600080fd5b506109876004803603602081101561097157600080fd5b8101908080359060200190929190505050612bea565b005b610b2d60048036036101408110156109a057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156109e757600080fd5b8201836020820111156109f957600080fd5b80359060200191846001830284011164010000000083111715610a1b57600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610aa757600080fd5b820183602082011115610ab957600080fd5b80359060200191846001830284011164010000000083111715610adb57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612d24565b60405180821515815260200191505060405180910390f35b348015610b5157600080fd5b50610b9e60048036036040811015610b6857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613253565b6040518082815260200191505060405180910390f35b348015610bc057600080fd5b50610d1b60048036036060811015610bd757600080fd5b810190808035906020019092919080359060200190640100000000811115610bfe57600080fd5b820183602082011115610c1057600080fd5b80359060200191846001830284011164010000000083111715610c3257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190640100000000811115610c9557600080fd5b820183602082011115610ca757600080fd5b80359060200191846001830284011164010000000083111715610cc957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050613278565b005b348015610d2957600080fd5b50610d32613307565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610d75578082015181840152602081019050610d5a565b505050509050019250505060405180910390f35b348015610d9557600080fd5b50610d9e6134b0565b6040518082815260200191505060405180910390f35b348015610dc057600080fd5b50610e9a60048036036040811015610dd757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610e1457600080fd5b820183602082011115610e2657600080fd5b80359060200191846001830284011164010000000083111715610e4857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506134b6565b005b348015610ea857600080fd5b5061100a6004803603610100811015610ec057600080fd5b8101908080359060200190640100000000811115610edd57600080fd5b820183602082011115610eef57600080fd5b80359060200191846020830284011164010000000083111715610f1157600080fd5b909192939192939080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610f5c57600080fd5b820183602082011115610f6e57600080fd5b80359060200191846001830284011164010000000083111715610f9057600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506134d8565b005b34801561101857600080fd5b506110656004803603604081101561102f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613696565b60405180806020018373ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019060200280838360005b838110156110c45780820151818401526020810190506110a9565b50505050905001935050505060405180910390f35b3480156110e557600080fd5b50611112600480360360208110156110fc57600080fd5b81019080803590602001909291905050506139f9565b005b34801561112057600080fd5b50611238600480360361014081101561113857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561117f57600080fd5b82018360208201111561119157600080fd5b803590602001918460018302840111640100000000831117156111b357600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613b98565b6040518082815260200191505060405180910390f35b34801561125a57600080fd5b506112bd6004803603604081101561127157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613bc5565b005b3480156112cb57600080fd5b5061130e600480360360208110156112e257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613f4c565b005b34801561131c57600080fd5b5061139f6004803603606081101561133357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614138565b005b3480156113ad57600080fd5b506113b6614796565b6040518082815260200191505060405180910390f35b3480156113d857600080fd5b506114f060048036036101408110156113f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561143757600080fd5b82018360208201111561144957600080fd5b8035906020019184600183028401116401000000008311171561146b57600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506147a0565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015611530578082015181840152602081019050611515565b50505050905090810190601f16801561155d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561157757600080fd5b506115ba6004803603602081101561158e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614948565b005b3480156115c857600080fd5b506115d161499f565b6040518082815260200191505060405180910390f35b3480156115f357600080fd5b506116606004803603606081101561160a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050614a1d565b005b34801561166e57600080fd5b50611677614e46565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156116b757808201518184015260208101905061169c565b50505050905090810190601f1680156116e45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6116fa614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156117645750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b801561179c57503073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b61180e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461190f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506003600081548092919060010191905055508173ffffffffffffffffffffffffffffffffffffffff167f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2660405160405180910390a28060045414611ad457611ad381612bea565b5b5050565b611aec604182614f2290919063ffffffff16565b82511015611b62576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000808060008060005b868110156123ca57611b7e8882614f5c565b80945081955082965050505060008460ff1614156120035789898051906020012014611c12576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323700000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8260001c9450611c2c604188614f2290919063ffffffff16565b8260001c1015611ca4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8751611cbd60208460001c614f8b90919063ffffffff16565b1115611d31576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006020838a01015190508851611d6782611d5960208760001c614f8b90919063ffffffff16565b614f8b90919063ffffffff16565b1115611ddb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60606020848b010190506320c13b0b60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168773ffffffffffffffffffffffffffffffffffffffff166320c13b0b8d846040518363ffffffff1660e01b8152600401808060200180602001838103835285818151815260200191508051906020019080838360005b83811015611e7d578082015181840152602081019050611e62565b50505050905090810190601f168015611eaa5780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015611ee3578082015181840152602081019050611ec8565b50505050905090810190601f168015611f105780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015611f2f57600080fd5b505afa158015611f43573d6000803e3d6000fd5b505050506040513d6020811015611f5957600080fd5b81019080805190602001909291905050507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611ffc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5050612248565b60018460ff161415612117578260001c94508473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806120a057506000600860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008c81526020019081526020016000205414155b612112576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b612247565b601e8460ff1611156121df5760018a60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c018281526020019150506040516020818303038152906040528051906020012060048603858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156121ce573d6000803e3d6000fd5b505050602060405103519450612246565b60018a85858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612239573d6000803e3d6000fd5b5050506020604051035194505b5b5b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1611801561230f5750600073ffffffffffffffffffffffffffffffffffffffff16600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b80156123485750600173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b6123ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323600000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8495508080600101915050611b6c565b50505050505050505050565b60008173ffffffffffffffffffffffffffffffffffffffff16600173ffffffffffffffffffffffffffffffffffffffff16141580156124a15750600073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b6000600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156125735750600073ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b6000804690508091505090565b6000600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156126525750600073ffffffffffffffffffffffffffffffffffffffff16600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b6126c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6126f1858585857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff614faa565b90508015612741573373ffffffffffffffffffffffffffffffffffffffff167f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb860405160405180910390a2612785565b3373ffffffffffffffffffffffffffffffffffffffff167facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37560405160405180910390a25b949350505050565b6000606061279d86868686612587565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b606060006020830267ffffffffffffffff811180156127e157600080fd5b506040519080825280601f01601f1916602001820160405280156128145781602001600182028036833780820191505090505b50905060005b8381101561283f5780850154806020830260208501015250808060010191505061281a565b508091505092915050565b60076020528060005260406000206000915090505481565b61286a614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156128d45750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b612946576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612a47576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844060405160405180910390a250565b612bf2614e7f565b600354811115612c6a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001811015612ce1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b806004819055507f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c936004546040518082815260200191505060405180910390a150565b6000806000612d3e8e8e8e8e8e8e8e8e8e8e6005546147a0565b905060056000815480929190600101919050555080805190602001209150612d67828286613278565b506000612d72614ff6565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612f58578073ffffffffffffffffffffffffffffffffffffffff166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b8152600401808d73ffffffffffffffffffffffffffffffffffffffff1681526020018c8152602001806020018a6001811115612e1557fe5b81526020018981526020018881526020018781526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff168152602001806020018473ffffffffffffffffffffffffffffffffffffffff16815260200183810383528d8d82818152602001925080828437600081840152601f19601f820116905080830192505050838103825285818151815260200191508051906020019080838360005b83811015612ee7578082015181840152602081019050612ecc565b50505050905090810190601f168015612f145780820380516001836020036101000a031916815260200191505b509e505050505050505050505050505050600060405180830381600087803b158015612f3f57600080fd5b505af1158015612f53573d6000803e3d6000fd5b505050505b6101f4612f7f6109c48b01603f60408d0281612f7057fe5b0461502790919063ffffffff16565b015a1015612ff5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60005a905061305e8f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e60008d14613053578e613059565b6109c45a035b614faa565b93506130735a8261504190919063ffffffff16565b90508380613082575060008a14155b8061308e575060008814155b613100576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60008089111561311a57613117828b8b8b8b615061565b90505b841561315d57837f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e826040518082815260200191505060405180910390a2613196565b837f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d23826040518082815260200191505060405180910390a25b5050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614613242578073ffffffffffffffffffffffffffffffffffffffff16639327136883856040518363ffffffff1660e01b815260040180838152602001821515815260200192505050600060405180830381600087803b15801561322957600080fd5b505af115801561323d573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b6008602052816000526040600020602052806000526040600020600091509150505481565b60006004549050600081116132f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b61330184848484611ad8565b50505050565b6060600060035467ffffffffffffffff8111801561332457600080fd5b506040519080825280602002602001820160405280156133535781602001602082028036833780820191505090505b50905060008060026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146134a757808383815181106133fe57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081806001019250506133bd565b82935050505090565b60055481565b600080825160208401855af4806000523d6020523d600060403e60403d016000fd5b6135238a8a80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505089615267565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146135615761356084615767565b5b6135af8787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050615838565b60008211156135c9576135c782600060018685615061565b505b3373ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b8960405180806020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281038252878782818152602001925060200280828437600081840152601f19601f820116905080830192505050965050505050505060405180910390a250505050505050505050565b60606000600173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806136da57506136d9846123d6565b5b61374c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600083116137c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303600000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8267ffffffffffffffff811180156137d957600080fd5b506040519080825280602002602001820160405280156138085781602001602082028036833780820191505090505b5091506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156138da5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b80156138e557508381105b156139a057818382815181106138f757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508080600101915050613870565b600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146139ee578260018203815181106139e357fe5b602002602001015191505b808352509250929050565b600073ffffffffffffffffffffffffffffffffffffffff16600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415613afb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330333000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff16817ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c60405160405180910390a350565b6000613bad8c8c8c8c8c8c8c8c8c8c8c6147a0565b8051906020012090509b9a5050505050505050505050565b613bcd614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015613c375750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b613ca9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614613da9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427660405160405180910390a25050565b613f54614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146140c6578073ffffffffffffffffffffffffffffffffffffffff166301ffc9a77fe6d7a83a000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b15801561401857600080fd5b505afa15801561402c573d6000803e3d6000fd5b505050506040513d602081101561404257600080fd5b81019080805190602001909291905050506140c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475333303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b60007f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c860001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa260405160405180910390a25050565b614140614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156141aa5750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156141e257503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b614254576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614355576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156143bf5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b614431576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614531576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf60405160405180910390a28073ffffffffffffffffffffffffffffffffffffffff167f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2660405160405180910390a2505050565b6000600454905090565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d60405180838380828437808301925050509250505060405180910390208c8c8c8c8c8c8c604051602001808c81526020018b73ffffffffffffffffffffffffffffffffffffffff1681526020018a815260200189815260200188600181111561483157fe5b81526020018781526020018681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019b505050505050505050505050604051602081830303815290604052805190602001209050601960f81b600160f81b6148bd61499f565b8360405160200180857effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152600101847effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526001018381526020018281526020019450505050506040516020818303038152906040529150509b9a5050505050505050505050565b614950614e7f565b61495981615767565b8073ffffffffffffffffffffffffffffffffffffffff167f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b060405160405180910390a250565b60007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a7946921860001b6149cd61257a565b30604051602001808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405160208183030381529060405280519060200120905090565b614a25614e7f565b806001600354031015614aa0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015614b0a5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b614b7c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614c7c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600360008154809291906001900391905055508173ffffffffffffffffffffffffffffffffffffffff167ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf60405160405180910390a28060045414614e4157614e4081612bea565b5b505050565b6040518060400160405280600581526020017f312e342e3100000000000000000000000000000000000000000000000000000081525081565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614614f20576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330333100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b565b600080831415614f355760009050614f56565b6000828402905082848281614f4657fe5b0414614f5157600080fd5b809150505b92915050565b60008060008360410260208101860151925060408101860151915060ff60418201870151169350509250925092565b600080828401905083811015614fa057600080fd5b8091505092915050565b6000600180811115614fb857fe5b836001811115614fc457fe5b1415614fdd576000808551602087018986f49050614fed565b600080855160208701888a87f190505b95945050505050565b6000807f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c860001b9050805491505090565b6000818310156150375781615039565b825b905092915050565b60008282111561505057600080fd5b600082840390508091505092915050565b600080600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461509e57826150a0565b325b9050600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156151b85761510a3a86106150e7573a6150e9565b855b6150fc888a614f8b90919063ffffffff16565b614f2290919063ffffffff16565b91508073ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050506151b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b61525d565b6151dd856151cf888a614f8b90919063ffffffff16565b614f2290919063ffffffff16565b91506151ea848284615b0e565b61525c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b5095945050505050565b6000600454146152df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8151811115615356576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60018110156153cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006001905060005b83518110156156d35760008482815181106153ed57fe5b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156154615750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b801561549957503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156154d157508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b615543576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614615644576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b80600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508092505080806001019150506153d6565b506001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550825160038190555081600481905550505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415615809576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475334303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60007f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d560001b90508181555050565b600073ffffffffffffffffffffffffffffffffffffffff1660016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461593a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001806000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614615b0a576159f682615bd2565b615a68576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b615a978260008360017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff614faa565b615b09576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b5050565b60008063a9059cbb8484604051602401808373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001925050506040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050602060008251602084016000896127105a03f13d60008114615bb55760208114615bbd5760009350615bc8565b819350615bc8565b600051158215171593505b5050509392505050565b600080823b90506000811191505091905056fea264697066735822122057398fa72884cf9a6cb78aab2fb58a6b927f0e9d97d75b015daaee0959a153bf64736f6c63430007060033").into()
1519 );
1520 let _tx_safe_multisend = TransactionRequest::new().to(safe_diamond_proxy_address).data::<Bytes>(
1522 hex!("000000000000000000000000000000000000000000000000000000000000000060a060405234801561001057600080fd5b503073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b8152505060805160601c6102756100646000398060e052506102756000f3fe60806040526004361061001e5760003560e01c80638d80ff0a14610023575b600080fd5b6100dc6004803603602081101561003957600080fd5b810190808035906020019064010000000081111561005657600080fd5b82018360208201111561006857600080fd5b8035906020019184600183028401116401000000008311171561008a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506100de565b005b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161415610183576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260308152602001806102106030913960400191505060405180910390fd5b805160205b8181101561020a578083015160f81c6001820184015160601c6015830185015160358401860151605585018701600085600081146101cd57600181146101dd576101e8565b6000808585888a5af191506101e8565b6000808585895af491505b5060008114156101f757600080fd5b8260550187019650505050505050610188565b50505056fe4d756c746953656e642073686f756c64206f6e6c792062652063616c6c6564207669612064656c656761746563616c6ca264697066735822122021102e6d5bc1da75411b41fe2792a1748bf5c49c794e51e81405ccd2399da13564736f6c63430007060033").into()
1523 );
1524 provider
1527 .send_transaction(_tx_safe_proxy_factory, None)
1528 .await
1529 .unwrap()
1530 .await
1531 .unwrap();
1532 provider
1533 .send_transaction(_tx_safe_compatibility_fallback_handler, None)
1534 .await
1535 .unwrap()
1536 .await
1537 .unwrap();
1538 provider
1539 .send_transaction(_tx_safe_multisend_call_only, None)
1540 .await
1541 .unwrap()
1542 .await
1543 .unwrap();
1544 provider
1545 .send_transaction(_tx_safe_singleton, None)
1546 .await
1547 .unwrap()
1548 .await
1549 .unwrap();
1550 provider
1551 .send_transaction(_tx_safe_multisend, None)
1552 .await
1553 .unwrap()
1554 .await
1555 .unwrap();
1556 }
1557 Ok(())
1558 }
1559
1560 #[async_std::test]
1561 async fn test_native_and_token_balances_in_anvil_with_multicall() -> anyhow::Result<()> {
1562 let kp = ChainKeypair::random();
1564 let kp_address = Address::from(&kp);
1565
1566 let anvil = hopr_chain_types::utils::create_anvil(None);
1568 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1569 let client = create_rpc_client_to_anvil(SurfRequestor::default(), &anvil, &contract_deployer);
1570 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1572 .await
1573 .expect("failed to deploy");
1574 deploy_multicall3_for_testing(client.clone()).await?;
1576
1577 let (native_balance, token_balance) =
1579 get_native_and_token_balances(instances.token, vec![kp_address.into()]).await?;
1580 assert_eq!(native_balance.len(), 1, "invalid native balance lens");
1581 assert_eq!(token_balance.len(), 1, "invalid token balance lens");
1582 assert_eq!(native_balance[0].as_u64(), 0u64, "wrong native balance");
1583 assert_eq!(token_balance[0].as_u64(), 0u64, "wrong token balance");
1584 drop(anvil);
1585 Ok(())
1586 }
1587
1588 #[async_std::test]
1589 async fn test_transfer_or_mint_tokens_in_anvil_with_multicall() -> anyhow::Result<()> {
1590 let mut addresses: Vec<ethers::types::Address> = Vec::new();
1591 for _ in 0..4 {
1592 addresses.push(get_random_address_for_testing().into());
1593 }
1594 let desired_amount = vec![U256::from(1), U256::from(2), U256::from(3), U256::from(4)];
1595
1596 let anvil = hopr_chain_types::utils::create_anvil(None);
1598 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1599 let client = create_rpc_client_to_anvil(SurfRequestor::default(), &anvil, &contract_deployer);
1600 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1602 .await
1603 .expect("failed to deploy");
1604
1605 deploy_multicall3_for_testing(client.clone()).await?;
1607 let encoded_minter_role: [u8; 32] = keccak256(b"MINTER_ROLE");
1609 instances
1610 .token
1611 .grant_role(
1612 encoded_minter_role.clone(),
1613 contract_deployer.public().to_address().into(),
1614 )
1615 .send()
1616 .await?
1617 .await?;
1618
1619 let check_minter_role = instances
1621 .token
1622 .has_role(
1623 encoded_minter_role.clone(),
1624 contract_deployer.public().to_address().into(),
1625 )
1626 .call()
1627 .await?;
1628 assert!(check_minter_role, "deployer does not have minter role yet");
1629
1630 let total_transferred_amount =
1632 transfer_or_mint_tokens(instances.token.clone(), addresses.clone(), desired_amount.clone()).await?;
1633
1634 let (native_balance, token_balance) =
1636 get_native_and_token_balances(instances.token, addresses.clone().into()).await?;
1637 assert_eq!(native_balance.len(), 4, "invalid native balance lens");
1638 assert_eq!(token_balance.len(), 4, "invalid token balance lens");
1639 for (i, amount) in desired_amount.iter().enumerate() {
1640 assert_eq!(token_balance[i].as_u64(), amount.as_u64(), "token balance unmatch");
1641 }
1642
1643 assert_eq!(
1644 total_transferred_amount,
1645 U256::from(10),
1646 "amount transferred does not equal to the desired amount"
1647 );
1648 Ok(())
1649 }
1650
1651 #[async_std::test]
1652 async fn test_transfer_or_mint_tokens_in_anvil_with_one_recipient() -> anyhow::Result<()> {
1653 let addresses: Vec<ethers::types::Address> = vec![get_random_address_for_testing().into()];
1654 let desired_amount = vec![U256::from(42)];
1655
1656 let anvil = hopr_chain_types::utils::create_anvil(None);
1658 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1659 let client = create_rpc_client_to_anvil(SurfRequestor::default(), &anvil, &contract_deployer);
1660 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1662 .await
1663 .expect("failed to deploy");
1664
1665 deploy_multicall3_for_testing(client.clone()).await?;
1667 let encoded_minter_role: [u8; 32] = keccak256(b"MINTER_ROLE");
1669 instances
1670 .token
1671 .grant_role(
1672 encoded_minter_role.clone(),
1673 contract_deployer.public().to_address().into(),
1674 )
1675 .send()
1676 .await?
1677 .await?;
1678
1679 let check_minter_role = instances
1681 .token
1682 .has_role(
1683 encoded_minter_role.clone(),
1684 contract_deployer.public().to_address().into(),
1685 )
1686 .call()
1687 .await?;
1688 assert!(check_minter_role, "deployer does not have minter role yet");
1689
1690 let total_transferred_amount =
1692 transfer_or_mint_tokens(instances.token.clone(), addresses.clone(), desired_amount.clone()).await?;
1693
1694 let (native_balance, token_balance) =
1696 get_native_and_token_balances(instances.token, addresses.clone().into()).await?;
1697 assert_eq!(native_balance.len(), 1, "invalid native balance lens");
1698 assert_eq!(token_balance.len(), 1, "invalid token balance lens");
1699 for (i, amount) in desired_amount.iter().enumerate() {
1700 assert_eq!(token_balance[i].as_u64(), amount.as_u64(), "token balance unmatch");
1701 }
1702
1703 assert_eq!(
1704 total_transferred_amount, desired_amount[0],
1705 "amount transferred does not equal to the desired amount"
1706 );
1707 Ok(())
1708 }
1709
1710 #[async_std::test]
1711 async fn test_transfer_or_mint_tokens_in_anvil_without_recipient() -> anyhow::Result<()> {
1712 let addresses: Vec<ethers::types::Address> = Vec::new();
1713 let desired_amount: Vec<U256> = Vec::new();
1714
1715 let anvil = hopr_chain_types::utils::create_anvil(None);
1717 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1718 let client = create_rpc_client_to_anvil(SurfRequestor::default(), &anvil, &contract_deployer);
1719 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1721 .await
1722 .expect("failed to deploy");
1723
1724 deploy_multicall3_for_testing(client.clone()).await?;
1726
1727 let total_transferred_amount =
1729 transfer_or_mint_tokens(instances.token.clone(), addresses.clone(), desired_amount.clone()).await?;
1730
1731 let (native_balance, token_balance) =
1733 get_native_and_token_balances(instances.token, addresses.clone().into()).await?;
1734 assert_eq!(native_balance.len(), 0, "invalid native balance lens");
1735 assert_eq!(token_balance.len(), 0, "invalid token balance lens");
1736 assert_eq!(
1741 total_transferred_amount,
1742 U256::from(0),
1743 "amount transferred does not equal to the desired amount"
1744 );
1745 Ok(())
1746 }
1747
1748 #[async_std::test]
1749 async fn test_transfer_native_tokens_in_anvil_with_multicall() -> anyhow::Result<()> {
1750 let mut addresses: Vec<ethers::types::Address> = Vec::new();
1751 for _ in 0..4 {
1752 addresses.push(get_random_address_for_testing().into());
1753 }
1754 let desired_amount = vec![U256::from(1), U256::from(2), U256::from(3), U256::from(4)];
1755
1756 let anvil = hopr_chain_types::utils::create_anvil(None);
1758 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1759 let client = create_rpc_client_to_anvil(SurfRequestor::default(), &anvil, &contract_deployer);
1760 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1761 .await
1762 .expect("failed to deploy");
1763
1764 deploy_multicall3_for_testing(client.clone()).await?;
1766
1767 let total_transferred_amount =
1769 transfer_native_tokens(client.clone(), addresses.clone(), desired_amount.clone()).await?;
1770
1771 let (native_balance, token_balance) =
1773 get_native_and_token_balances(instances.token, addresses.clone().into()).await?;
1774 assert_eq!(native_balance.len(), 4, "invalid native balance lens");
1775 assert_eq!(token_balance.len(), 4, "invalid token balance lens");
1776 for (i, amount) in desired_amount.iter().enumerate() {
1777 assert_eq!(native_balance[i].as_u64(), amount.as_u64(), "native balance unmatch");
1778 }
1779
1780 assert_eq!(
1781 total_transferred_amount,
1782 U256::from(10),
1783 "amount transferred does not equal to the desired amount"
1784 );
1785 Ok(())
1786 }
1787
1788 #[async_std::test]
1789 async fn test_register_safes_and_nodes_then_deregister_nodes_in_anvil_with_multicall() -> anyhow::Result<()> {
1790 let mut safe_addresses: Vec<ethers::types::Address> = Vec::new();
1791 let mut node_addresses: Vec<ethers::types::Address> = Vec::new();
1792 for _ in 0..4 {
1793 safe_addresses.push(get_random_address_for_testing().into());
1794 node_addresses.push(get_random_address_for_testing().into());
1795 }
1796
1797 let anvil = hopr_chain_types::utils::create_anvil(None);
1799 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1800 let client = create_rpc_client_to_anvil(SurfRequestor::default(), &anvil, &contract_deployer);
1801 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1802 .await
1803 .expect("failed to deploy");
1804 deploy_multicall3_for_testing(client.clone()).await?;
1806
1807 let (removed_amt, added_amt) = register_safes_and_nodes_on_network_registry(
1809 instances.network_registry.clone(),
1810 safe_addresses.clone(),
1811 node_addresses.clone(),
1812 )
1813 .await?;
1814
1815 assert_eq!(removed_amt, 0, "should not remove any safe");
1816 assert_eq!(added_amt, 4, "there should be 4 additions");
1817
1818 let registered_safes = get_registered_safes_for_nodes_on_network_registry(
1820 instances.network_registry.clone(),
1821 node_addresses.clone(),
1822 )
1823 .await?;
1824
1825 assert_eq!(safe_addresses.len(), registered_safes.len(), "returned length unmatch");
1826 for (i, safe_addr) in safe_addresses.iter().enumerate() {
1827 assert_eq!(safe_addr, ®istered_safes[i], "registered safe addresses unmatch");
1828 }
1829
1830 let deregisterd_nodes = deregister_nodes_from_network_registry(
1832 instances.network_registry.clone(),
1833 node_addresses.split_at(3).0.to_vec(),
1834 )
1835 .await?;
1836 assert_eq!(deregisterd_nodes, 3, "cannot deregister all the nodes");
1837
1838 let (removed_amt_2, added_amt_2) = register_safes_and_nodes_on_network_registry(
1840 instances.network_registry.clone(),
1841 safe_addresses.clone(),
1842 node_addresses.clone(),
1843 )
1844 .await?;
1845
1846 assert_eq!(removed_amt_2, 0, "should not remove any safe");
1847 assert_eq!(added_amt_2, 3, "there should be 3 additions");
1848 Ok(())
1849 }
1850
1851 #[async_std::test]
1852 async fn test_deploy_proxy() -> anyhow::Result<()> {
1853 let prediction = deploy_proxy(
1854 H160::from_str("41675c099f32341bf84bfc5382af534df5c7461a")?,
1855 hex!("09e458584ce79e57b65cb303dc136c5d53e17b676599b9b7bc03815e0eef5172").into(),
1856 H160::from_str(SAFE_SAFEPROXYFACTORY_ADDRESS)?,
1857 )?;
1858
1859 assert_eq!(
1860 prediction,
1861 H160::from_str("ec5c8d045dfa1f93785125c26e187e9439f67105")?,
1862 "cannot reproduce proxy"
1863 );
1864 Ok(())
1865 }
1866 #[async_std::test]
1867 async fn test_get_salt_from_salt_nonce() -> anyhow::Result<()> {
1868 let salt = get_salt_from_salt_nonce(
1869 hex!("b63e800d00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000002a15de4410d4c8af0a7b6c12803120f43c42b8200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000098b275485c406573d042848d66eb9d63fca311c00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000").into(),
1870 U256::from_dec_str("103994836888229670573364883831672511342967953907147914065931589108526220754063")?.into(),
1871 )?;
1872
1873 assert_eq!(
1874 salt.to_vec(),
1875 Bytes::from_str("09e458584ce79e57b65cb303dc136c5d53e17b676599b9b7bc03815e0eef5172")?,
1876 "cannot reproduce salt"
1877 );
1878 Ok(())
1879 }
1880
1881 #[async_std::test]
1882 async fn test_safe_and_module_address_prediction() -> anyhow::Result<()> {
1883 let _ = env_logger::builder().is_test(true).try_init();
1885
1886 let mut admin_addresses: Vec<ethers::types::Address> = Vec::new();
1888 for _ in 0..2 {
1889 admin_addresses.push(get_random_address_for_testing().into());
1890 }
1891
1892 let anvil = hopr_chain_types::utils::create_anvil(None);
1894 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1895 let client = create_rpc_client_to_anvil(SurfRequestor::default(), &anvil, &contract_deployer);
1896 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1897 .await
1898 .expect("failed to deploy");
1899 deploy_multicall3_for_testing(client.clone()).await?;
1901 deploy_safe_suites(client.clone()).await?;
1903
1904 let caller = client.default_sender().expect("client must have a sender");
1905
1906 let default_target = format!("{:?}{}", instances.channels.address(), DEFAULT_CAPABILITY_PERMISSIONS);
1908 debug!("default target {:?}", default_target);
1909 let curr_nonce = client
1911 .get_transaction_count(caller, Some(ethers::types::BlockNumber::Pending.into()))
1912 .await?;
1913 let nonce = keccak256(ethers::abi::encode_packed(&[
1914 ethers::abi::Token::Address(caller),
1915 ethers::abi::Token::Uint(curr_nonce),
1916 ])?);
1917
1918 let module_address = predict_module_address(
1919 caller,
1920 nonce,
1921 instances.stake_factory.address(),
1922 instances.module_implementation.address(),
1923 )?;
1924 debug!("predict_module_addr {:?}", module_address);
1925
1926 let safe_address = predict_safe_address(
1927 instances.stake_factory.address(),
1928 vec![H160::from_str("9062a96b9e947b2b57283e705c97b871f5eb6561")?],
1929 nonce,
1930 H160::from_str(SAFE_COMPATIBILITYFALLBACKHANDLER_ADDRESS)?,
1931 H160::from_str(SAFE_SAFE_ADDRESS)?,
1932 H160::from_str(SAFE_SAFEPROXYFACTORY_ADDRESS)?,
1933 )?;
1934
1935 debug!("predict_safe_address {:?}", safe_address);
1936
1937 let deployment_receipt = instances
1939 .stake_factory
1940 .clone(
1941 instances.module_implementation.address(),
1942 vec![caller],
1943 nonce.into(),
1944 U256::from_str(&default_target)?.into(),
1945 )
1946 .send()
1947 .await?
1948 .await?
1949 .unwrap();
1950 debug!("deployment_receipt {:?}", deployment_receipt);
1951 let module_log = deployment_receipt
1953 .logs
1954 .iter()
1955 .find(|log| log.topics[0].eq(&NEW_HOPR_NODE_STAKE_MODULE_TOPIC.parse::<H256>().unwrap()))
1956 .ok_or(HelperErrors::ContractNotDeployed("module".into()))?; debug!("module_log {:?}", module_log);
1959 let safe_log = deployment_receipt
1960 .logs
1961 .iter()
1962 .find(|log| log.topics[0].eq(&NEW_HOPR_NODE_STAKE_SAFE_TOPIC.parse::<H256>().unwrap()))
1963 .ok_or(HelperErrors::ContractNotDeployed("safe".into()))?; debug!("safe_log {:?}", safe_log);
1965 let module_addr = H160::decode(module_log.data.clone())?;
1966 debug!("module_addr {:?}", module_addr);
1967
1968 let safe_addr = H160::decode(safe_log.data.clone())?;
1969 debug!("safe_addr {:?}", safe_addr);
1970
1971 assert_eq!(module_addr, module_address, "module prediction does not match");
1972 assert_eq!(safe_addr, safe_address, "safe prediction does not match");
1973 Ok(())
1974 }
1975
1976 #[async_std::test]
1977 async fn test_deploy_safe_and_module() -> anyhow::Result<()> {
1978 let _ = env_logger::builder().is_test(true).try_init();
1979
1980 let mut admin_addresses: Vec<ethers::types::Address> = Vec::new();
1982 for _ in 0..2 {
1983 admin_addresses.push(get_random_address_for_testing().into());
1984 }
1985 let mut node_addresses: Vec<ethers::types::Address> = Vec::new();
1986 for _ in 0..2 {
1987 node_addresses.push(get_random_address_for_testing().into());
1988 }
1989
1990 let anvil = hopr_chain_types::utils::create_anvil(None);
1992 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
1993 let client = create_rpc_client_to_anvil(SurfRequestor::default(), &anvil, &contract_deployer);
1994 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
1995 .await
1996 .expect("failed to deploy");
1997 deploy_multicall3_for_testing(client.clone()).await?;
1999 deploy_safe_suites(client.clone()).await?;
2001
2002 let (safe, node_module) = deploy_safe_module_with_targets_and_nodes(
2004 instances.stake_factory,
2005 instances.token.address(),
2006 instances.channels.address(),
2007 instances.module_implementation.address(),
2008 instances.announcements.address(),
2009 U256::max_value(),
2010 Some(node_addresses.clone()),
2011 admin_addresses.clone(),
2012 U256::from(2),
2013 )
2014 .await?;
2015
2016 let try_get_announcement_target = node_module
2018 .try_get_target(instances.announcements.address())
2019 .call()
2020 .await?;
2021
2022 assert!(try_get_announcement_target.0, "announcement is not a target");
2023
2024 let allowance = instances
2026 .token
2027 .allowance(safe.address(), instances.channels.address())
2028 .await?;
2029
2030 assert_eq!(allowance, U256::max_value(), "allowance is not set");
2031
2032 for node_address in node_addresses {
2034 let is_node_included = node_module.is_node(node_address).call().await?;
2035 assert!(is_node_included, "failed to include a node");
2036 }
2037
2038 let owners = safe.get_owners().call().await?;
2040 let thresold = safe.get_threshold().call().await?;
2041
2042 assert_eq!(owners.len(), 2, "should have 2 owners");
2043 for (i, owner) in owners.iter().enumerate() {
2044 assert_eq!(owner, &admin_addresses[i], "admin is wrong");
2045 }
2046 assert_eq!(thresold, U256::from(2), "threshold should be two");
2047 Ok(())
2048 }
2049
2050 #[async_std::test]
2051 async fn test_safe_tx_via_multisend() -> anyhow::Result<()> {
2052 let _ = env_logger::builder().is_test(true).try_init();
2054
2055 let desired_amount = vec![U256::from(1), U256::from(2), U256::from(3), U256::from(4)];
2057
2058 let anvil = hopr_chain_types::utils::create_anvil(None);
2060 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
2061 let client = create_rpc_client_to_anvil(SurfRequestor::default(), &anvil, &contract_deployer);
2062 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
2063 .await
2064 .expect("failed to deploy");
2065 deploy_multicall3_for_testing(client.clone()).await?;
2067 deploy_safe_suites(client.clone()).await?;
2069
2070 let (safe, _node_module) = deploy_safe_module_with_targets_and_nodes(
2072 instances.stake_factory,
2073 instances.token.address(),
2074 instances.channels.address(),
2075 instances.module_implementation.address(),
2076 instances.announcements.address(),
2077 U256::max_value(),
2078 None,
2079 vec![contract_deployer.public().to_address().into()],
2080 U256::from(1),
2081 )
2082 .await?;
2083
2084 let is_owner = safe.get_owners().call().await?;
2086 assert_eq!(is_owner.len(), 1, "safe has too many owners");
2087 assert_eq!(
2088 is_owner[0],
2089 contract_deployer.public().to_address().into(),
2090 "safe wrong owner"
2091 );
2092
2093 let allowance = instances
2095 .token
2096 .allowance(safe.address(), instances.channels.address())
2097 .await?;
2098
2099 assert_eq!(allowance, U256::max_value(), "allowance initiation is wrong");
2100
2101 let mut multisend_txns: Vec<MultisendTransaction> = Vec::new();
2102 for val in desired_amount {
2103 multisend_txns.push(MultisendTransaction {
2104 encoded_data: ApproveCall {
2106 spender: instances.channels.address(),
2107 value: val,
2108 }
2109 .encode()
2110 .into(),
2111 tx_operation: SafeTxOperation::Call,
2112 to: instances.token.address(),
2113 value: U256::zero(),
2114 });
2115 }
2116
2117 let chain_id = client.get_chainid().await?;
2119 let safe_nonce = safe.nonce().await?;
2120 debug!("safe address {:?}", safe.address());
2121 debug!("chain_id {:?}", chain_id);
2122 debug!("safe_nonce {:?}", safe_nonce);
2123
2124 send_multisend_safe_transaction_with_threshold_one(
2126 safe.clone(),
2127 contract_deployer,
2128 H160::from_str(SAFE_MULTISEND_ADDRESS)?,
2129 multisend_txns,
2130 chain_id,
2131 safe_nonce,
2132 )
2133 .await?;
2134
2135 let new_allowance = instances
2137 .token
2138 .allowance(safe.address(), instances.channels.address())
2139 .await?;
2140
2141 assert_eq!(new_allowance, U256::from(4), "final allowance is not desired");
2142 Ok(())
2143 }
2144
2145 #[async_std::test]
2146 async fn test_register_nodes_to_node_safe_registry() -> anyhow::Result<()> {
2147 let _ = env_logger::builder().is_test(true).try_init();
2149
2150 let anvil = hopr_chain_types::utils::create_anvil(None);
2152 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
2153 let client = create_rpc_client_to_anvil(SurfRequestor::default(), &anvil, &contract_deployer);
2154 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
2155 .await
2156 .expect("failed to deploy");
2157 deploy_multicall3_for_testing(client.clone()).await?;
2159 deploy_safe_suites(client.clone()).await?;
2161
2162 let deployer_vec: Vec<H160> = vec![contract_deployer.public().to_address().into()];
2163
2164 let (safe, node_module) = deploy_safe_module_with_targets_and_nodes(
2166 instances.stake_factory,
2167 instances.token.address(),
2168 instances.channels.address(),
2169 instances.module_implementation.address(),
2170 instances.announcements.address(),
2171 U256::max_value(),
2172 Some(deployer_vec.clone()),
2173 deployer_vec.clone(),
2174 U256::from(1),
2175 )
2176 .await?;
2177
2178 instances
2180 .safe_registry
2181 .register_safe_by_node(safe.address())
2182 .send()
2183 .await?
2184 .await?;
2185
2186 let get_registered_safe =
2188 get_registered_safes_for_nodes_on_node_safe_registry(instances.safe_registry.clone(), deployer_vec.clone())
2189 .await?;
2190
2191 assert_eq!(get_registered_safe.len(), 1, "cannot read registered safe");
2192 assert_eq!(get_registered_safe[0], safe.address(), "registered safe is wrong");
2193
2194 deregister_nodes_from_node_safe_registry_and_remove_from_module(
2196 instances.safe_registry.clone(),
2197 deployer_vec.clone(),
2198 vec![node_module.address()],
2199 contract_deployer.clone(),
2200 )
2201 .await?;
2202
2203 let get_registered_safe =
2205 get_registered_safes_for_nodes_on_node_safe_registry(instances.safe_registry.clone(), deployer_vec.clone())
2206 .await?;
2207
2208 assert_eq!(get_registered_safe.len(), 1, "cannot read registered safe");
2209 assert_eq!(get_registered_safe[0], H160::zero(), "node is still registered");
2210
2211 let is_removed = node_module
2213 .is_node(contract_deployer.public().to_address().into())
2214 .call()
2215 .await?;
2216 assert!(!is_removed, "node is not removed");
2217 Ok(())
2218 }
2219
2220 #[async_std::test]
2221 async fn test_include_nodes_to_module() -> anyhow::Result<()> {
2222 let _ = env_logger::builder().is_test(true).try_init();
2224
2225 let mut node_addresses: Vec<ethers::types::Address> = Vec::new();
2226 for _ in 0..2 {
2227 node_addresses.push(get_random_address_for_testing().into());
2228 }
2229
2230 let anvil = hopr_chain_types::utils::create_anvil(None);
2232 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
2233 let client = create_rpc_client_to_anvil(SurfRequestor::default(), &anvil, &contract_deployer);
2234 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
2235 .await
2236 .expect("failed to deploy");
2237 deploy_multicall3_for_testing(client.clone()).await?;
2239 deploy_safe_suites(client.clone()).await?;
2241
2242 let deployer_vec: Vec<H160> = vec![contract_deployer.public().to_address().into()];
2243
2244 let (safe, node_module) = deploy_safe_module_with_targets_and_nodes(
2246 instances.stake_factory,
2247 instances.token.address(),
2248 instances.channels.address(),
2249 instances.module_implementation.address(),
2250 instances.announcements.address(),
2251 U256::max_value(),
2252 None,
2253 deployer_vec.clone(),
2254 U256::from(1),
2255 )
2256 .await?;
2257
2258 for node_addr in node_addresses.clone() {
2260 let node_is_not_included = node_module.is_node(node_addr).call().await?;
2262 assert!(!node_is_not_included, "node should not be included");
2263 }
2264
2265 include_nodes_to_module(safe, node_addresses.clone(), node_module.address(), contract_deployer).await?;
2267
2268 for node_addr in node_addresses {
2271 let node_is_included = node_module.is_node(node_addr).call().await?;
2273 assert!(node_is_included, "node should be included");
2274 }
2275 Ok(())
2276 }
2277
2278 #[async_std::test]
2279 async fn test_migrate_nodes_to_new_network() -> anyhow::Result<()> {
2280 let _ = env_logger::builder().is_test(true).try_init();
2282
2283 let mut node_addresses: Vec<ethers::types::Address> = Vec::new();
2284 for _ in 0..2 {
2285 node_addresses.push(get_random_address_for_testing().into());
2286 }
2287
2288 let anvil = hopr_chain_types::utils::create_anvil(None);
2290 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
2291 let self_address: H160 = contract_deployer.public().to_address().into();
2292 let client = create_rpc_client_to_anvil(SurfRequestor::default(), &anvil, &contract_deployer);
2293 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
2294 .await
2295 .expect("failed to deploy");
2296 deploy_multicall3_for_testing(client.clone()).await?;
2298 deploy_safe_suites(client.clone()).await?;
2300
2301 let new_safe_registry = HoprNodeSafeRegistry::deploy(client.clone(), ())?.send().await?;
2303 let new_token = HoprToken::deploy(client.clone(), ())?.send().await?;
2304 let new_channels = HoprChannels::deploy(
2305 client.clone(),
2306 ethers::abi::Token::Tuple(vec![
2307 ethers::abi::Token::Address(new_token.address()),
2308 ethers::abi::Token::Uint(1_u32.into()),
2309 ethers::abi::Token::Address(new_safe_registry.address()),
2310 ]),
2311 )?
2312 .send()
2313 .await?;
2314 let new_announcements =
2315 HoprAnnouncements::deploy(client.clone(), ethers::abi::Token::Address(new_safe_registry.address()))?
2316 .send()
2317 .await?;
2318 let _new_network_registry = HoprNetworkRegistry::deploy(
2319 client.clone(),
2320 (
2321 ethers::types::Address::from(instances.network_registry_proxy.address()),
2322 self_address,
2323 self_address,
2324 ),
2325 )?
2326 .send()
2327 .await?;
2328
2329 let deployer_vec: Vec<H160> = vec![self_address];
2330
2331 let (safe, node_module) = deploy_safe_module_with_targets_and_nodes(
2333 instances.stake_factory,
2334 instances.token.address(),
2335 instances.channels.address(),
2336 instances.module_implementation.address(),
2337 instances.announcements.address(),
2338 U256::max_value(),
2339 None,
2340 deployer_vec.clone(),
2341 U256::from(1),
2342 )
2343 .await?;
2344
2345 let old_channels_inclusion = node_module.try_get_target(instances.channels.address()).call().await?;
2347 assert!(old_channels_inclusion.0, "old channel should be included");
2348 let new_channels_inclusion = node_module.try_get_target(new_channels.address()).call().await?;
2349 assert!(!new_channels_inclusion.0, "new channel should not be included");
2350
2351 migrate_nodes(
2353 safe,
2354 node_module.address(),
2355 new_channels.address(),
2356 new_token.address(),
2357 new_announcements.address(),
2358 U256::max_value(),
2359 contract_deployer,
2360 )
2361 .await?;
2362
2363 let old_channels_inclusion = node_module.try_get_target(instances.channels.address()).call().await?;
2365 assert!(old_channels_inclusion.0, "old channel should still be included");
2366 let new_channels_inclusion = node_module.try_get_target(new_channels.address()).call().await?;
2367 assert!(new_channels_inclusion.0, "new channel should now be included");
2368 Ok(())
2369 }
2370
2371 #[async_std::test]
2372 async fn test_debug_node_safe_module_setup_on_balance_and_registries() -> anyhow::Result<()> {
2373 let _ = env_logger::builder().is_test(true).try_init();
2375
2376 let mut node_addresses: Vec<ethers::types::Address> = Vec::new();
2377 for _ in 0..2 {
2378 node_addresses.push(get_random_address_for_testing().into());
2379 }
2380
2381 let anvil = hopr_chain_types::utils::create_anvil(None);
2383 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
2384 let client = create_rpc_client_to_anvil(SurfRequestor::default(), &anvil, &contract_deployer);
2385 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
2386 .await
2387 .expect("failed to deploy");
2388 deploy_multicall3_for_testing(client.clone()).await?;
2390 deploy_safe_suites(client.clone()).await?;
2392
2393 let deployer_vec: Vec<H160> = vec![contract_deployer.public().to_address().into()];
2394
2395 let (safe, _) = deploy_safe_module_with_targets_and_nodes(
2397 instances.stake_factory,
2398 instances.token.address(),
2399 instances.channels.address(),
2400 instances.module_implementation.address(),
2401 instances.announcements.address(),
2402 U256::max_value(),
2403 None,
2404 deployer_vec.clone(),
2405 U256::from(1),
2406 )
2407 .await?;
2408 let registered_safe_before_registration = debug_node_safe_module_setup_on_balance_and_registries(
2409 instances.network_registry.clone(),
2410 instances.safe_registry.clone(),
2411 &node_addresses[0],
2412 )
2413 .await?;
2414
2415 assert_eq!(
2416 registered_safe_before_registration,
2417 H160::zero(),
2418 "safe is already registered"
2419 );
2420
2421 let (_, _) = register_safes_and_nodes_on_network_registry(
2423 instances.network_registry.clone(),
2424 vec![safe.address()],
2425 vec![node_addresses[0]],
2426 )
2427 .await?;
2428
2429 let registered_safe_after_registration = debug_node_safe_module_setup_on_balance_and_registries(
2430 instances.network_registry.clone(),
2431 instances.safe_registry.clone(),
2432 &node_addresses[0],
2433 )
2434 .await?;
2435
2436 assert_eq!(
2437 registered_safe_after_registration,
2438 safe.address(),
2439 "safe is not registered"
2440 );
2441 Ok(())
2442 }
2443
2444 #[async_std::test]
2445 async fn test_debug_node_safe_module_setup_main() -> anyhow::Result<()> {
2446 let _ = env_logger::builder().is_test(true).try_init();
2448
2449 let mut node_addresses: Vec<ethers::types::Address> = Vec::new();
2450 for _ in 0..2 {
2451 node_addresses.push(get_random_address_for_testing().into());
2452 }
2453
2454 let anvil = hopr_chain_types::utils::create_anvil(None);
2456 let contract_deployer = ChainKeypair::from_secret(anvil.keys()[0].to_bytes().as_ref())?;
2457 let client = create_rpc_client_to_anvil(SurfRequestor::default(), &anvil, &contract_deployer);
2458 let instances = ContractInstances::deploy_for_testing(client.clone(), &contract_deployer)
2459 .await
2460 .expect("failed to deploy");
2461 deploy_multicall3_for_testing(client.clone()).await?;
2463 deploy_safe_suites(client.clone()).await?;
2465
2466 let deployer_vec: Vec<H160> = vec![contract_deployer.public().to_address().into()];
2467
2468 let (safe, node_module) = deploy_safe_module_with_targets_and_nodes(
2470 instances.stake_factory,
2471 instances.token.address(),
2472 instances.channels.address(),
2473 instances.module_implementation.address(),
2474 instances.announcements.address(),
2475 U256::max_value(),
2476 None,
2477 deployer_vec.clone(),
2478 U256::from(1),
2479 )
2480 .await?;
2481
2482 let (_, _) = register_safes_and_nodes_on_network_registry(
2484 instances.network_registry.clone(),
2485 vec![safe.address()],
2486 vec![node_addresses[0]],
2487 )
2488 .await?;
2489
2490 debug_node_safe_module_setup_main(
2491 instances.token.clone(),
2492 &node_module.address(),
2493 &node_addresses[0],
2494 &safe.address(),
2495 &instances.channels.address(),
2496 &instances.announcements.address(),
2497 )
2498 .await?;
2499 Ok(())
2500 }
2501}