mep_vm/
error.rs

1// Copyright 2015-2020 Parity Technologies (UK) Ltd.
2// This file is part of Parity Ethereum.
3
4// Parity Ethereum is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Parity Ethereum is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Parity Ethereum.  If not, see <http://www.gnu.org/licenses/>.
16
17//! VM errors module
18
19use ::{ResumeCall, ResumeCreate};
20use ethereum_types::Address;
21use action_params::ActionParams;
22use std::fmt;
23use ethtrie;
24
25#[derive(Debug)]
26pub enum TrapKind {
27	Call(ActionParams),
28	Create(ActionParams, Address),
29}
30
31pub enum TrapError<Call, Create> {
32	Call(ActionParams, Call),
33	Create(ActionParams, Address, Create),
34}
35
36/// VM errors.
37#[derive(Debug, Clone, PartialEq)]
38pub enum Error {
39	/// `OutOfGas` is returned when transaction execution runs out of gas.
40	/// The state should be reverted to the state from before the
41	/// transaction execution. But it does not mean that transaction
42	/// was invalid. Balance still should be transfered and nonce
43	/// should be increased.
44	OutOfGas,
45	/// `BadJumpDestination` is returned when execution tried to move
46	/// to position that wasn't marked with JUMPDEST instruction
47	BadJumpDestination {
48		/// Position the code tried to jump to.
49		destination: usize
50	},
51	/// `BadInstructions` is returned when given instruction is not supported
52	BadInstruction {
53		/// Unrecognized opcode
54		instruction: u8,
55	},
56	/// `StackUnderflow` when there is not enough stack elements to execute instruction
57	StackUnderflow {
58		/// Invoked instruction
59		instruction: &'static str,
60		/// How many stack elements was requested by instruction
61		wanted: usize,
62		/// How many elements were on stack
63		on_stack: usize
64	},
65	/// When execution would exceed defined Stack Limit
66	OutOfStack {
67		/// Invoked instruction
68		instruction: &'static str,
69		/// How many stack elements instruction wanted to push
70		wanted: usize,
71		/// What was the stack limit
72		limit: usize
73	},
74	/// Built-in contract failed on given input
75	BuiltIn(&'static str),
76	/// When execution tries to modify the state in static context
77	MutableCallInStaticContext,
78	/// Likely to cause consensus issues.
79	Internal(String),
80	/// Wasm runtime error
81	Wasm(String),
82	/// Out of bounds access in RETURNDATACOPY.
83	OutOfBounds,
84	/// Execution has been reverted with REVERT.
85	Reverted,
86}
87
88impl From<Box<ethtrie::TrieError>> for Error {
89	fn from(err: Box<ethtrie::TrieError>) -> Self {
90		Error::Internal(format!("Internal error: {}", err))
91	}
92}
93
94impl From<ethtrie::TrieError> for Error {
95	fn from(err: ethtrie::TrieError) -> Self {
96		Error::Internal(format!("Internal error: {}", err))
97	}
98}
99
100impl fmt::Display for Error {
101	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
102		use self::Error::*;
103		match *self {
104			OutOfGas => write!(f, "Out of gas"),
105			BadJumpDestination { destination } => write!(f, "Bad jump destination {:x}", destination),
106			BadInstruction { instruction } => write!(f, "Bad instruction {:x}",  instruction),
107			StackUnderflow { instruction, wanted, on_stack } => write!(f, "Stack underflow {} {}/{}", instruction, wanted, on_stack),
108			OutOfStack { instruction, wanted, limit } => write!(f, "Out of stack {} {}/{}", instruction, wanted, limit),
109			BuiltIn(name) => write!(f, "Built-in failed: {}", name),
110			Internal(ref msg) => write!(f, "Internal error: {}", msg),
111			MutableCallInStaticContext => write!(f, "Mutable call in static context"),
112			Wasm(ref msg) => write!(f, "Internal error: {}", msg),
113			OutOfBounds => write!(f, "Out of bounds"),
114			Reverted => write!(f, "Reverted"),
115		}
116	}
117}
118
119pub type Result<T> = ::std::result::Result<T, Error>;
120pub type TrapResult<T, Call, Create> = ::std::result::Result<Result<T>, TrapError<Call, Create>>;
121
122pub type ExecTrapResult<T> = TrapResult<T, Box<dyn ResumeCall>, Box<dyn ResumeCreate>>;
123pub type ExecTrapError = TrapError<Box<dyn ResumeCall>, Box<dyn ResumeCreate>>;