1use std::collections::HashMap;
61use std::sync::{Arc, Mutex};
62
63use alloy_dyn_abi::DynSolValue;
64use alloy_primitives::{Address, U256};
65use eyre::{bail, Result};
66
67use super::*;
68
69#[derive(Debug, Clone, Default)]
71pub struct DebugHandler;
72
73impl DebugHandler {
74 pub fn new() -> Self {
79 Self
80 }
81}
82
83#[derive(Debug, Clone)]
85pub struct SimulationDebugHandler {
86 variables: Arc<Mutex<HashMap<String, DynSolValue>>>,
88 functions: Arc<Mutex<HashMap<String, DynSolValue>>>,
90 log: Arc<Mutex<Vec<String>>>,
92 verbose: bool,
94}
95
96impl Default for SimulationDebugHandler {
97 fn default() -> Self {
98 Self::new()
99 }
100}
101
102impl SimulationDebugHandler {
103 pub fn new() -> Self {
105 Self {
106 variables: Arc::new(Mutex::new(HashMap::new())),
107 functions: Arc::new(Mutex::new(HashMap::new())),
108 log: Arc::new(Mutex::new(Vec::new())),
109 verbose: true,
110 }
111 }
112
113 pub fn set_variable(&self, name: &str, value: DynSolValue) {
115 if let Ok(mut vars) = self.variables.lock() {
116 vars.insert(name.to_string(), value);
117 }
118 }
119
120 pub fn set_function(&self, name: &str, return_value: DynSolValue) {
122 if let Ok(mut funcs) = self.functions.lock() {
123 funcs.insert(name.to_string(), return_value);
124 }
125 }
126
127 pub fn get_log(&self) -> Vec<String> {
129 if let Ok(log) = self.log.lock() {
130 log.clone()
131 } else {
132 vec![]
133 }
134 }
135
136 pub fn clear_log(&self) {
138 if let Ok(mut log) = self.log.lock() {
139 log.clear();
140 }
141 }
142
143 fn log_operation(&self, message: String) {
145 if self.verbose {
146 if let Ok(mut log) = self.log.lock() {
147 log.push(message);
148 }
149 }
150 }
151
152 fn generate_default_value(&self, hint: &str) -> DynSolValue {
154 match hint {
155 name if name.contains("balance")
156 || name.contains("amount")
157 || name.contains("value") =>
158 {
159 DynSolValue::Uint(U256::from(1000000), 256) }
161 name if name.contains("address")
162 || name.contains("owner")
163 || name.contains("sender") =>
164 {
165 DynSolValue::Address(Address::from([0x42; 20])) }
167 name if name.contains("count") || name.contains("length") || name.contains("index") => {
168 DynSolValue::Uint(U256::from(5), 256) }
170 name if name.contains("enabled")
171 || name.contains("active")
172 || name.contains("flag") =>
173 {
174 DynSolValue::Bool(true) }
176 name if name.contains("name") || name.contains("symbol") || name.contains("uri") => {
177 DynSolValue::String(format!("Mock_{name}")) }
179 _ => DynSolValue::Uint(U256::from(42), 256), }
181 }
182}
183
184impl VariableHandler for DebugHandler {
185 fn get_variable_value(&self, name: &str, snapshot_id: usize) -> Result<DynSolValue> {
186 bail!(
187 "DebugHandler::get_variable_value called with name='{}', snapshot_id={}",
188 name,
189 snapshot_id
190 )
191 }
192}
193
194impl MappingArrayHandler for DebugHandler {
195 fn get_mapping_or_array_value(
196 &self,
197 root: DynSolValue,
198 indices: Vec<DynSolValue>,
199 snapshot_id: usize,
200 ) -> Result<DynSolValue> {
201 let indices_str = indices.iter().map(|v| format!("{v:?}")).collect::<Vec<_>>().join(", ");
202 bail!(
203 "DebugHandler::get_mapping_or_array_value called with root={:?}, indices=[{}], snapshot_id={}",
204 root,
205 indices_str,
206 snapshot_id
207 )
208 }
209}
210
211impl FunctionCallHandler for DebugHandler {
212 fn call_function(
213 &self,
214 name: &str,
215 args: &[DynSolValue],
216 callee: Option<&DynSolValue>,
217 snapshot_id: usize,
218 ) -> Result<DynSolValue> {
219 let args_str = args.iter().map(|v| format!("{v:?}")).collect::<Vec<_>>().join(", ");
220 let callee_str = callee.map(|c| format!("{c:?}")).unwrap_or_else(|| "None".to_string());
221 bail!(
222 "DebugHandler::call_function called with name='{}', args=[{}], callee={}, snapshot_id={}",
223 name,
224 args_str,
225 callee_str,
226 snapshot_id
227 )
228 }
229}
230
231impl MemberAccessHandler for DebugHandler {
232 fn access_member(
233 &self,
234 value: DynSolValue,
235 member: &str,
236 snapshot_id: usize,
237 ) -> Result<DynSolValue> {
238 bail!(
239 "DebugHandler::access_member called with value={:?}, member='{}', snapshot_id={}",
240 value,
241 member,
242 snapshot_id
243 )
244 }
245}
246
247impl MsgHandler for DebugHandler {
248 fn get_msg_sender(&self, snapshot_id: usize) -> Result<DynSolValue> {
249 bail!("DebugHandler::get_msg_sender called with snapshot_id={}", snapshot_id)
250 }
251
252 fn get_msg_value(&self, snapshot_id: usize) -> Result<DynSolValue> {
253 bail!("DebugHandler::get_msg_value called with snapshot_id={}", snapshot_id)
254 }
255}
256
257impl TxHandler for DebugHandler {
258 fn get_tx_origin(&self, snapshot_id: usize) -> Result<DynSolValue> {
259 bail!("DebugHandler::get_tx_origin called with snapshot_id={}", snapshot_id)
260 }
261}
262
263impl BlockHandler for DebugHandler {
264 fn get_block_number(&self, snapshot_id: usize) -> Result<DynSolValue> {
265 bail!("DebugHandler::get_block_number called with snapshot_id={}", snapshot_id)
266 }
267
268 fn get_block_timestamp(&self, snapshot_id: usize) -> Result<DynSolValue> {
269 bail!("DebugHandler::get_block_timestamp called with snapshot_id={}", snapshot_id)
270 }
271}
272
273impl ValidationHandler for DebugHandler {
274 fn validate_value(&self, value: DynSolValue) -> Result<DynSolValue> {
275 Ok(value)
276 }
277}
278
279impl VariableHandler for SimulationDebugHandler {
281 fn get_variable_value(&self, name: &str, snapshot_id: usize) -> Result<DynSolValue> {
282 self.log_operation(format!("get_variable_value: name='{name}', snapshot_id={snapshot_id}"));
283
284 if let Ok(vars) = self.variables.lock() {
285 if let Some(value) = vars.get(name) {
286 self.log_operation(format!(" -> returning stored value: {value:?}"));
287 return Ok(value.clone());
288 }
289 }
290
291 let default_value = self.generate_default_value(name);
293 self.log_operation(format!(" -> generating default value: {default_value:?}"));
294 Ok(default_value)
295 }
296}
297
298impl MappingArrayHandler for SimulationDebugHandler {
299 fn get_mapping_or_array_value(
300 &self,
301 root: DynSolValue,
302 indices: Vec<DynSolValue>,
303 snapshot_id: usize,
304 ) -> Result<DynSolValue> {
305 let indices_str = indices.iter().map(|v| format!("{v:?}")).collect::<Vec<_>>().join(", ");
306 self.log_operation(format!(
307 "get_mapping_or_array_value: root={root:?}, indices=[{indices_str}], snapshot_id={snapshot_id}"
308 ));
309
310 let result = match indices.first() {
313 Some(DynSolValue::Uint(index, _)) => {
314 DynSolValue::Uint(U256::from(1000 + index.to::<u64>()), 256)
316 }
317 Some(DynSolValue::Address(_)) => {
318 DynSolValue::Uint(U256::from(1000000), 256)
320 }
321 Some(DynSolValue::String(key)) => {
322 self.generate_default_value(key)
324 }
325 _ => DynSolValue::Uint(U256::from(42), 256),
326 };
327
328 self.log_operation(format!(" -> returning: {result:?}"));
329 Ok(result)
330 }
331}
332
333impl FunctionCallHandler for SimulationDebugHandler {
334 fn call_function(
335 &self,
336 name: &str,
337 args: &[DynSolValue],
338 callee: Option<&DynSolValue>,
339 snapshot_id: usize,
340 ) -> Result<DynSolValue> {
341 let args_str = args.iter().map(|v| format!("{v:?}")).collect::<Vec<_>>().join(", ");
342 let callee_str = callee.map(|c| format!("{c:?}")).unwrap_or_else(|| "None".to_string());
343 self.log_operation(format!(
344 "call_function: name='{name}', args=[{args_str}], callee={callee_str}, snapshot_id={snapshot_id}"
345 ));
346
347 if let Ok(funcs) = self.functions.lock() {
348 if let Some(value) = funcs.get(name) {
349 self.log_operation(format!(" -> returning stored value: {value:?}"));
350 return Ok(value.clone());
351 }
352 }
353
354 let result = match name {
356 "balanceOf" => DynSolValue::Uint(U256::from(1000000), 256),
357 "totalSupply" => DynSolValue::Uint(U256::from(1000000000), 256),
358 "approve" | "transfer" => DynSolValue::Bool(true),
359 "name" => DynSolValue::String("MockToken".to_string()),
360 "symbol" => DynSolValue::String("MTK".to_string()),
361 "decimals" => DynSolValue::Uint(U256::from(18), 256),
362 _ => self.generate_default_value(name),
363 };
364
365 self.log_operation(format!(" -> returning generated value: {result:?}"));
366 Ok(result)
367 }
368}
369
370impl MemberAccessHandler for SimulationDebugHandler {
371 fn access_member(
372 &self,
373 value: DynSolValue,
374 member: &str,
375 snapshot_id: usize,
376 ) -> Result<DynSolValue> {
377 self.log_operation(format!(
378 "access_member: value={value:?}, member='{member}', snapshot_id={snapshot_id}"
379 ));
380
381 let result = match member {
383 "length" => DynSolValue::Uint(U256::from(10), 256), "balance" => DynSolValue::Uint(U256::from(1000000), 256), "code" => DynSolValue::Bytes(vec![0x60, 0x80, 0x60, 0x40]), _ => self.generate_default_value(member),
387 };
388
389 self.log_operation(format!(" -> returning: {result:?}"));
390 Ok(result)
391 }
392}
393
394impl MsgHandler for SimulationDebugHandler {
395 fn get_msg_sender(&self, snapshot_id: usize) -> Result<DynSolValue> {
396 self.log_operation(format!("get_msg_sender: snapshot_id={snapshot_id}"));
397 let result = DynSolValue::Address(Address::from([0x42; 20])); self.log_operation(format!(" -> returning: {result:?}"));
399 Ok(result)
400 }
401
402 fn get_msg_value(&self, snapshot_id: usize) -> Result<DynSolValue> {
403 self.log_operation(format!("get_msg_value: snapshot_id={snapshot_id}"));
404 let result = DynSolValue::Uint(U256::from(1000000000000000000u64), 256); self.log_operation(format!(" -> returning: {result:?}"));
406 Ok(result)
407 }
408}
409
410impl TxHandler for SimulationDebugHandler {
411 fn get_tx_origin(&self, snapshot_id: usize) -> Result<DynSolValue> {
412 self.log_operation(format!("get_tx_origin: snapshot_id={snapshot_id}"));
413 let result = DynSolValue::Address(Address::from([0x11; 20])); self.log_operation(format!(" -> returning: {result:?}"));
415 Ok(result)
416 }
417}
418
419impl BlockHandler for SimulationDebugHandler {
420 fn get_block_number(&self, snapshot_id: usize) -> Result<DynSolValue> {
421 self.log_operation(format!("get_block_number: snapshot_id={snapshot_id}"));
422 let result = DynSolValue::Uint(U256::from(18500000), 256); self.log_operation(format!(" -> returning: {result:?}"));
424 Ok(result)
425 }
426
427 fn get_block_timestamp(&self, snapshot_id: usize) -> Result<DynSolValue> {
428 self.log_operation(format!("get_block_timestamp: snapshot_id={snapshot_id}"));
429 let result = DynSolValue::Uint(U256::from(1700000000), 256); self.log_operation(format!(" -> returning: {result:?}"));
431 Ok(result)
432 }
433}
434
435impl VariableHandler for Arc<SimulationDebugHandler> {
437 fn get_variable_value(&self, name: &str, snapshot_id: usize) -> Result<DynSolValue> {
438 self.as_ref().get_variable_value(name, snapshot_id)
439 }
440}
441
442impl MappingArrayHandler for Arc<SimulationDebugHandler> {
443 fn get_mapping_or_array_value(
444 &self,
445 root: DynSolValue,
446 indices: Vec<DynSolValue>,
447 snapshot_id: usize,
448 ) -> Result<DynSolValue> {
449 self.as_ref().get_mapping_or_array_value(root, indices, snapshot_id)
450 }
451}
452
453impl FunctionCallHandler for Arc<SimulationDebugHandler> {
454 fn call_function(
455 &self,
456 name: &str,
457 args: &[DynSolValue],
458 callee: Option<&DynSolValue>,
459 snapshot_id: usize,
460 ) -> Result<DynSolValue> {
461 self.as_ref().call_function(name, args, callee, snapshot_id)
462 }
463}
464
465impl MemberAccessHandler for Arc<SimulationDebugHandler> {
466 fn access_member(
467 &self,
468 value: DynSolValue,
469 member: &str,
470 snapshot_id: usize,
471 ) -> Result<DynSolValue> {
472 self.as_ref().access_member(value, member, snapshot_id)
473 }
474}
475
476impl MsgHandler for Arc<SimulationDebugHandler> {
477 fn get_msg_sender(&self, snapshot_id: usize) -> Result<DynSolValue> {
478 self.as_ref().get_msg_sender(snapshot_id)
479 }
480
481 fn get_msg_value(&self, snapshot_id: usize) -> Result<DynSolValue> {
482 self.as_ref().get_msg_value(snapshot_id)
483 }
484}
485
486impl TxHandler for Arc<SimulationDebugHandler> {
487 fn get_tx_origin(&self, snapshot_id: usize) -> Result<DynSolValue> {
488 self.as_ref().get_tx_origin(snapshot_id)
489 }
490}
491
492impl BlockHandler for Arc<SimulationDebugHandler> {
493 fn get_block_number(&self, snapshot_id: usize) -> Result<DynSolValue> {
494 self.as_ref().get_block_number(snapshot_id)
495 }
496
497 fn get_block_timestamp(&self, snapshot_id: usize) -> Result<DynSolValue> {
498 self.as_ref().get_block_timestamp(snapshot_id)
499 }
500}
501
502impl ValidationHandler for Arc<SimulationDebugHandler> {
503 fn validate_value(&self, value: DynSolValue) -> Result<DynSolValue> {
504 Ok(value)
505 }
506}
507
508pub fn create_debug_handlers() -> EvaluatorHandlers {
510 EvaluatorHandlers::new()
511 .with_variable_handler(Box::new(DebugHandler::new()))
512 .with_mapping_array_handler(Box::new(DebugHandler::new()))
513 .with_function_call_handler(Box::new(DebugHandler::new()))
514 .with_member_access_handler(Box::new(DebugHandler::new()))
515 .with_msg_handler(Box::new(DebugHandler::new()))
516 .with_tx_handler(Box::new(DebugHandler::new()))
517 .with_block_handler(Box::new(DebugHandler::new()))
518 .with_validation_handler(Box::new(DebugHandler::new()))
519}
520
521pub fn create_simulation_debug_handlers() -> (EvaluatorHandlers, Arc<SimulationDebugHandler>) {
523 let handler = Arc::new(SimulationDebugHandler::new());
524 let handlers = EvaluatorHandlers::new()
525 .with_variable_handler(Box::new(handler.clone()))
526 .with_mapping_array_handler(Box::new(handler.clone()))
527 .with_function_call_handler(Box::new(handler.clone()))
528 .with_member_access_handler(Box::new(handler.clone()))
529 .with_msg_handler(Box::new(handler.clone()))
530 .with_tx_handler(Box::new(handler.clone()))
531 .with_block_handler(Box::new(handler.clone()))
532 .with_validation_handler(Box::new(handler.clone()));
533
534 (handlers, handler)
535}