1use alloy::primitives::{Address, Bytes, U256};
4use alloy::sol_types::SolCall;
5
6use super::Operation;
7
8pub trait SafeCall {
10 fn to(&self) -> Address;
12
13 fn value(&self) -> U256;
15
16 fn data(&self) -> Bytes;
18
19 fn operation(&self) -> Operation;
21}
22
23#[derive(Debug, Clone)]
25pub struct Call {
26 pub to: Address,
28 pub value: U256,
30 pub data: Bytes,
32 pub operation: Operation,
34}
35
36impl Call {
37 pub fn new(to: Address, value: U256, data: impl Into<Bytes>) -> Self {
39 Self {
40 to,
41 value,
42 data: data.into(),
43 operation: Operation::Call,
44 }
45 }
46
47 pub fn call(to: Address, data: impl Into<Bytes>) -> Self {
49 Self::new(to, U256::ZERO, data)
50 }
51
52 pub fn delegate_call(to: Address, data: impl Into<Bytes>) -> Self {
54 Self {
55 to,
56 value: U256::ZERO,
57 data: data.into(),
58 operation: Operation::DelegateCall,
59 }
60 }
61
62 pub fn with_operation(mut self, operation: Operation) -> Self {
64 self.operation = operation;
65 self
66 }
67
68 pub fn with_value(mut self, value: U256) -> Self {
70 self.value = value;
71 self
72 }
73}
74
75impl SafeCall for Call {
76 fn to(&self) -> Address {
77 self.to
78 }
79
80 fn value(&self) -> U256 {
81 self.value
82 }
83
84 fn data(&self) -> Bytes {
85 self.data.clone()
86 }
87
88 fn operation(&self) -> Operation {
89 self.operation
90 }
91}
92
93#[derive(Debug, Clone)]
95pub struct TypedCall<C: SolCall> {
96 pub to: Address,
98 pub value: U256,
100 pub call: C,
102 pub operation: Operation,
104}
105
106impl<C: SolCall> TypedCall<C> {
107 pub fn new(to: Address, call: C) -> Self {
109 Self {
110 to,
111 value: U256::ZERO,
112 call,
113 operation: Operation::Call,
114 }
115 }
116
117 pub fn with_value(mut self, value: U256) -> Self {
119 self.value = value;
120 self
121 }
122
123 pub fn with_operation(mut self, operation: Operation) -> Self {
125 self.operation = operation;
126 self
127 }
128}
129
130impl<C: SolCall + Clone> SafeCall for TypedCall<C> {
131 fn to(&self) -> Address {
132 self.to
133 }
134
135 fn value(&self) -> U256 {
136 self.value
137 }
138
139 fn data(&self) -> Bytes {
140 self.call.abi_encode().into()
141 }
142
143 fn operation(&self) -> Operation {
144 self.operation
145 }
146}
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151 use alloy::primitives::address;
152
153 #[test]
154 fn test_call_new() {
155 let to = address!("0x1234567890123456789012345678901234567890");
156 let value = U256::from(1000);
157 let data = Bytes::from(vec![0x01, 0x02, 0x03]);
158
159 let call = Call::new(to, value, data.clone());
160
161 assert_eq!(call.to(), to);
162 assert_eq!(call.value(), value);
163 assert_eq!(call.data(), data);
164 assert_eq!(call.operation(), Operation::Call);
165 }
166
167 #[test]
168 fn test_call_delegate() {
169 let to = address!("0x1234567890123456789012345678901234567890");
170 let data = Bytes::from(vec![0x01, 0x02, 0x03]);
171
172 let call = Call::delegate_call(to, data.clone());
173
174 assert_eq!(call.to(), to);
175 assert_eq!(call.value(), U256::ZERO);
176 assert_eq!(call.data(), data);
177 assert_eq!(call.operation(), Operation::DelegateCall);
178 }
179}