cfx_executor/stack/
frame_return.rs1use 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
8pub(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
37pub type FrameResult = vm::Result<FrameReturn>;
39
40#[derive(Debug)]
43pub struct FrameReturn {
44 pub space: Space,
46
47 pub gas_left: U256,
49
50 pub apply_state: bool,
52
53 pub return_data: ReturnData,
55
56 pub create_address: Option<Address>,
58
59 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}