builder_relayer_client_rust/encode/
safe.rs1use crate::types::{OperationType, SafeTransaction};
2use ethers::abi::{Token, encode};
3use hex::ToHex;
4
5fn pack_tx(tx: &SafeTransaction) -> Vec<u8> {
7 let mut out = Vec::new();
9 out.push(tx.operation as u8);
10 let addr_bytes = hex::decode(tx.to.trim_start_matches("0x")).unwrap_or_default();
12 let mut addr_fixed = vec![0u8; 20];
13 if addr_bytes.len() == 20 {
14 addr_fixed.copy_from_slice(&addr_bytes);
15 } else if addr_bytes.len() > 20 {
16 addr_fixed.copy_from_slice(&addr_bytes[addr_bytes.len() - 20..]);
17 }
18 out.extend_from_slice(&addr_fixed);
19 let value = ethers::types::U256::from_dec_str(&tx.value).unwrap_or_default();
21 let mut value_be = [0u8; 32];
22 value.to_big_endian(&mut value_be);
23 out.extend_from_slice(&value_be);
24 let data_bytes = hex::decode(tx.data.trim_start_matches("0x")).unwrap_or_default();
26 let mut len_be = [0u8; 32];
27 ethers::types::U256::from(data_bytes.len()).to_big_endian(&mut len_be);
28 out.extend_from_slice(&len_be);
29 out.extend_from_slice(&data_bytes);
31 out
32}
33
34pub fn create_safe_multisend_transaction(
35 txns: &[SafeTransaction],
36 safe_multisend_address: &str,
37) -> SafeTransaction {
38 if txns.len() == 1 {
39 return txns[0].clone();
40 }
41 let mut packed: Vec<u8> = Vec::new();
42 for t in txns {
43 packed.extend_from_slice(&pack_tx(t));
44 }
45 let calldata = encode(&[Token::Bytes(packed)]);
48 let selector = &keccak256(b"multiSend(bytes)")[..4];
49 let mut final_data = Vec::from(selector);
50 final_data.extend_from_slice(&calldata);
51 SafeTransaction {
52 to: safe_multisend_address.to_string(),
53 value: "0".to_string(),
54 data: format!("0x{}", final_data.encode_hex::<String>()),
55 operation: OperationType::DelegateCall,
56 }
57}
58
59fn keccak256(data: &[u8]) -> [u8; 32] {
60 use sha3::{Digest, Keccak256};
61 let mut h = Keccak256::new();
62 h.update(data);
63 let out = h.finalize();
64 let mut arr = [0u8; 32];
65 arr.copy_from_slice(&out);
66 arr
67}