revm_precompile/
interface.rs

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