1use crate::cell::*;
2use crate::error::Error;
3use crate::num::*;
4
5use crate::models::account::StorageUsedShort;
6use crate::models::currency::CurrencyCollection;
7
8#[derive(Debug, Clone, Eq, PartialEq, Store, Load)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct StoragePhase {
14 pub storage_fees_collected: Tokens,
16 pub storage_fees_due: Option<Tokens>,
19 pub status_change: AccountStatusChange,
21}
22
23#[derive(Debug, Clone, Eq, PartialEq, Store, Load)]
27#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
28pub struct CreditPhase {
29 pub due_fees_collected: Option<Tokens>,
31 pub credit: CurrencyCollection,
34}
35
36#[derive(Debug, Clone, Eq, PartialEq)]
40#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
41#[cfg_attr(feature = "serde", serde(tag = "ty"))]
42pub enum ComputePhase {
43 Skipped(SkippedComputePhase),
45 Executed(ExecutedComputePhase),
47}
48
49impl Store for ComputePhase {
50 fn store_into(
51 &self,
52 builder: &mut CellBuilder,
53 context: &mut dyn CellContext,
54 ) -> Result<(), Error> {
55 match self {
56 Self::Skipped(phase) => {
57 ok!(builder.store_bit_zero());
58 phase.store_into(builder, context)
59 }
60 Self::Executed(phase) => {
61 let cell = {
62 let mut builder = CellBuilder::new();
63 ok!(phase.gas_used.store_into(&mut builder, context));
64 ok!(phase.gas_limit.store_into(&mut builder, context));
65 ok!(phase.gas_credit.store_into(&mut builder, context));
66 ok!(builder.store_u8(phase.mode as u8));
67 ok!(builder.store_u32(phase.exit_code as u32));
68 ok!(phase.exit_arg.store_into(&mut builder, context));
69 ok!(builder.store_u32(phase.vm_steps));
70 ok!(builder.store_u256(&phase.vm_init_state_hash));
71 ok!(builder.store_u256(&phase.vm_final_state_hash));
72 ok!(builder.build_ext(context))
73 };
74
75 let flags = 0b1000u8
76 | ((phase.success as u8) << 2)
77 | ((phase.msg_state_used as u8) << 1)
78 | (phase.account_activated as u8);
79 ok!(builder.store_small_uint(flags, 4));
80 ok!(phase.gas_fees.store_into(builder, context));
81 builder.store_reference(cell)
82 }
83 }
84 }
85}
86
87impl<'a> Load<'a> for ComputePhase {
88 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
89 if !ok!(slice.load_bit()) {
90 return Ok(Self::Skipped(ok!(SkippedComputePhase::load_from(slice))));
91 }
92
93 let flags = ok!(slice.load_small_uint(3));
94 let gas_fees = ok!(Tokens::load_from(slice));
95
96 let slice = &mut ok!(slice.load_reference_as_slice());
97 Ok(Self::Executed(ExecutedComputePhase {
98 success: flags & 0b100 != 0,
99 msg_state_used: flags & 0b010 != 0,
100 account_activated: flags & 0b001 != 0,
101 gas_fees,
102 gas_used: ok!(VarUint56::load_from(slice)),
103 gas_limit: ok!(VarUint56::load_from(slice)),
104 gas_credit: ok!(Option::<VarUint24>::load_from(slice)),
105 mode: ok!(slice.load_u8()) as i8,
106 exit_code: ok!(slice.load_u32()) as i32,
107 exit_arg: ok!(Option::<i32>::load_from(slice)),
108 vm_steps: ok!(slice.load_u32()),
109 vm_init_state_hash: ok!(slice.load_u256()),
110 vm_final_state_hash: ok!(slice.load_u256()),
111 }))
112 }
113}
114
115#[derive(Debug, Clone, Eq, PartialEq)]
117#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
118pub struct ExecutedComputePhase {
119 pub success: bool,
121 pub msg_state_used: bool,
123 pub account_activated: bool,
125 pub gas_fees: Tokens,
127 pub gas_used: VarUint56,
129 pub gas_limit: VarUint56,
131 pub gas_credit: Option<VarUint24>,
133 pub mode: i8,
135 pub exit_code: i32,
137 pub exit_arg: Option<i32>,
139 pub vm_steps: u32,
141 pub vm_init_state_hash: HashBytes,
143 pub vm_final_state_hash: HashBytes,
145}
146
147#[derive(Debug, Copy, Clone, Eq, PartialEq, Store, Load)]
149#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
150pub struct SkippedComputePhase {
151 pub reason: ComputePhaseSkipReason,
153}
154
155#[derive(Debug, Copy, Clone, Eq, PartialEq)]
157#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
158pub enum ComputePhaseSkipReason {
159 NoState,
161 BadState,
163 NoGas,
165 Suspended,
167}
168
169impl Store for ComputePhaseSkipReason {
170 fn store_into(&self, builder: &mut CellBuilder, _: &mut dyn CellContext) -> Result<(), Error> {
171 let (tag, bits) = match self {
172 Self::NoState => (0b00, 2),
173 Self::BadState => (0b01, 2),
174 Self::NoGas => (0b10, 2),
175 Self::Suspended => (0b110, 3),
176 };
177 builder.store_small_uint(tag, bits)
178 }
179}
180
181impl<'a> Load<'a> for ComputePhaseSkipReason {
182 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
183 match slice.load_small_uint(2) {
184 Ok(0b00) => Ok(Self::NoState),
185 Ok(0b01) => Ok(Self::BadState),
186 Ok(0b10) => Ok(Self::NoGas),
187 Ok(_) => {
188 if ok!(slice.load_bit()) {
189 Err(Error::InvalidTag)
191 } else {
192 Ok(Self::Suspended)
194 }
195 }
196 Err(e) => Err(e),
197 }
198 }
199}
200
201#[derive(Debug, Clone, Eq, PartialEq)]
206#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
207pub struct ActionPhase {
208 pub success: bool,
210 pub valid: bool,
212 pub no_funds: bool,
214 pub status_change: AccountStatusChange,
216 pub total_fwd_fees: Option<Tokens>,
218 pub total_action_fees: Option<Tokens>,
220 pub result_code: i32,
222 pub result_arg: Option<i32>,
224 pub total_actions: u16,
226 pub special_actions: u16,
228 pub skipped_actions: u16,
230 pub messages_created: u16,
232 pub action_list_hash: HashBytes,
234 pub total_message_size: StorageUsedShort,
236}
237
238impl Store for ActionPhase {
239 fn store_into(
240 &self,
241 builder: &mut CellBuilder,
242 context: &mut dyn CellContext,
243 ) -> Result<(), Error> {
244 let flags = ((self.success as u8) << 2) | ((self.valid as u8) << 1) | self.no_funds as u8;
245 let counts = ((self.total_actions as u64) << 48)
246 | ((self.special_actions as u64) << 32)
247 | ((self.skipped_actions as u64) << 16)
248 | self.messages_created as u64;
249
250 ok!(builder.store_small_uint(flags, 3));
251 ok!(self.status_change.store_into(builder, context));
252 ok!(self.total_fwd_fees.store_into(builder, context));
253 ok!(self.total_action_fees.store_into(builder, context));
254 ok!(builder.store_u32(self.result_code as u32));
255 ok!(self.result_arg.store_into(builder, context));
256 ok!(builder.store_u64(counts));
257 ok!(builder.store_u256(&self.action_list_hash));
258 self.total_message_size.store_into(builder, context)
259 }
260}
261
262impl<'a> Load<'a> for ActionPhase {
263 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
264 let flags = ok!(slice.load_small_uint(3));
265
266 let status_change = ok!(AccountStatusChange::load_from(slice));
267 let total_fwd_fees = ok!(Option::<Tokens>::load_from(slice));
268 let total_action_fees = ok!(Option::<Tokens>::load_from(slice));
269 let result_code = ok!(slice.load_u32()) as i32;
270 let result_arg = ok!(Option::<i32>::load_from(slice));
271
272 let counts = ok!(slice.load_u64());
273
274 Ok(Self {
275 success: flags & 0b100 != 0,
276 valid: flags & 0b010 != 0,
277 no_funds: flags & 0b001 != 0,
278 status_change,
279 total_fwd_fees,
280 total_action_fees,
281 result_code,
282 result_arg,
283 total_actions: (counts >> 48) as u16,
284 special_actions: (counts >> 32) as u16,
285 skipped_actions: (counts >> 16) as u16,
286 messages_created: counts as u16,
287 action_list_hash: ok!(slice.load_u256()),
288 total_message_size: ok!(StorageUsedShort::load_from(slice)),
289 })
290 }
291}
292
293#[derive(Debug, Clone, Eq, PartialEq)]
297#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
298#[cfg_attr(feature = "serde", serde(tag = "ty"))]
299pub enum BouncePhase {
300 NegativeFunds,
304 NoFunds(NoFundsBouncePhase),
306 Executed(ExecutedBouncePhase),
308}
309
310impl Store for BouncePhase {
311 fn store_into(
312 &self,
313 builder: &mut CellBuilder,
314 context: &mut dyn CellContext,
315 ) -> Result<(), Error> {
316 match self {
317 Self::NegativeFunds => builder.store_small_uint(0b00, 2),
318 Self::NoFunds(phase) => {
319 ok!(builder.store_small_uint(0b01, 2));
320 phase.store_into(builder, context)
321 }
322 Self::Executed(phase) => {
323 ok!(builder.store_bit_one());
324 phase.store_into(builder, context)
325 }
326 }
327 }
328}
329
330impl<'a> Load<'a> for BouncePhase {
331 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
332 Ok(if ok!(slice.load_bit()) {
333 match ExecutedBouncePhase::load_from(slice) {
334 Ok(phase) => Self::Executed(phase),
335 Err(e) => return Err(e),
336 }
337 } else if ok!(slice.load_bit()) {
338 match NoFundsBouncePhase::load_from(slice) {
339 Ok(phase) => Self::NoFunds(phase),
340 Err(e) => return Err(e),
341 }
342 } else {
343 Self::NegativeFunds
344 })
345 }
346}
347
348#[derive(Debug, Clone, Eq, PartialEq, Store, Load)]
350#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
351pub struct NoFundsBouncePhase {
352 pub msg_size: StorageUsedShort,
354 pub req_fwd_fees: Tokens,
356}
357
358#[derive(Debug, Clone, Eq, PartialEq, Store, Load)]
360#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
361pub struct ExecutedBouncePhase {
362 pub msg_size: StorageUsedShort,
364 pub msg_fees: Tokens,
366 pub fwd_fees: Tokens,
368}
369
370#[derive(Debug, Clone, Copy, Eq, PartialEq)]
372#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
373pub enum AccountStatusChange {
374 Unchanged = 0b0,
376 Frozen = 0b10,
378 Deleted = 0b11,
380}
381
382impl Store for AccountStatusChange {
383 fn store_into(&self, builder: &mut CellBuilder, _: &mut dyn CellContext) -> Result<(), Error> {
384 if *self == Self::Unchanged {
385 builder.store_bit_zero()
386 } else {
387 builder.store_small_uint(*self as u8, 2)
388 }
389 }
390}
391
392impl<'a> Load<'a> for AccountStatusChange {
393 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
394 Ok(if !ok!(slice.load_bit()) {
395 Self::Unchanged
396 } else if ok!(slice.load_bit()) {
397 Self::Deleted
398 } else {
399 Self::Frozen
400 })
401 }
402}