cfx_executor/state/state_object/
basic_fields.rs

1use super::{RequireFields, State};
2use crate::try_loaded;
3use cfx_bytes::Bytes;
4use cfx_statedb::Result as DbResult;
5use cfx_types::{
6    address_util::AddressUtil, Address, AddressSpaceUtil, AddressWithSpace,
7    Space, H256, U256,
8};
9use cfx_vm_types::extract_7702_payload;
10use keccak_hash::KECCAK_EMPTY;
11#[cfg(test)]
12use primitives::StorageLayout;
13use std::sync::Arc;
14
15impl State {
16    pub fn exists(&self, address: &AddressWithSpace) -> DbResult<bool> {
17        Ok(self.read_account_lock(address)?.is_some())
18    }
19
20    /// Touch an account to mark it as warm
21    pub fn touch(&self, address: &AddressWithSpace) -> DbResult<()> {
22        self.exists(address)?;
23        Ok(())
24    }
25
26    pub fn exists_and_not_null(
27        &self, address: &AddressWithSpace,
28    ) -> DbResult<bool> {
29        let acc = try_loaded!(self.read_account_lock(address));
30        Ok(!acc.is_null())
31    }
32
33    pub fn balance(&self, address: &AddressWithSpace) -> DbResult<U256> {
34        let acc = try_loaded!(self.read_account_lock(address));
35        Ok(*acc.balance())
36    }
37
38    pub fn add_balance(
39        &mut self, address: &AddressWithSpace, by: &U256,
40    ) -> DbResult<()> {
41        // Mark address as warm.
42        self.touch(address)?;
43
44        // The caller should guarantee the validity of address.
45
46        if !by.is_zero() {
47            self.write_account_or_new_lock(address)?.add_balance(by);
48        }
49
50        Ok(())
51    }
52
53    pub fn sub_balance(
54        &mut self, address: &AddressWithSpace, by: &U256,
55    ) -> DbResult<()> {
56        // Mark address as warm.
57        self.touch(address)?;
58
59        if !by.is_zero() {
60            self.write_account_lock(address)?.sub_balance(by);
61        }
62        Ok(())
63    }
64
65    pub fn transfer_balance(
66        &mut self, from: &AddressWithSpace, to: &AddressWithSpace, by: &U256,
67    ) -> DbResult<()> {
68        self.sub_balance(from, by)?;
69        self.add_balance(to, by)?;
70        Ok(())
71    }
72
73    pub fn nonce(&self, address: &AddressWithSpace) -> DbResult<U256> {
74        let acc = try_loaded!(self.read_account_lock(address));
75        Ok(*acc.nonce())
76    }
77
78    pub fn inc_nonce(&mut self, address: &AddressWithSpace) -> DbResult<bool> {
79        Ok(self.write_account_or_new_lock(address)?.inc_nonce())
80    }
81
82    pub fn set_nonce(
83        &mut self, address: &AddressWithSpace, nonce: &U256,
84    ) -> DbResult<()> {
85        self.write_account_or_new_lock(address)?.set_nonce(&nonce);
86        Ok(())
87    }
88
89    pub fn is_contract_with_code(
90        &self, address: &AddressWithSpace,
91    ) -> DbResult<bool> {
92        if address.space == Space::Native
93            && !address.address.is_contract_address()
94        {
95            return Ok(false);
96        }
97
98        let acc = try_loaded!(self.read_account_lock(address));
99        Ok(acc.code_hash() != KECCAK_EMPTY)
100    }
101
102    pub fn is_eip684_empty(
103        &self, address: &AddressWithSpace,
104    ) -> DbResult<bool> {
105        let Some(acc) = self.read_account_lock(address)? else {
106            return Ok(true);
107        };
108        Ok(acc.code_hash() == KECCAK_EMPTY && acc.nonce().is_zero())
109    }
110
111    pub fn is_eip158_empty(
112        &self, address: &AddressWithSpace,
113    ) -> DbResult<bool> {
114        let Some(acc) = self.read_account_lock(address)? else {
115            return Ok(true);
116        };
117        Ok(acc.code_hash() == KECCAK_EMPTY
118            && acc.nonce().is_zero()
119            && acc.balance().is_zero())
120    }
121
122    pub fn code_hash(&self, address: &AddressWithSpace) -> DbResult<H256> {
123        let acc = try_loaded!(self.read_account_lock(address));
124        Ok(acc.code_hash())
125    }
126
127    pub fn has_no_code(&self, address: &AddressWithSpace) -> DbResult<bool> {
128        let Some(acc) = self.read_account_lock(address)? else {
129            return Ok(true);
130        };
131        Ok(acc.code_hash() == KECCAK_EMPTY)
132    }
133
134    pub fn code_size(&self, address: &AddressWithSpace) -> DbResult<usize> {
135        let acc = try_loaded!(
136            self.read_account_ext_lock(address, RequireFields::Code)
137        );
138        Ok(acc.code_size())
139    }
140
141    pub fn code_owner(&self, address: &AddressWithSpace) -> DbResult<Address> {
142        address.assert_native();
143        let acc = try_loaded!(
144            self.read_account_ext_lock(address, RequireFields::Code)
145        );
146        Ok(acc.code_owner())
147    }
148
149    pub fn code(
150        &self, address: &AddressWithSpace,
151    ) -> DbResult<Option<Arc<Vec<u8>>>> {
152        let acc = try_loaded!(
153            self.read_account_ext_lock(address, RequireFields::Code)
154        );
155        Ok(acc.code())
156    }
157
158    pub fn code_with_hash_on_call(
159        &self, address: &AddressWithSpace,
160    ) -> DbResult<(Option<Arc<Vec<u8>>>, H256)> {
161        let authority_acc = try_loaded!(
162            self.read_account_ext_lock(address, RequireFields::Code)
163        );
164        let authority_code = authority_acc.code();
165        let authority_code_hash = authority_acc.code_hash();
166
167        std::mem::drop(authority_acc);
168
169        let (code, code_hash) = if address.space == Space::Native {
170            // Core space does not support-7702
171            (authority_code, authority_code_hash)
172        } else if let Some(delegated_address) = authority_code
173            .as_ref()
174            .and_then(|x| extract_7702_payload(&**x))
175        {
176            let delegated_acc = try_loaded!(self.read_account_ext_lock(
177                &delegated_address.with_space(address.space),
178                RequireFields::Code
179            ));
180            (delegated_acc.code(), delegated_acc.code_hash())
181        } else {
182            (authority_code, authority_code_hash)
183        };
184
185        Ok((code, code_hash))
186    }
187
188    pub fn init_code(
189        &mut self, address: &AddressWithSpace, code: Bytes, owner: Address,
190        transaction_hash: H256,
191    ) -> DbResult<()> {
192        self.write_account_lock(address)?.init_code(
193            code,
194            owner,
195            transaction_hash,
196        );
197        Ok(())
198    }
199
200    pub fn created_at_transaction(
201        &self, address: &AddressWithSpace, transaction_hash: H256,
202    ) -> DbResult<bool> {
203        Ok(
204            if let Some(acc) =
205                self.read_account_ext_lock(&address, RequireFields::None)?
206            {
207                acc.create_transaction_hash() == Some(transaction_hash)
208            } else {
209                false
210            },
211        )
212    }
213
214    pub fn set_authorization(
215        &mut self, authority: &AddressWithSpace, address: &Address,
216    ) -> DbResult<()> {
217        self.write_account_or_new_lock(authority)?
218            .set_authorization(address);
219        Ok(())
220    }
221
222    pub fn admin(&self, address: &Address) -> DbResult<Address> {
223        let acc = try_loaded!(self.read_native_account_lock(address));
224        Ok(*acc.admin())
225    }
226
227    pub fn set_admin(
228        &mut self, contract_address: &Address, admin: &Address,
229    ) -> DbResult<()> {
230        self.write_native_account_lock(&contract_address)?
231            .set_admin(admin);
232        Ok(())
233    }
234
235    #[cfg(test)]
236    pub fn set_storage_layout(
237        &mut self, address: &AddressWithSpace, layout: StorageLayout,
238    ) -> DbResult<()> {
239        self.write_account_lock(address)?.set_storage_layout(layout);
240        Ok(())
241    }
242}