Skip to main content

anvil_polkadot/substrate_node/
impersonation.rs

1//! Support for "cheat codes" / bypass functions
2//! Same logic as for anvil, except the `H160` usage over `Address`.
3
4use std::collections::HashSet;
5use subxt::utils::H160;
6
7/// 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(crate) struct ImpersonationManager {
12    /// All accounts that are currently impersonated
13    pub impersonated_accounts: HashSet<H160>,
14    /// If set to true will make the `is_impersonated` function always return true
15    pub auto_impersonate_accounts: bool,
16}
17
18impl ImpersonationManager {
19    /// Sets the account to impersonate
20    ///
21    /// This also accepts the actual code hash if the address is a contract to bypass EIP-3607
22    ///
23    /// Returns `true` if the account is already impersonated
24    pub fn impersonate(&mut self, addr: H160) -> bool {
25        trace!(target: "cheats", "Start impersonating {:?}", addr);
26        // When somebody **explicitly** impersonates an account we need to store it so we are able
27        // to return it from `eth_accounts`. That's why we do not simply call `is_impersonated()`
28        // which does not check that list when auto impersonation is enabled.
29        if self.impersonated_accounts.contains(&addr) {
30            // need to check if already impersonated, so we don't overwrite the code
31            return true;
32        }
33        self.impersonated_accounts.insert(addr)
34    }
35
36    /// Removes the account that from the impersonated set
37    pub fn stop_impersonating(&mut self, addr: &H160) {
38        trace!(target: "cheats", "Stop impersonating {:?}", addr);
39        self.impersonated_accounts.remove(addr);
40    }
41
42    /// Returns true if the `addr` is currently impersonated
43    pub fn is_impersonated(&self, addr: H160) -> bool {
44        if self.auto_impersonate_accounts() {
45            true
46        } else {
47            self.impersonated_accounts.contains(&addr)
48        }
49    }
50
51    /// Returns true is auto impersonation is enabled
52    pub fn auto_impersonate_accounts(&self) -> bool {
53        self.auto_impersonate_accounts
54    }
55
56    /// Sets the auto impersonation flag which if set to true will make the `is_impersonated`
57    /// function always return true
58    pub fn set_auto_impersonate_account(&mut self, enabled: bool) {
59        trace!(target: "cheats", "Auto impersonation set to {:?}", enabled);
60        self.auto_impersonate_accounts = enabled
61    }
62}