-
Notifications
You must be signed in to change notification settings - Fork 648
/
Copy pathresult.rs
195 lines (178 loc) · 5.74 KB
/
result.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
use crate::{Log, State, B160};
use alloc::vec::Vec;
use bytes::Bytes;
use ruint::aliases::U256;
pub type EVMResult<DBError> = core::result::Result<ResultAndState, EVMError<DBError>>;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ResultAndState {
/// Status of execution
pub result: ExecutionResult,
/// State that got updated
pub state: State,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ExecutionResult {
/// Returned successfully
Success {
reason: Eval,
gas_used: u64,
gas_refunded: u64,
logs: Vec<Log>,
output: Output,
},
/// Reverted by `REVERT` opcode that doesn't spend all gas.
Revert { gas_used: u64, output: Bytes },
/// Reverted for various reasons and spend all gas.
Halt {
reason: Halt,
/// Halting will spend all the gas, and will be equal to gas_limit.
gas_used: u64,
},
}
impl ExecutionResult {
/// Returns if transaction execution is successful.
/// 1 indicates success, 0 indicates revert.
/// https://eips.ethereum.org/EIPS/eip-658
pub fn is_success(&self) -> bool {
matches!(self, Self::Success { .. })
}
/// Return logs, if execution is not successful, function will return empty vec.
pub fn logs(&self) -> Vec<Log> {
match self {
Self::Success { logs, .. } => logs.clone(),
_ => Vec::new(),
}
}
/// Consumes the type and returns logs, if execution is not successful, function will return empty vec.
pub fn into_logs(self) -> Vec<Log> {
match self {
Self::Success { logs, .. } => logs,
_ => Vec::new(),
}
}
pub fn gas_used(&self) -> u64 {
let (Self::Success { gas_used, .. }
| Self::Revert { gas_used, .. }
| Self::Halt { gas_used, .. }) = self;
*gas_used
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Output {
#[cfg_attr(feature = "serde", serde(with = "crate::utilities::serde_hex_bytes"))]
Call(Bytes),
Create(
#[cfg_attr(feature = "serde", serde(with = "crate::utilities::serde_hex_bytes"))] Bytes,
Option<B160>,
),
}
impl Output {
/// Returns the output data of the execution output.
pub fn into_data(self) -> Bytes {
match self {
Output::Call(data) => data,
Output::Create(data, _) => data,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum EVMError<DBError> {
Transaction(InvalidTransaction),
/// REVM specific and related to environment.
PrevrandaoNotSet,
Database(DBError),
}
impl<DBError> From<InvalidTransaction> for EVMError<DBError> {
fn from(invalid: InvalidTransaction) -> Self {
EVMError::Transaction(invalid)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum InvalidTransaction {
GasMaxFeeGreaterThanPriorityFee,
GasPriceLessThanBasefee,
CallerGasLimitMoreThanBlock,
CallGasCostMoreThanGasLimit,
/// EIP-3607 Reject transactions from senders with deployed code
RejectCallerWithCode,
/// Transaction account does not have enough amount of ether to cover transferred value and gas_limit*gas_price.
LackOfFundForMaxFee {
fee: u64,
balance: U256,
},
/// Overflow payment in transaction.
OverflowPaymentInTransaction,
/// Nonce overflows in transaction.
NonceOverflowInTransaction,
NonceTooHigh {
tx: u64,
state: u64,
},
NonceTooLow {
tx: u64,
state: u64,
},
/// EIP-3860: Limit and meter initcode
CreateInitcodeSizeLimit,
InvalidChainId,
/// Access list is not supported is not supported
/// for blocks before Berlin hardfork.
AccessListNotSupported,
}
/// When transaction return successfully without halts.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Eval {
Stop,
Return,
SelfDestruct,
}
/// Indicates that the EVM has experienced an exceptional halt. This causes execution to
/// immediately end with all gas being consumed.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Halt {
OutOfGas(OutOfGasError),
OpcodeNotFound,
InvalidFEOpcode,
InvalidJump,
NotActivated,
StackUnderflow,
StackOverflow,
OutOfOffset,
CreateCollision,
PrecompileError,
NonceOverflow,
/// Create init code size exceeds limit (runtime).
CreateContractSizeLimit,
/// Error on created contract that begins with EF
CreateContractStartingWithEF,
/// EIP-3860: Limit and meter initcode. Initcode size limit exceeded.
CreateInitcodeSizeLimit,
/* Internal Halts that can be only found inside Inspector */
OverflowPayment,
StateChangeDuringStaticCall,
CallNotAllowedInsideStatic,
OutOfFund,
CallTooDeep,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum OutOfGasError {
// Basic OOG error
BasicOutOfGas,
// Tried to expand past REVM limit
MemoryLimit,
// Basic OOG error from memory expansion
Memory,
// Precompile threw OOG error
Precompile,
// When performing something that takes a U256 and casts down to a u64, if its too large this would fire
// i.e. in `as_usize_or_fail`
InvalidOperand,
}