cfx_executor/state/state_object/
basic_fields.rs1use 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 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 self.touch(address)?;
43
44 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 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 (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}