iota_adapter_latest/
error.rs1use iota_types::{
6 error::{ExecutionError, IotaError},
7 execution_status::{ExecutionFailureStatus, MoveLocation, MoveLocationOpt},
8};
9use move_binary_format::{
10 errors::{Location, VMError},
11 file_format::FunctionDefinitionIndex,
12};
13use move_core_types::{
14 resolver::MoveResolver,
15 vm_status::{StatusCode, StatusType},
16};
17use move_vm_runtime::move_vm::MoveVM;
18
19pub(crate) fn convert_vm_error<S: MoveResolver<Err = IotaError>>(
20 error: VMError,
21 vm: &MoveVM,
22 state_view: &S,
23) -> ExecutionError {
24 let kind = match (error.major_status(), error.sub_status(), error.location()) {
25 (StatusCode::EXECUTED, _, _) => {
26 debug_assert!(false, "VmError shouldn't ever report successful execution");
28 ExecutionFailureStatus::VMInvariantViolation
29 }
30 (StatusCode::ABORTED, None, _) => {
31 debug_assert!(false, "No abort code");
32 ExecutionFailureStatus::VMInvariantViolation
34 }
35 (StatusCode::ABORTED, Some(code), Location::Module(id)) => {
36 let abort_location_id = state_view.relocate(id).unwrap_or_else(|_| id.clone());
37 let offset = error.offsets().first().copied().map(|(f, i)| (f.0, i));
38 debug_assert!(offset.is_some(), "Move should set the location on aborts");
39 let (function, instruction) = offset.unwrap_or((0, 0));
40 let function_name = vm.load_module(id, state_view).ok().map(|module| {
41 let fdef = module.function_def_at(FunctionDefinitionIndex(function));
42 let fhandle = module.function_handle_at(fdef.function);
43 module.identifier_at(fhandle.name).to_string()
44 });
45 ExecutionFailureStatus::MoveAbort(
46 MoveLocation {
47 module: abort_location_id,
48 function,
49 instruction,
50 function_name,
51 },
52 code,
53 )
54 }
55 (StatusCode::OUT_OF_GAS, _, _) => ExecutionFailureStatus::InsufficientGas,
56 (_, _, location) => match error.major_status().status_type() {
57 StatusType::Execution => {
58 debug_assert!(error.major_status() != StatusCode::ABORTED);
59 let location = match location {
60 Location::Module(id) => {
61 let offset = error.offsets().first().copied().map(|(f, i)| (f.0, i));
62 debug_assert!(
63 offset.is_some(),
64 "Move should set the location on all execution errors. Error {error}"
65 );
66 let (function, instruction) = offset.unwrap_or((0, 0));
67 let function_name = vm.load_module(id, state_view).ok().map(|module| {
68 let fdef = module.function_def_at(FunctionDefinitionIndex(function));
69 let fhandle = module.function_handle_at(fdef.function);
70 module.identifier_at(fhandle.name).to_string()
71 });
72 Some(MoveLocation {
73 module: id.clone(),
74 function,
75 instruction,
76 function_name,
77 })
78 }
79 _ => None,
80 };
81 ExecutionFailureStatus::MovePrimitiveRuntimeError(MoveLocationOpt(location))
82 }
83 StatusType::Validation
84 | StatusType::Verification
85 | StatusType::Deserialization
86 | StatusType::Unknown => ExecutionFailureStatus::VMVerificationOrDeserializationError,
87 StatusType::InvariantViolation => ExecutionFailureStatus::VMInvariantViolation,
88 },
89 };
90 ExecutionError::new_with_source(kind, error)
91}