cfx_executor/stack/
frame_return.rs

1use super::{FrameLocal, RuntimeRes};
2use crate::substate::Substate;
3
4use cfx_types::{Address, Space, U256};
5use cfx_vm_interpreter::FinalizationResult;
6use cfx_vm_types::{self as vm, ReturnData};
7
8/// Processes the result of a frame's execution and updates the state and
9/// resources accordingly.
10pub(super) fn process_return<'a>(
11    frame_local: FrameLocal<'a>, result: vm::Result<FinalizationResult>,
12    resources: &mut RuntimeRes<'a>,
13) -> FrameResult {
14    let is_create = frame_local.create_address.is_some();
15    let frame_result =
16        result.map(|result| FrameReturn::new(frame_local, result));
17
18    let apply_state = frame_result.as_ref().map_or(false, |r| r.apply_state);
19
20    if apply_state {
21        resources.state.discard_checkpoint();
22    } else {
23        resources.state.revert_to_checkpoint();
24    }
25
26    if is_create {
27        resources.tracer.record_create_result(&frame_result);
28    } else {
29        resources.tracer.record_call_result(&frame_result);
30    }
31
32    resources.callstack.pop();
33
34    frame_result
35}
36
37/// The result of executing a frame
38pub type FrameResult = vm::Result<FrameReturn>;
39
40/// The result of executing a frame on a successful complete or an expected
41/// revert.
42#[derive(Debug)]
43pub struct FrameReturn {
44    /// The space the current frame belongs.
45    pub space: Space,
46
47    /// Final amount of gas left.
48    pub gas_left: U256,
49
50    /// Apply execution state changes or revert them.
51    pub apply_state: bool,
52
53    /// Return data buffer.
54    pub return_data: ReturnData,
55
56    /// The address of a newly created contract, if applicable.
57    pub create_address: Option<Address>,
58
59    /// Changes produced during execution for post-execution logic, if
60    /// `apply_state` is true.
61    pub substate: Option<Substate>,
62}
63
64impl Into<FinalizationResult> for FrameReturn {
65    fn into(self) -> FinalizationResult {
66        FinalizationResult {
67            gas_left: self.gas_left,
68            apply_state: self.apply_state,
69            return_data: self.return_data,
70        }
71    }
72}
73
74impl FrameReturn {
75    fn new(frame_local: FrameLocal, result: FinalizationResult) -> Self {
76        let substate;
77        let create_address;
78        if result.apply_state {
79            substate = Some(frame_local.substate);
80            create_address = frame_local.create_address;
81        } else {
82            substate = None;
83            create_address = None;
84        };
85        FrameReturn {
86            space: frame_local.space,
87            gas_left: result.gas_left,
88            apply_state: result.apply_state,
89            return_data: result.return_data,
90            create_address,
91            substate,
92        }
93    }
94}