foundry_evm_symbolic/runtime/
calldata.rs1use super::*;
2
3#[derive(Clone, Debug)]
4pub(crate) struct SymCalldata {
5 pub(crate) size: usize,
6 pub(crate) size_word: SymWord,
7 pub(crate) bytes: Vec<SymWord>,
8}
9
10impl SymCalldata {
11 pub(crate) fn new(bytes: Vec<SymWord>) -> Self {
13 Self { size_word: SymWord::Concrete(U256::from(bytes.len())), size: bytes.len(), bytes }
14 }
15
16 pub(crate) const fn new_symbolic_size(bytes: Vec<SymWord>, size_word: SymWord) -> Self {
18 Self { size: bytes.len(), size_word, bytes }
19 }
20
21 pub(crate) fn load_word(&self, offset: SymWord) -> Result<SymWord, SymbolicError> {
23 match offset {
24 SymWord::Concrete(offset) => {
25 if offset > U256::from(usize::MAX) {
26 return Ok(SymWord::zero());
27 }
28 self.load(offset.to::<usize>())
29 }
30 SymWord::Expr(offset) => self.load_dynamic(offset),
31 }
32 }
33
34 pub(crate) fn load(&self, offset: usize) -> Result<SymWord, SymbolicError> {
36 Ok(word_from_bytes((0..32).map(|idx| self.byte(offset + idx))))
37 }
38
39 pub(crate) fn byte(&self, offset: usize) -> SymWord {
41 self.bytes.get(offset).cloned().unwrap_or_else(SymWord::zero)
42 }
43
44 pub(crate) fn load_dynamic(&self, offset: Expr) -> Result<SymWord, SymbolicError> {
46 let mut result = Expr::Const(U256::ZERO);
47 for candidate in (0..self.size).rev() {
48 result = Expr::Ite(
49 Box::new(BoolExpr::eq(offset.clone(), Expr::Const(U256::from(candidate)))),
50 Box::new(self.load(candidate)?.into_expr()),
51 Box::new(result),
52 );
53 }
54 Ok(SymWord::Expr(result))
55 }
56
57 pub(crate) fn byte_dynamic_with_delta(&self, offset: Expr, delta: usize) -> SymWord {
59 let mut result = Expr::Const(U256::ZERO);
60 for candidate in (delta..self.size).rev() {
61 result = Expr::Ite(
62 Box::new(BoolExpr::eq(offset.clone(), Expr::Const(U256::from(candidate - delta)))),
63 Box::new(self.byte(candidate).into_expr()),
64 Box::new(result),
65 );
66 }
67 SymWord::Expr(result)
68 }
69}
70
71pub(crate) fn call_input_from_memory(
73 memory: &SymMemory,
74 offset: SymWord,
75 size: &BoundedCopySize,
76) -> Vec<SymWord> {
77 match size {
78 BoundedCopySize::Concrete(size) => memory.read_bytes_offset(offset, *size),
79 BoundedCopySize::Symbolic { size, max_size } => {
80 memory.read_bytes_symbolic_size(offset, size.clone(), *max_size)
81 }
82 }
83}
84
85pub(crate) fn bounded_copy_size_word(size: &BoundedCopySize) -> SymWord {
87 match size {
88 BoundedCopySize::Concrete(size) => SymWord::Concrete(U256::from(*size)),
89 BoundedCopySize::Symbolic { size, .. } => size.clone(),
90 }
91}
92
93pub(crate) fn bounded_copy_size_parts(size: &BoundedCopySize) -> (SymWord, usize, bool) {
95 match size {
96 BoundedCopySize::Concrete(size) => (SymWord::Concrete(U256::from(*size)), *size, false),
97 BoundedCopySize::Symbolic { size, max_size } => (size.clone(), *max_size, true),
98 }
99}
100
101pub(crate) fn calldata_from_call_input(input: Vec<SymWord>, size: &BoundedCopySize) -> SymCalldata {
103 match size {
104 BoundedCopySize::Concrete(_) => SymCalldata::new(input),
105 BoundedCopySize::Symbolic { size, .. } => {
106 SymCalldata::new_symbolic_size(input, size.clone())
107 }
108 }
109}