edb_engine/analysis/
function.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 foundry_compilers::artifacts::{
20    ast::SourceLocation, FunctionDefinition, FunctionTypeName, ModifierDefinition, StateMutability,
21    Visibility,
22};
23use once_cell::sync::OnceCell;
24use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
25use serde::{Deserialize, Serialize};
26
27use crate::analysis::{macros::universal_id, ContractRef, StepRef};
28
29universal_id! {
30    /// A Universal Function Identifier (UFID) is a unique identifier for a function in contract execution.
31    UFID => 0
32}
33
34/// A reference-counted pointer to a Function for efficient sharing across multiple contexts.
35///
36/// This type alias provides thread-safe reference counting for Function instances,
37/// allowing them to be shared between different parts of the analysis system
38/// without copying the entire function data.
39#[derive(Debug, Clone)]
40pub struct FunctionRef {
41    inner: Arc<RwLock<Function>>,
42    /* cached readonly fields*/
43    ufid: OnceCell<UFID>,
44    contract: OnceCell<Option<ContractRef>>,
45}
46
47impl From<Function> for FunctionRef {
48    fn from(function: Function) -> Self {
49        Self::new(function)
50    }
51}
52
53impl FunctionRef {
54    /// Creates a new FunctionRef from a Function.
55    pub fn new(inner: Function) -> Self {
56        Self {
57            inner: Arc::new(RwLock::new(inner)),
58            ufid: OnceCell::new(),
59            contract: OnceCell::new(),
60        }
61    }
62}
63
64impl FunctionRef {
65    pub(crate) fn read(&self) -> RwLockReadGuard<'_, Function> {
66        self.inner.read()
67    }
68
69    pub(crate) fn write(&self) -> RwLockWriteGuard<'_, Function> {
70        self.inner.write()
71    }
72}
73
74impl FunctionRef {
75    /// Returns the UFID of this function.
76    pub fn ufid(&self) -> UFID {
77        *self.ufid.get_or_init(|| self.inner.read().ufid)
78    }
79
80    /// Returns the contract that this function belongs to.
81    pub fn contract(&self) -> Option<ContractRef> {
82        self.contract.get_or_init(|| self.inner.read().contract.clone()).clone()
83    }
84
85    /// Returns the name of this function.
86    pub fn name(&self) -> String {
87        self.read().definition.name().to_string()
88    }
89
90    /// Returns the visibility of this function.
91    pub fn visibility(&self) -> Visibility {
92        self.read().definition.visibility().clone()
93    }
94
95    /// Returns the state mutability of this function.
96    pub fn state_mutability(&self) -> Option<StateMutability> {
97        self.read().definition.state_mutability().cloned()
98    }
99
100    /// Returns the source location of this function.
101    pub fn src(&self) -> SourceLocation {
102        *self.read().definition.src()
103    }
104}
105
106impl Serialize for FunctionRef {
107    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
108    where
109        S: serde::Serializer,
110    {
111        self.inner.read().serialize(serializer)
112    }
113}
114
115impl<'de> Deserialize<'de> for FunctionRef {
116    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
117    where
118        D: serde::Deserializer<'de>,
119    {
120        let function = Function::deserialize(deserializer)?;
121        Ok(Self::new(function))
122    }
123}
124
125/// A reference-counted pointer to a FunctionTypeName for efficient sharing across multiple contexts.
126///
127/// This type alias provides thread-safe reference counting for FunctionTypeName instances,
128/// allowing them to be shared between different parts of the analysis system
129/// without copying the entire function data.
130#[derive(Debug, Clone)]
131pub struct FunctionTypeNameRef {
132    inner: Arc<RwLock<FunctionTypeName>>,
133}
134
135impl From<FunctionTypeName> for FunctionTypeNameRef {
136    fn from(function_type: FunctionTypeName) -> Self {
137        Self::new(function_type)
138    }
139}
140
141impl FunctionTypeNameRef {
142    /// Creates a new FunctionTypeNameRef from a FunctionTypeName.
143    pub fn new(inner: FunctionTypeName) -> Self {
144        Self { inner: Arc::new(RwLock::new(inner)) }
145    }
146}
147
148#[allow(unused)]
149impl FunctionTypeNameRef {
150    pub(crate) fn read(&self) -> RwLockReadGuard<'_, FunctionTypeName> {
151        self.inner.read()
152    }
153
154    pub(crate) fn write(&self) -> RwLockWriteGuard<'_, FunctionTypeName> {
155        self.inner.write()
156    }
157}
158
159impl FunctionTypeNameRef {
160    /// Returns the visibility of this function type.
161    pub fn visibility(&self) -> Visibility {
162        self.read().visibility.clone()
163    }
164
165    /// Returns the state mutability of this function type.
166    pub fn state_mutability(&self) -> StateMutability {
167        self.read().state_mutability.clone()
168    }
169
170    /// Returns the source location of this function type.
171    pub fn src(&self) -> SourceLocation {
172        self.read().src
173    }
174}
175
176impl Serialize for FunctionTypeNameRef {
177    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
178    where
179        S: serde::Serializer,
180    {
181        self.inner.read().serialize(serializer)
182    }
183}
184
185impl<'de> Deserialize<'de> for FunctionTypeNameRef {
186    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
187    where
188        D: serde::Deserializer<'de>,
189    {
190        let function_type = FunctionTypeName::deserialize(deserializer)?;
191        Ok(Self::new(function_type))
192    }
193}
194
195/// Represents a function or modifier in a smart contract with its metadata and type information.
196#[derive(Debug, Clone, Serialize, Deserialize)]
197pub struct Function {
198    /// The unique function identifier.
199    pub ufid: UFID,
200    /// The contract that this function belongs to.
201    pub contract: Option<ContractRef>,
202    /// The function or modifier definition.
203    pub definition: FunctionVariant,
204    /// List of steps in this function.
205    pub steps: Vec<StepRef>,
206}
207
208/// The variant types for function definitions.
209#[derive(Debug, Clone, Serialize, Deserialize, derive_more::From)]
210pub enum FunctionVariant {
211    /// A function definition.
212    Function(#[from] FunctionDefinition),
213    /// A modifier definition.
214    Modifier(#[from] ModifierDefinition),
215}
216
217impl FunctionVariant {
218    /// Returns the name of this function.
219    pub fn name(&self) -> &str {
220        match self {
221            Self::Function(definition) => &definition.name,
222            Self::Modifier(definition) => &definition.name,
223        }
224    }
225
226    /// Returns the visibility of this function.
227    pub fn visibility(&self) -> &Visibility {
228        match self {
229            Self::Function(definition) => &definition.visibility,
230            Self::Modifier(definition) => &definition.visibility,
231        }
232    }
233
234    /// Returns the source location of this function.
235    pub fn src(&self) -> &SourceLocation {
236        match self {
237            Self::Function(definition) => &definition.src,
238            Self::Modifier(definition) => &definition.src,
239        }
240    }
241
242    /// Returns the state mutability of this function.
243    pub fn state_mutability(&self) -> Option<&StateMutability> {
244        match self {
245            Self::Function(definition) => definition.state_mutability.as_ref(),
246            Self::Modifier(_) => None,
247        }
248    }
249}
250
251impl Function {
252    /// Creates a new Function with the given contract and definition.
253    pub fn new_function(contract: Option<ContractRef>, definition: FunctionDefinition) -> Self {
254        Self {
255            ufid: UFID::next(),
256            contract,
257            definition: FunctionVariant::Function(definition),
258            steps: vec![],
259        }
260    }
261
262    /// Creates a new Function with the given contract and definition.
263    pub fn new_modifier(contract: ContractRef, definition: ModifierDefinition) -> Self {
264        Self {
265            ufid: UFID::next(),
266            contract: Some(contract),
267            definition: FunctionVariant::Modifier(definition),
268            steps: vec![],
269        }
270    }
271}