revm_context_interface/
result.rs

1//! Result of the EVM execution. Containing both execution result, state and errors.
2//!
3//! [`ExecutionResult`] is the result of the EVM execution.
4//!
5//! [`InvalidTransaction`] is the error that is returned when the transaction is invalid.
6//!
7//! [`InvalidHeader`] is the error that is returned when the header is invalid.
8//!
9//! [`SuccessReason`] is the reason that the transaction successfully completed.
10use crate::transaction::TransactionError;
11use core::fmt::{self, Debug};
12use database_interface::DBErrorMarker;
13use primitives::{Address, Bytes, Log, U256};
14use std::{boxed::Box, string::String, vec::Vec};
15
16/// Trait for the halt reason.
17pub trait HaltReasonTr: Clone + Debug + PartialEq + Eq + From<HaltReason> {}
18
19impl<T> HaltReasonTr for T where T: Clone + Debug + PartialEq + Eq + From<HaltReason> {}
20
21/// Tuple containing evm execution result and state.s
22#[derive(Clone, Debug, PartialEq, Eq, Hash)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24pub struct ResultAndState<R, S> {
25    /// Execution result
26    pub result: R,
27    /// Output State.
28    pub state: S,
29}
30
31/// Tuple containing multiple execution results and state.
32pub type ResultVecAndState<R, S> = ResultAndState<Vec<R>, S>;
33
34impl<R, S> ResultAndState<R, S> {
35    /// Creates new ResultAndState.
36    pub fn new(result: R, state: S) -> Self {
37        Self { result, state }
38    }
39}
40
41/// Result of a transaction execution
42#[derive(Clone, Debug, PartialEq, Eq, Hash)]
43#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
44pub enum ExecutionResult<HaltReasonTy = HaltReason> {
45    /// Returned successfully
46    Success {
47        /// Reason for the success.
48        reason: SuccessReason,
49        /// Gas used by the transaction.s
50        gas_used: u64,
51        /// Gas refunded by the transaction.
52        gas_refunded: u64,
53        /// Logs emitted by the transaction.
54        logs: Vec<Log>,
55        /// Output of the transaction.
56        output: Output,
57    },
58    /// Reverted by `REVERT` opcode that doesn't spend all gas
59    Revert {
60        /// Gas used by the transaction.
61        gas_used: u64,
62        /// Output of the transaction.
63        output: Bytes,
64    },
65    /// Reverted for various reasons and spend all gas
66    Halt {
67        /// Reason for the halt.
68        reason: HaltReasonTy,
69        /// Gas used by the transaction.
70        ///
71        /// Halting will spend all the gas, and will be equal to gas_limit.
72        gas_used: u64,
73    },
74}
75
76impl<HaltReasonTy> ExecutionResult<HaltReasonTy> {
77    /// Returns if transaction execution is successful.
78    ///
79    /// 1 indicates success, 0 indicates revert.
80    ///
81    /// <https://eips.ethereum.org/EIPS/eip-658>
82    pub fn is_success(&self) -> bool {
83        matches!(self, Self::Success { .. })
84    }
85
86    /// Maps a `DBError` to a new error type using the provided closure, leaving other variants unchanged.
87    pub fn map_haltreason<F, OHR>(self, op: F) -> ExecutionResult<OHR>
88    where
89        F: FnOnce(HaltReasonTy) -> OHR,
90    {
91        match self {
92            Self::Success {
93                reason,
94                gas_used,
95                gas_refunded,
96                logs,
97                output,
98            } => ExecutionResult::Success {
99                reason,
100                gas_used,
101                gas_refunded,
102                logs,
103                output,
104            },
105            Self::Revert { gas_used, output } => ExecutionResult::Revert { gas_used, output },
106            Self::Halt { reason, gas_used } => ExecutionResult::Halt {
107                reason: op(reason),
108                gas_used,
109            },
110        }
111    }
112
113    /// Returns created address if execution is Create transaction
114    /// and Contract was created.
115    pub fn created_address(&self) -> Option<Address> {
116        match self {
117            Self::Success { output, .. } => output.address().cloned(),
118            _ => None,
119        }
120    }
121
122    /// Returns true if execution result is a Halt.
123    pub fn is_halt(&self) -> bool {
124        matches!(self, Self::Halt { .. })
125    }
126
127    /// Returns the output data of the execution.
128    ///
129    /// Returns [`None`] if the execution was halted.
130    pub fn output(&self) -> Option<&Bytes> {
131        match self {
132            Self::Success { output, .. } => Some(output.data()),
133            Self::Revert { output, .. } => Some(output),
134            _ => None,
135        }
136    }
137
138    /// Consumes the type and returns the output data of the execution.
139    ///
140    /// Returns [`None`] if the execution was halted.
141    pub fn into_output(self) -> Option<Bytes> {
142        match self {
143            Self::Success { output, .. } => Some(output.into_data()),
144            Self::Revert { output, .. } => Some(output),
145            _ => None,
146        }
147    }
148
149    /// Returns the logs if execution is successful, or an empty list otherwise.
150    pub fn logs(&self) -> &[Log] {
151        match self {
152            Self::Success { logs, .. } => logs.as_slice(),
153            _ => &[],
154        }
155    }
156
157    /// Consumes [`self`] and returns the logs if execution is successful, or an empty list otherwise.
158    pub fn into_logs(self) -> Vec<Log> {
159        match self {
160            Self::Success { logs, .. } => logs,
161            _ => Vec::new(),
162        }
163    }
164
165    /// Returns the gas used.
166    pub fn gas_used(&self) -> u64 {
167        match *self {
168            Self::Success { gas_used, .. }
169            | Self::Revert { gas_used, .. }
170            | Self::Halt { gas_used, .. } => gas_used,
171        }
172    }
173}
174
175/// Output of a transaction execution
176#[derive(Debug, Clone, PartialEq, Eq, Hash)]
177#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
178pub enum Output {
179    /// Output of a call.
180    Call(Bytes),
181    /// Output of a create.
182    Create(Bytes, Option<Address>),
183}
184
185impl Output {
186    /// Returns the output data of the execution output.
187    pub fn into_data(self) -> Bytes {
188        match self {
189            Output::Call(data) => data,
190            Output::Create(data, _) => data,
191        }
192    }
193
194    /// Returns the output data of the execution output.
195    pub fn data(&self) -> &Bytes {
196        match self {
197            Output::Call(data) => data,
198            Output::Create(data, _) => data,
199        }
200    }
201
202    /// Returns the created address, if any.
203    pub fn address(&self) -> Option<&Address> {
204        match self {
205            Output::Call(_) => None,
206            Output::Create(_, address) => address.as_ref(),
207        }
208    }
209}
210
211/// Main EVM error
212#[derive(Debug, Clone, PartialEq, Eq)]
213#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
214pub enum EVMError<DBError, TransactionError = InvalidTransaction> {
215    /// Transaction validation error
216    Transaction(TransactionError),
217    /// Header validation error
218    Header(InvalidHeader),
219    /// Database error
220    Database(DBError),
221    /// Custom error
222    ///
223    /// Useful for handler registers where custom logic would want to return their own custom error.
224    Custom(String),
225}
226
227impl<DBError: DBErrorMarker, TX> From<DBError> for EVMError<DBError, TX> {
228    fn from(value: DBError) -> Self {
229        Self::Database(value)
230    }
231}
232
233/// Trait for converting a string to an [`EVMError::Custom`] error.
234pub trait FromStringError {
235    /// Converts a string to an [`EVMError::Custom`] error.
236    fn from_string(value: String) -> Self;
237}
238
239impl<DB, TX> FromStringError for EVMError<DB, TX> {
240    fn from_string(value: String) -> Self {
241        Self::Custom(value)
242    }
243}
244
245impl<DB, TXE: From<InvalidTransaction>> From<InvalidTransaction> for EVMError<DB, TXE> {
246    fn from(value: InvalidTransaction) -> Self {
247        Self::Transaction(TXE::from(value))
248    }
249}
250
251impl<DBError, TransactionValidationErrorT> EVMError<DBError, TransactionValidationErrorT> {
252    /// Maps a `DBError` to a new error type using the provided closure, leaving other variants unchanged.
253    pub fn map_db_err<F, E>(self, op: F) -> EVMError<E, TransactionValidationErrorT>
254    where
255        F: FnOnce(DBError) -> E,
256    {
257        match self {
258            Self::Transaction(e) => EVMError::Transaction(e),
259            Self::Header(e) => EVMError::Header(e),
260            Self::Database(e) => EVMError::Database(op(e)),
261            Self::Custom(e) => EVMError::Custom(e),
262        }
263    }
264}
265
266impl<DBError, TransactionValidationErrorT> core::error::Error
267    for EVMError<DBError, TransactionValidationErrorT>
268where
269    DBError: core::error::Error + 'static,
270    TransactionValidationErrorT: core::error::Error + 'static,
271{
272    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
273        match self {
274            Self::Transaction(e) => Some(e),
275            Self::Header(e) => Some(e),
276            Self::Database(e) => Some(e),
277            Self::Custom(_) => None,
278        }
279    }
280}
281
282impl<DBError, TransactionValidationErrorT> fmt::Display
283    for EVMError<DBError, TransactionValidationErrorT>
284where
285    DBError: fmt::Display,
286    TransactionValidationErrorT: fmt::Display,
287{
288    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
289        match self {
290            Self::Transaction(e) => write!(f, "transaction validation error: {e}"),
291            Self::Header(e) => write!(f, "header validation error: {e}"),
292            Self::Database(e) => write!(f, "database error: {e}"),
293            Self::Custom(e) => f.write_str(e),
294        }
295    }
296}
297
298impl<DBError, TransactionValidationErrorT> From<InvalidHeader>
299    for EVMError<DBError, TransactionValidationErrorT>
300{
301    fn from(value: InvalidHeader) -> Self {
302        Self::Header(value)
303    }
304}
305
306/// Transaction validation error.
307#[derive(Debug, Clone, PartialEq, Eq, Hash)]
308#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
309pub enum InvalidTransaction {
310    /// When using the EIP-1559 fee model introduced in the London upgrade, transactions specify two primary fee fields:
311    /// - `gas_max_fee`: The maximum total fee a user is willing to pay, inclusive of both base fee and priority fee.
312    /// - `gas_priority_fee`: The extra amount a user is willing to give directly to the miner, often referred to as the "tip".
313    ///
314    /// Provided `gas_priority_fee` exceeds the total `gas_max_fee`.
315    PriorityFeeGreaterThanMaxFee,
316    /// EIP-1559: `gas_price` is less than `basefee`.
317    GasPriceLessThanBasefee,
318    /// `gas_limit` in the tx is bigger than `block_gas_limit`.
319    CallerGasLimitMoreThanBlock,
320    /// Initial gas for a Call is bigger than `gas_limit`.
321    ///
322    /// Initial gas for a Call contains:
323    /// - initial stipend gas
324    /// - gas for access list and input data
325    CallGasCostMoreThanGasLimit {
326        /// Initial gas for a Call.
327        initial_gas: u64,
328        /// Gas limit for the transaction.
329        gas_limit: u64,
330    },
331    /// Gas floor calculated from EIP-7623 Increase calldata cost
332    /// is more than the gas limit.
333    ///
334    /// Tx data is too large to be executed.
335    GasFloorMoreThanGasLimit {
336        /// Gas floor calculated from EIP-7623 Increase calldata cost.
337        gas_floor: u64,
338        /// Gas limit for the transaction.
339        gas_limit: u64,
340    },
341    /// EIP-3607 Reject transactions from senders with deployed code
342    RejectCallerWithCode,
343    /// Transaction account does not have enough amount of ether to cover transferred value and gas_limit*gas_price.
344    LackOfFundForMaxFee {
345        /// Fee for the transaction.
346        fee: Box<U256>,
347        /// Balance of the sender.
348        balance: Box<U256>,
349    },
350    /// Overflow payment in transaction.
351    OverflowPaymentInTransaction,
352    /// Nonce overflows in transaction.
353    NonceOverflowInTransaction,
354    /// Nonce is too high.
355    NonceTooHigh {
356        /// Nonce of the transaction.
357        tx: u64,
358        /// Nonce of the state.
359        state: u64,
360    },
361    /// Nonce is too low.
362    NonceTooLow {
363        /// Nonce of the transaction.
364        tx: u64,
365        /// Nonce of the state.
366        state: u64,
367    },
368    /// EIP-3860: Limit and meter initcode
369    CreateInitCodeSizeLimit,
370    /// Transaction chain id does not match the config chain id.
371    InvalidChainId,
372    /// Missing chain id.
373    MissingChainId,
374    /// Transaction gas limit is greater than the cap.
375    TxGasLimitGreaterThanCap {
376        /// Transaction gas limit.
377        gas_limit: u64,
378        /// Gas limit cap.
379        cap: u64,
380    },
381    /// Access list is not supported for blocks before the Berlin hardfork.
382    AccessListNotSupported,
383    /// `max_fee_per_blob_gas` is not supported for blocks before the Cancun hardfork.
384    MaxFeePerBlobGasNotSupported,
385    /// `blob_hashes`/`blob_versioned_hashes` is not supported for blocks before the Cancun hardfork.
386    BlobVersionedHashesNotSupported,
387    /// Block `blob_gas_price` is greater than tx-specified `max_fee_per_blob_gas` after Cancun.
388    BlobGasPriceGreaterThanMax,
389    /// There should be at least one blob in Blob transaction.
390    EmptyBlobs,
391    /// Blob transaction can't be a create transaction.
392    ///
393    /// `to` must be present
394    BlobCreateTransaction,
395    /// Transaction has more then `max` blobs
396    TooManyBlobs {
397        /// Maximum number of blobs allowed.
398        max: usize,
399        /// Number of blobs in the transaction.
400        have: usize,
401    },
402    /// Blob transaction contains a versioned hash with an incorrect version
403    BlobVersionNotSupported,
404    /// EOF create should have `to` address
405    EofCreateShouldHaveToAddress,
406    /// EIP-7702 is not enabled.
407    AuthorizationListNotSupported,
408    /// EIP-7702 transaction has invalid fields set.
409    AuthorizationListInvalidFields,
410    /// Empty Authorization List is not allowed.
411    EmptyAuthorizationList,
412    /// EIP-2930 is not supported.
413    Eip2930NotSupported,
414    /// EIP-1559 is not supported.
415    Eip1559NotSupported,
416    /// EIP-4844 is not supported.
417    Eip4844NotSupported,
418    /// EIP-7702 is not supported.
419    Eip7702NotSupported,
420    /// EIP-7873 is not supported.
421    Eip7873NotSupported,
422    // TODO (EOF)
423    // /// EIP-7873 needs to have at least one initcode.
424    // Eip7873EmptyInitcodeList,
425    // /// EIP-7873 initcode can't be zero length.
426    // Eip7873EmptyInitcode {
427    //     i: usize,
428    // },
429    // /// EIP-7873 initcodes can't be more than [`MAX_INITCODE_COUNT`].
430    // Eip7873TooManyInitcodes {
431    //     size: usize,
432    // },
433    // /// EIP-7873 initcodes can't be more than [`MAX_INITCODE_SIZE`].
434    // Eip7873InitcodeTooLarge {
435    //     i: usize,
436    //     size: usize,
437    // },
438    /// EIP-7873 initcode transaction should have `to` address.
439    Eip7873MissingTarget,
440}
441
442impl TransactionError for InvalidTransaction {}
443
444impl core::error::Error for InvalidTransaction {}
445
446impl fmt::Display for InvalidTransaction {
447    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
448        match self {
449            Self::PriorityFeeGreaterThanMaxFee => {
450                write!(f, "priority fee is greater than max fee")
451            }
452            Self::GasPriceLessThanBasefee => {
453                write!(f, "gas price is less than basefee")
454            }
455            Self::CallerGasLimitMoreThanBlock => {
456                write!(f, "caller gas limit exceeds the block gas limit")
457            }
458            Self::TxGasLimitGreaterThanCap { gas_limit, cap } => {
459                write!(
460                    f,
461                    "transaction gas limit ({gas_limit}) is greater than the cap ({cap})"
462                )
463            }
464            Self::CallGasCostMoreThanGasLimit {
465                initial_gas,
466                gas_limit,
467            } => {
468                write!(
469                    f,
470                    "call gas cost ({initial_gas}) exceeds the gas limit ({gas_limit})"
471                )
472            }
473            Self::GasFloorMoreThanGasLimit {
474                gas_floor,
475                gas_limit,
476            } => {
477                write!(
478                    f,
479                    "gas floor ({gas_floor}) exceeds the gas limit ({gas_limit})"
480                )
481            }
482            Self::RejectCallerWithCode => {
483                write!(f, "reject transactions from senders with deployed code")
484            }
485            Self::LackOfFundForMaxFee { fee, balance } => {
486                write!(f, "lack of funds ({balance}) for max fee ({fee})")
487            }
488            Self::OverflowPaymentInTransaction => {
489                write!(f, "overflow payment in transaction")
490            }
491            Self::NonceOverflowInTransaction => {
492                write!(f, "nonce overflow in transaction")
493            }
494            Self::NonceTooHigh { tx, state } => {
495                write!(f, "nonce {tx} too high, expected {state}")
496            }
497            Self::NonceTooLow { tx, state } => {
498                write!(f, "nonce {tx} too low, expected {state}")
499            }
500            Self::CreateInitCodeSizeLimit => {
501                write!(f, "create initcode size limit")
502            }
503            Self::InvalidChainId => write!(f, "invalid chain ID"),
504            Self::MissingChainId => write!(f, "missing chain ID"),
505            Self::AccessListNotSupported => write!(f, "access list not supported"),
506            Self::MaxFeePerBlobGasNotSupported => {
507                write!(f, "max fee per blob gas not supported")
508            }
509            Self::BlobVersionedHashesNotSupported => {
510                write!(f, "blob versioned hashes not supported")
511            }
512            Self::BlobGasPriceGreaterThanMax => {
513                write!(f, "blob gas price is greater than max fee per blob gas")
514            }
515            Self::EmptyBlobs => write!(f, "empty blobs"),
516            Self::BlobCreateTransaction => write!(f, "blob create transaction"),
517            Self::TooManyBlobs { max, have } => {
518                write!(f, "too many blobs, have {have}, max {max}")
519            }
520            Self::BlobVersionNotSupported => write!(f, "blob version not supported"),
521            Self::EofCreateShouldHaveToAddress => write!(f, "EOF crate should have `to` address"),
522            Self::AuthorizationListNotSupported => write!(f, "authorization list not supported"),
523            Self::AuthorizationListInvalidFields => {
524                write!(f, "authorization list tx has invalid fields")
525            }
526            Self::EmptyAuthorizationList => write!(f, "empty authorization list"),
527            Self::Eip2930NotSupported => write!(f, "Eip2930 is not supported"),
528            Self::Eip1559NotSupported => write!(f, "Eip1559 is not supported"),
529            Self::Eip4844NotSupported => write!(f, "Eip4844 is not supported"),
530            Self::Eip7702NotSupported => write!(f, "Eip7702 is not supported"),
531            Self::Eip7873NotSupported => write!(f, "Eip7873 is not supported"),
532            // TODO(EOF)
533            // Self::Eip7873EmptyInitcodeList => {
534            //     write!(f, "Eip7873 initcode list should have at least one initcode")
535            // }
536            // Self::Eip7873EmptyInitcode { i } => {
537            //     write!(f, "Eip7873 initcode {i} can't be zero length")
538            // }
539            // Self::Eip7873TooManyInitcodes { size } => {
540            //     write!(
541            //         f,
542            //         "Eip7873 initcodes can't be more than {MAX_INITCODE_COUNT}, have {size}"
543            //     )
544            // }
545            // Self::Eip7873InitcodeTooLarge { i, size } => {
546            //     write!(
547            //         f,
548            //         "Eip7873 initcode {i} can't be more than {MAX_INITCODE_SIZE}, have {size}"
549            //     )
550            // }
551            Self::Eip7873MissingTarget => {
552                write!(f, "Eip7873 initcode transaction should have `to` address")
553            }
554        }
555    }
556}
557
558/// Errors related to misconfiguration of a [`crate::Block`].
559#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
560#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
561pub enum InvalidHeader {
562    /// `prevrandao` is not set for Merge and above.
563    PrevrandaoNotSet,
564    /// `excess_blob_gas` is not set for Cancun and above.
565    ExcessBlobGasNotSet,
566}
567
568impl core::error::Error for InvalidHeader {}
569
570impl fmt::Display for InvalidHeader {
571    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
572        match self {
573            Self::PrevrandaoNotSet => write!(f, "`prevrandao` not set"),
574            Self::ExcessBlobGasNotSet => write!(f, "`excess_blob_gas` not set"),
575        }
576    }
577}
578
579/// Reason a transaction successfully completed.
580#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
581#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
582pub enum SuccessReason {
583    /// Stop [`state::bytecode::opcode::STOP`] opcode.
584    Stop,
585    /// Return [`state::bytecode::opcode::RETURN`] opcode.
586    Return,
587    /// Self destruct opcode.
588    SelfDestruct,
589    /// EOF [`state::bytecode::opcode::RETURNCONTRACT`] opcode.
590    EofReturnContract,
591}
592
593/// Indicates that the EVM has experienced an exceptional halt.
594///
595/// This causes execution to immediately end with all gas being consumed.
596#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
597#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
598pub enum HaltReason {
599    /// Out of gas error.
600    OutOfGas(OutOfGasError),
601    /// Opcode not found error.
602    OpcodeNotFound,
603    /// Invalid FE opcode error.
604    InvalidFEOpcode,
605    /// Invalid jump destination.
606    InvalidJump,
607    /// The feature or opcode is not activated in hardfork.
608    NotActivated,
609    /// Attempting to pop a value from an empty stack.
610    StackUnderflow,
611    /// Attempting to push a value onto a full stack.
612    StackOverflow,
613    /// Invalid memory or storage offset for [`state::bytecode::opcode::RETURNDATACOPY`].
614    OutOfOffset,
615    /// Address collision during contract creation.
616    CreateCollision,
617    /// Precompile error.
618    PrecompileError,
619    /// Nonce overflow.
620    NonceOverflow,
621    /// Create init code size exceeds limit (runtime).
622    CreateContractSizeLimit,
623    /// Error on created contract that begins with EF
624    CreateContractStartingWithEF,
625    /// EIP-3860: Limit and meter initcode. Initcode size limit exceeded.
626    CreateInitCodeSizeLimit,
627
628    /* Internal Halts that can be only found inside Inspector */
629    /// Overflow payment. Not possible to happen on mainnet.
630    OverflowPayment,
631    /// State change during static call.
632    StateChangeDuringStaticCall,
633    /// Call not allowed inside static call.
634    CallNotAllowedInsideStatic,
635    /// Out of funds to pay for the call.
636    OutOfFunds,
637    /// Call is too deep.
638    CallTooDeep,
639
640    /// Aux data overflow, new aux data is larger than [u16] max size.
641    EofAuxDataOverflow,
642    /// Aux data is smaller than already present data size.
643    EofAuxDataTooSmall,
644    /// EOF Subroutine stack overflow
645    SubRoutineStackOverflow,
646    /// Check for target address validity is only done inside subcall.
647    InvalidEXTCALLTarget,
648}
649
650/// Out of gas errors.
651#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
652#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
653pub enum OutOfGasError {
654    /// Basic OOG error. Not enough gas to execute the opcode.
655    Basic,
656    /// Tried to expand past memory limit.
657    MemoryLimit,
658    /// Basic OOG error from memory expansion
659    Memory,
660    /// Precompile threw OOG error
661    Precompile,
662    /// When performing something that takes a U256 and casts down to a u64, if its too large this would fire
663    /// i.e. in `as_usize_or_fail`
664    InvalidOperand,
665    /// When performing SSTORE the gasleft is less than or equal to 2300
666    ReentrancySentry,
667}