1use crate::cell::*;
2use crate::error::Error;
3use crate::models::account::StorageUsedShort;
4use crate::models::currency::CurrencyCollection;
5use crate::num::*;
6
7#[derive(Debug, Clone, Eq, PartialEq, Store, Load)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12pub struct StoragePhase {
13 pub storage_fees_collected: Tokens,
15 pub storage_fees_due: Option<Tokens>,
18 pub status_change: AccountStatusChange,
20}
21
22#[derive(Debug, Clone, Eq, PartialEq, Store, Load)]
26#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
27pub struct CreditPhase {
28 pub due_fees_collected: Option<Tokens>,
30 pub credit: CurrencyCollection,
33}
34
35#[derive(Debug, Clone, Eq, PartialEq)]
39#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
40#[cfg_attr(feature = "serde", serde(tag = "ty"))]
41pub enum ComputePhase {
42 Skipped(SkippedComputePhase),
44 Executed(ExecutedComputePhase),
46}
47
48impl Store for ComputePhase {
49 fn store_into(
50 &self,
51 builder: &mut CellBuilder,
52 context: &dyn CellContext,
53 ) -> Result<(), Error> {
54 match self {
55 Self::Skipped(phase) => {
56 ok!(builder.store_bit_zero());
57 phase.store_into(builder, context)
58 }
59 Self::Executed(phase) => {
60 let cell = {
61 let mut builder = CellBuilder::new();
62 ok!(phase.gas_used.store_into(&mut builder, context));
63 ok!(phase.gas_limit.store_into(&mut builder, context));
64 ok!(phase.gas_credit.store_into(&mut builder, context));
65 ok!(builder.store_u8(phase.mode as u8));
66 ok!(builder.store_u32(phase.exit_code as u32));
67 ok!(phase.exit_arg.store_into(&mut builder, context));
68 ok!(builder.store_u32(phase.vm_steps));
69 ok!(builder.store_u256(&phase.vm_init_state_hash));
70 ok!(builder.store_u256(&phase.vm_final_state_hash));
71 ok!(builder.build_ext(context))
72 };
73
74 let flags = 0b1000u8
75 | ((phase.success as u8) << 2)
76 | ((phase.msg_state_used as u8) << 1)
77 | (phase.account_activated as u8);
78 ok!(builder.store_small_uint(flags, 4));
79 ok!(phase.gas_fees.store_into(builder, context));
80 builder.store_reference(cell)
81 }
82 }
83 }
84}
85
86impl<'a> Load<'a> for ComputePhase {
87 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
88 if !ok!(slice.load_bit()) {
89 return Ok(Self::Skipped(ok!(SkippedComputePhase::load_from(slice))));
90 }
91
92 let flags = ok!(slice.load_small_uint(3));
93 let gas_fees = ok!(Tokens::load_from(slice));
94
95 let slice = &mut ok!(slice.load_reference_as_slice());
96 Ok(Self::Executed(ExecutedComputePhase {
97 success: flags & 0b100 != 0,
98 msg_state_used: flags & 0b010 != 0,
99 account_activated: flags & 0b001 != 0,
100 gas_fees,
101 gas_used: ok!(VarUint56::load_from(slice)),
102 gas_limit: ok!(VarUint56::load_from(slice)),
103 gas_credit: ok!(Option::<VarUint24>::load_from(slice)),
104 mode: ok!(slice.load_u8()) as i8,
105 exit_code: ok!(slice.load_u32()) as i32,
106 exit_arg: ok!(Option::<i32>::load_from(slice)),
107 vm_steps: ok!(slice.load_u32()),
108 vm_init_state_hash: ok!(slice.load_u256()),
109 vm_final_state_hash: ok!(slice.load_u256()),
110 }))
111 }
112}
113
114#[derive(Debug, Clone, Eq, PartialEq)]
116#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
117pub struct ExecutedComputePhase {
118 pub success: bool,
120 pub msg_state_used: bool,
122 pub account_activated: bool,
124 pub gas_fees: Tokens,
126 pub gas_used: VarUint56,
128 pub gas_limit: VarUint56,
130 pub gas_credit: Option<VarUint24>,
132 pub mode: i8,
134 pub exit_code: i32,
136 pub exit_arg: Option<i32>,
138 pub vm_steps: u32,
140 pub vm_init_state_hash: HashBytes,
142 pub vm_final_state_hash: HashBytes,
144}
145
146#[derive(Debug, Copy, Clone, Eq, PartialEq, Store, Load)]
148#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
149pub struct SkippedComputePhase {
150 pub reason: ComputePhaseSkipReason,
152}
153
154#[derive(Debug, Copy, Clone, Eq, PartialEq)]
156#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
157pub enum ComputePhaseSkipReason {
158 NoState,
160 BadState,
162 NoGas,
164 Suspended,
166}
167
168impl Store for ComputePhaseSkipReason {
169 fn store_into(&self, builder: &mut CellBuilder, _: &dyn CellContext) -> Result<(), Error> {
170 let (tag, bits) = match self {
171 Self::NoState => (0b00, 2),
172 Self::BadState => (0b01, 2),
173 Self::NoGas => (0b10, 2),
174 Self::Suspended => (0b110, 3),
175 };
176 builder.store_small_uint(tag, bits)
177 }
178}
179
180impl<'a> Load<'a> for ComputePhaseSkipReason {
181 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
182 match slice.load_small_uint(2) {
183 Ok(0b00) => Ok(Self::NoState),
184 Ok(0b01) => Ok(Self::BadState),
185 Ok(0b10) => Ok(Self::NoGas),
186 Ok(_) => {
187 if ok!(slice.load_bit()) {
188 Err(Error::InvalidTag)
190 } else {
191 Ok(Self::Suspended)
193 }
194 }
195 Err(e) => Err(e),
196 }
197 }
198}
199
200#[derive(Debug, Clone, Eq, PartialEq)]
205#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
206pub struct ActionPhase {
207 pub success: bool,
209 pub valid: bool,
211 pub no_funds: bool,
213 pub status_change: AccountStatusChange,
215 pub total_fwd_fees: Option<Tokens>,
217 pub total_action_fees: Option<Tokens>,
219 pub result_code: i32,
221 pub result_arg: Option<i32>,
223 pub total_actions: u16,
225 pub special_actions: u16,
227 pub skipped_actions: u16,
229 pub messages_created: u16,
231 pub action_list_hash: HashBytes,
233 pub total_message_size: StorageUsedShort,
235}
236
237impl Store for ActionPhase {
238 fn store_into(
239 &self,
240 builder: &mut CellBuilder,
241 context: &dyn CellContext,
242 ) -> Result<(), Error> {
243 let flags = ((self.success as u8) << 2) | ((self.valid as u8) << 1) | self.no_funds as u8;
244 let counts = ((self.total_actions as u64) << 48)
245 | ((self.special_actions as u64) << 32)
246 | ((self.skipped_actions as u64) << 16)
247 | self.messages_created as u64;
248
249 ok!(builder.store_small_uint(flags, 3));
250 ok!(self.status_change.store_into(builder, context));
251 ok!(self.total_fwd_fees.store_into(builder, context));
252 ok!(self.total_action_fees.store_into(builder, context));
253 ok!(builder.store_u32(self.result_code as u32));
254 ok!(self.result_arg.store_into(builder, context));
255 ok!(builder.store_u64(counts));
256 ok!(builder.store_u256(&self.action_list_hash));
257 self.total_message_size.store_into(builder, context)
258 }
259}
260
261impl<'a> Load<'a> for ActionPhase {
262 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
263 let flags = ok!(slice.load_small_uint(3));
264
265 let status_change = ok!(AccountStatusChange::load_from(slice));
266 let total_fwd_fees = ok!(Option::<Tokens>::load_from(slice));
267 let total_action_fees = ok!(Option::<Tokens>::load_from(slice));
268 let result_code = ok!(slice.load_u32()) as i32;
269 let result_arg = ok!(Option::<i32>::load_from(slice));
270
271 let counts = ok!(slice.load_u64());
272
273 Ok(Self {
274 success: flags & 0b100 != 0,
275 valid: flags & 0b010 != 0,
276 no_funds: flags & 0b001 != 0,
277 status_change,
278 total_fwd_fees,
279 total_action_fees,
280 result_code,
281 result_arg,
282 total_actions: (counts >> 48) as u16,
283 special_actions: (counts >> 32) as u16,
284 skipped_actions: (counts >> 16) as u16,
285 messages_created: counts as u16,
286 action_list_hash: ok!(slice.load_u256()),
287 total_message_size: ok!(StorageUsedShort::load_from(slice)),
288 })
289 }
290}
291
292#[derive(Debug, Clone, Eq, PartialEq)]
296#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
297#[cfg_attr(feature = "serde", serde(tag = "ty"))]
298pub enum BouncePhase {
299 NegativeFunds,
303 NoFunds(NoFundsBouncePhase),
305 Executed(ExecutedBouncePhase),
307}
308
309impl Store for BouncePhase {
310 fn store_into(
311 &self,
312 builder: &mut CellBuilder,
313 context: &dyn CellContext,
314 ) -> Result<(), Error> {
315 match self {
316 Self::NegativeFunds => builder.store_small_uint(0b00, 2),
317 Self::NoFunds(phase) => {
318 ok!(builder.store_small_uint(0b01, 2));
319 phase.store_into(builder, context)
320 }
321 Self::Executed(phase) => {
322 ok!(builder.store_bit_one());
323 phase.store_into(builder, context)
324 }
325 }
326 }
327}
328
329impl<'a> Load<'a> for BouncePhase {
330 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
331 Ok(if ok!(slice.load_bit()) {
332 match ExecutedBouncePhase::load_from(slice) {
333 Ok(phase) => Self::Executed(phase),
334 Err(e) => return Err(e),
335 }
336 } else if ok!(slice.load_bit()) {
337 match NoFundsBouncePhase::load_from(slice) {
338 Ok(phase) => Self::NoFunds(phase),
339 Err(e) => return Err(e),
340 }
341 } else {
342 Self::NegativeFunds
343 })
344 }
345}
346
347#[derive(Debug, Clone, Eq, PartialEq, Store, Load)]
349#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
350pub struct NoFundsBouncePhase {
351 pub msg_size: StorageUsedShort,
353 pub req_fwd_fees: Tokens,
355}
356
357#[derive(Debug, Clone, Eq, PartialEq, Store, Load)]
359#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
360pub struct ExecutedBouncePhase {
361 pub msg_size: StorageUsedShort,
363 pub msg_fees: Tokens,
365 pub fwd_fees: Tokens,
367}
368
369#[derive(Debug, Clone, Copy, Eq, PartialEq)]
371#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
372pub enum AccountStatusChange {
373 Unchanged = 0b0,
375 Frozen = 0b10,
377 Deleted = 0b11,
379}
380
381impl Store for AccountStatusChange {
382 fn store_into(&self, builder: &mut CellBuilder, _: &dyn CellContext) -> Result<(), Error> {
383 if *self == Self::Unchanged {
384 builder.store_bit_zero()
385 } else {
386 builder.store_small_uint(*self as u8, 2)
387 }
388 }
389}
390
391impl<'a> Load<'a> for AccountStatusChange {
392 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
393 Ok(if !ok!(slice.load_bit()) {
394 Self::Unchanged
395 } else if ok!(slice.load_bit()) {
396 Self::Deleted
397 } else {
398 Self::Frozen
399 })
400 }
401}