blockifier/transaction/
errors.rs

1use cairo_vm::types::errors::program_errors::ProgramError;
2use num_bigint::BigUint;
3use starknet_api::block::GasPrice;
4use starknet_api::core::{ClassHash, ContractAddress, EntryPointSelector, Nonce};
5use starknet_api::execution_resources::GasAmount;
6use starknet_api::transaction::fields::{AllResourceBounds, Fee, Resource};
7use starknet_api::transaction::TransactionVersion;
8use starknet_api::StarknetApiError;
9use starknet_types_core::felt::FromStrError;
10use thiserror::Error;
11
12use crate::bouncer::BouncerWeights;
13use crate::execution::call_info::Retdata;
14use crate::execution::errors::{ConstructorEntryPointExecutionError, EntryPointExecutionError};
15use crate::execution::stack_trace::{gen_tx_execution_error_trace, Cairo1RevertSummary};
16use crate::fee::fee_checks::FeeCheckError;
17use crate::state::errors::StateError;
18
19#[derive(Debug, Error)]
20pub enum ResourceBoundsError {
21    #[error(
22        "Max {resource} price ({max_gas_price}) is lower than the actual gas price: \
23         {actual_gas_price}."
24    )]
25    MaxGasPriceTooLow { resource: Resource, max_gas_price: GasPrice, actual_gas_price: GasPrice },
26    #[error(
27        "Max {resource} amount ({max_gas_amount}) is lower than the minimal gas amount: \
28         {minimal_gas_amount}."
29    )]
30    MaxGasAmountTooLow {
31        resource: Resource,
32        max_gas_amount: GasAmount,
33        minimal_gas_amount: GasAmount,
34    },
35}
36
37// TODO(Yoni, 1/9/2024): implement Display for Fee.
38#[derive(Debug, Error)]
39pub enum TransactionFeeError {
40    #[error("Cairo resource names must be contained in fee cost dict.")]
41    CairoResourcesNotContainedInFeeCosts,
42    #[error(transparent)]
43    ExecuteFeeTransferError(#[from] EntryPointExecutionError),
44    #[error("Actual fee ({}) exceeded max fee ({}).", actual_fee.0, max_fee.0)]
45    FeeTransferError { max_fee: Fee, actual_fee: Fee },
46    #[error("Actual fee ({}) exceeded paid fee on L1 ({}).", actual_fee.0, paid_fee.0)]
47    InsufficientFee { paid_fee: Fee, actual_fee: Fee },
48    #[error("Resources bounds ({bounds}) exceed balance ({balance}).")]
49    ResourcesBoundsExceedBalance { bounds: AllResourceBounds, balance: BigUint },
50    #[error(
51        "Resource {resource} bounds (max amount: {max_amount}, max price): {max_price}) exceed \
52         balance ({balance})."
53    )]
54    GasBoundsExceedBalance {
55        resource: Resource,
56        max_amount: GasAmount,
57        max_price: GasPrice,
58        balance: BigUint,
59    },
60    #[error("Max fee ({}) exceeds balance ({balance}).", max_fee.0, )]
61    MaxFeeExceedsBalance { max_fee: Fee, balance: BigUint },
62    #[error("Max fee ({}) is too low. Minimum fee: {}.", max_fee.0, min_fee.0)]
63    MaxFeeTooLow { min_fee: Fee, max_fee: Fee },
64    #[error("Resource bounds were not satisfied: {}", errors.iter().map(|e| format!("{e}")).collect::<Vec<_>>().join("\n"))]
65    InsufficientResourceBounds { errors: Vec<ResourceBoundsError> },
66    #[error("Missing L1 gas bounds in resource bounds.")]
67    MissingL1GasBounds,
68    #[error(transparent)]
69    StateError(#[from] StateError),
70}
71
72#[derive(Debug, Error)]
73pub enum TransactionExecutionError {
74    #[error(
75        "Declare transaction version {} must have a contract class of Cairo \
76         version {cairo_version:?}.", **declare_version
77    )]
78    ContractClassVersionMismatch { declare_version: TransactionVersion, cairo_version: u64 },
79    #[error("{}", gen_tx_execution_error_trace(self))]
80    ContractConstructorExecutionFailed(#[from] ConstructorEntryPointExecutionError),
81    #[error("Class with hash {:#066x} is already declared.", **class_hash)]
82    DeclareTransactionError { class_hash: ClassHash },
83    #[error("{}", gen_tx_execution_error_trace(self))]
84    ExecutionError {
85        error: Box<EntryPointExecutionError>,
86        class_hash: ClassHash,
87        storage_address: ContractAddress,
88        selector: EntryPointSelector,
89    },
90    #[error(transparent)]
91    FeeCheckError(#[from] FeeCheckError),
92    #[error(transparent)]
93    FromStr(#[from] FromStrError),
94    #[error("{panic_reason}")]
95    PanicInValidate { panic_reason: Cairo1RevertSummary },
96    #[error("The `validate` entry point should return `VALID`. Got {actual:?}.")]
97    InvalidValidateReturnData { actual: Retdata },
98    #[error(
99        "Transaction version {:?} is not supported. Supported versions: \
100         {:?}.", **version, allowed_versions.iter().map(|v| **v).collect::<Vec<_>>()
101    )]
102    InvalidVersion { version: TransactionVersion, allowed_versions: Vec<TransactionVersion> },
103    #[error(transparent)]
104    StarknetApiError(#[from] StarknetApiError),
105    #[error(transparent)]
106    StateError(#[from] StateError),
107    #[error(transparent)]
108    TransactionFeeError(#[from] Box<TransactionFeeError>),
109    #[error(transparent)]
110    TransactionPreValidationError(#[from] Box<TransactionPreValidationError>),
111    #[error(transparent)]
112    TryFromIntError(#[from] std::num::TryFromIntError),
113    #[error(
114        "Transaction size exceeds the maximum block capacity. Max block capacity: {}, \
115         transaction size: {}.", *max_capacity, *tx_size
116    )]
117    TransactionTooLarge { max_capacity: Box<BouncerWeights>, tx_size: Box<BouncerWeights> },
118    #[error("{}", gen_tx_execution_error_trace(self))]
119    ValidateTransactionError {
120        error: Box<EntryPointExecutionError>,
121        class_hash: ClassHash,
122        storage_address: ContractAddress,
123        selector: EntryPointSelector,
124    },
125    #[error("Cairo0 validate error with retdata: {0:?}")]
126    ValidateCairo0Error(Retdata),
127    #[error(
128        "Invalid segment structure: PC {0} was visited, but the beginning of the segment {1} was \
129         not."
130    )]
131    InvalidSegmentStructure(usize, usize),
132    #[error(transparent)]
133    ProgramError(#[from] ProgramError),
134}
135
136#[derive(Debug, Error)]
137pub enum TransactionPreValidationError {
138    #[error(
139        "Invalid transaction nonce of contract at address {:#066x}. Account nonce: \
140         {:#066x}; got: {:#066x}.", ***address, **account_nonce, **incoming_tx_nonce
141    )]
142    InvalidNonce { address: ContractAddress, account_nonce: Nonce, incoming_tx_nonce: Nonce },
143    #[error(transparent)]
144    StateError(#[from] StateError),
145    #[error(transparent)]
146    TransactionFeeError(#[from] Box<TransactionFeeError>),
147}
148
149#[derive(Debug, Error)]
150pub enum NumericConversionError {
151    #[error("Conversion of {0} to u128 unsuccessful.")]
152    U128ToUsizeError(u128),
153    #[error("Conversion of {0} to u64 unsuccessful.")]
154    U64ToUsizeError(u64),
155}