1//! Support for "cheat codes" / bypass functions
23use alloy_primitives::{Address, map::AddressHashSet};
4use parking_lot::RwLock;
5use std::sync::Arc;
67/// Manages user modifications that may affect the node's behavior
8///
9/// Contains the state of executed, non-eth standard cheat code RPC
10#[derive(Clone, Debug, Default)]
11pub struct CheatsManager {
12/// shareable state
13state: Arc<RwLock<CheatsState>>,
14}
1516impl CheatsManager {
17/// Sets the account to impersonate
18 ///
19 /// Returns `true` if the account is already impersonated
20pub fn impersonate(&self, addr: Address) -> bool {
21trace!(target: "cheats", "Start impersonating {:?}", addr);
22let mut state = self.state.write();
23// When somebody **explicitly** impersonates an account we need to store it so we are able
24 // to return it from `eth_accounts`. That's why we do not simply call `is_impersonated()`
25 // which does not check that list when auto impersonation is enabled.
26if state.impersonated_accounts.contains(&addr) {
27// need to check if already impersonated, so we don't overwrite the code
28return true;
29 }
30state.impersonated_accounts.insert(addr)
31 }
3233/// Removes the account that from the impersonated set
34pub fn stop_impersonating(&self, addr: &Address) {
35trace!(target: "cheats", "Stop impersonating {:?}", addr);
36self.state.write().impersonated_accounts.remove(addr);
37 }
3839/// Returns true if the `addr` is currently impersonated
40pub fn is_impersonated(&self, addr: Address) -> bool {
41if self.auto_impersonate_accounts() {
42true
43} else {
44self.state.read().impersonated_accounts.contains(&addr)
45 }
46 }
4748/// Returns true is auto impersonation is enabled
49pub fn auto_impersonate_accounts(&self) -> bool {
50self.state.read().auto_impersonate_accounts
51 }
5253/// Sets the auto impersonation flag which if set to true will make the `is_impersonated`
54 /// function always return true
55pub fn set_auto_impersonate_account(&self, enabled: bool) {
56trace!(target: "cheats", "Auto impersonation set to {:?}", enabled);
57self.state.write().auto_impersonate_accounts = enabled58 }
5960/// Returns all accounts that are currently being impersonated.
61pub fn impersonated_accounts(&self) -> AddressHashSet {
62self.state.read().impersonated_accounts.clone()
63 }
64}
6566/// Container type for all the state variables
67#[derive(Clone, Debug, Default)]
68pub struct CheatsState {
69/// All accounts that are currently impersonated
70pub impersonated_accounts: AddressHashSet,
71/// If set to true will make the `is_impersonated` function always return true
72pub auto_impersonate_accounts: bool,
73}