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#[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}