revm_precompile/
interface.rs

1//! Interface for the precompiles. It contains the precompile result type,
2//! the precompile output type, and the precompile error type.
3use core::fmt;
4use primitives::Bytes;
5use std::string::String;
6
7/// A precompile operation result type
8///
9/// Returns either `Ok((gas_used, return_bytes))` or `Err(error)`.
10pub type PrecompileResult = Result<PrecompileOutput, PrecompileError>;
11
12/// Precompile execution output
13#[derive(Clone, Debug, PartialEq, Eq, Hash)]
14pub struct PrecompileOutput {
15    /// Gas used by the precompile
16    pub gas_used: u64,
17    /// Output bytes
18    pub bytes: Bytes,
19}
20
21impl PrecompileOutput {
22    /// Returns new precompile output with the given gas used and output bytes.
23    pub fn new(gas_used: u64, bytes: Bytes) -> Self {
24        Self { gas_used, bytes }
25    }
26}
27
28/// Precompile function type. Takes input and gas limit and returns precompile result.
29pub type PrecompileFn = fn(&[u8], u64) -> PrecompileResult;
30
31/// Precompile error type.
32#[derive(Clone, Debug, PartialEq, Eq, Hash)]
33pub enum PrecompileError {
34    /// out of gas is the main error. Others are here just for completeness
35    OutOfGas,
36    /// Blake2 errors
37    Blake2WrongLength,
38    /// Blake2 wrong final indicator flag
39    Blake2WrongFinalIndicatorFlag,
40    /// Modexp errors
41    ModexpExpOverflow,
42    /// Modexp base overflow
43    ModexpBaseOverflow,
44    /// Modexp mod overflow
45    ModexpModOverflow,
46    /// Modexp limit all input sizes.
47    ModexpEip7823LimitSize,
48    /// Bn128 errors
49    Bn128FieldPointNotAMember,
50    /// Bn128 affine g failed to create
51    Bn128AffineGFailedToCreate,
52    /// Bn128 pair length
53    Bn128PairLength,
54    // Blob errors
55    /// The input length is not exactly 192 bytes
56    BlobInvalidInputLength,
57    /// The commitment does not match the versioned hash
58    BlobMismatchedVersion,
59    /// The proof verification failed
60    BlobVerifyKzgProofFailed,
61    /// Fatal error with a custom error message
62    Fatal(String),
63    /// Catch-all variant for other errors
64    Other(String),
65}
66
67impl PrecompileError {
68    /// Returns another error with the given message.
69    pub fn other(err: impl Into<String>) -> Self {
70        Self::Other(err.into())
71    }
72
73    /// Returns `true` if the error is out of gas.
74    pub fn is_oog(&self) -> bool {
75        matches!(self, Self::OutOfGas)
76    }
77}
78
79impl core::error::Error for PrecompileError {}
80
81impl fmt::Display for PrecompileError {
82    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        let s = match self {
84            Self::OutOfGas => "out of gas",
85            Self::Blake2WrongLength => "wrong input length for blake2",
86            Self::Blake2WrongFinalIndicatorFlag => "wrong final indicator flag for blake2",
87            Self::ModexpExpOverflow => "modexp exp overflow",
88            Self::ModexpBaseOverflow => "modexp base overflow",
89            Self::ModexpModOverflow => "modexp mod overflow",
90            Self::ModexpEip7823LimitSize => "Modexp limit all input sizes.",
91            Self::Bn128FieldPointNotAMember => "field point not a member of bn128 curve",
92            Self::Bn128AffineGFailedToCreate => "failed to create affine g point for bn128 curve",
93            Self::Bn128PairLength => "bn128 invalid pair length",
94            Self::BlobInvalidInputLength => "invalid blob input length",
95            Self::BlobMismatchedVersion => "mismatched blob version",
96            Self::BlobVerifyKzgProofFailed => "verifying blob kzg proof failed",
97            Self::Fatal(s) => s,
98            Self::Other(s) => s,
99        };
100        f.write_str(s)
101    }
102}