1use alloy_primitives::{Address, Bytes, U256};
2use tracing::debug;
3
4#[derive(Clone, Debug, Eq, PartialEq)]
5pub enum CallType {
6 Unknown,
7 Call,
8 DelegateCall,
9 StaticCall,
10 InternalCall,
11 CalculationCall,
12 CustomCall,
13}
14
15#[derive(Clone, Debug)]
16pub struct CallStack {
17 pub is_relative: bool,
18 pub stack_offset: u32,
19 pub data_offset: u32,
20 pub data_len: usize,
21}
22
23impl CallStack {
24 pub fn new(is_relative: bool, stack_offset: u32, data_offset: u32, data_len: usize) -> Self {
25 Self { is_relative, stack_offset, data_offset, data_len }
26 }
27}
28
29#[derive(Clone, Debug)]
30pub struct MulticallerCall {
31 pub call_type: CallType,
32 pub call_data: Bytes,
33 pub to: Address,
34 pub value: Option<U256>,
35 pub call_stack: Option<CallStack>,
36 pub return_stack: Option<CallStack>,
37}
38
39impl MulticallerCall {
40 pub fn new(opcode_type: CallType, to: Address, call_data: &Bytes, value: Option<U256>) -> MulticallerCall {
41 MulticallerCall { call_type: opcode_type, to, call_data: call_data.clone(), value, call_stack: None, return_stack: None }
42 }
43
44 pub fn new_call(to: Address, call_data: &Bytes) -> MulticallerCall {
45 MulticallerCall::new(CallType::Call, to, call_data, None)
46 }
47
48 pub fn new_call_with_value(to: Address, call_data: &Bytes, value: U256) -> MulticallerCall {
49 MulticallerCall::new(CallType::Call, to, call_data, Some(value))
50 }
51 pub fn new_internal_call(call_data: &Bytes) -> MulticallerCall {
52 MulticallerCall::new(CallType::InternalCall, Address::ZERO, call_data, None)
53 }
54
55 pub fn new_calculation_call(call_data: &Bytes) -> MulticallerCall {
56 MulticallerCall::new(CallType::CalculationCall, Address::ZERO, call_data, None)
57 }
58
59 pub fn new_delegate_call(to: Address, call_data: &Bytes) -> MulticallerCall {
60 MulticallerCall::new(CallType::DelegateCall, to, call_data, None)
61 }
62
63 pub fn new_static_call(to: Address, call_data: &Bytes) -> MulticallerCall {
64 MulticallerCall::new(CallType::StaticCall, to, call_data, None)
65 }
66
67 pub fn new_custom_call(call_data: &Bytes) -> MulticallerCall {
68 MulticallerCall::new(CallType::CustomCall, Address::ZERO, call_data, None)
69 }
70
71 pub fn set_call_stack(&mut self, is_relative: bool, stack_offset: u32, data_offset: u32, data_len: usize) -> &mut Self {
81 self.call_stack = Some(CallStack::new(is_relative, stack_offset, data_offset, data_len));
88 self
89 }
90
91 pub fn set_return_stack(&mut self, is_relative: bool, stack_offset: u32, data_offset: u32, data_len: usize) -> &mut Self {
105 self.return_stack = Some(CallStack::new(is_relative, stack_offset, data_offset, data_len));
107 self
108 }
109
110 }
121
122#[derive(Clone, Debug, Default)]
123pub struct MulticallerCalls {
124 pub opcodes_vec: Vec<MulticallerCall>,
125}
126
127impl MulticallerCalls {
128 pub fn new() -> Self {
129 Self::default()
130 }
131
132 pub fn len(&self) -> usize {
133 self.opcodes_vec.len()
134 }
135
136 pub fn is_empty(&self) -> bool {
137 self.opcodes_vec.is_empty()
138 }
139
140 pub fn log(&self) {
141 for (i, o) in self.opcodes_vec.iter().enumerate() {
142 debug!("{} {:?}", i, o);
143 }
144 }
145
146 pub fn clean(&mut self) -> &mut Self {
147 self.opcodes_vec = Vec::new();
148 self
149 }
150
151 pub fn add(&mut self, opcode: MulticallerCall) -> &mut Self {
152 self.opcodes_vec.push(opcode);
153 self
154 }
155
156 pub fn insert(&mut self, opcode: MulticallerCall) -> &mut Self {
157 self.opcodes_vec.insert(0, opcode);
158 self
159 }
160
161 pub fn merge(&mut self, opcodes: MulticallerCalls) -> &mut Self {
162 self.opcodes_vec.extend(opcodes.opcodes_vec);
163 self
164 }
165
166 pub fn get(&self, idx: usize) -> Option<&MulticallerCall> {
167 self.opcodes_vec.get(idx)
168 }
169}