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 from_bytes_with_size(bytes: SymBytes, size_word: SymExpr) -> Self {
17 Self { size: bytes.len(), size_word, bytes }
18 }
19
20 pub(crate) fn size_word(&self) -> SymExpr {
21 self.size_word.clone()
22 }
23
24 pub(crate) fn load_word(
25 &self,
26 cx: &mut SymCx,
27 offset: SymExpr,
28 ) -> Result<SymExpr, SymbolicError> {
29 if let Some(offset) = offset.as_const() {
30 let Ok(offset) = usize::try_from(offset) else {
31 return Ok(SymExpr::zero(cx));
32 };
33 self.load(cx, offset)
34 } else {
35 self.load_dynamic(cx, &offset)
36 }
37 }
38
39 pub(crate) fn load(&self, cx: &mut SymCx, offset: usize) -> Result<SymExpr, SymbolicError> {
40 Ok(self.bytes.word_at(cx, offset))
41 }
42
43 pub(crate) fn load_dynamic(
44 &self,
45 cx: &mut SymCx,
46 offset: &SymExpr,
47 ) -> Result<SymExpr, SymbolicError> {
48 let mut result = SymExpr::zero(cx);
49 for candidate in (0..self.size).rev() {
50 let candidate_expr = SymExpr::constant(cx, U256::from(candidate));
51 let condition = SymBoolExpr::eq(cx, offset.clone(), candidate_expr);
52 let word = self.load(cx, candidate)?;
53 result = SymExpr::ite(cx, condition, word, result);
54 }
55 Ok(result)
56 }
57
58 pub(crate) fn read_bytes_offset(
59 &self,
60 cx: &mut SymCx,
61 offset: SymExpr,
62 size: usize,
63 ) -> SymBytes {
64 self.bytes.read_offset(cx, offset, size)
65 }
66}
67
68impl BoundedCopySize {
69 pub(crate) fn read_from_memory(
70 &self,
71 cx: &mut SymCx,
72 memory: &SymMemory,
73 offset: SymExpr,
74 ) -> SymBytes {
75 match self {
76 Self::Concrete(size) => memory.read_bytes_offset(cx, offset, *size),
77 Self::Symbolic { size, max_size } => {
78 memory.read_bytes_symbolic_size(cx, offset, size.clone(), *max_size)
79 }
80 }
81 }
82
83 pub(crate) fn size_word(&self, cx: &mut SymCx) -> SymExpr {
84 match self {
85 Self::Concrete(size) => SymExpr::constant(cx, U256::from(*size)),
86 Self::Symbolic { size, .. } => size.clone(),
87 }
88 }
89
90 pub(crate) fn parts(&self, cx: &mut SymCx) -> (SymExpr, usize, bool) {
91 match self {
92 Self::Concrete(size) => (SymExpr::constant(cx, U256::from(*size)), *size, false),
93 Self::Symbolic { size, max_size } => (size.clone(), *max_size, true),
94 }
95 }
96
97 pub(crate) fn calldata(&self, cx: &mut SymCx, input: SymBytes) -> SymCalldata {
98 match self {
99 Self::Concrete(_) => SymCalldata::from_bytes(cx, input),
100 Self::Symbolic { size, .. } => SymCalldata::from_bytes_with_size(input, size.clone()),
101 }
102 }
103}