foundry_evm_symbolic/runtime/
calldata.rs1use super::*;
2
3#[derive(Clone, Debug)]
4pub(crate) struct SymCalldata {
5 size: usize,
6 size_word: SymExpr,
7 bytes: SymBytes,
8}
9
10impl SymCalldata {
11 pub(crate) fn from_bytes(cx: &mut SymCx, bytes: SymBytes) -> Self {
12 let size = bytes.len();
13 Self { size_word: SymExpr::constant(cx, U256::from(size)), size, bytes }
14 }
15
16 pub(crate) fn size_word(&self) -> SymExpr {
17 self.size_word.clone()
18 }
19
20 pub(crate) fn load_word(&self, cx: &mut SymCx, offset: SymExpr) -> SymExpr {
21 if let Some(offset) = offset.as_const() {
22 let Ok(offset) = usize::try_from(offset) else {
23 return SymExpr::zero(cx);
24 };
25 self.bytes.word_at(cx, offset)
26 } else {
27 self.load_dynamic(cx, &offset)
28 }
29 }
30
31 fn load_dynamic(&self, cx: &mut SymCx, offset: &SymExpr) -> SymExpr {
32 let mut result = SymExpr::zero(cx);
33 for candidate in (0..self.size).rev() {
34 let candidate_expr = SymExpr::constant(cx, U256::from(candidate));
35 let condition = SymBoolExpr::eq(cx, offset.clone(), candidate_expr);
36 let word = self.bytes.word_at(cx, candidate);
37 result = SymExpr::ite(cx, condition, word, result);
38 }
39 result
40 }
41
42 pub(crate) fn read_bytes_offset(
43 &self,
44 cx: &mut SymCx,
45 offset: SymExpr,
46 size: usize,
47 ) -> SymBytes {
48 self.bytes.read_offset(cx, offset, size)
49 }
50}
51
52impl BoundedCopySize {
53 pub(crate) fn expand_memory(&self, cx: &mut SymCx, memory: &mut SymMemory, offset: SymExpr) {
54 let size = self.size_word(cx);
55 memory.expand_range(cx, offset, size);
56 }
57
58 pub(crate) fn read_from_memory(
59 &self,
60 cx: &mut SymCx,
61 memory: &SymMemory,
62 offset: SymExpr,
63 ) -> SymBytes {
64 match self {
65 Self::Concrete(size) => memory.read_bytes_offset(cx, offset, *size),
66 Self::Symbolic { size, max_size } => {
67 memory.read_bytes_symbolic_size(cx, offset, size.clone(), *max_size)
68 }
69 }
70 }
71
72 pub(crate) fn size_word(&self, cx: &mut SymCx) -> SymExpr {
73 match self {
74 Self::Concrete(size) => SymExpr::constant(cx, U256::from(*size)),
75 Self::Symbolic { size, .. } => size.clone(),
76 }
77 }
78
79 pub(crate) fn parts(&self, cx: &mut SymCx) -> (SymExpr, usize, bool) {
80 match self {
81 Self::Concrete(size) => (SymExpr::constant(cx, U256::from(*size)), *size, false),
82 Self::Symbolic { size, max_size } => (size.clone(), *max_size, true),
83 }
84 }
85
86 pub(crate) fn calldata(&self, cx: &mut SymCx, input: SymBytes) -> SymCalldata {
87 match self {
88 Self::Concrete(_) => SymCalldata::from_bytes(cx, input),
89 Self::Symbolic { size, .. } => {
90 SymCalldata { size: input.len(), size_word: size.clone(), bytes: input }
91 }
92 }
93 }
94}