neo_devpack_solidity/runtime/state/state_impl/
accounts.rs1use super::*;
2
3impl StateManager {
4 pub fn get_account(&self, address: &str) -> Option<&AccountState> {
6 self.accounts.get(address)
7 }
8
9 pub fn get_balance(&self, address: &str) -> Result<u64, RuntimeError> {
11 Ok(self
12 .accounts
13 .get(address)
14 .map(|account| account.balance)
15 .unwrap_or(0))
16 }
17
18 pub fn set_balance(&mut self, address: &str, balance: u64) -> Result<(), RuntimeError> {
20 let old_balance = self.get_balance(address)?;
21
22 let created_at = self.current_timestamp();
23 let account = self
24 .accounts
25 .entry(address.to_string())
26 .or_insert_with(|| AccountState {
27 address: address.to_string(),
28 balance: 0,
29 nonce: 0,
30 code: None,
31 code_hash: None,
32 storage_root: None,
33 created_at,
34 });
35
36 account.balance = balance;
37
38 self.record_change(StateChange {
40 change_type: StateChangeType::BalanceChange,
41 account: address.to_string(),
42 key: None,
43 old_value: Some(old_balance.to_le_bytes().to_vec()),
44 new_value: balance.to_le_bytes().to_vec(),
45 });
46
47 Ok(())
48 }
49
50 pub fn get_nonce(&self, address: &str) -> Result<u64, RuntimeError> {
52 Ok(self
53 .accounts
54 .get(address)
55 .map(|account| account.nonce)
56 .unwrap_or(0))
57 }
58
59 pub fn set_nonce(&mut self, address: &str, nonce: u64) -> Result<(), RuntimeError> {
61 let old_nonce = self.get_nonce(address)?;
62
63 let created_at = self.current_timestamp();
64 let account = self
65 .accounts
66 .entry(address.to_string())
67 .or_insert_with(|| AccountState {
68 address: address.to_string(),
69 balance: 0,
70 nonce: 0,
71 code: None,
72 code_hash: None,
73 storage_root: None,
74 created_at,
75 });
76
77 account.nonce = nonce;
78
79 self.record_change(StateChange {
81 change_type: StateChangeType::NonceChange,
82 account: address.to_string(),
83 key: None,
84 old_value: Some(old_nonce.to_le_bytes().to_vec()),
85 new_value: nonce.to_le_bytes().to_vec(),
86 });
87
88 Ok(())
89 }
90
91 pub fn get_code(&self, address: &str) -> Option<&[u8]> {
93 self.accounts
94 .get(address)
95 .and_then(|account| account.code.as_ref())
96 .map(|code| code.as_slice())
97 }
98
99 pub fn set_code(&mut self, address: &str, code: &[u8]) -> Result<(), RuntimeError> {
101 let old_code = self.get_code(address).map(|c| c.to_vec());
102
103 let created_at = self.current_timestamp();
104 let code_hash = self.calculate_hash(code);
105
106 let account = self
107 .accounts
108 .entry(address.to_string())
109 .or_insert_with(|| AccountState {
110 address: address.to_string(),
111 balance: 0,
112 nonce: 0,
113 code: None,
114 code_hash: None,
115 storage_root: None,
116 created_at,
117 });
118 account.code = Some(code.to_vec());
119 account.code_hash = Some(code_hash);
120
121 self.record_change(StateChange {
123 change_type: StateChangeType::CodeChange,
124 account: address.to_string(),
125 key: None,
126 old_value: old_code,
127 new_value: code.to_vec(),
128 });
129
130 Ok(())
131 }
132
133 pub fn create_account(
135 &mut self,
136 address: &str,
137 initial_balance: u64,
138 ) -> Result<(), RuntimeError> {
139 if self.accounts.contains_key(address) {
140 return Err(RuntimeError::StateError {
141 message: format!("Account {address} already exists"),
142 });
143 }
144
145 let account = AccountState {
146 address: address.to_string(),
147 balance: initial_balance,
148 nonce: 0,
149 code: None,
150 code_hash: None,
151 storage_root: None,
152 created_at: self.current_timestamp(),
153 };
154
155 self.accounts.insert(address.to_string(), account);
156
157 self.record_change(StateChange {
159 change_type: StateChangeType::AccountCreation,
160 account: address.to_string(),
161 key: None,
162 old_value: None,
163 new_value: initial_balance.to_le_bytes().to_vec(),
164 });
165
166 Ok(())
167 }
168
169 pub fn delete_account(&mut self, address: &str) -> Result<(), RuntimeError> {
171 if let Some(account) = self.accounts.remove(address) {
172 self.record_change(StateChange {
174 change_type: StateChangeType::AccountDeletion,
175 account: address.to_string(),
176 key: None,
177 old_value: Some(account.balance.to_le_bytes().to_vec()),
178 new_value: vec![],
179 });
180 }
181
182 Ok(())
183 }
184
185 pub fn account_exists(&self, address: &str) -> bool {
187 self.accounts.contains_key(address)
188 }
189
190 pub fn transfer(&mut self, from: &str, to: &str, amount: u64) -> Result<(), RuntimeError> {
192 let from_balance = self.get_balance(from)?;
193 let to_balance = self.get_balance(to)?;
194
195 if from_balance < amount {
196 return Err(RuntimeError::StateError {
197 message: "Insufficient balance".to_string(),
198 });
199 }
200
201 self.set_balance(from, from_balance - amount)?;
202 self.set_balance(to, to_balance + amount)?;
203
204 Ok(())
205 }
206}