edb_engine/eval/
evaluator.rs

1// EDB - Ethereum Debugger
2// Copyright (C) 2024 Zhuo Zhang and Wuqi Zhang
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU Affero General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU Affero General Public License for more details.
13//
14// You should have received a copy of the GNU Affero General Public License
15// along with this program. If not, see <https://www.gnu.org/licenses/>.
16
17use std::sync::Arc;
18
19use alloy_dyn_abi::DynSolValue;
20use alloy_primitives::{Address, B256, I256, U256};
21use eyre::{bail, Result};
22use revm::database::CacheDB;
23use revm::{Database, DatabaseCommit, DatabaseRef};
24use solang_parser::pt::{Expression, Identifier, Loc, Parameter, Type};
25
26use crate::eval::handlers::debug::create_debug_handlers;
27use crate::eval::handlers::edb::EdbHandler;
28use crate::EngineContext;
29
30use super::handlers::EvaluatorHandlers;
31use super::utils::parse_input;
32
33/// Main expression evaluator for Solidity-like expressions.
34///
35/// The `ExpressionEvaluator` parses and evaluates Solidity-like expressions against
36/// configurable data sources through the handler pattern. It supports a wide range
37/// of expression types including variables, function calls, arithmetic operations,
38/// type casting, and blockchain context access.
39///
40/// # Architecture
41///
42/// The evaluator uses a handler-based architecture where different aspects of
43/// evaluation are delegated to specialized handlers:
44/// - Variable resolution
45/// - Function calls
46/// - Mapping/array access
47/// - Member access
48/// - Blockchain context (`msg`, `tx`, `block`)
49/// - Value validation
50///
51/// # Supported Operations
52///
53/// - **Variables**: Local variables, state variables, special variables (`this`)
54/// - **Literals**: Numbers (decimal/hex), strings, booleans, addresses
55/// - **Arithmetic**: `+`, `-`, `*`, `/`, `%`, `**`
56/// - **Comparison**: `==`, `!=`, `<`, `<=`, `>`, `>=`
57/// - **Logical**: `&&`, `||`, `!`
58/// - **Bitwise**: `&`, `|`, `^`, `~`, `<<`, `>>`
59/// - **Indexing**: Arrays and mappings with bracket notation
60/// - **Member Access**: Dot notation for structs and contract members
61/// - **Function Calls**: Contract functions and built-in functions
62/// - **Type Casting**: Explicit type conversions (e.g., `uint256(value)`)
63/// - **Ternary**: Conditional operator `? :`
64///
65/// # Example
66///
67/// ```rust,ignore
68/// use edb_engine::eval::{ExpressionEvaluator, handlers::EdbHandler};
69///
70/// // Create evaluator with EDB handlers
71/// let handlers = EdbHandler::create_handlers(engine_context);
72/// let evaluator = ExpressionEvaluator::new(handlers);
73///
74/// // Evaluate various expressions
75/// let balance = evaluator.eval("balances[msg.sender]", snapshot_id)?;
76/// let is_owner = evaluator.eval("msg.sender == owner", snapshot_id)?;
77/// let calculation = evaluator.eval("totalSupply() * price / 1e18", snapshot_id)?;
78/// ```
79#[derive(Clone)]
80pub struct ExpressionEvaluator {
81    handlers: EvaluatorHandlers,
82}
83
84impl ExpressionEvaluator {
85    /// Create a new evaluator with the given handlers
86    pub fn new(handlers: EvaluatorHandlers) -> Self {
87        Self { handlers }
88    }
89
90    /// Create a new evaluator with default (empty) handlers
91    pub fn new_default() -> Self {
92        Self { handlers: EvaluatorHandlers::new() }
93    }
94
95    /// Create a new evaluator with debug handlers that always error
96    pub fn new_debug() -> Self {
97        let handlers = create_debug_handlers();
98        Self { handlers }
99    }
100
101    /// Create a new evaluator with EDB handlers using the given context
102    pub fn new_edb<DB>(context: Arc<EngineContext<DB>>) -> Self
103    where
104        DB: Database + DatabaseCommit + DatabaseRef + Clone + Send + Sync + 'static,
105        <CacheDB<DB> as Database>::Error: Clone + Send + Sync,
106        <DB as Database>::Error: Clone + Send + Sync,
107    {
108        let handlers = EdbHandler::create_handlers(context);
109        Self { handlers }
110    }
111
112    /// Evaluate an expression against a specific snapshot
113    pub fn eval(&self, expr: &str, snapshot_id: usize) -> Result<DynSolValue> {
114        // Parse the expression
115        let parsed_expr =
116            parse_input(expr).map_err(|_| eyre::eyre!("Invalid expression \"{expr}\""))?;
117
118        // Evaluate the parsed expression
119        let value = self.evaluate_expression(&parsed_expr, snapshot_id)?;
120
121        // If a validation handler is set, validate the final value
122        if let Some(validation_handler) = &self.handlers.validation_handler {
123            validation_handler.validate_value(value)
124        } else {
125            Ok(value)
126        }
127    }
128
129    /// Main evaluation dispatcher for different expression types
130    fn evaluate_expression(&self, expr: &Expression, snapshot_id: usize) -> Result<DynSolValue> {
131        match expr {
132            // Literals
133            Expression::NumberLiteral(_, value, _, ident) => {
134                if ident.is_none() {
135                    self.evaluate_number_literal(value)
136                } else {
137                    bail!("Invalid number literal")
138                }
139            }
140            Expression::HexNumberLiteral(_, value, ident) => {
141                if ident.is_none() {
142                    self.evaluate_number_literal(value)
143                } else {
144                    bail!("Invalid hex number literal")
145                }
146            }
147            Expression::StringLiteral(literals) => self.evaluate_string_literal(literals),
148            Expression::BoolLiteral(_, value) => Ok(DynSolValue::Bool(*value)),
149            Expression::AddressLiteral(_, addr) => self.evaluate_address_literal(addr),
150
151            // Variables and member access
152            Expression::Variable(ident) => self.evaluate_variable(ident, snapshot_id),
153            Expression::MemberAccess(_, base, member) => {
154                self.evaluate_member_access(base, member, snapshot_id)
155            }
156
157            // Array and mapping access
158            Expression::ArraySubscript(_, array, index) => self.evaluate_array_or_mapping_access(
159                array,
160                index.as_ref().map(|v| &**v),
161                snapshot_id,
162            ),
163
164            // Function calls
165            Expression::FunctionCall(_, func, args) => {
166                self.evaluate_function_call(func, args, snapshot_id)
167            }
168
169            // Arithmetic operations
170            Expression::Add(_, left, right) => {
171                self.evaluate_binary_arithmetic(left, right, snapshot_id, ArithmeticOp::Add)
172            }
173            Expression::Subtract(_, left, right) => {
174                self.evaluate_binary_arithmetic(left, right, snapshot_id, ArithmeticOp::Subtract)
175            }
176            Expression::Multiply(_, left, right) => {
177                self.evaluate_binary_arithmetic(left, right, snapshot_id, ArithmeticOp::Multiply)
178            }
179            Expression::Divide(_, left, right) => {
180                self.evaluate_binary_arithmetic(left, right, snapshot_id, ArithmeticOp::Divide)
181            }
182            Expression::Modulo(_, left, right) => {
183                self.evaluate_binary_arithmetic(left, right, snapshot_id, ArithmeticOp::Modulo)
184            }
185            Expression::Power(_, base, exp) => {
186                self.evaluate_binary_arithmetic(base, exp, snapshot_id, ArithmeticOp::Power)
187            }
188
189            // Bitwise operations
190            Expression::BitwiseAnd(_, left, right) => {
191                self.evaluate_bitwise(left, right, snapshot_id, BitwiseOp::And)
192            }
193            Expression::BitwiseOr(_, left, right) => {
194                self.evaluate_bitwise(left, right, snapshot_id, BitwiseOp::Or)
195            }
196            Expression::BitwiseXor(_, left, right) => {
197                self.evaluate_bitwise(left, right, snapshot_id, BitwiseOp::Xor)
198            }
199            Expression::BitwiseNot(_, operand) => self.evaluate_bitwise_not(operand, snapshot_id),
200            Expression::ShiftLeft(_, left, right) => {
201                self.evaluate_bitwise(left, right, snapshot_id, BitwiseOp::ShiftLeft)
202            }
203            Expression::ShiftRight(_, left, right) => {
204                self.evaluate_bitwise(left, right, snapshot_id, BitwiseOp::ShiftRight)
205            }
206
207            // Comparison operations
208            Expression::Equal(_, left, right) => {
209                self.evaluate_comparison(left, right, snapshot_id, ComparisonOp::Equal)
210            }
211            Expression::NotEqual(_, left, right) => {
212                self.evaluate_comparison(left, right, snapshot_id, ComparisonOp::NotEqual)
213            }
214            Expression::Less(_, left, right) => {
215                self.evaluate_comparison(left, right, snapshot_id, ComparisonOp::Less)
216            }
217            Expression::More(_, left, right) => {
218                self.evaluate_comparison(left, right, snapshot_id, ComparisonOp::Greater)
219            }
220            Expression::LessEqual(_, left, right) => {
221                self.evaluate_comparison(left, right, snapshot_id, ComparisonOp::LessEqual)
222            }
223            Expression::MoreEqual(_, left, right) => {
224                self.evaluate_comparison(left, right, snapshot_id, ComparisonOp::GreaterEqual)
225            }
226
227            // Logical operations
228            Expression::And(_, left, right) => {
229                self.evaluate_logical(left, right, snapshot_id, LogicalOp::And)
230            }
231            Expression::Or(_, left, right) => {
232                self.evaluate_logical(left, right, snapshot_id, LogicalOp::Or)
233            }
234            Expression::Not(_, operand) => self.evaluate_logical_not(operand, snapshot_id),
235
236            // Unary operations
237            Expression::UnaryPlus(_, operand) => self.evaluate_expression(operand, snapshot_id),
238            Expression::Negate(_, operand) => self.evaluate_unary_minus(operand, snapshot_id),
239
240            // Ternary conditional
241            Expression::ConditionalOperator(_, condition, true_expr, false_expr) => {
242                self.evaluate_conditional(condition, true_expr, false_expr, snapshot_id)
243            }
244
245            // Parenthesis (just evaluate the inner expression)
246            Expression::Parenthesis(_, inner) => self.evaluate_expression(inner, snapshot_id),
247
248            // Array slice: arr[start:end]
249            Expression::ArraySlice(_, array, start, end) => {
250                self.evaluate_array_slice(array, start.as_deref(), end.as_deref(), snapshot_id)
251            }
252
253            // Hex literal: hex"deadbeef"
254            Expression::HexLiteral(literals) => self.evaluate_hex_literal(literals),
255
256            // Array literal: [1, 2, 3]
257            Expression::ArrayLiteral(_, elements) => {
258                self.evaluate_array_literal(elements, snapshot_id)
259            }
260
261            // List (tuple): (a, b, c)
262            Expression::List(_, parameters) => {
263                self.evaluate_list_parameters(parameters, snapshot_id)
264            }
265
266            Expression::New(..)
267            | Expression::Delete(..)
268            | Expression::PostDecrement(..)
269            | Expression::PostIncrement(..)
270            | Expression::PreDecrement(..)
271            | Expression::PreIncrement(..)
272            | Expression::Assign(..)
273            | Expression::AssignAdd(..)
274            | Expression::AssignSubtract(..)
275            | Expression::AssignMultiply(..)
276            | Expression::AssignDivide(..)
277            | Expression::AssignModulo(..)
278            | Expression::AssignShiftLeft(..)
279            | Expression::AssignShiftRight(..)
280            | Expression::AssignAnd(..)
281            | Expression::AssignOr(..)
282            | Expression::AssignXor(..)
283            | Expression::FunctionCallBlock(..)
284            | Expression::NamedFunctionCall(..)
285            | Expression::RationalNumberLiteral(..)
286            | Expression::Type(..) => bail!("Unsupported expression type: {:?}", expr),
287        }
288    }
289
290    /// Evaluate number literals (default to uint256 unless explicitly typed)
291    fn evaluate_number_literal(&self, value: &str) -> Result<DynSolValue> {
292        // Remove underscores and parse
293        let cleaned = value.replace('_', "");
294
295        // Check for hex prefix
296        let val = if cleaned.starts_with("0x") || cleaned.starts_with("0X") {
297            U256::from_str_radix(&cleaned[2..], 16)?
298        } else {
299            U256::from_str_radix(&cleaned, 10)?
300        };
301
302        Ok(DynSolValue::Uint(val, 256))
303    }
304
305    /// Evaluate string literals
306    fn evaluate_string_literal(
307        &self,
308        literals: &[solang_parser::pt::StringLiteral],
309    ) -> Result<DynSolValue> {
310        let mut result = String::new();
311        for lit in literals {
312            result.push_str(&lit.string);
313        }
314        Ok(DynSolValue::String(result))
315    }
316
317    /// Evaluate address literals
318    fn evaluate_address_literal(&self, addr: &str) -> Result<DynSolValue> {
319        let address = addr.parse::<Address>()?;
320        Ok(DynSolValue::Address(address))
321    }
322
323    /// Evaluate variables (including special ones like msg.sender)
324    fn evaluate_variable(&self, ident: &Identifier, snapshot_id: usize) -> Result<DynSolValue> {
325        match ident.name.as_str() {
326            "msg" | "tx" | "block" => {
327                // These need to be handled in member access
328                bail!("Cannot evaluate {} directly, use member access", ident.name)
329            }
330            name => {
331                // Get variable value from snapshot
332                self.get_variable_value(name, snapshot_id)
333            }
334        }
335    }
336
337    /// Evaluate member access (e.g., msg.sender, array.length)
338    fn evaluate_member_access(
339        &self,
340        base: &Expression,
341        member: &Identifier,
342        snapshot_id: usize,
343    ) -> Result<DynSolValue> {
344        // Special handling for global variables (msg, tx, block)
345        if let Expression::Variable(base_ident) = base {
346            match (base_ident.name.as_str(), member.name.as_str()) {
347                ("msg", "sender") => return self.get_msg_sender(snapshot_id),
348                ("msg", "value") => return self.get_msg_value(snapshot_id),
349                ("tx", "origin") => return self.get_tx_origin(snapshot_id),
350                ("block", "number") => return self.get_block_number(snapshot_id),
351                ("block", "timestamp") => return self.get_block_timestamp(snapshot_id),
352                // Additional msg/tx/block properties should be handled by extending handlers
353                // rather than hardcoding values here
354                _ => {}
355            }
356        }
357
358        // Regular member access with built-in property handling
359        let base_value = self.evaluate_expression(base, snapshot_id)?;
360
361        // First try built-in properties, then fall back to handlers
362        if let Some(builtin_result) = self.handle_builtin_property(&base_value, &member.name)? {
363            return Ok(builtin_result);
364        }
365
366        // Handle struct member access via handler
367        if let DynSolValue::CustomStruct { name, prop_names, tuple } = base_value {
368            if let Some((idx, _)) = prop_names.iter().enumerate().find(|(_, n)| *n == &member.name)
369            {
370                if let Some(value) = tuple.get(idx) {
371                    return Ok(value.clone());
372                } else {
373                    bail!("Struct {} has no member named {}", name, member.name);
374                }
375            } else {
376                bail!("Struct {} has no member named {}", name, member.name);
377            }
378        }
379
380        self.access_member(base_value, &member.name, snapshot_id)
381    }
382
383    /// Evaluate array or mapping access
384    fn evaluate_array_or_mapping_access(
385        &self,
386        base: &Expression,
387        index: Option<&Expression>,
388        snapshot_id: usize,
389    ) -> Result<DynSolValue> {
390        let index = index.ok_or_else(|| eyre::eyre!("Array/mapping access requires an index"))?;
391
392        // Collect all indices for multi-level access
393        let (root, indices) = self.collect_access_chain(base, vec![index], snapshot_id)?;
394
395        // Get the value using all indices at once
396        self.get_mapping_or_array_value(root, indices, snapshot_id)
397    }
398
399    /// Collect the full chain of array/mapping accesses
400    fn collect_access_chain<'a>(
401        &self,
402        expr: &'a Expression,
403        mut indices: Vec<&'a Expression>,
404        snapshot_id: usize,
405    ) -> Result<(DynSolValue, Vec<DynSolValue>)> {
406        match expr {
407            Expression::ArraySubscript(_, base, Some(index)) => {
408                indices.insert(0, index);
409                self.collect_access_chain(base, indices, snapshot_id)
410            }
411            _ => {
412                // Base case - evaluate the root expression
413                let root = self.evaluate_expression(expr, snapshot_id)?;
414                let evaluated_indices = indices
415                    .into_iter()
416                    .map(|idx| self.evaluate_expression(idx, snapshot_id))
417                    .collect::<Result<Vec<_>>>()?;
418                Ok((root, evaluated_indices))
419            }
420        }
421    }
422
423    /// Evaluate function calls
424    fn evaluate_function_call(
425        &self,
426        func: &Expression,
427        args: &[Expression],
428        snapshot_id: usize,
429    ) -> Result<DynSolValue> {
430        // Evaluate arguments
431        let arg_values = args
432            .iter()
433            .map(|arg| self.evaluate_expression(arg, snapshot_id))
434            .collect::<Result<Vec<_>>>()?;
435
436        // Determine function name and callee
437        let (func_name, callee) = match func {
438            Expression::Variable(ident) => (ident.name.clone(), None),
439            Expression::MemberAccess(_, base, member) => {
440                let callee = self.evaluate_expression(base, snapshot_id)?;
441
442                // Handle built-in properties/methods
443                if let Some(result) =
444                    self.handle_builtin_member_call(&member.name, &callee, &arg_values)?
445                {
446                    return Ok(result);
447                }
448
449                (member.name.clone(), Some(callee))
450            }
451            Expression::Type(_, ty) if arg_values.len() == 1 => {
452                // Type conversion like uint256(x)
453                let arg = arg_values.into_iter().next().unwrap();
454                return self.evaluate_type_casting(ty, arg);
455            }
456            _ => bail!("Unsupported function call expression: {}", func),
457        };
458
459        // Call the function
460        self.call_function(&func_name, &arg_values, callee.as_ref(), snapshot_id)
461    }
462
463    /// Handle built-in properties (like string.length, address.balance)
464    fn handle_builtin_property(
465        &self,
466        value: &DynSolValue,
467        property_name: &str,
468    ) -> Result<Option<DynSolValue>> {
469        match (property_name, value) {
470            // ============ LENGTH PROPERTIES ============
471            ("length", DynSolValue::String(s)) => {
472                Ok(Some(DynSolValue::Uint(U256::from(s.len()), 256)))
473            }
474            ("length", DynSolValue::Bytes(b)) => {
475                Ok(Some(DynSolValue::Uint(U256::from(b.len()), 256)))
476            }
477            ("length", DynSolValue::FixedBytes(_, size)) => {
478                Ok(Some(DynSolValue::Uint(U256::from(*size), 256)))
479            }
480            ("length", DynSolValue::Tuple(arr)) => {
481                Ok(Some(DynSolValue::Uint(U256::from(arr.len()), 256)))
482            }
483
484            // ============ ADDRESS PROPERTIES ============
485            // Note: These should ultimately be handled by specialized handlers
486            // that can access blockchain state, but we define the interface here
487            ("balance", DynSolValue::Address(_)) => {
488                // Delegate to handler - this is blockchain state
489                Ok(None)
490            }
491            ("code", DynSolValue::Address(_)) => {
492                // Delegate to handler - this is blockchain state
493                Ok(None)
494            }
495            ("codehash", DynSolValue::Address(_)) => {
496                // Delegate to handler - this is blockchain state
497                Ok(None)
498            }
499            ("codesize", DynSolValue::Address(_)) => {
500                // Delegate to handler - this is blockchain state
501                Ok(None)
502            }
503
504            // ============ NUMERIC PROPERTIES ============
505            ("abs", DynSolValue::Int(val, bits)) => {
506                // Absolute value for signed integers
507                let abs_val = if val.is_negative() { val.wrapping_neg() } else { *val };
508                Ok(Some(DynSolValue::Uint(abs_val.into_raw(), *bits)))
509            }
510
511            // ============ TYPE CHECKING PROPERTIES ============
512            ("isZero", DynSolValue::Uint(val, _bits)) => Ok(Some(DynSolValue::Bool(val.is_zero()))),
513            ("isZero", DynSolValue::Int(val, _bits)) => Ok(Some(DynSolValue::Bool(val.is_zero()))),
514            ("isZero", DynSolValue::Address(addr)) => {
515                Ok(Some(DynSolValue::Bool(*addr == Address::ZERO)))
516            }
517
518            _ => Ok(None), // Not a built-in property we handle
519        }
520    }
521
522    /// Handle built-in member calls (methods with arguments, like array.push(), string.concat())
523    fn handle_builtin_member_call(
524        &self,
525        member_name: &str,
526        callee: &DynSolValue,
527        args: &[DynSolValue],
528    ) -> Result<Option<DynSolValue>> {
529        match (member_name, callee, args.len()) {
530            // Note: Length properties are handled in handle_builtin_property since they take no arguments
531
532            // ============ ARRAY/LIST METHODS ============
533
534            // Push method for arrays (returns new length) - with element
535            ("push", DynSolValue::Tuple(arr), 1) => {
536                let new_length = arr.len() + 1;
537                Ok(Some(DynSolValue::Uint(U256::from(new_length), 256)))
538            }
539            // Push method for arrays - empty push (some Solidity arrays support this)
540            ("push", DynSolValue::Tuple(arr), 0) => {
541                let new_length = arr.len() + 1;
542                Ok(Some(DynSolValue::Uint(U256::from(new_length), 256)))
543            }
544            // Pop method for arrays (returns popped element)
545            ("pop", DynSolValue::Tuple(arr), 0) => {
546                if arr.is_empty() {
547                    bail!("Cannot pop from empty array")
548                } else {
549                    // Return the last element (actual popping behavior)
550                    Ok(Some(arr.last().unwrap().clone()))
551                }
552            }
553
554            // ============ STRING METHODS ============
555
556            // String concatenation
557            ("concat", DynSolValue::String(s), 1) => {
558                if let DynSolValue::String(other) = &args[0] {
559                    Ok(Some(DynSolValue::String(format!("{s}{other}"))))
560                } else {
561                    Ok(None)
562                }
563            }
564            // String slice/substring (start index)
565            ("slice", DynSolValue::String(s), 1) => {
566                if let DynSolValue::Uint(start, _) = &args[0] {
567                    let start_idx = start.to::<usize>();
568                    if start_idx <= s.len() {
569                        Ok(Some(DynSolValue::String(s[start_idx..].to_string())))
570                    } else {
571                        Ok(Some(DynSolValue::String(String::new())))
572                    }
573                } else {
574                    Ok(None)
575                }
576            }
577            // String slice/substring (start and end)
578            ("slice", DynSolValue::String(s), 2) => {
579                if let (DynSolValue::Uint(start, _), DynSolValue::Uint(end, _)) =
580                    (&args[0], &args[1])
581                {
582                    let start_idx = start.to::<usize>();
583                    let end_idx = end.to::<usize>();
584                    if start_idx <= end_idx && end_idx <= s.len() {
585                        Ok(Some(DynSolValue::String(s[start_idx..end_idx].to_string())))
586                    } else {
587                        Ok(Some(DynSolValue::String(String::new())))
588                    }
589                } else {
590                    Ok(None)
591                }
592            }
593
594            // ============ BYTES METHODS ============
595
596            // Bytes concatenation
597            ("concat", DynSolValue::Bytes(b1), 1) => {
598                if let DynSolValue::Bytes(b2) = &args[0] {
599                    let mut result = b1.clone();
600                    result.extend_from_slice(b2);
601                    Ok(Some(DynSolValue::Bytes(result)))
602                } else {
603                    Ok(None)
604                }
605            }
606            // Bytes slice (start index)
607            ("slice", DynSolValue::Bytes(b), 1) => {
608                if let DynSolValue::Uint(start, _) = &args[0] {
609                    let start_idx = start.to::<usize>();
610                    if start_idx <= b.len() {
611                        Ok(Some(DynSolValue::Bytes(b[start_idx..].to_vec())))
612                    } else {
613                        Ok(Some(DynSolValue::Bytes(Vec::new())))
614                    }
615                } else {
616                    Ok(None)
617                }
618            }
619            // Bytes slice (start and end)
620            ("slice", DynSolValue::Bytes(b), 2) => {
621                if let (DynSolValue::Uint(start, _), DynSolValue::Uint(end, _)) =
622                    (&args[0], &args[1])
623                {
624                    let start_idx = start.to::<usize>();
625                    let end_idx = end.to::<usize>();
626                    if start_idx <= end_idx && end_idx <= b.len() {
627                        Ok(Some(DynSolValue::Bytes(b[start_idx..end_idx].to_vec())))
628                    } else {
629                        Ok(Some(DynSolValue::Bytes(Vec::new())))
630                    }
631                } else {
632                    Ok(None)
633                }
634            }
635
636            // ============ MATH FUNCTIONS ============
637
638            // Math.min for uint values
639            ("min", DynSolValue::Uint(a, bits), 1) => {
640                if let DynSolValue::Uint(b, _) = &args[0] {
641                    Ok(Some(DynSolValue::Uint((*a).min(*b), *bits)))
642                } else {
643                    Ok(None)
644                }
645            }
646            // Math.max for uint values
647            ("max", DynSolValue::Uint(a, bits), 1) => {
648                if let DynSolValue::Uint(b, _) = &args[0] {
649                    Ok(Some(DynSolValue::Uint((*a).max(*b), *bits)))
650                } else {
651                    Ok(None)
652                }
653            }
654
655            // ============ TYPE CHECKING FUNCTIONS ============
656
657            // Check if string is empty
658            ("isEmpty", DynSolValue::String(s), 0) => Ok(Some(DynSolValue::Bool(s.is_empty()))),
659            // Check if bytes is empty
660            ("isEmpty", DynSolValue::Bytes(b), 0) => Ok(Some(DynSolValue::Bool(b.is_empty()))),
661            // Check if array is empty
662            ("isEmpty", DynSolValue::Tuple(arr), 0) => Ok(Some(DynSolValue::Bool(arr.is_empty()))),
663
664            _ => Ok(None), // Not a built-in we handle
665        }
666    }
667
668    /// Evaluate binary arithmetic operations
669    fn evaluate_binary_arithmetic(
670        &self,
671        left: &Expression,
672        right: &Expression,
673        snapshot_id: usize,
674        op: ArithmeticOp,
675    ) -> Result<DynSolValue> {
676        let left_val = self.evaluate_expression(left, snapshot_id)?;
677        let right_val = self.evaluate_expression(right, snapshot_id)?;
678
679        self.apply_arithmetic_op(left_val, right_val, op)
680    }
681
682    /// Apply arithmetic operation on DynSolValues
683    fn apply_arithmetic_op(
684        &self,
685        left: DynSolValue,
686        right: DynSolValue,
687        op: ArithmeticOp,
688    ) -> Result<DynSolValue> {
689        match (left, right) {
690            (DynSolValue::Uint(l, bits1), DynSolValue::Uint(r, bits2)) => {
691                let bits = bits1.max(bits2);
692                let result = match op {
693                    ArithmeticOp::Add => l.saturating_add(r),
694                    ArithmeticOp::Subtract => l.saturating_sub(r),
695                    ArithmeticOp::Multiply => l.saturating_mul(r),
696                    ArithmeticOp::Divide => {
697                        if r.is_zero() {
698                            bail!("Division by zero");
699                        }
700                        l / r
701                    }
702                    ArithmeticOp::Modulo => {
703                        if r.is_zero() {
704                            bail!("Modulo by zero");
705                        }
706                        l % r
707                    }
708                    ArithmeticOp::Power => l.saturating_pow(r),
709                };
710                Ok(DynSolValue::Uint(result, bits))
711            }
712            (DynSolValue::Int(l, bits1), DynSolValue::Int(r, bits2)) => {
713                let bits = bits1.max(bits2);
714                let result = match op {
715                    ArithmeticOp::Add => l.saturating_add(r),
716                    ArithmeticOp::Subtract => l.saturating_sub(r),
717                    ArithmeticOp::Multiply => l.saturating_mul(r),
718                    ArithmeticOp::Divide => {
719                        if r.is_zero() {
720                            bail!("Division by zero");
721                        }
722                        l / r
723                    }
724                    ArithmeticOp::Modulo => {
725                        if r.is_zero() {
726                            bail!("Modulo by zero");
727                        }
728                        l % r
729                    }
730                    ArithmeticOp::Power => {
731                        // Convert to U256 for power operation
732                        let base_u = U256::from_le_bytes(l.to_le_bytes::<32>());
733                        let exp_u = U256::from_le_bytes(r.to_le_bytes::<32>());
734                        let result_u = base_u.saturating_pow(exp_u);
735                        I256::from_le_bytes(result_u.to_le_bytes::<32>())
736                    }
737                };
738                Ok(DynSolValue::Int(result, bits))
739            }
740            _ => bail!("Cannot apply arithmetic operation to non-numeric types"),
741        }
742    }
743
744    /// Evaluate bitwise operations
745    fn evaluate_bitwise(
746        &self,
747        left: &Expression,
748        right: &Expression,
749        snapshot_id: usize,
750        op: BitwiseOp,
751    ) -> Result<DynSolValue> {
752        let left_val = self.evaluate_expression(left, snapshot_id)?;
753        let right_val = self.evaluate_expression(right, snapshot_id)?;
754
755        self.apply_bitwise_op(left_val, right_val, op)
756    }
757
758    /// Apply bitwise operation
759    fn apply_bitwise_op(
760        &self,
761        left: DynSolValue,
762        right: DynSolValue,
763        op: BitwiseOp,
764    ) -> Result<DynSolValue> {
765        match (left, right) {
766            (DynSolValue::Uint(l, bits1), DynSolValue::Uint(r, bits2)) => {
767                let bits = bits1.max(bits2);
768                let result = match op {
769                    BitwiseOp::And => l & r,
770                    BitwiseOp::Or => l | r,
771                    BitwiseOp::Xor => l ^ r,
772                    BitwiseOp::ShiftLeft => l << r,
773                    BitwiseOp::ShiftRight => l >> r,
774                };
775                Ok(DynSolValue::Uint(result, bits))
776            }
777            _ => bail!("Bitwise operations require unsigned integer types"),
778        }
779    }
780
781    /// Evaluate bitwise NOT
782    fn evaluate_bitwise_not(
783        &self,
784        operand: &Expression,
785        snapshot_id: usize,
786    ) -> Result<DynSolValue> {
787        let val = self.evaluate_expression(operand, snapshot_id)?;
788        match val {
789            DynSolValue::Uint(v, bits) => Ok(DynSolValue::Uint(!v, bits)),
790            _ => bail!("Bitwise NOT requires unsigned integer type"),
791        }
792    }
793
794    /// Evaluate comparison operations
795    fn evaluate_comparison(
796        &self,
797        left: &Expression,
798        right: &Expression,
799        snapshot_id: usize,
800        op: ComparisonOp,
801    ) -> Result<DynSolValue> {
802        let left_val = self.evaluate_expression(left, snapshot_id)?;
803        let right_val = self.evaluate_expression(right, snapshot_id)?;
804
805        let result = self.apply_comparison_op(left_val, right_val, op)?;
806        Ok(DynSolValue::Bool(result))
807    }
808
809    /// Apply comparison operation
810    fn apply_comparison_op(
811        &self,
812        left: DynSolValue,
813        right: DynSolValue,
814        op: ComparisonOp,
815    ) -> Result<bool> {
816        match (left, right) {
817            (DynSolValue::Uint(l, _), DynSolValue::Uint(r, _)) => Ok(match op {
818                ComparisonOp::Equal => l == r,
819                ComparisonOp::NotEqual => l != r,
820                ComparisonOp::Less => l < r,
821                ComparisonOp::Greater => l > r,
822                ComparisonOp::LessEqual => l <= r,
823                ComparisonOp::GreaterEqual => l >= r,
824            }),
825            (DynSolValue::Int(l, _), DynSolValue::Int(r, _)) => Ok(match op {
826                ComparisonOp::Equal => l == r,
827                ComparisonOp::NotEqual => l != r,
828                ComparisonOp::Less => l < r,
829                ComparisonOp::Greater => l > r,
830                ComparisonOp::LessEqual => l <= r,
831                ComparisonOp::GreaterEqual => l >= r,
832            }),
833            (DynSolValue::Bool(l), DynSolValue::Bool(r)) => Ok(match op {
834                ComparisonOp::Equal => l == r,
835                ComparisonOp::NotEqual => l != r,
836                _ => bail!("Cannot compare booleans with <, >, <=, >="),
837            }),
838            (DynSolValue::Address(l), DynSolValue::Address(r)) => Ok(match op {
839                ComparisonOp::Equal => l == r,
840                ComparisonOp::NotEqual => l != r,
841                _ => bail!("Cannot compare addresses with <, >, <=, >="),
842            }),
843            (DynSolValue::String(l), DynSolValue::String(r)) => Ok(match op {
844                ComparisonOp::Equal => l == r,
845                ComparisonOp::NotEqual => l != r,
846                _ => bail!("Cannot compare strings with <, >, <=, >="),
847            }),
848            _ => bail!("Cannot compare values of different types"),
849        }
850    }
851
852    /// Evaluate logical operations
853    fn evaluate_logical(
854        &self,
855        left: &Expression,
856        right: &Expression,
857        snapshot_id: usize,
858        op: LogicalOp,
859    ) -> Result<DynSolValue> {
860        let left_val = self.evaluate_expression(left, snapshot_id)?;
861
862        // Short-circuit evaluation
863        match op {
864            LogicalOp::And => {
865                if !self.to_bool(&left_val)? {
866                    return Ok(DynSolValue::Bool(false));
867                }
868                let right_val = self.evaluate_expression(right, snapshot_id)?;
869                Ok(DynSolValue::Bool(self.to_bool(&right_val)?))
870            }
871            LogicalOp::Or => {
872                if self.to_bool(&left_val)? {
873                    return Ok(DynSolValue::Bool(true));
874                }
875                let right_val = self.evaluate_expression(right, snapshot_id)?;
876                Ok(DynSolValue::Bool(self.to_bool(&right_val)?))
877            }
878        }
879    }
880
881    /// Evaluate logical NOT
882    fn evaluate_logical_not(
883        &self,
884        operand: &Expression,
885        snapshot_id: usize,
886    ) -> Result<DynSolValue> {
887        let val = self.evaluate_expression(operand, snapshot_id)?;
888        Ok(DynSolValue::Bool(!self.to_bool(&val)?))
889    }
890
891    /// Convert value to boolean
892    fn to_bool(&self, val: &DynSolValue) -> Result<bool> {
893        match val {
894            DynSolValue::Bool(b) => Ok(*b),
895            DynSolValue::Uint(v, _) => Ok(!v.is_zero()),
896            DynSolValue::Int(v, _) => Ok(!v.is_zero()),
897            _ => bail!("Cannot convert {:?} to boolean", val),
898        }
899    }
900
901    /// Evaluate unary minus
902    fn evaluate_unary_minus(
903        &self,
904        operand: &Expression,
905        snapshot_id: usize,
906    ) -> Result<DynSolValue> {
907        let val = self.evaluate_expression(operand, snapshot_id)?;
908        match val {
909            DynSolValue::Uint(v, bits) => {
910                // Convert to signed integer and negate
911                let signed = I256::from_raw(v);
912                Ok(DynSolValue::Int(-signed, bits))
913            }
914            DynSolValue::Int(v, bits) => Ok(DynSolValue::Int(-v, bits)),
915            _ => bail!("Unary minus requires numeric type"),
916        }
917    }
918
919    /// Evaluate conditional (ternary) operator
920    fn evaluate_conditional(
921        &self,
922        condition: &Expression,
923        true_expr: &Expression,
924        false_expr: &Expression,
925        snapshot_id: usize,
926    ) -> Result<DynSolValue> {
927        let cond_val = self.evaluate_expression(condition, snapshot_id)?;
928
929        if self.to_bool(&cond_val)? {
930            self.evaluate_expression(true_expr, snapshot_id)
931        } else {
932            self.evaluate_expression(false_expr, snapshot_id)
933        }
934    }
935
936    /// Evaluate array slice: arr[start:end]
937    fn evaluate_array_slice(
938        &self,
939        array: &Expression,
940        start: Option<&Expression>,
941        end: Option<&Expression>,
942        snapshot_id: usize,
943    ) -> Result<DynSolValue> {
944        let array_val = self.evaluate_expression(array, snapshot_id)?;
945
946        // Get the array elements
947        let elements = match array_val {
948            DynSolValue::Array(elements) => elements,
949            DynSolValue::FixedArray(elements) => elements,
950            _ => bail!("Array slice can only be applied to arrays, got {:?}", array_val),
951        };
952
953        // Evaluate start and end indices
954        let start_idx = if let Some(start_expr) = start {
955            let start_val = self.evaluate_expression(start_expr, snapshot_id)?;
956            match start_val {
957                DynSolValue::Uint(v, _) => v.to::<usize>(),
958                _ => bail!("Array slice start index must be an unsigned integer"),
959            }
960        } else {
961            0
962        };
963
964        let end_idx = if let Some(end_expr) = end {
965            let end_val = self.evaluate_expression(end_expr, snapshot_id)?;
966            match end_val {
967                DynSolValue::Uint(v, _) => v.to::<usize>(),
968                _ => bail!("Array slice end index must be an unsigned integer"),
969            }
970        } else {
971            elements.len()
972        };
973
974        // Validate indices
975        if start_idx > end_idx {
976            bail!("Array slice start index {} is greater than end index {}", start_idx, end_idx);
977        }
978        if end_idx > elements.len() {
979            bail!("Array slice end index {} exceeds array length {}", end_idx, elements.len());
980        }
981
982        // Create the slice
983        let slice = elements[start_idx..end_idx].to_vec();
984        Ok(DynSolValue::Array(slice))
985    }
986
987    /// Evaluate hex literal: hex"deadbeef"
988    fn evaluate_hex_literal(
989        &self,
990        literals: &[solang_parser::pt::HexLiteral],
991    ) -> Result<DynSolValue> {
992        let mut bytes = Vec::new();
993
994        for lit in literals {
995            // Parse hex string to bytes
996            let hex_str = &lit.hex;
997            // Remove any spaces or underscores that might be in the hex literal
998            let cleaned = hex_str.replace(['_', ' '], "");
999
1000            // Ensure even number of characters
1001            let hex = if cleaned.len() % 2 != 0 { format!("0{cleaned}") } else { cleaned };
1002
1003            // Convert hex string to bytes
1004            for chunk in hex.as_bytes().chunks(2) {
1005                let hex_byte = std::str::from_utf8(chunk)?;
1006                let byte = u8::from_str_radix(hex_byte, 16)?;
1007                bytes.push(byte);
1008            }
1009        }
1010
1011        Ok(DynSolValue::Bytes(bytes))
1012    }
1013
1014    /// Evaluate array literal: [1, 2, 3]
1015    fn evaluate_array_literal(
1016        &self,
1017        elements: &[Expression],
1018        snapshot_id: usize,
1019    ) -> Result<DynSolValue> {
1020        let mut values = Vec::new();
1021
1022        for element in elements {
1023            let val = self.evaluate_expression(element, snapshot_id)?;
1024            values.push(val);
1025        }
1026
1027        Ok(DynSolValue::Array(values))
1028    }
1029
1030    /// Evaluate list (tuple): (a, b, c)
1031    fn evaluate_list_parameters(
1032        &self,
1033        parameters: &[(Loc, Option<Parameter>)],
1034        snapshot_id: usize,
1035    ) -> Result<DynSolValue> {
1036        let mut values = Vec::new();
1037
1038        for (_, param_opt) in parameters {
1039            if let Some(param) = param_opt {
1040                values.push(self.evaluate_expression(&param.ty, snapshot_id)?);
1041            } else {
1042                bail!("Invalid none parameter in list");
1043            }
1044        }
1045
1046        Ok(DynSolValue::Tuple(values))
1047    }
1048
1049    /// Evaluate type casting: uint256(x), address(y), etc.
1050    fn evaluate_type_casting(&self, target_type: &Type, value: DynSolValue) -> Result<DynSolValue> {
1051        match target_type {
1052            // Address casting
1053            Type::Address => match value {
1054                DynSolValue::Address(addr) => Ok(DynSolValue::Address(addr)),
1055                DynSolValue::Uint(val, _) => {
1056                    // Convert U256 to Address (take lower 160 bits)
1057                    let addr_bytes = val.to_be_bytes::<32>();
1058                    let addr = Address::from_slice(&addr_bytes[12..]);
1059                    Ok(DynSolValue::Address(addr))
1060                }
1061                DynSolValue::FixedBytes(bytes, 20) => {
1062                    let addr = Address::from_slice(&bytes[..20]);
1063                    Ok(DynSolValue::Address(addr))
1064                }
1065                _ => bail!("Cannot cast {:?} to address", value),
1066            },
1067
1068            // Unsigned integer casting with proper size and truncation
1069            Type::Uint(bits) => {
1070                let target_bits = *bits as usize;
1071                // Create mask for truncation
1072                let mask = if target_bits >= 256 {
1073                    U256::MAX
1074                } else {
1075                    (U256::from(1) << target_bits) - U256::from(1)
1076                };
1077                match value {
1078                    DynSolValue::Uint(val, _) => {
1079                        let truncated = val & mask;
1080                        Ok(DynSolValue::Uint(truncated, target_bits))
1081                    }
1082                    DynSolValue::Int(val, _) => {
1083                        let unsigned = val.into_raw() & mask;
1084                        Ok(DynSolValue::Uint(unsigned, target_bits))
1085                    }
1086                    DynSolValue::Address(addr) => {
1087                        let val = U256::from_be_slice(addr.as_slice()) & mask;
1088                        Ok(DynSolValue::Uint(val, target_bits))
1089                    }
1090                    DynSolValue::Bool(b) => {
1091                        let val = if b { U256::from(1) } else { U256::ZERO };
1092                        Ok(DynSolValue::Uint(val, target_bits))
1093                    }
1094                    _ => bail!("Cannot cast {:?} to uint{}", value, target_bits),
1095                }
1096            }
1097
1098            // Signed integer casting with proper size and truncation
1099            Type::Int(bits) => {
1100                let target_bits = *bits as usize;
1101                // For signed integers, we need to handle sign extension properly
1102                let truncate_signed = |val: I256| -> I256 {
1103                    if target_bits >= 256 {
1104                        return val;
1105                    }
1106                    // Create mask for the value bits
1107                    let mask = (U256::from(1) << target_bits) - U256::from(1);
1108                    let truncated = val.into_raw() & mask;
1109
1110                    // Check if the sign bit is set
1111                    let sign_bit = U256::from(1) << (target_bits - 1);
1112                    if truncated & sign_bit != U256::ZERO {
1113                        // Negative number - sign extend
1114                        let extension = U256::MAX ^ mask;
1115                        I256::from_raw(truncated | extension)
1116                    } else {
1117                        // Positive number
1118                        I256::from_raw(truncated)
1119                    }
1120                };
1121
1122                match value {
1123                    DynSolValue::Int(val, _) => {
1124                        let truncated = truncate_signed(val);
1125                        Ok(DynSolValue::Int(truncated, target_bits))
1126                    }
1127                    DynSolValue::Uint(val, _) => {
1128                        let signed = I256::from_raw(val);
1129                        let truncated = truncate_signed(signed);
1130                        Ok(DynSolValue::Int(truncated, target_bits))
1131                    }
1132                    DynSolValue::Bool(b) => {
1133                        let val = if b { I256::from_raw(U256::from(1)) } else { I256::ZERO };
1134                        Ok(DynSolValue::Int(val, target_bits))
1135                    }
1136                    _ => bail!("Cannot cast {:?} to int{}", value, target_bits),
1137                }
1138            }
1139
1140            // Boolean casting
1141            Type::Bool => match value {
1142                DynSolValue::Bool(b) => Ok(DynSolValue::Bool(b)),
1143                DynSolValue::Uint(val, _) => Ok(DynSolValue::Bool(!val.is_zero())),
1144                DynSolValue::Int(val, _) => Ok(DynSolValue::Bool(!val.is_zero())),
1145                _ => bail!("Cannot cast {:?} to bool", value),
1146            },
1147
1148            // Fixed bytes casting (e.g., bytes32)
1149            Type::Bytes(size) => {
1150                let target_size = *size as usize;
1151                match value {
1152                    DynSolValue::Bytes(bytes) => {
1153                        // Always use 32-byte buffer for B256
1154                        let mut fixed_bytes = vec![0u8; 32];
1155                        let copy_len = bytes.len().min(target_size);
1156                        fixed_bytes[..copy_len].copy_from_slice(&bytes[..copy_len]);
1157                        Ok(DynSolValue::FixedBytes(B256::from_slice(&fixed_bytes), target_size))
1158                    }
1159                    DynSolValue::FixedBytes(bytes, _) => {
1160                        // Convert between different fixed sizes
1161                        let mut fixed_bytes = vec![0u8; 32];
1162                        let copy_len = bytes.len().min(target_size).min(32);
1163                        fixed_bytes[..copy_len].copy_from_slice(&bytes[..copy_len]);
1164                        Ok(DynSolValue::FixedBytes(B256::from_slice(&fixed_bytes), target_size))
1165                    }
1166                    DynSolValue::String(s) => {
1167                        // Convert string to fixed bytes
1168                        let bytes = s.as_bytes();
1169                        let mut fixed_bytes = vec![0u8; 32];
1170                        let copy_len = bytes.len().min(target_size);
1171                        fixed_bytes[..copy_len].copy_from_slice(&bytes[..copy_len]);
1172                        Ok(DynSolValue::FixedBytes(B256::from_slice(&fixed_bytes), target_size))
1173                    }
1174                    DynSolValue::Uint(val, _) => {
1175                        // Convert uint to fixed bytes (big-endian)
1176                        let mut fixed_bytes = vec![0u8; 32];
1177                        let be_bytes = val.to_be_bytes::<32>();
1178                        if target_size < 32 {
1179                            // Copy from the end of be_bytes (rightmost bytes for smaller sizes)
1180                            let src_start = 32 - target_size;
1181                            fixed_bytes[..target_size].copy_from_slice(&be_bytes[src_start..]);
1182                        } else {
1183                            fixed_bytes = be_bytes.to_vec();
1184                        }
1185                        Ok(DynSolValue::FixedBytes(B256::from_slice(&fixed_bytes), target_size))
1186                    }
1187                    _ => bail!("Cannot cast {:?} to bytes{}", value, target_size),
1188                }
1189            }
1190
1191            // Dynamic bytes casting (simplified)
1192            Type::DynamicBytes => match value {
1193                DynSolValue::Bytes(bytes) => Ok(DynSolValue::Bytes(bytes)),
1194                DynSolValue::FixedBytes(bytes, _) => Ok(DynSolValue::Bytes(bytes.to_vec())),
1195                DynSolValue::String(s) => Ok(DynSolValue::Bytes(s.into_bytes())),
1196                DynSolValue::Uint(val, _) => Ok(DynSolValue::Bytes(val.to_be_bytes_vec())),
1197                _ => bail!("Cannot cast {:?} to bytes", value),
1198            },
1199
1200            // String casting
1201            Type::String => match value {
1202                DynSolValue::String(s) => Ok(DynSolValue::String(s)),
1203                DynSolValue::Bytes(bytes) => {
1204                    let s =
1205                        String::from_utf8(bytes).map_err(|_| eyre::eyre!("Invalid UTF-8 bytes"))?;
1206                    Ok(DynSolValue::String(s))
1207                }
1208                DynSolValue::FixedBytes(bytes, _) => {
1209                    let s = String::from_utf8(bytes.to_vec())
1210                        .map_err(|_| eyre::eyre!("Invalid UTF-8 bytes"))?;
1211                    Ok(DynSolValue::String(s))
1212                }
1213                _ => bail!("Cannot cast {:?} to string", value),
1214            },
1215
1216            // Unsupported types
1217            _ => bail!("Type casting to {:?} is not yet supported", target_type),
1218        }
1219    }
1220
1221    // ========== Utility function stubs ==========
1222    // These will be implemented later by the user
1223
1224    /// Get variable value from snapshot using handler
1225    fn get_variable_value(&self, name: &str, snapshot_id: usize) -> Result<DynSolValue> {
1226        match &self.handlers.variable_handler {
1227            Some(handler) => handler.get_variable_value(name, snapshot_id),
1228            None => bail!("No variable handler configured"),
1229        }
1230    }
1231
1232    /// Get mapping or array value using multiple indices
1233    fn get_mapping_or_array_value(
1234        &self,
1235        root: DynSolValue,
1236        indices: Vec<DynSolValue>,
1237        snapshot_id: usize,
1238    ) -> Result<DynSolValue> {
1239        match &self.handlers.mapping_array_handler {
1240            Some(handler) => handler.get_mapping_or_array_value(root, indices, snapshot_id),
1241            None => bail!("No mapping/array handler configured"),
1242        }
1243    }
1244
1245    /// Call a function
1246    fn call_function(
1247        &self,
1248        name: &str,
1249        args: &[DynSolValue],
1250        callee: Option<&DynSolValue>,
1251        snapshot_id: usize,
1252    ) -> Result<DynSolValue> {
1253        match &self.handlers.function_call_handler {
1254            Some(handler) => handler.call_function(name, args, callee, snapshot_id),
1255            None => bail!("No function call handler configured"),
1256        }
1257    }
1258
1259    /// Access member of a value (for handler delegation)
1260    fn access_member(
1261        &self,
1262        value: DynSolValue,
1263        member: &str,
1264        snapshot_id: usize,
1265    ) -> Result<DynSolValue> {
1266        // This method is only called after built-in properties have been checked
1267        // in evaluate_member_access, so we delegate directly to handlers
1268        match &self.handlers.member_access_handler {
1269            Some(handler) => handler.access_member(value, member, snapshot_id),
1270            None => bail!("No member access handler configured"),
1271        }
1272    }
1273
1274    /// Get msg.sender
1275    fn get_msg_sender(&self, snapshot_id: usize) -> Result<DynSolValue> {
1276        match &self.handlers.msg_handler {
1277            Some(handler) => handler.get_msg_sender(snapshot_id),
1278            None => bail!("No msg handler configured"),
1279        }
1280    }
1281
1282    /// Get msg.value
1283    fn get_msg_value(&self, snapshot_id: usize) -> Result<DynSolValue> {
1284        match &self.handlers.msg_handler {
1285            Some(handler) => handler.get_msg_value(snapshot_id),
1286            None => bail!("No msg handler configured"),
1287        }
1288    }
1289
1290    /// Get tx.origin
1291    fn get_tx_origin(&self, snapshot_id: usize) -> Result<DynSolValue> {
1292        match &self.handlers.tx_handler {
1293            Some(handler) => handler.get_tx_origin(snapshot_id),
1294            None => bail!("No tx handler configured"),
1295        }
1296    }
1297
1298    /// Get block.number
1299    fn get_block_number(&self, snapshot_id: usize) -> Result<DynSolValue> {
1300        match &self.handlers.block_handler {
1301            Some(handler) => handler.get_block_number(snapshot_id),
1302            None => bail!("No block handler configured"),
1303        }
1304    }
1305
1306    /// Get block.timestamp
1307    fn get_block_timestamp(&self, snapshot_id: usize) -> Result<DynSolValue> {
1308        match &self.handlers.block_handler {
1309            Some(handler) => handler.get_block_timestamp(snapshot_id),
1310            None => bail!("No block handler configured"),
1311        }
1312    }
1313}
1314
1315// Operation enums for better code organization
1316#[derive(Debug)]
1317enum ArithmeticOp {
1318    Add,
1319    Subtract,
1320    Multiply,
1321    Divide,
1322    Modulo,
1323    Power,
1324}
1325
1326#[derive(Debug)]
1327enum BitwiseOp {
1328    And,
1329    Or,
1330    Xor,
1331    ShiftLeft,
1332    ShiftRight,
1333}
1334
1335#[derive(Debug)]
1336enum ComparisonOp {
1337    Equal,
1338    NotEqual,
1339    Less,
1340    Greater,
1341    LessEqual,
1342    GreaterEqual,
1343}
1344
1345#[derive(Debug)]
1346enum LogicalOp {
1347    And,
1348    Or,
1349}
1350
1351#[cfg(test)]
1352mod tests {
1353    use super::*;
1354    use crate::eval::handlers::debug::{create_debug_handlers, create_simulation_debug_handlers};
1355    use crate::eval::handlers::{MappingArrayHandler, MemberAccessHandler};
1356    use alloy_primitives::{address, U256};
1357
1358    #[test]
1359    fn test_evaluate_number_literal() {
1360        // Just test that the structure exists and basic methods work
1361        // Since we don't have a real context, we can't fully test yet
1362
1363        // Test parsing different number formats
1364        let evaluator = ExpressionEvaluator::new_default();
1365
1366        // Test hex number
1367        let result = evaluator.evaluate_number_literal("0x1234");
1368        assert!(result.is_ok());
1369        if let Ok(DynSolValue::Uint(val, bits)) = result {
1370            assert_eq!(val, U256::from(0x1234));
1371            assert_eq!(bits, 256);
1372        }
1373
1374        // Test decimal number
1375        let result = evaluator.evaluate_number_literal("42");
1376        assert!(result.is_ok());
1377        if let Ok(DynSolValue::Uint(val, bits)) = result {
1378            assert_eq!(val, U256::from(42));
1379            assert_eq!(bits, 256);
1380        }
1381
1382        // Test number with underscores
1383        let result = evaluator.evaluate_number_literal("1_000_000");
1384        assert!(result.is_ok());
1385        if let Ok(DynSolValue::Uint(val, bits)) = result {
1386            assert_eq!(val, U256::from(1000000));
1387            assert_eq!(bits, 256);
1388        }
1389    }
1390
1391    #[test]
1392    fn test_apply_arithmetic_ops() {
1393        let evaluator = ExpressionEvaluator::new_default();
1394
1395        // Test addition
1396        let left = DynSolValue::Uint(U256::from(10), 256);
1397        let right = DynSolValue::Uint(U256::from(20), 256);
1398        let result = evaluator.apply_arithmetic_op(left, right, ArithmeticOp::Add);
1399        assert!(result.is_ok());
1400        if let Ok(DynSolValue::Uint(val, _)) = result {
1401            assert_eq!(val, U256::from(30));
1402        }
1403
1404        // Test subtraction
1405        let left = DynSolValue::Uint(U256::from(30), 256);
1406        let right = DynSolValue::Uint(U256::from(10), 256);
1407        let result = evaluator.apply_arithmetic_op(left, right, ArithmeticOp::Subtract);
1408        assert!(result.is_ok());
1409        if let Ok(DynSolValue::Uint(val, _)) = result {
1410            assert_eq!(val, U256::from(20));
1411        }
1412
1413        // Test multiplication
1414        let left = DynSolValue::Uint(U256::from(5), 256);
1415        let right = DynSolValue::Uint(U256::from(6), 256);
1416        let result = evaluator.apply_arithmetic_op(left, right, ArithmeticOp::Multiply);
1417        assert!(result.is_ok());
1418        if let Ok(DynSolValue::Uint(val, _)) = result {
1419            assert_eq!(val, U256::from(30));
1420        }
1421
1422        // Test division
1423        let left = DynSolValue::Uint(U256::from(100), 256);
1424        let right = DynSolValue::Uint(U256::from(5), 256);
1425        let result = evaluator.apply_arithmetic_op(left, right, ArithmeticOp::Divide);
1426        assert!(result.is_ok());
1427        if let Ok(DynSolValue::Uint(val, _)) = result {
1428            assert_eq!(val, U256::from(20));
1429        }
1430
1431        // Test division by zero
1432        let left = DynSolValue::Uint(U256::from(100), 256);
1433        let right = DynSolValue::Uint(U256::from(0), 256);
1434        let result = evaluator.apply_arithmetic_op(left, right, ArithmeticOp::Divide);
1435        assert!(result.is_err());
1436    }
1437
1438    #[test]
1439    fn test_comparison_ops() {
1440        let evaluator = ExpressionEvaluator::new_default();
1441
1442        // Test equality
1443        let left = DynSolValue::Uint(U256::from(10), 256);
1444        let right = DynSolValue::Uint(U256::from(10), 256);
1445        let result = evaluator.apply_comparison_op(left, right, ComparisonOp::Equal);
1446        assert_eq!(result.unwrap(), true);
1447
1448        // Test inequality
1449        let left = DynSolValue::Uint(U256::from(10), 256);
1450        let right = DynSolValue::Uint(U256::from(20), 256);
1451        let result = evaluator.apply_comparison_op(left, right, ComparisonOp::NotEqual);
1452        assert_eq!(result.unwrap(), true);
1453
1454        // Test less than
1455        let left = DynSolValue::Uint(U256::from(10), 256);
1456        let right = DynSolValue::Uint(U256::from(20), 256);
1457        let result = evaluator.apply_comparison_op(left, right, ComparisonOp::Less);
1458        assert_eq!(result.unwrap(), true);
1459
1460        // Test greater than
1461        let left = DynSolValue::Uint(U256::from(30), 256);
1462        let right = DynSolValue::Uint(U256::from(20), 256);
1463        let result = evaluator.apply_comparison_op(left, right, ComparisonOp::Greater);
1464        assert_eq!(result.unwrap(), true);
1465    }
1466
1467    #[test]
1468    fn test_to_bool() {
1469        let evaluator = ExpressionEvaluator::new_default();
1470
1471        // Test bool value
1472        assert_eq!(evaluator.to_bool(&DynSolValue::Bool(true)).unwrap(), true);
1473        assert_eq!(evaluator.to_bool(&DynSolValue::Bool(false)).unwrap(), false);
1474
1475        // Test uint values
1476        assert_eq!(evaluator.to_bool(&DynSolValue::Uint(U256::from(1), 256)).unwrap(), true);
1477        assert_eq!(evaluator.to_bool(&DynSolValue::Uint(U256::from(0), 256)).unwrap(), false);
1478        assert_eq!(evaluator.to_bool(&DynSolValue::Uint(U256::from(100), 256)).unwrap(), true);
1479
1480        // Test int values
1481        assert_eq!(
1482            evaluator.to_bool(&DynSolValue::Int(I256::from_raw(U256::from(1)), 256)).unwrap(),
1483            true
1484        );
1485        assert_eq!(
1486            evaluator.to_bool(&DynSolValue::Int(I256::from_raw(U256::from(0)), 256)).unwrap(),
1487            false
1488        );
1489        assert_eq!(
1490            evaluator
1491                .to_bool(&DynSolValue::Int(I256::from_raw(U256::from(1)).wrapping_neg(), 256))
1492                .unwrap(),
1493            true
1494        );
1495    }
1496
1497    // ========== Direct eval() method tests ==========
1498
1499    #[test]
1500    fn test_eval_number_literals() {
1501        let evaluator = ExpressionEvaluator::new_default();
1502
1503        // Test decimal numbers
1504        let result = evaluator.eval("42", 0);
1505        assert!(result.is_ok());
1506        if let Ok(DynSolValue::Uint(val, bits)) = result {
1507            assert_eq!(val, U256::from(42));
1508            assert_eq!(bits, 256);
1509        }
1510
1511        // Test hex numbers
1512        let result = evaluator.eval("0x1234", 0);
1513        assert!(result.is_ok());
1514        if let Ok(DynSolValue::Uint(val, bits)) = result {
1515            assert_eq!(val, U256::from(0x1234));
1516            assert_eq!(bits, 256);
1517        }
1518
1519        // Test numbers with underscores
1520        let result = evaluator.eval("1_000_000", 0);
1521        assert!(result.is_ok());
1522        if let Ok(DynSolValue::Uint(val, bits)) = result {
1523            assert_eq!(val, U256::from(1_000_000));
1524            assert_eq!(bits, 256);
1525        }
1526
1527        // Test large hex numbers
1528        let result =
1529            evaluator.eval("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 0);
1530        assert!(result.is_ok());
1531        if let Ok(DynSolValue::Uint(val, bits)) = result {
1532            assert_eq!(val, U256::MAX);
1533            assert_eq!(bits, 256);
1534        }
1535    }
1536
1537    #[test]
1538    fn test_eval_string_literals() {
1539        let evaluator = ExpressionEvaluator::new_default();
1540
1541        // Test simple string
1542        let result = evaluator.eval("\"hello world\"", 0);
1543        assert!(result.is_ok());
1544        if let Ok(DynSolValue::String(s)) = result {
1545            assert_eq!(s, "hello world");
1546        }
1547
1548        // Test empty string
1549        let result = evaluator.eval("\"\"", 0);
1550        assert!(result.is_ok());
1551        if let Ok(DynSolValue::String(s)) = result {
1552            assert_eq!(s, "");
1553        }
1554    }
1555
1556    #[test]
1557    fn test_eval_bool_literals() {
1558        let evaluator = ExpressionEvaluator::new_default();
1559
1560        // Test true
1561        let result = evaluator.eval("true", 0);
1562        assert!(result.is_ok());
1563        if let Ok(DynSolValue::Bool(b)) = result {
1564            assert_eq!(b, true);
1565        }
1566
1567        // Test false
1568        let result = evaluator.eval("false", 0);
1569        assert!(result.is_ok());
1570        if let Ok(DynSolValue::Bool(b)) = result {
1571            assert_eq!(b, false);
1572        }
1573    }
1574
1575    #[test]
1576    fn test_eval_arithmetic_expressions() {
1577        let evaluator = ExpressionEvaluator::new_default();
1578
1579        // Test simple addition
1580        let result = evaluator.eval("10 + 20", 0);
1581        assert!(result.is_ok());
1582        if let Ok(DynSolValue::Uint(val, _)) = result {
1583            assert_eq!(val, U256::from(30));
1584        }
1585
1586        // Test subtraction
1587        let result = evaluator.eval("50 - 20", 0);
1588        assert!(result.is_ok());
1589        if let Ok(DynSolValue::Uint(val, _)) = result {
1590            assert_eq!(val, U256::from(30));
1591        }
1592
1593        // Test multiplication
1594        let result = evaluator.eval("6 * 7", 0);
1595        assert!(result.is_ok());
1596        if let Ok(DynSolValue::Uint(val, _)) = result {
1597            assert_eq!(val, U256::from(42));
1598        }
1599
1600        // Test division
1601        let result = evaluator.eval("100 / 5", 0);
1602        assert!(result.is_ok());
1603        if let Ok(DynSolValue::Uint(val, _)) = result {
1604            assert_eq!(val, U256::from(20));
1605        }
1606
1607        // Test modulo
1608        let result = evaluator.eval("17 % 5", 0);
1609        assert!(result.is_ok());
1610        if let Ok(DynSolValue::Uint(val, _)) = result {
1611            assert_eq!(val, U256::from(2));
1612        }
1613
1614        // Test power
1615        let result = evaluator.eval("2 ** 8", 0);
1616        assert!(result.is_ok());
1617        if let Ok(DynSolValue::Uint(val, _)) = result {
1618            assert_eq!(val, U256::from(256));
1619        }
1620    }
1621
1622    #[test]
1623    fn test_eval_complex_arithmetic() {
1624        let evaluator = ExpressionEvaluator::new_default();
1625
1626        // Test precedence: 2 + 3 * 4 = 14
1627        let result = evaluator.eval("2 + 3 * 4", 0);
1628        assert!(result.is_ok());
1629        if let Ok(DynSolValue::Uint(val, _)) = result {
1630            assert_eq!(val, U256::from(14));
1631        }
1632
1633        // Test parentheses: (2 + 3) * 4 = 20
1634        let result = evaluator.eval("(2 + 3) * 4", 0);
1635        assert!(result.is_ok());
1636        if let Ok(DynSolValue::Uint(val, _)) = result {
1637            assert_eq!(val, U256::from(20));
1638        }
1639
1640        // Test complex expression: (10 + 5) * 2 - 8 / 4 = 28
1641        let result = evaluator.eval("(10 + 5) * 2 - 8 / 4", 0);
1642        assert!(result.is_ok());
1643        if let Ok(DynSolValue::Uint(val, _)) = result {
1644            assert_eq!(val, U256::from(28));
1645        }
1646    }
1647
1648    #[test]
1649    fn test_eval_unary_operations() {
1650        let evaluator = ExpressionEvaluator::new_default();
1651
1652        // Test unary plus
1653        let result = evaluator.eval("+42", 0);
1654        assert!(result.is_ok());
1655        if let Ok(DynSolValue::Uint(val, _)) = result {
1656            assert_eq!(val, U256::from(42));
1657        }
1658
1659        // Test unary minus (converts to signed)
1660        let result = evaluator.eval("-42", 0);
1661        assert!(result.is_ok());
1662        if let Ok(DynSolValue::Int(val, _)) = result {
1663            assert_eq!(val, I256::from_raw(U256::from(42)).wrapping_neg());
1664        }
1665
1666        // Test logical not on boolean
1667        let result = evaluator.eval("!true", 0);
1668        assert!(result.is_ok());
1669        if let Ok(DynSolValue::Bool(b)) = result {
1670            assert_eq!(b, false);
1671        }
1672
1673        // Test logical not on number (non-zero becomes false)
1674        let result = evaluator.eval("!42", 0);
1675        assert!(result.is_ok());
1676        if let Ok(DynSolValue::Bool(b)) = result {
1677            assert_eq!(b, false);
1678        }
1679
1680        // Test logical not on zero (becomes true)
1681        let result = evaluator.eval("!0", 0);
1682        assert!(result.is_ok());
1683        if let Ok(DynSolValue::Bool(b)) = result {
1684            assert_eq!(b, true);
1685        }
1686    }
1687
1688    #[test]
1689    fn test_eval_comparison_operations() {
1690        let evaluator = ExpressionEvaluator::new_default();
1691
1692        // Test equality
1693        let result = evaluator.eval("10 == 10", 0);
1694        assert!(result.is_ok());
1695        if let Ok(DynSolValue::Bool(b)) = result {
1696            assert_eq!(b, true);
1697        }
1698
1699        let result = evaluator.eval("10 == 20", 0);
1700        assert!(result.is_ok());
1701        if let Ok(DynSolValue::Bool(b)) = result {
1702            assert_eq!(b, false);
1703        }
1704
1705        // Test inequality
1706        let result = evaluator.eval("10 != 20", 0);
1707        assert!(result.is_ok());
1708        if let Ok(DynSolValue::Bool(b)) = result {
1709            assert_eq!(b, true);
1710        }
1711
1712        // Test less than
1713        let result = evaluator.eval("10 < 20", 0);
1714        assert!(result.is_ok());
1715        if let Ok(DynSolValue::Bool(b)) = result {
1716            assert_eq!(b, true);
1717        }
1718
1719        // Test greater than
1720        let result = evaluator.eval("30 > 20", 0);
1721        assert!(result.is_ok());
1722        if let Ok(DynSolValue::Bool(b)) = result {
1723            assert_eq!(b, true);
1724        }
1725
1726        // Test less than or equal
1727        let result = evaluator.eval("10 <= 10", 0);
1728        assert!(result.is_ok());
1729        if let Ok(DynSolValue::Bool(b)) = result {
1730            assert_eq!(b, true);
1731        }
1732
1733        // Test greater than or equal
1734        let result = evaluator.eval("20 >= 10", 0);
1735        assert!(result.is_ok());
1736        if let Ok(DynSolValue::Bool(b)) = result {
1737            assert_eq!(b, true);
1738        }
1739    }
1740
1741    #[test]
1742    fn test_eval_logical_operations() {
1743        let evaluator = ExpressionEvaluator::new_default();
1744
1745        // Test logical AND
1746        let result = evaluator.eval("true && true", 0);
1747        assert!(result.is_ok());
1748        if let Ok(DynSolValue::Bool(b)) = result {
1749            assert_eq!(b, true);
1750        }
1751
1752        let result = evaluator.eval("true && false", 0);
1753        assert!(result.is_ok());
1754        if let Ok(DynSolValue::Bool(b)) = result {
1755            assert_eq!(b, false);
1756        }
1757
1758        // Test logical OR
1759        let result = evaluator.eval("true || false", 0);
1760        assert!(result.is_ok());
1761        if let Ok(DynSolValue::Bool(b)) = result {
1762            assert_eq!(b, true);
1763        }
1764
1765        let result = evaluator.eval("false || false", 0);
1766        assert!(result.is_ok());
1767        if let Ok(DynSolValue::Bool(b)) = result {
1768            assert_eq!(b, false);
1769        }
1770
1771        // Test short-circuit evaluation with numbers
1772        let result = evaluator.eval("0 && 42", 0);
1773        assert!(result.is_ok());
1774        if let Ok(DynSolValue::Bool(b)) = result {
1775            assert_eq!(b, false);
1776        }
1777
1778        let result = evaluator.eval("1 || 0", 0);
1779        assert!(result.is_ok());
1780        if let Ok(DynSolValue::Bool(b)) = result {
1781            assert_eq!(b, true);
1782        }
1783    }
1784
1785    #[test]
1786    fn test_eval_ternary_operator() {
1787        let evaluator = ExpressionEvaluator::new_default();
1788
1789        // Test true condition
1790        let result = evaluator.eval("true ? 42 : 99", 0);
1791        assert!(result.is_ok());
1792        if let Ok(DynSolValue::Uint(val, _)) = result {
1793            assert_eq!(val, U256::from(42));
1794        }
1795
1796        // Test false condition
1797        let result = evaluator.eval("false ? 42 : 99", 0);
1798        assert!(result.is_ok());
1799        if let Ok(DynSolValue::Uint(val, _)) = result {
1800            assert_eq!(val, U256::from(99));
1801        }
1802
1803        // Test with expression condition
1804        let result = evaluator.eval("(10 > 5) ? \"yes\" : \"no\"", 0);
1805        assert!(result.is_ok());
1806        if let Ok(DynSolValue::String(s)) = result {
1807            assert_eq!(s, "yes");
1808        }
1809
1810        // Test nested ternary
1811        let result = evaluator.eval("true ? (false ? 1 : 2) : 3", 0);
1812        assert!(result.is_ok());
1813        if let Ok(DynSolValue::Uint(val, _)) = result {
1814            assert_eq!(val, U256::from(2));
1815        }
1816    }
1817
1818    #[test]
1819    fn test_eval_error_cases() {
1820        let evaluator = ExpressionEvaluator::new_default();
1821
1822        // Test division by zero
1823        let result = evaluator.eval("10 / 0", 0);
1824        assert!(result.is_err());
1825        assert!(result.unwrap_err().to_string().contains("Division by zero"));
1826
1827        // Test modulo by zero
1828        let result = evaluator.eval("10 % 0", 0);
1829        assert!(result.is_err());
1830        assert!(result.unwrap_err().to_string().contains("Modulo by zero"));
1831
1832        // Test invalid syntax (this will be caught by the parser)
1833        let result = evaluator.eval("10 +", 0);
1834        assert!(result.is_err());
1835
1836        // Test variables (should fail since no handler configured)
1837        let result = evaluator.eval("someVariable", 0);
1838        assert!(result.is_err());
1839        assert!(result.unwrap_err().to_string().contains("No variable handler configured"));
1840
1841        // Test msg.sender (should fail since no handler configured)
1842        let result = evaluator.eval("msg.sender", 0);
1843        assert!(result.is_err());
1844        assert!(result.unwrap_err().to_string().contains("No msg handler configured"));
1845    }
1846
1847    #[test]
1848    fn test_eval_complex_expressions() {
1849        let evaluator = ExpressionEvaluator::new_default();
1850
1851        // Test complex arithmetic with precedence
1852        let result = evaluator.eval("(2 + 3) * 4 - 1", 0);
1853        assert!(result.is_ok());
1854        if let Ok(DynSolValue::Uint(val, _)) = result {
1855            assert_eq!(val, U256::from(19)); // (2+3)*4-1 = 5*4-1 = 20-1 = 19
1856        }
1857
1858        // Test complex logical expressions
1859        let result = evaluator.eval("(5 > 3) && (2 == 2) || false", 0);
1860        assert!(result.is_ok());
1861        if let Ok(DynSolValue::Bool(b)) = result {
1862            assert_eq!(b, true);
1863        }
1864
1865        // Test nested conditional expressions
1866        let result = evaluator.eval("5 > 3 ? (2 + 2) : (3 * 3)", 0);
1867        assert!(result.is_ok());
1868        if let Ok(DynSolValue::Uint(val, _)) = result {
1869            assert_eq!(val, U256::from(4));
1870        }
1871    }
1872
1873    #[test]
1874    fn test_eval_with_debug_handlers() {
1875        let handlers = create_debug_handlers();
1876        let evaluator = ExpressionEvaluator::new(handlers);
1877
1878        // Test that debug handlers provide detailed error messages
1879        let result = evaluator.eval("someVariable", 0);
1880        assert!(result.is_err());
1881        let error = result.unwrap_err().to_string();
1882        assert!(error.contains("DebugHandler::get_variable_value"));
1883        assert!(error.contains("name='someVariable'"));
1884        assert!(error.contains("snapshot_id=0"));
1885
1886        // Test debug handler for function calls
1887        let result = evaluator.eval("someFunction(1, 2)", 0);
1888        assert!(result.is_err());
1889        let error = result.unwrap_err().to_string();
1890        assert!(error.contains("DebugHandler::call_function"));
1891        assert!(error.contains("name='someFunction'"));
1892    }
1893
1894    #[test]
1895    fn test_eval_type_casting_comprehensive() {
1896        let evaluator = ExpressionEvaluator::new_default();
1897
1898        // ===== ADDRESS CASTING =====
1899
1900        // Address from uint256 (zero address)
1901        let result = evaluator.eval("address(0)", 0);
1902        assert!(result.is_ok());
1903        if let Ok(DynSolValue::Address(addr)) = result {
1904            assert_eq!(addr, Address::ZERO);
1905        }
1906
1907        // Address from uint256 (non-zero address)
1908        let result = evaluator.eval("address(0x1234567890123456789012345678901234567890)", 0);
1909        assert!(result.is_ok());
1910
1911        // Address from bytes20 (should work)
1912        // Note: This would require proper bytes literal parsing
1913
1914        // ===== UINT CASTING =====
1915
1916        // Uint256 from bool (true -> 1)
1917        let result = evaluator.eval("uint256(true)", 0);
1918        assert!(result.is_ok());
1919        if let Ok(DynSolValue::Uint(val, bits)) = result {
1920            assert_eq!(val, U256::from(1));
1921            assert_eq!(bits, 256);
1922        }
1923
1924        // Uint256 from bool (false -> 0)
1925        let result = evaluator.eval("uint256(false)", 0);
1926        assert!(result.is_ok());
1927        if let Ok(DynSolValue::Uint(val, bits)) = result {
1928            assert_eq!(val, U256::ZERO);
1929            assert_eq!(bits, 256);
1930        }
1931
1932        // Uint8 truncation test
1933        let result = evaluator.eval("uint8(257)", 0);
1934        assert!(result.is_ok());
1935        if let Ok(DynSolValue::Uint(val, bits)) = result {
1936            assert_eq!(val, U256::from(1)); // 257 % 256 = 1
1937            assert_eq!(bits, 8);
1938        }
1939
1940        // Uint16 truncation test
1941        let result = evaluator.eval("uint16(65537)", 0);
1942        assert!(result.is_ok());
1943        if let Ok(DynSolValue::Uint(val, bits)) = result {
1944            assert_eq!(val, U256::from(1)); // 65537 % 65536 = 1
1945            assert_eq!(bits, 16);
1946        }
1947
1948        // Uint32 from large number
1949        let result = evaluator.eval("uint32(0xFFFFFFFF)", 0);
1950        assert!(result.is_ok());
1951        if let Ok(DynSolValue::Uint(val, bits)) = result {
1952            assert_eq!(val, U256::from(0xFFFFFFFF_u32));
1953            assert_eq!(bits, 32);
1954        }
1955
1956        // ===== INT CASTING =====
1957
1958        // Int256 from bool
1959        let result = evaluator.eval("int256(true)", 0);
1960        assert!(result.is_ok());
1961        if let Ok(DynSolValue::Int(val, bits)) = result {
1962            assert_eq!(val, I256::from_raw(U256::from(1)));
1963            assert_eq!(bits, 256);
1964        }
1965
1966        // Int8 from positive number
1967        let result = evaluator.eval("int8(127)", 0);
1968        assert!(result.is_ok());
1969        if let Ok(DynSolValue::Int(val, bits)) = result {
1970            assert_eq!(val, I256::from_raw(U256::from(127)));
1971            assert_eq!(bits, 8);
1972        }
1973
1974        // Int8 overflow/truncation (128 becomes -128 in two's complement)
1975        let result = evaluator.eval("int8(128)", 0);
1976        assert!(result.is_ok());
1977        if let Ok(DynSolValue::Int(_val, bits)) = result {
1978            // In 8-bit signed, 128 (0x80) should be -128 due to sign extension
1979            assert_eq!(bits, 8);
1980            // The exact value depends on how sign extension is handled
1981        }
1982
1983        // ===== BOOL CASTING =====
1984
1985        // Bool from uint (non-zero -> true)
1986        let result = evaluator.eval("bool(1)", 0);
1987        assert!(result.is_ok());
1988        if let Ok(DynSolValue::Bool(b)) = result {
1989            assert_eq!(b, true);
1990        }
1991
1992        // Bool from uint (zero -> false)
1993        let result = evaluator.eval("bool(0)", 0);
1994        assert!(result.is_ok());
1995        if let Ok(DynSolValue::Bool(b)) = result {
1996            assert_eq!(b, false);
1997        }
1998
1999        // Bool from large uint (non-zero -> true)
2000        let result = evaluator.eval("bool(0xFFFFFFFFFFFFFFFF)", 0);
2001        assert!(result.is_ok());
2002        if let Ok(DynSolValue::Bool(b)) = result {
2003            assert_eq!(b, true);
2004        }
2005
2006        // Bool from int (positive -> true)
2007        let result = evaluator.eval("bool(int256(1))", 0);
2008        assert!(result.is_ok());
2009        if let Ok(DynSolValue::Bool(b)) = result {
2010            assert_eq!(b, true);
2011        }
2012
2013        // ===== BYTES CASTING =====
2014
2015        // Note: These would require proper bytes literal syntax support
2016        // bytes32 from string would be: bytes32("hello")
2017        // bytes from uint would be: bytes(uint256(0x1234))
2018
2019        // ===== CHAINED CASTING =====
2020
2021        // Multiple casts in one expression
2022        let result = evaluator.eval("bool(uint8(257))", 0);
2023        assert!(result.is_ok());
2024        if let Ok(DynSolValue::Bool(b)) = result {
2025            // 257 -> uint8(1) -> bool(true)
2026            assert_eq!(b, true);
2027        }
2028
2029        // Cast in arithmetic expression
2030        let result = evaluator.eval("uint256(true) + uint256(false)", 0);
2031        assert!(result.is_ok());
2032        if let Ok(DynSolValue::Uint(val, _)) = result {
2033            assert_eq!(val, U256::from(1)); // 1 + 0 = 1
2034        }
2035
2036        // Cast with comparison
2037        let result = evaluator.eval("uint8(300) == uint8(44)", 0);
2038        assert!(result.is_ok());
2039        if let Ok(DynSolValue::Bool(b)) = result {
2040            // 300 % 256 = 44, 44 % 256 = 44, so they're equal
2041            assert_eq!(b, true);
2042        }
2043
2044        // ===== ERROR CASES =====
2045
2046        // Invalid cast combinations should fail gracefully
2047        // These might not parse correctly, but should not panic
2048
2049        // ===== COMPLEX CASTING SCENARIOS =====
2050
2051        // Cast in ternary operator
2052        let result = evaluator.eval("true ? uint256(1) : uint256(0)", 0);
2053        assert!(result.is_ok());
2054        if let Ok(DynSolValue::Uint(val, _)) = result {
2055            assert_eq!(val, U256::from(1));
2056        }
2057
2058        // Nested casts with different bit sizes
2059        let result = evaluator.eval("uint256(uint8(uint16(65793)))", 0);
2060        assert!(result.is_ok());
2061        if let Ok(DynSolValue::Uint(val, bits)) = result {
2062            // 65793 % 65536 = 257, 257 % 256 = 1
2063            assert_eq!(val, U256::from(1));
2064            assert_eq!(bits, 256);
2065        }
2066
2067        // Address arithmetic with casting
2068        let result = evaluator.eval("uint256(address(0x1234)) + 1", 0);
2069        assert!(result.is_ok());
2070
2071        // Bool logic with casting
2072        let result = evaluator.eval("bool(1) && bool(0)", 0);
2073        assert!(result.is_ok());
2074        if let Ok(DynSolValue::Bool(b)) = result {
2075            assert_eq!(b, false); // true && false = false
2076        }
2077
2078        // Mixed type operations requiring implicit casting behavior
2079        let result = evaluator.eval("uint8(255) + 1", 0);
2080        assert!(result.is_ok());
2081        // This tests whether the cast happens before or after the addition
2082    }
2083
2084    #[test]
2085    fn test_eval_error_propagation() {
2086        let evaluator = ExpressionEvaluator::new_default();
2087
2088        // Test division by zero (should be caught during evaluation)
2089        let result = evaluator.eval("5 / 0", 0);
2090        eprintln!("Error: {:?}", result);
2091        assert!(result.unwrap_err().to_string().to_lowercase().contains("division by zero"));
2092
2093        // Test invalid operations
2094        let result = evaluator.eval("5 + true", 0);
2095        assert!(result.is_err());
2096
2097        // Test handler not configured errors
2098        let result = evaluator.eval("unknownVar", 0);
2099        assert!(result.is_err());
2100        assert!(result
2101            .unwrap_err()
2102            .to_string()
2103            .to_lowercase()
2104            .contains("no variable handler configured"));
2105    }
2106
2107    #[test]
2108    fn test_eval_edge_cases() {
2109        let evaluator = ExpressionEvaluator::new_default();
2110
2111        // Test large numbers
2112        let result = evaluator.eval(
2113            "115792089237316195423570985008687907853269984665640564039457584007913129639935",
2114            0,
2115        );
2116        assert!(result.is_ok());
2117        if let Ok(DynSolValue::Uint(val, _)) = result {
2118            assert_eq!(val, U256::MAX);
2119        }
2120
2121        // Test negative numbers (should convert to signed)
2122        let result = evaluator.eval("-42", 0);
2123        assert!(result.is_ok());
2124        if let Ok(DynSolValue::Int(val, _)) = result {
2125            assert!(val < I256::ZERO);
2126        }
2127
2128        // Test string literals
2129        let result = evaluator.eval("\"hello world\"", 0);
2130        assert!(result.is_ok());
2131        if let Ok(DynSolValue::String(s)) = result {
2132            assert_eq!(s, "hello world");
2133        }
2134
2135        // Test address literals
2136        let result = evaluator.eval("0x1234567890123456789012345678901234567890", 0);
2137        assert!(result.is_ok());
2138    }
2139
2140    #[test]
2141    fn test_eval_array_literals() {
2142        // Note: Since array literal syntax like [1, 2, 3] may not be directly supported
2143        // by the current parser, we test array-related functionality that is available
2144
2145        // Test array length access (this uses member access)
2146        let (handlers, debug_handler) = create_simulation_debug_handlers();
2147        let evaluator_with_handlers = ExpressionEvaluator::new(handlers);
2148
2149        // Test accessing array.length property
2150        let result = evaluator_with_handlers.eval("arrayVar.length", 0);
2151        assert!(result.is_ok());
2152        if let Ok(DynSolValue::Uint(val, _)) = result {
2153            assert_eq!(val, U256::from(10)); // Default length from debug handler
2154        }
2155
2156        // Test address balance property (common array-like access pattern)
2157        let result = evaluator_with_handlers.eval("someAddress.balance", 0);
2158        assert!(result.is_ok());
2159        if let Ok(DynSolValue::Uint(val, _)) = result {
2160            assert_eq!(val, U256::from(1000000)); // Default balance from debug handler
2161        }
2162
2163        // Test code property (bytes-like array access)
2164        let result = evaluator_with_handlers.eval("contractAddr.code", 0);
2165        assert!(result.is_ok());
2166        if let Ok(DynSolValue::Bytes(_)) = result {
2167            // Should succeed in getting code bytes
2168        }
2169
2170        // Check that array-related operations are logged
2171        let log = debug_handler.get_log();
2172        assert!(!log.is_empty());
2173        assert!(log.iter().any(|entry| entry.contains("access_member")));
2174
2175        // Verify multiple member accesses were logged
2176        let member_accesses = log.iter().filter(|entry| entry.contains("access_member")).count();
2177        assert!(member_accesses >= 3, "Should have logged at least 3 member accesses");
2178    }
2179
2180    #[test]
2181    fn test_eval_hex_literals() {
2182        let evaluator = ExpressionEvaluator::new_default();
2183
2184        // Test simple hex numbers (these are parsed as number literals with hex format)
2185        let result = evaluator.eval("0x42", 0);
2186        assert!(result.is_ok());
2187        if let Ok(DynSolValue::Uint(val, _)) = result {
2188            assert_eq!(val, U256::from(0x42));
2189        }
2190
2191        // Test larger hex number
2192        let result = evaluator.eval("0x1234ABCD", 0);
2193        assert!(result.is_ok());
2194        if let Ok(DynSolValue::Uint(val, _)) = result {
2195            assert_eq!(val, U256::from(0x1234ABCD));
2196        }
2197
2198        // Test max hex value for different bit sizes
2199        let result = evaluator.eval("0xFF", 0);
2200        assert!(result.is_ok());
2201        if let Ok(DynSolValue::Uint(val, _)) = result {
2202            assert_eq!(val, U256::from(255));
2203        }
2204
2205        // Test hex with all hex digits
2206        let result = evaluator.eval("0xDEADBEEF", 0);
2207        assert!(result.is_ok());
2208        if let Ok(DynSolValue::Uint(val, _)) = result {
2209            assert_eq!(val, U256::from(0xDEADBEEFu32));
2210        }
2211
2212        // Test arithmetic with hex literals
2213        let result = evaluator.eval("0x10 + 0x20", 0);
2214        assert!(result.is_ok());
2215        if let Ok(DynSolValue::Uint(val, _)) = result {
2216            assert_eq!(val, U256::from(0x30)); // 16 + 32 = 48
2217        }
2218
2219        // Test type casting with hex
2220        let result = evaluator.eval("address(0x0)", 0);
2221        assert!(result.is_ok());
2222        if let Ok(DynSolValue::Address(addr)) = result {
2223            assert_eq!(addr, Address::ZERO);
2224        }
2225
2226        // Test hex address
2227        let result = evaluator.eval("address(0x1234567890123456789012345678901234567890)", 0);
2228        assert!(result.is_ok());
2229        if let Ok(DynSolValue::Address(_)) = result {
2230            // Should succeed in parsing as an address
2231        } else {
2232            panic!("Failed to cast hex literal to address");
2233        }
2234    }
2235
2236    #[test]
2237    fn test_eval_list_tuples() {
2238        // Note: Since tuple syntax like (a, b, c) may not be directly supported
2239        // by the current parser, we test tuple-related functionality that is available
2240
2241        let (handlers, debug_handler) = create_simulation_debug_handlers();
2242        let evaluator = ExpressionEvaluator::new(handlers);
2243
2244        // Test function calls that return multiple values (tuple-like behavior)
2245        let result = evaluator.eval("multiReturnFunc()", 0);
2246        assert!(result.is_ok());
2247        if let Ok(DynSolValue::Tuple(values)) = result {
2248            assert!(!values.is_empty());
2249        }
2250
2251        // Test variable assignment that could be tuple-like
2252        let result = evaluator.eval("tupleVar", 0);
2253        assert!(result.is_ok());
2254        // The debug handler should return a tuple for variables ending in "Tuple" or similar
2255
2256        // Test struct-like access which is similar to tuple access
2257        let result = evaluator.eval("structVar.field1", 0);
2258        assert!(result.is_ok());
2259        if let Ok(DynSolValue::Uint(val, _)) = result {
2260            assert_eq!(val, U256::from(42)); // Default value from debug handler for member access
2261        }
2262
2263        // Test nested member access (tuple-like operations)
2264        let result = evaluator.eval("nestedStruct.inner.value", 0);
2265        assert!(result.is_ok());
2266
2267        // Test tuple element access simulation via array-like access
2268        // Since actual tuple syntax might not be supported, we simulate it
2269        let result = evaluator.eval("pairData.first", 0);
2270        assert!(result.is_ok());
2271
2272        let result = evaluator.eval("pairData.second", 0);
2273        assert!(result.is_ok());
2274
2275        // Check that tuple-related operations are logged
2276        let log = debug_handler.get_log();
2277        assert!(!log.is_empty());
2278
2279        // Verify that function calls and member accesses were logged
2280        let function_calls = log.iter().filter(|entry| entry.contains("call_function")).count();
2281        let member_accesses = log.iter().filter(|entry| entry.contains("access_member")).count();
2282
2283        assert!(function_calls >= 1, "Should have logged at least 1 function call");
2284        assert!(member_accesses >= 4, "Should have logged at least 4 member accesses");
2285    }
2286
2287    #[test]
2288    fn test_simulation_debug_handler_basic() {
2289        let (handlers, debug_handler) = create_simulation_debug_handlers();
2290        let evaluator = ExpressionEvaluator::new(handlers);
2291
2292        // Test variable access with auto-generated values
2293        let result = evaluator.eval("balance", 0);
2294        assert!(result.is_ok());
2295        if let Ok(DynSolValue::Uint(val, _)) = result {
2296            assert_eq!(val, U256::from(1000000)); // Expected balance default
2297        }
2298
2299        // Test msg.sender access
2300        let result = evaluator.eval("msg.sender", 0);
2301        assert!(result.is_ok());
2302        if let Ok(DynSolValue::Address(addr)) = result {
2303            assert_eq!(addr, Address::from([0x42; 20])); // Expected mock address
2304        }
2305
2306        // Check that operations were logged
2307        let log = debug_handler.get_log();
2308        assert!(!log.is_empty());
2309        assert!(log.iter().any(|entry| entry.contains("get_variable_value")));
2310        assert!(log.iter().any(|entry| entry.contains("get_msg_sender")));
2311    }
2312
2313    #[test]
2314    fn test_simulation_debug_handler_custom_values() {
2315        let (handlers, debug_handler) = create_simulation_debug_handlers();
2316        let evaluator = ExpressionEvaluator::new(handlers);
2317
2318        // Set custom variable values
2319        debug_handler.set_variable("myBalance", DynSolValue::Uint(U256::from(5000), 256));
2320        debug_handler.set_variable("myAddress", DynSolValue::Address(Address::from([0x99; 20])));
2321
2322        // Test that custom values are returned
2323        let result = evaluator.eval("myBalance", 0);
2324        assert!(result.is_ok());
2325        if let Ok(DynSolValue::Uint(val, _)) = result {
2326            assert_eq!(val, U256::from(5000));
2327        }
2328
2329        let result = evaluator.eval("myAddress", 0);
2330        assert!(result.is_ok());
2331        if let Ok(DynSolValue::Address(addr)) = result {
2332            assert_eq!(addr, Address::from([0x99; 20]));
2333        }
2334
2335        // Verify logging captured the custom values
2336        let log = debug_handler.get_log();
2337        assert!(log.iter().any(|entry| entry.contains("returning stored value")));
2338    }
2339
2340    #[test]
2341    fn test_simulation_debug_handler_complex_expressions() {
2342        let (handlers, debug_handler) = create_simulation_debug_handlers();
2343        let evaluator = ExpressionEvaluator::new(handlers);
2344
2345        // Set up some mock data
2346        debug_handler.set_variable("userBalance", DynSolValue::Uint(U256::from(2000), 256));
2347        debug_handler.set_function("balanceOf", DynSolValue::Uint(U256::from(1500), 256));
2348
2349        debug_handler.clear_log(); // Clear previous logs
2350
2351        // Test complex expression with variables and function calls
2352        let result = evaluator.eval("userBalance + balanceOf(msg.sender)", 0);
2353        assert!(result.is_ok());
2354        if let Ok(DynSolValue::Uint(val, _)) = result {
2355            assert_eq!(val, U256::from(3500)); // 2000 + 1500
2356        }
2357
2358        // Check the execution log for detailed tracing
2359        let log = debug_handler.get_log();
2360        println!("Execution log:");
2361        for entry in &log {
2362            println!("  {}", entry);
2363        }
2364
2365        // Verify all operations were logged
2366        assert!(log.iter().any(|entry| entry.contains("get_variable_value: name='userBalance'")));
2367        assert!(log.iter().any(|entry| entry.contains("call_function: name='balanceOf'")));
2368        assert!(log.iter().any(|entry| entry.contains("get_msg_sender")));
2369    }
2370
2371    #[test]
2372    fn test_simulation_debug_handler_mapping_access() {
2373        let (handlers, debug_handler) = create_simulation_debug_handlers();
2374        let _evaluator = ExpressionEvaluator::new(handlers);
2375
2376        debug_handler.clear_log();
2377
2378        // Test mapping access (this would require actual mapping syntax parsing)
2379        // For now we test the handler directly
2380        let mock_mapping = DynSolValue::Uint(U256::from(0), 256); // Mock mapping root
2381        let indices = vec![DynSolValue::Address(Address::from([0x11; 20]))]; // Mock address key
2382
2383        let result = debug_handler.get_mapping_or_array_value(mock_mapping, indices, 0);
2384        assert!(result.is_ok());
2385        if let Ok(DynSolValue::Uint(val, _)) = result {
2386            assert_eq!(val, U256::from(1000000)); // Expected address mapping value
2387        }
2388
2389        // Check logging
2390        let log = debug_handler.get_log();
2391        assert!(log.iter().any(|entry| entry.contains("get_mapping_or_array_value")));
2392    }
2393
2394    #[test]
2395    fn test_simulation_debug_handler_member_access() {
2396        let (handlers, debug_handler) = create_simulation_debug_handlers();
2397        let _evaluator = ExpressionEvaluator::new(handlers);
2398
2399        // Test member access (this would require actual member access syntax)
2400        // For now we test the handler directly
2401        let mock_object = DynSolValue::Address(Address::from([0x42; 20]));
2402
2403        let result = debug_handler.access_member(mock_object, "balance", 0);
2404        assert!(result.is_ok());
2405        if let Ok(DynSolValue::Uint(val, _)) = result {
2406            assert_eq!(val, U256::from(1000000)); // Expected balance value
2407        }
2408
2409        let result = debug_handler.access_member(DynSolValue::Uint(U256::ZERO, 256), "length", 0);
2410        assert!(result.is_ok());
2411        if let Ok(DynSolValue::Uint(val, _)) = result {
2412            assert_eq!(val, U256::from(10)); // Expected array length
2413        }
2414    }
2415
2416    #[test]
2417    fn test_debug_handler_comparison() {
2418        // Compare error-only debug handler vs simulation debug handler
2419
2420        // Test with error-only debug handler
2421        let error_handlers = create_debug_handlers();
2422        let error_evaluator = ExpressionEvaluator::new(error_handlers);
2423
2424        let result = error_evaluator.eval("someVar", 0);
2425        assert!(result.is_err());
2426        assert!(result.unwrap_err().to_string().contains("DebugHandler::get_variable_value"));
2427
2428        // Test with simulation debug handler
2429        let (sim_handlers, _sim_debug) = create_simulation_debug_handlers();
2430        let sim_evaluator = ExpressionEvaluator::new(sim_handlers);
2431
2432        let result = sim_evaluator.eval("someVar", 0);
2433        assert!(result.is_ok()); // Should succeed with mock value
2434        if let Ok(DynSolValue::Uint(val, _)) = result {
2435            assert_eq!(val, U256::from(42)); // Expected default value
2436        }
2437    }
2438
2439    #[test]
2440    fn test_eval_mixed_type_operations() {
2441        let evaluator = ExpressionEvaluator::new_default();
2442
2443        // Test mixing numbers in comparisons
2444        let result = evaluator.eval("(10 + 5) == 15", 0);
2445        assert!(result.is_ok());
2446        if let Ok(DynSolValue::Bool(b)) = result {
2447            assert_eq!(b, true);
2448        }
2449
2450        // Test boolean in arithmetic context (through logical operations)
2451        let result = evaluator.eval("!(10 == 5)", 0);
2452        assert!(result.is_ok());
2453        if let Ok(DynSolValue::Bool(b)) = result {
2454            assert_eq!(b, true);
2455        }
2456
2457        // Test complex mixed expression
2458        let result = evaluator.eval("(2 * 3 > 5) && (10 / 2 == 5)", 0);
2459        assert!(result.is_ok());
2460        if let Ok(DynSolValue::Bool(b)) = result {
2461            assert_eq!(b, true);
2462        }
2463    }
2464
2465    #[test]
2466    fn test_eval_type_casting() {
2467        let evaluator = ExpressionEvaluator::new_default();
2468
2469        // Test mixing numbers in comparisons
2470        let result = evaluator.eval("address(0x0)", 0);
2471        assert!(result.is_ok());
2472        if let Ok(DynSolValue::Address(addr)) = result {
2473            assert_eq!(addr, address!("0x0000000000000000000000000000000000000000"));
2474        }
2475    }
2476
2477    #[test]
2478    fn test_eval_parentheses_precedence() {
2479        let evaluator = ExpressionEvaluator::new_default();
2480
2481        // Test nested parentheses
2482        let result = evaluator.eval("((2 + 3) * (4 - 1))", 0);
2483        assert!(result.is_ok());
2484        if let Ok(DynSolValue::Uint(val, _)) = result {
2485            assert_eq!(val, U256::from(15)); // (5) * (3) = 15
2486        }
2487
2488        // Test multiple levels
2489        let result = evaluator.eval("(((10)))", 0);
2490        assert!(result.is_ok());
2491        if let Ok(DynSolValue::Uint(val, _)) = result {
2492            assert_eq!(val, U256::from(10));
2493        }
2494
2495        // Test mixing with unary operators
2496        let result = evaluator.eval("-(2 + 3)", 0);
2497        assert!(result.is_ok());
2498        if let Ok(DynSolValue::Int(val, _)) = result {
2499            assert_eq!(val, I256::from_raw(U256::from(5)).wrapping_neg());
2500        }
2501    }
2502
2503    #[test]
2504    fn test_advanced_simulation_scenarios() {
2505        let (handlers, debug_handler) = create_simulation_debug_handlers();
2506        let evaluator = ExpressionEvaluator::new(handlers);
2507
2508        // Test ERC20 token simulation
2509        debug_handler.set_variable("token", DynSolValue::Address(Address::from([0xAB; 20])));
2510        debug_handler.set_function("balanceOf", DynSolValue::Uint(U256::from(50000), 256));
2511        debug_handler.set_function("totalSupply", DynSolValue::Uint(U256::from(1000000), 256));
2512
2513        // Test token balance query
2514        let result = evaluator.eval("balanceOf()", 0);
2515        assert!(result.is_ok());
2516        if let Ok(DynSolValue::Uint(val, _)) = result {
2517            assert_eq!(val, U256::from(50000));
2518        }
2519
2520        // Test complex DeFi calculations
2521        let result = evaluator.eval("(balanceOf() * 100) / totalSupply()", 0);
2522        assert!(result.is_ok());
2523        if let Ok(DynSolValue::Uint(val, _)) = result {
2524            assert_eq!(val, U256::from(5)); // 50000 * 100 / 1000000 = 5
2525        }
2526
2527        // Verify comprehensive logging
2528        let log = debug_handler.get_log();
2529        assert!(log.iter().any(|entry| entry.contains("balanceOf")));
2530        assert!(log.iter().any(|entry| entry.contains("totalSupply")));
2531    }
2532
2533    #[test]
2534    fn test_blockchain_context_simulation() {
2535        let (handlers, _debug_handler) = create_simulation_debug_handlers();
2536        let evaluator = ExpressionEvaluator::new(handlers);
2537
2538        // Test blockchain context access
2539        let result = evaluator.eval("msg.sender", 0);
2540        assert!(result.is_ok());
2541        if let Ok(DynSolValue::Address(addr)) = result {
2542            assert_eq!(addr, Address::from([0x42; 20]));
2543        }
2544
2545        let result = evaluator.eval("msg.value", 0);
2546        assert!(result.is_ok());
2547        if let Ok(DynSolValue::Uint(val, _)) = result {
2548            assert_eq!(val, U256::from(1000000000000000000u64)); // 1 ETH
2549        }
2550
2551        let result = evaluator.eval("block.number", 0);
2552        assert!(result.is_ok());
2553        if let Ok(DynSolValue::Uint(val, _)) = result {
2554            assert_eq!(val, U256::from(18500000));
2555        }
2556
2557        let result = evaluator.eval("block.timestamp", 0);
2558        assert!(result.is_ok());
2559        if let Ok(DynSolValue::Uint(val, _)) = result {
2560            assert_eq!(val, U256::from(1700000000));
2561        }
2562
2563        let result = evaluator.eval("tx.origin", 0);
2564        assert!(result.is_ok());
2565        if let Ok(DynSolValue::Address(addr)) = result {
2566            assert_eq!(addr, Address::from([0x11; 20]));
2567        }
2568
2569        // Test time-based calculations
2570        let result = evaluator.eval("block.timestamp + 3600", 0); // Add 1 hour
2571        assert!(result.is_ok());
2572        if let Ok(DynSolValue::Uint(val, _)) = result {
2573            assert_eq!(val, U256::from(1700003600));
2574        }
2575    }
2576
2577    #[test]
2578    fn test_complex_mapping_and_array_operations() {
2579        let (handlers, debug_handler) = create_simulation_debug_handlers();
2580        let evaluator = ExpressionEvaluator::new(handlers);
2581
2582        // Test array access with dynamic values
2583        debug_handler.set_variable("userIndex", DynSolValue::Uint(U256::from(5), 256));
2584
2585        // Test nested data structure access
2586        let result = evaluator.eval("users[userIndex].balance", 0);
2587        assert!(result.is_ok());
2588
2589        // Test mapping access with address keys
2590        let result = evaluator.eval("balances[msg.sender]", 0);
2591        assert!(result.is_ok());
2592        if let Ok(DynSolValue::Uint(val, _)) = result {
2593            assert_eq!(val, U256::from(1000000)); // Default mapping value for address
2594        }
2595
2596        // Test complex nested access
2597        let result = evaluator.eval("tokenData[token].holders[owner].amount", 0);
2598        assert!(result.is_ok());
2599
2600        // Verify mapping/array operations are logged
2601        let log = debug_handler.get_log();
2602        assert!(log.iter().any(|entry| entry.contains("get_mapping_or_array_value")));
2603        assert!(log.iter().any(|entry| entry.contains("access_member")));
2604    }
2605
2606    #[test]
2607    fn test_advanced_function_call_scenarios() {
2608        let (handlers, debug_handler) = create_simulation_debug_handlers();
2609        let evaluator = ExpressionEvaluator::new(handlers);
2610
2611        // Set up complex function return values
2612        debug_handler.set_function(
2613            "getReserves",
2614            DynSolValue::Tuple(vec![
2615                DynSolValue::Uint(U256::from(1000000), 256),
2616                DynSolValue::Uint(U256::from(500000), 256),
2617                DynSolValue::Uint(U256::from(1700000000), 256),
2618            ]),
2619        );
2620
2621        // Test function calls with different argument patterns
2622        let result = evaluator.eval("getReserves()", 0);
2623        assert!(result.is_ok());
2624        if let Ok(DynSolValue::Tuple(values)) = result {
2625            assert_eq!(values.len(), 3);
2626        }
2627
2628        // Test standard ERC20 functions
2629        let result = evaluator.eval("name()", 0);
2630        assert!(result.is_ok());
2631        if let Ok(DynSolValue::String(name)) = result {
2632            assert_eq!(name, "MockToken");
2633        }
2634
2635        let result = evaluator.eval("symbol()", 0);
2636        assert!(result.is_ok());
2637        if let Ok(DynSolValue::String(symbol)) = result {
2638            assert_eq!(symbol, "MTK");
2639        }
2640
2641        let result = evaluator.eval("decimals()", 0);
2642        assert!(result.is_ok());
2643        if let Ok(DynSolValue::Uint(decimals, _)) = result {
2644            assert_eq!(decimals, U256::from(18));
2645        }
2646
2647        // Test boolean return functions
2648        let result = evaluator.eval("approve()", 0);
2649        assert!(result.is_ok());
2650        if let Ok(DynSolValue::Bool(success)) = result {
2651            assert!(success);
2652        }
2653    }
2654
2655    #[test]
2656    fn test_cross_handler_interactions() {
2657        let (handlers, debug_handler) = create_simulation_debug_handlers();
2658        let evaluator = ExpressionEvaluator::new(handlers);
2659
2660        // Test expression combining multiple handler types
2661        let result = evaluator.eval("(msg.value * balanceOf()) / totalSupply()", 0);
2662        assert!(result.is_ok());
2663
2664        // Test complex conditional-like expressions
2665        let result = evaluator.eval("msg.value > 0 && balanceOf() > 1000", 0);
2666        assert!(result.is_ok());
2667        if let Ok(DynSolValue::Bool(is_valid)) = result {
2668            assert!(is_valid);
2669        }
2670
2671        // Test address comparisons
2672        let result = evaluator.eval("msg.sender == tx.origin", 0);
2673        assert!(result.is_ok());
2674        if let Ok(DynSolValue::Bool(is_same)) = result {
2675            assert!(!is_same); // Different mock addresses
2676        }
2677
2678        // Test numerical operations with blockchain context
2679        let result = evaluator.eval("block.number % 100", 0);
2680        assert!(result.is_ok());
2681
2682        // Verify all handler types were used
2683        let log = debug_handler.get_log();
2684        assert!(log.iter().any(|entry| entry.contains("get_msg_")));
2685        assert!(log.iter().any(|entry| entry.contains("get_tx_")));
2686        assert!(log.iter().any(|entry| entry.contains("get_block_")));
2687        assert!(log.iter().any(|entry| entry.contains("call_function")));
2688    }
2689
2690    #[test]
2691    fn test_error_handling_and_recovery() {
2692        let (handlers, debug_handler) = create_simulation_debug_handlers();
2693        let evaluator = ExpressionEvaluator::new(handlers);
2694
2695        // Test invalid operations that should fail gracefully
2696        let result = evaluator.eval("1 / 0", 0);
2697        assert!(result.is_err());
2698        let error_msg = result.unwrap_err().to_string().to_lowercase();
2699        assert!(error_msg.contains("division") && error_msg.contains("zero"));
2700
2701        // Test type mismatches
2702        let result = evaluator.eval("true + 5", 0);
2703        assert!(result.is_err());
2704
2705        // Test successful operations after errors (handler state preserved)
2706        let result = evaluator.eval("msg.sender", 0);
2707        assert!(result.is_ok());
2708
2709        // Verify error cases are logged appropriately
2710        let log = debug_handler.get_log();
2711        assert!(log.iter().any(|entry| entry.contains("get_msg_sender")));
2712    }
2713
2714    #[test]
2715    fn test_performance_and_logging_metrics() {
2716        let (handlers, debug_handler) = create_simulation_debug_handlers();
2717        let evaluator = ExpressionEvaluator::new(handlers);
2718
2719        // Clear initial logs
2720        debug_handler.clear_log();
2721
2722        // Execute a complex expression
2723        let result = evaluator
2724            .eval("((balanceOf() * msg.value) / totalSupply()) > (block.timestamp % 1000)", 0);
2725        assert!(result.is_ok());
2726
2727        // Analyze logging output
2728        let log = debug_handler.get_log();
2729        assert!(!log.is_empty());
2730
2731        // Verify specific operations were logged
2732        let function_calls = log.iter().filter(|entry| entry.contains("call_function")).count();
2733        let msg_accesses = log.iter().filter(|entry| entry.contains("get_msg_")).count();
2734        let block_accesses = log.iter().filter(|entry| entry.contains("get_block_")).count();
2735
2736        assert!(function_calls >= 2); // balanceOf, totalSupply
2737        assert!(msg_accesses >= 1); // msg.value
2738        assert!(block_accesses >= 1); // block.timestamp
2739
2740        // Test log clearing functionality
2741        debug_handler.clear_log();
2742        let cleared_log = debug_handler.get_log();
2743        assert!(cleared_log.is_empty());
2744    }
2745
2746    #[test]
2747    fn test_dynamic_value_simulation() {
2748        let (handlers, _debug_handler) = create_simulation_debug_handlers();
2749        let evaluator = ExpressionEvaluator::new(handlers);
2750
2751        // Test different value types based on naming conventions that match the debug handler patterns exactly
2752        // The debug handler looks for exact word matches with .contains()
2753
2754        // Test balance/amount/value types -> Uint (with specific values)
2755        let balance_result = evaluator.eval("balance", 0);
2756        if let Ok(DynSolValue::Uint(val, _)) = balance_result {
2757            assert_eq!(val, U256::from(1000000)); // 1M as default balance
2758        } else {
2759            panic!("Expected balance to return Uint(1000000, 256)");
2760        }
2761
2762        let amount_result = evaluator.eval("amount", 0);
2763        if let Ok(DynSolValue::Uint(val, _)) = amount_result {
2764            assert_eq!(val, U256::from(1000000)); // Same as balance/amount/value
2765        } else {
2766            panic!("Expected amount to return Uint(1000000, 256)");
2767        }
2768
2769        let value_result = evaluator.eval("value", 0);
2770        if let Ok(DynSolValue::Uint(val, _)) = value_result {
2771            assert_eq!(val, U256::from(1000000)); // Same as balance/amount/value
2772        } else {
2773            panic!("Expected value to return Uint(1000000, 256)");
2774        }
2775
2776        // Test address/owner/sender types -> Address (using variable names that contain the keywords)
2777        let address_result = evaluator.eval("myaddress", 0);
2778        assert!(matches!(address_result.unwrap(), DynSolValue::Address(_)));
2779
2780        let owner_result = evaluator.eval("owner", 0);
2781        assert!(matches!(owner_result.unwrap(), DynSolValue::Address(_)));
2782
2783        let sender_result = evaluator.eval("sender", 0);
2784        assert!(matches!(sender_result.unwrap(), DynSolValue::Address(_)));
2785
2786        // Test count/length/index types -> Uint (with value 5)
2787        let count_result = evaluator.eval("count", 0);
2788        if let Ok(DynSolValue::Uint(val, _)) = count_result {
2789            assert_eq!(val, U256::from(5)); // Default count/length
2790        } else {
2791            panic!("Expected count to return Uint(5, 256)");
2792        }
2793
2794        let length_result = evaluator.eval("length", 0);
2795        if let Ok(DynSolValue::Uint(val, _)) = length_result {
2796            assert_eq!(val, U256::from(5)); // Default count/length
2797        } else {
2798            panic!("Expected length to return Uint(5, 256)");
2799        }
2800
2801        let index_result = evaluator.eval("index", 0);
2802        if let Ok(DynSolValue::Uint(val, _)) = index_result {
2803            assert_eq!(val, U256::from(5)); // Default count/length/index
2804        } else {
2805            panic!("Expected index to return Uint(5, 256)");
2806        }
2807
2808        // Test enabled/active/flag types -> Bool
2809        let enabled_result = evaluator.eval("enabled", 0);
2810        if let Ok(DynSolValue::Bool(val)) = enabled_result {
2811            assert!(val); // Default boolean
2812        } else {
2813            panic!("Expected enabled to return Bool(true)");
2814        }
2815
2816        let active_result = evaluator.eval("active", 0);
2817        if let Ok(DynSolValue::Bool(val)) = active_result {
2818            assert!(val); // Default boolean
2819        } else {
2820            panic!("Expected active to return Bool(true)");
2821        }
2822
2823        let flag_result = evaluator.eval("flag", 0);
2824        if let Ok(DynSolValue::Bool(val)) = flag_result {
2825            assert!(val); // Default boolean
2826        } else {
2827            panic!("Expected flag to return Bool(true)");
2828        }
2829
2830        // Test name/symbol/uri types -> String
2831        let name_result = evaluator.eval("name", 0);
2832        if let Ok(DynSolValue::String(val)) = name_result {
2833            assert_eq!(val, "Mock_name"); // Mock string format
2834        } else {
2835            panic!("Expected name to return String");
2836        }
2837
2838        let symbol_result = evaluator.eval("symbol", 0);
2839        if let Ok(DynSolValue::String(val)) = symbol_result {
2840            assert_eq!(val, "Mock_symbol"); // Mock string format
2841        } else {
2842            panic!("Expected symbol to return String");
2843        }
2844
2845        let uri_result = evaluator.eval("uri", 0);
2846        if let Ok(DynSolValue::String(val)) = uri_result {
2847            assert_eq!(val, "Mock_uri"); // Mock string format
2848        } else {
2849            panic!("Expected uri to return String");
2850        }
2851
2852        // Test fallback case -> Uint(42, 256)
2853        let fallback_result = evaluator.eval("randomVariable", 0);
2854        if let Ok(DynSolValue::Uint(val, _)) = fallback_result {
2855            assert_eq!(val, U256::from(42));
2856        } else {
2857            panic!("Expected fallback to return Uint(42, 256)");
2858        }
2859    }
2860
2861    #[test]
2862    fn test_enhanced_builtin_properties() {
2863        let (handlers, debug_handler) = create_simulation_debug_handlers();
2864        let evaluator = ExpressionEvaluator::new(handlers);
2865
2866        // Set up test data
2867        debug_handler.set_variable("testString", DynSolValue::String("Hello".to_string()));
2868        debug_handler.set_variable("testBytes", DynSolValue::Bytes(vec![1, 2, 3]));
2869        debug_handler.set_variable("testAddress", DynSolValue::Address(Address::ZERO));
2870        debug_handler.set_variable(
2871            "testInt",
2872            DynSolValue::Int(I256::from_raw(U256::from(42).wrapping_neg()), 256),
2873        );
2874        debug_handler.set_variable("zeroInt", DynSolValue::Int(I256::ZERO, 256));
2875        debug_handler.set_variable("zeroUint", DynSolValue::Uint(U256::ZERO, 256));
2876        debug_handler.set_variable("nonZeroUint", DynSolValue::Uint(U256::from(123), 256));
2877
2878        // ============ LENGTH PROPERTIES ============
2879
2880        // Test string.length
2881        let result = evaluator.eval("testString.length", 0);
2882        assert!(result.is_ok());
2883        if let Ok(DynSolValue::Uint(len, _)) = result {
2884            assert_eq!(len, U256::from(5)); // "Hello" length
2885        }
2886
2887        // Test bytes.length
2888        let result = evaluator.eval("testBytes.length", 0);
2889        assert!(result.is_ok());
2890        if let Ok(DynSolValue::Uint(len, _)) = result {
2891            assert_eq!(len, U256::from(3));
2892        }
2893
2894        // ============ NUMERIC PROPERTIES ============
2895
2896        // Test int.abs (negative value)
2897        let result = evaluator.eval("testInt.abs", 0);
2898        assert!(result.is_ok());
2899        if let Ok(DynSolValue::Uint(val, _)) = result {
2900            assert_eq!(val, U256::from(42));
2901        }
2902
2903        // ============ TYPE CHECKING PROPERTIES ============
2904
2905        // Test isZero for zero values
2906        let result = evaluator.eval("zeroInt.isZero", 0);
2907        assert!(result.is_ok());
2908        if let Ok(DynSolValue::Bool(is_zero)) = result {
2909            assert!(is_zero);
2910        }
2911
2912        let result = evaluator.eval("zeroUint.isZero", 0);
2913        assert!(result.is_ok());
2914        if let Ok(DynSolValue::Bool(is_zero)) = result {
2915            assert!(is_zero);
2916        }
2917
2918        let result = evaluator.eval("testAddress.isZero", 0);
2919        assert!(result.is_ok());
2920        if let Ok(DynSolValue::Bool(is_zero)) = result {
2921            assert!(is_zero); // Address::ZERO
2922        }
2923
2924        // Test isZero for non-zero values
2925        let result = evaluator.eval("nonZeroUint.isZero", 0);
2926        assert!(result.is_ok());
2927        if let Ok(DynSolValue::Bool(is_zero)) = result {
2928            assert!(!is_zero);
2929        }
2930    }
2931
2932    #[test]
2933    fn test_builtin_member_functions() {
2934        let (handlers, debug_handler) = create_simulation_debug_handlers();
2935        let evaluator = ExpressionEvaluator::new(handlers);
2936
2937        // Set up test data
2938        debug_handler.set_variable("testString", DynSolValue::String("Hello World".to_string()));
2939        debug_handler.set_variable("emptyString", DynSolValue::String("".to_string()));
2940        debug_handler.set_variable("myBytes", DynSolValue::Bytes(vec![1, 2, 3, 4, 5]));
2941        debug_handler.set_variable("emptyBytes", DynSolValue::Bytes(vec![]));
2942        debug_handler.set_variable(
2943            "myArray",
2944            DynSolValue::Tuple(vec![
2945                DynSolValue::Uint(U256::from(10), 256),
2946                DynSolValue::Uint(U256::from(20), 256),
2947                DynSolValue::Uint(U256::from(30), 256),
2948            ]),
2949        );
2950        debug_handler.set_variable("emptyArray", DynSolValue::Tuple(vec![]));
2951        debug_handler.set_variable("testAddress", DynSolValue::Address(Address::from([0x42; 20])));
2952        debug_handler.set_variable("numberA", DynSolValue::Uint(U256::from(100), 256));
2953        debug_handler.set_variable("numberB", DynSolValue::Uint(U256::from(200), 256));
2954
2955        // ============ LENGTH PROPERTIES ============
2956
2957        // Test string.length
2958        let result = evaluator.eval("testString.length", 0);
2959        assert!(result.is_ok());
2960        if let Ok(DynSolValue::Uint(len, _)) = result {
2961            assert_eq!(len, U256::from(11)); // "Hello World" length
2962        }
2963
2964        // Test bytes.length
2965        let result = evaluator.eval("myBytes.length", 0);
2966        assert!(result.is_ok());
2967        if let Ok(DynSolValue::Uint(len, _)) = result {
2968            assert_eq!(len, U256::from(5));
2969        }
2970
2971        // Test array.length
2972        let result = evaluator.eval("myArray.length", 0);
2973        assert!(result.is_ok());
2974        if let Ok(DynSolValue::Uint(len, _)) = result {
2975            assert_eq!(len, U256::from(3));
2976        }
2977
2978        // ============ ARRAY/LIST METHODS ============
2979
2980        // Test array.push() - empty push
2981        let result = evaluator.eval("myArray.push()", 0);
2982        assert!(result.is_ok());
2983        if let Ok(DynSolValue::Uint(new_len, _)) = result {
2984            assert_eq!(new_len, U256::from(4)); // Original 3 + 1
2985        }
2986
2987        // Test array.push(element)
2988        debug_handler.set_variable("newElement", DynSolValue::Uint(U256::from(40), 256));
2989        let result = evaluator.eval("myArray.push(newElement)", 0);
2990        assert!(result.is_ok());
2991        if let Ok(DynSolValue::Uint(new_len, _)) = result {
2992            assert_eq!(new_len, U256::from(4)); // Original 3 + 1
2993        }
2994
2995        // Test array.pop()
2996        let result = evaluator.eval("myArray.pop()", 0);
2997        assert!(result.is_ok());
2998        if let Ok(DynSolValue::Uint(popped_val, _)) = result {
2999            assert_eq!(popped_val, U256::from(30)); // Last element of myArray
3000        }
3001
3002        // Test pop on empty array (should fail)
3003        let result = evaluator.eval("emptyArray.pop()", 0);
3004        assert!(result.is_err());
3005        assert!(result.unwrap_err().to_string().contains("Cannot pop from empty array"));
3006
3007        // ============ STRING METHODS ============
3008
3009        // Test string.concat()
3010        debug_handler.set_variable("suffix", DynSolValue::String(" Test".to_string()));
3011        let result = evaluator.eval("testString.concat(suffix)", 0);
3012        assert!(result.is_ok());
3013        if let Ok(DynSolValue::String(concatenated)) = result {
3014            assert_eq!(concatenated, "Hello World Test");
3015        }
3016
3017        // Test string.slice(start)
3018        debug_handler.set_variable("startIndex", DynSolValue::Uint(U256::from(6), 256));
3019        let result = evaluator.eval("testString.slice(startIndex)", 0);
3020        assert!(result.is_ok());
3021        if let Ok(DynSolValue::String(sliced)) = result {
3022            assert_eq!(sliced, "World");
3023        }
3024
3025        // Test string.slice(start, end)
3026        debug_handler.set_variable("endIndex", DynSolValue::Uint(U256::from(5), 256));
3027        let result = evaluator.eval("testString.slice(0, endIndex)", 0);
3028        assert!(result.is_ok());
3029        if let Ok(DynSolValue::String(sliced)) = result {
3030            assert_eq!(sliced, "Hello");
3031        }
3032
3033        // ============ BYTES METHODS ============
3034
3035        // Test bytes.concat()
3036        debug_handler.set_variable("moreBytes", DynSolValue::Bytes(vec![6, 7, 8]));
3037        let result = evaluator.eval("myBytes.concat(moreBytes)", 0);
3038        assert!(result.is_ok());
3039        if let Ok(DynSolValue::Bytes(concatenated)) = result {
3040            assert_eq!(concatenated, vec![1, 2, 3, 4, 5, 6, 7, 8]);
3041        }
3042
3043        // Test bytes.slice(start)
3044        let result = evaluator.eval("myBytes.slice(2)", 0);
3045        assert!(result.is_ok());
3046        if let Ok(DynSolValue::Bytes(sliced)) = result {
3047            assert_eq!(sliced, vec![3, 4, 5]);
3048        }
3049
3050        // Test bytes.slice(start, end)
3051        let result = evaluator.eval("myBytes.slice(1, 4)", 0);
3052        assert!(result.is_ok());
3053        if let Ok(DynSolValue::Bytes(sliced)) = result {
3054            assert_eq!(sliced, vec![2, 3, 4]);
3055        }
3056
3057        // ============ ADDRESS METHODS ============
3058        // Note: Address properties like balance, code, codehash, isContract should be
3059        // handled by handlers since they require blockchain state access
3060
3061        // ============ MATH FUNCTIONS ============
3062
3063        // Test number.min()
3064        let result = evaluator.eval("numberA.min(numberB)", 0);
3065        assert!(result.is_ok());
3066        if let Ok(DynSolValue::Uint(min_val, _)) = result {
3067            assert_eq!(min_val, U256::from(100));
3068        }
3069
3070        // Test number.max()
3071        let result = evaluator.eval("numberA.max(numberB)", 0);
3072        assert!(result.is_ok());
3073        if let Ok(DynSolValue::Uint(max_val, _)) = result {
3074            assert_eq!(max_val, U256::from(200));
3075        }
3076
3077        // ============ TYPE CHECKING FUNCTIONS ============
3078
3079        // Test string.isEmpty()
3080        let result = evaluator.eval("testString.isEmpty()", 0);
3081        assert!(result.is_ok());
3082        if let Ok(DynSolValue::Bool(is_empty)) = result {
3083            assert!(!is_empty);
3084        }
3085
3086        let result = evaluator.eval("emptyString.isEmpty()", 0);
3087        assert!(result.is_ok());
3088        if let Ok(DynSolValue::Bool(is_empty)) = result {
3089            assert!(is_empty);
3090        }
3091
3092        // Test bytes.isEmpty()
3093        let result = evaluator.eval("myBytes.isEmpty()", 0);
3094        assert!(result.is_ok());
3095        if let Ok(DynSolValue::Bool(is_empty)) = result {
3096            assert!(!is_empty);
3097        }
3098
3099        let result = evaluator.eval("emptyBytes.isEmpty()", 0);
3100        assert!(result.is_ok());
3101        if let Ok(DynSolValue::Bool(is_empty)) = result {
3102            assert!(is_empty);
3103        }
3104
3105        // Test array.isEmpty()
3106        let result = evaluator.eval("myArray.isEmpty()", 0);
3107        assert!(result.is_ok());
3108        if let Ok(DynSolValue::Bool(is_empty)) = result {
3109            assert!(!is_empty);
3110        }
3111
3112        let result = evaluator.eval("emptyArray.isEmpty()", 0);
3113        assert!(result.is_ok());
3114        if let Ok(DynSolValue::Bool(is_empty)) = result {
3115            assert!(is_empty);
3116        }
3117    }
3118
3119    #[test]
3120    fn test_extremely_complex_expressions() {
3121        let (handlers, debug_handler) = create_simulation_debug_handlers();
3122        let evaluator = ExpressionEvaluator::new(handlers);
3123
3124        // Set up complex mock data for realistic DeFi/protocol scenarios
3125        debug_handler.set_function(
3126            "getPoolData",
3127            DynSolValue::Tuple(vec![
3128                DynSolValue::Uint(U256::from(1000000), 256), // reserve0
3129                DynSolValue::Uint(U256::from(2000000), 256), // reserve1
3130                DynSolValue::Uint(U256::from(1700000000), 256), // lastUpdate
3131            ]),
3132        );
3133
3134        debug_handler.set_function("calculateFee", DynSolValue::Uint(U256::from(3000), 256)); // 0.3% fee
3135        debug_handler.set_function("getPrice", DynSolValue::Uint(U256::from(2000), 256)); // Price in USD
3136        debug_handler.set_function("getUserBalance", DynSolValue::Uint(U256::from(50000), 256));
3137        debug_handler.set_function("getSlippageTolerance", DynSolValue::Uint(U256::from(100), 256)); // 1%
3138
3139        // Complex Expression 1: Multi-step DeFi liquidity calculation with slippage protection
3140        let complex_expr1 = "((getUserBalance() * getPrice()) / 1000000) > ((calculateFee() * msg.value * getSlippageTolerance()) / (10000 * 100)) && (block.timestamp - 1700000000) < 3600 && msg.sender != tx.origin";
3141
3142        let result = evaluator.eval(complex_expr1, 0);
3143        assert!(result.is_ok());
3144        if let Ok(DynSolValue::Bool(is_valid)) = result {
3145            // This complex condition should evaluate based on our mock values
3146            println!("Complex DeFi condition result: {}", is_valid);
3147        }
3148
3149        // Complex Expression 2: Nested conditional with multiple function calls and arithmetic
3150        let complex_expr2 = "(((balanceOf() + getUserBalance()) * (getPrice() - calculateFee())) / totalSupply()) > (msg.value * ((block.number % 100) + 1)) ? ((getSlippageTolerance() * 2) + (block.timestamp % 1000)) : ((calculateFee() * 3) - (msg.value / 1000))";
3151
3152        let result = evaluator.eval(complex_expr2, 0);
3153        assert!(result.is_ok());
3154        println!("Complex ternary expression result: {:?}", result);
3155
3156        // Complex Expression 3: Advanced protocol governance voting calculation
3157        let complex_expr3 = "((balanceOf() * (block.number - 18500000)) + (getUserBalance() * getSlippageTolerance())) >= ((totalSupply() / 100) * ((msg.value > 1000000000000000000) ? (calculateFee() + 500) : (calculateFee() - 200))) && (block.timestamp > 1700000000) && ((tx.origin == msg.sender) || (getPrice() > 1800))";
3158
3159        let result = evaluator.eval(complex_expr3, 0);
3160        assert!(result.is_ok());
3161        if let Ok(DynSolValue::Bool(governance_valid)) = result {
3162            println!("Complex governance voting condition: {}", governance_valid);
3163        }
3164
3165        // Verify all operations were logged
3166        let log = debug_handler.get_log();
3167        assert!(!log.is_empty());
3168
3169        // Should contain multiple function calls and complex operations
3170        let function_calls = log.iter().filter(|entry| entry.contains("call_function")).count();
3171        assert!(function_calls >= 10, "Should have many function calls in complex expressions");
3172    }
3173
3174    #[test]
3175    fn test_ultra_complex_nested_expressions() {
3176        let (handlers, debug_handler) = create_simulation_debug_handlers();
3177        let evaluator = ExpressionEvaluator::new(handlers);
3178
3179        // Set up extremely complex scenario data
3180        debug_handler.set_function(
3181            "getLiquidityData",
3182            DynSolValue::Tuple(vec![
3183                DynSolValue::Uint(U256::from(5000000), 256),
3184                DynSolValue::Uint(U256::from(3000000), 256),
3185                DynSolValue::Uint(U256::from(8000000), 256),
3186            ]),
3187        );
3188
3189        debug_handler.set_function("calculateRewards", DynSolValue::Uint(U256::from(12500), 256));
3190        debug_handler.set_function("getMultiplier", DynSolValue::Uint(U256::from(150), 256)); // 1.5x
3191        debug_handler.set_function("getRiskFactor", DynSolValue::Uint(U256::from(80), 256)); // 0.8x
3192        debug_handler.set_function("getTimeDecay", DynSolValue::Uint(U256::from(95), 256)); // 0.95x
3193
3194        // Ultra Complex Expression: Multi-layered yield farming calculation with time decay and risk adjustment
3195        let ultra_complex = r#"
3196            (
3197                (
3198                    (
3199                        (balanceOf() * getMultiplier() * getRiskFactor()) / (100 * 100)
3200                    ) +
3201                    (
3202                        (calculateRewards() * getTimeDecay() * ((block.timestamp - 1700000000) / 86400)) / (100 * 365)
3203                    )
3204                ) *
3205                (
3206                    (msg.value > (totalSupply() / 1000)) ?
3207                    (
3208                        ((getPrice() + calculateFee()) * (block.number % 1000)) / 500
3209                    ) :
3210                    (
3211                        ((getPrice() - calculateFee()) * (block.timestamp % 10000)) / 2000
3212                    )
3213                )
3214            ) >=
3215            (
3216                (
3217                    (getUserBalance() * (100 + getSlippageTolerance())) / 100
3218                ) +
3219                (
3220                    ((msg.sender == tx.origin) ? (calculateRewards() * 2) : (calculateRewards() / 2)) *
3221                    ((block.number > 18500000) ? getMultiplier() : (getMultiplier() / 2))
3222                ) / 100
3223            )
3224        "#.replace('\n', "").replace(' ', "");
3225
3226        let result = evaluator.eval(&ultra_complex, 0);
3227        assert!(result.is_ok());
3228        if let Ok(DynSolValue::Bool(result_bool)) = result {
3229            println!("Ultra complex yield farming condition: {}", result_bool);
3230        }
3231
3232        // Verify extensive logging occurred
3233        let log = debug_handler.get_log();
3234        let total_operations = log.len();
3235        assert!(
3236            total_operations >= 20,
3237            "Ultra complex expression should generate many log entries, got: {}",
3238            total_operations
3239        );
3240
3241        println!("Total operations logged: {}", total_operations);
3242        println!("Sample log entries: {:?}", log.iter().take(5).collect::<Vec<_>>());
3243    }
3244}