safe_rs/encoding/
multisend.rs1use alloy::primitives::Bytes;
11
12use crate::types::SafeCall;
13
14pub fn encode_transaction(call: &impl SafeCall) -> Vec<u8> {
18 let data = call.data();
19 let data_len = data.len();
20
21 let mut encoded = Vec::with_capacity(85 + data_len);
23
24 encoded.push(call.operation().as_u8());
26
27 encoded.extend_from_slice(call.to().as_slice());
29
30 encoded.extend_from_slice(&call.value().to_be_bytes::<32>());
32
33 let mut data_len_bytes = [0u8; 32];
35 data_len_bytes[24..].copy_from_slice(&(data_len as u64).to_be_bytes());
36 encoded.extend_from_slice(&data_len_bytes);
37
38 encoded.extend_from_slice(&data);
40
41 encoded
42}
43
44pub fn encode_multisend_data(calls: &[impl SafeCall]) -> Bytes {
46 let mut encoded = Vec::new();
47
48 for call in calls {
49 encoded.extend(encode_transaction(call));
50 }
51
52 Bytes::from(encoded)
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58 use crate::types::Call;
59 use alloy::primitives::{address, U256};
60
61 #[test]
62 fn test_encode_single_transaction() {
63 let call = Call::new(
64 address!("0x1234567890123456789012345678901234567890"),
65 U256::from(1000),
66 vec![0xa9, 0x05, 0x9c, 0xbb], );
68
69 let encoded = encode_transaction(&call);
70
71 assert_eq!(encoded[0], 0); assert_eq!(
76 &encoded[1..21],
77 address!("0x1234567890123456789012345678901234567890").as_slice()
78 );
79
80 let value_bytes = &encoded[21..53];
82 assert_eq!(value_bytes[31], 0xe8); assert_eq!(value_bytes[30], 0x03);
84
85 let len_bytes = &encoded[53..85];
87 assert_eq!(len_bytes[31], 4); assert_eq!(&encoded[85..], &[0xa9, 0x05, 0x9c, 0xbb]);
91 }
92
93 #[test]
94 fn test_encode_delegate_call() {
95 let call = Call::delegate_call(
96 address!("0xabcdefabcdefabcdefabcdefabcdefabcdefabcd"),
97 vec![0x01, 0x02],
98 );
99
100 let encoded = encode_transaction(&call);
101 assert_eq!(encoded[0], 1); }
103
104 #[test]
105 fn test_encode_multisend_data() {
106 let calls = vec![
107 Call::call(
108 address!("0x1111111111111111111111111111111111111111"),
109 vec![0x01],
110 ),
111 Call::call(
112 address!("0x2222222222222222222222222222222222222222"),
113 vec![0x02],
114 ),
115 ];
116
117 let encoded = encode_multisend_data(&calls);
118
119 assert_eq!(encoded.len(), 172);
122 }
123
124 #[test]
125 fn test_encode_empty_data() {
126 let call = Call::call(
127 address!("0x1234567890123456789012345678901234567890"),
128 vec![],
129 );
130
131 let encoded = encode_transaction(&call);
132
133 assert_eq!(encoded.len(), 85);
135
136 let len_bytes = &encoded[53..85];
138 assert!(len_bytes.iter().all(|&b| b == 0));
139 }
140}