ccnext_query_builder/abi/
utils.rs1use alloy::{dyn_abi::{Decoder, DynSolType}, sol_types::Error};
2
3use super::models::FieldMetadata;
4
5const WORD_SIZE: usize = 32;
6
7#[derive(Debug)]
8pub enum ComputeAbiOffsetsError {
9 FailedToDecode(Error)
10}
11
12pub fn compute_abi_offsets(types: Vec<DynSolType>, abi: Vec<u8>) -> Result<Vec<FieldMetadata>, ComputeAbiOffsetsError>{
13 let mut reader = Decoder::new(&abi, false);
14
15 match decode_offset_recursive(&mut reader, types, 0)
16 {
17 Ok(result) => {
18 Ok(result)
19 },
20 Err(err) => {
21 Err(ComputeAbiOffsetsError::FailedToDecode(err))
22 }
23 }
24}
25
26fn decode_offset_recursive(reader: &mut Decoder, types: Vec<DynSolType>, base_offset: usize) -> Result<Vec<FieldMetadata>, Error> {
27 let mut result = Vec::new();
28 for sol_type in types {
29 match sol_type.clone() {
30 DynSolType::Bool
31 | DynSolType::Int(_)
32 | DynSolType::Uint(_)
33 | DynSolType::FixedBytes(_)
34 | DynSolType::Address => {
35 let relative_offset = reader.offset();
36 let absolute_offset = base_offset + relative_offset;
37 let word = reader.take_word()?;
38 result.push(FieldMetadata{
39 offset: absolute_offset,
40 children: vec![],
41 is_dynamic: false,
42 size: Some(WORD_SIZE),
43 sol_type: sol_type,
44 value: Some(word.0.to_vec())
45 });
46 },
47 DynSolType::Bytes | DynSolType::String => {
48 let offset = reader.take_offset()?;
49 let mut sub_reader = reader.child(offset)?;
50 let size = sub_reader.take_offset()?; let data = sub_reader.take_slice(size)?;
52 let dynamic_field_absolute_offset = base_offset + offset + WORD_SIZE;
53 result.push(FieldMetadata{
54 offset: dynamic_field_absolute_offset,
55 children: vec![],
56 is_dynamic: true,
57 size: Some(size),
58 sol_type: sol_type,
59 value: Some(data.to_vec())
60 });
61 },
62 DynSolType::Array(array_element_sol_type_boxed) => {
63 let field_dynamic_offset = reader.take_offset()?; let absolute_offset = base_offset + field_dynamic_offset;
66 let mut sub_reader = reader.child(field_dynamic_offset)?; let number_of_elements = sub_reader.take_offset()?; let array_element_sol_type_unboxed = *array_element_sol_type_boxed;
72
73 let array_components: Vec<DynSolType> = match array_element_sol_type_unboxed.clone() {
75 DynSolType::Tuple(dyn_sol_types) => dyn_sol_types,
78 other => {
79 let mut types = Vec::new();
80 for _ in 0..number_of_elements {
81 types.push(other.clone());
82 }
83 types
84 }
85 };
86
87 let mut children = Vec::new();
88 if is_dynamic(array_element_sol_type_unboxed.clone()) {
89
90 let mut dynamic_array_relative_offsets = Vec::new();
93 for _ in 0..number_of_elements {
94 let child_element_offset = sub_reader.take_offset()?;
95 dynamic_array_relative_offsets.push(child_element_offset);
96 }
97
98 for array_element_offset in dynamic_array_relative_offsets {
101
102 let semi_absolute_positon = field_dynamic_offset+array_element_offset+WORD_SIZE;
104 let mut child_element_sub_reader = reader.child(semi_absolute_positon)?;
105
106 let position = base_offset+semi_absolute_positon;
108
109 let children_of_child = decode_offset_recursive(&mut child_element_sub_reader, array_components.clone(), position)?;
111
112 children.push(FieldMetadata {
113 children: children_of_child,
114 is_dynamic: true,
115 offset: position,
116 size: None,
117 sol_type: array_element_sol_type_unboxed.clone(),
118 value: None
119 });
120 }
121 } else {
122 children = decode_offset_recursive(&mut sub_reader, array_components, absolute_offset)?;
126 }
127
128 result.push(FieldMetadata {
129 children: children,
130 is_dynamic: true,
131 offset: absolute_offset,
132 size: None,
133 sol_type: sol_type,
134 value: None
135 });
136 },
137 DynSolType::FixedArray(array_element_sol_type_boxed, number_of_elements) => {
138
139 let array_element_sol_type_unboxed = *array_element_sol_type_boxed;
142
143 let array_components: Vec<DynSolType> = match array_element_sol_type_unboxed.clone() {
145 DynSolType::Tuple(dyn_sol_types) => dyn_sol_types,
147 other => {
148 let mut types = Vec::new();
149 for _ in 0..number_of_elements {
150 types.push(other.clone());
151 }
152 types
153 }
154 };
155
156
157
158 if is_dynamic(array_element_sol_type_unboxed.clone()) {
160
161 let offset = reader.take_offset()?;
163 let absolute_offset = base_offset + offset;
164
165 let mut sub_reader = reader.child(offset)?;
167 let children = decode_offset_recursive(&mut sub_reader, array_components, absolute_offset)?;
168 result.push(FieldMetadata {
169 children: children,
170 is_dynamic: true,
171 offset: absolute_offset,
172 size: None,
173 value: None,
174 sol_type: sol_type
175 });
176
177 } else {
178 let absolute_offset = base_offset + reader.offset();
180 let children = decode_offset_recursive(reader, array_components, absolute_offset)?;
181 result.push(FieldMetadata {
182 children: children,
183 is_dynamic: false,
184 offset: absolute_offset,
185 size: None,
186 value: None,
187 sol_type: sol_type
188 });
189 }
190 },
191 DynSolType::Tuple(tuple_components) => {
192 if is_dynamic(sol_type.clone()) {
193 let offset_of_tuple = base_offset + reader.offset();
194 let offset_of_dynamic_data = reader.take_offset()?;
195 let mut sub_reader = reader.child(offset_of_dynamic_data)?;
196 let children = decode_offset_recursive(&mut sub_reader, tuple_components, offset_of_dynamic_data)?;
197 result.push(FieldMetadata {
198 offset: offset_of_tuple,
199 children: children,
200 is_dynamic: true,
201 size: None,
202 sol_type: sol_type,
203 value: None
204 });
205 } else {
206 let offset_of_tuple = base_offset + reader.offset();
207 let children = decode_offset_recursive(reader, tuple_components, base_offset)?;
208 result.push(FieldMetadata {
209 offset: offset_of_tuple,
210 children: children,
211 is_dynamic: false,
212 size: None,
213 sol_type: sol_type,
214 value: None
215 });
216 }
217 },
218 DynSolType::Function => {
219 return Err(Error::custom("Cannot decode functions, with this decoder.."));
220 }
221 }
222 }
223
224 Ok(result)
225}
226
227pub fn is_dynamic(sol_type: DynSolType) -> bool {
228
229
230 match sol_type {
252 DynSolType::Bool => false,
253 DynSolType::Int(_) => false,
254 DynSolType::Uint(_) => false,
255 DynSolType::FixedBytes(_) => false,
256 DynSolType::Address => false,
257 DynSolType::Function => todo!(),
258 DynSolType::Bytes => true,
259 DynSolType::String => true,
260 DynSolType::Array(_array_children) => true,
261 DynSolType::FixedArray(array_children, _array_size) => {
262 if is_dynamic(*array_children) {
263 true
264 } else {
265 false
266 }
267 },
268 DynSolType::Tuple(tuple_components) => {
269 for tuple_component in tuple_components {
270 if is_dynamic(tuple_component) {
271 return true;
272 }
273 }
274
275 false
276 },
277 }
278}