builder_relayer_client_rust/encode/
safe.rs1use crate::types::{OperationType, SafeTransaction};
2use alloy::primitives::{Address, U256};
3use alloy::sol;
4use alloy::sol_types::SolCall;
5
6fn pack_tx(tx: &SafeTransaction) -> Vec<u8> {
8 let mut out = Vec::new();
10 out.push(tx.operation as u8);
11
12 let addr: Address = tx.to.parse().unwrap_or(Address::ZERO);
14 out.extend_from_slice(addr.as_slice());
15
16 let value = U256::from_str_radix(&tx.value, 10).unwrap_or(U256::ZERO);
18 out.extend_from_slice(&value.to_be_bytes::<32>());
19
20 let data_bytes = hex::decode(tx.data.trim_start_matches("0x")).unwrap_or_default();
22 let len = U256::from(data_bytes.len());
23 out.extend_from_slice(&len.to_be_bytes::<32>());
24
25 out.extend_from_slice(&data_bytes);
27 out
28}
29
30pub fn create_safe_multisend_transaction(
31 txns: &[SafeTransaction],
32 safe_multisend_address: &str,
33) -> SafeTransaction {
34 if txns.len() == 1 {
35 return txns[0].clone();
36 }
37 let mut packed: Vec<u8> = Vec::new();
38 for t in txns {
39 packed.extend_from_slice(&pack_tx(t));
40 }
41
42 sol! {
45 function multiSend(bytes memory transactions);
46 }
47
48 let call = multiSendCall {
49 transactions: packed.into(),
50 };
51 let calldata = call.abi_encode();
52
53 SafeTransaction {
54 to: safe_multisend_address.to_string(),
55 value: "0".to_string(),
56 data: format!("0x{}", hex::encode(calldata)),
57 operation: OperationType::DelegateCall,
58 }
59}