Skip to content

Commit fc24a5a

Browse files
authored
feat(katana-rpc): add ContractErrorData when it applies (dojoengine#1297)
* feat(katana-rpc): add ContractErrorData when it applies * fix: adjust StarknetApiError enum to include data * fix: clippy * fix: rework enum for StarknetApiError * fix: sort StarknetApiError code into ascending order * fix: group common fields at the bottom * fix: get StarknetApiError error fields before consuming it
1 parent 570f2d0 commit fc24a5a

File tree

2 files changed

+88
-35
lines changed

2 files changed

+88
-35
lines changed

crates/katana/rpc/src/api/starknet.rs

Lines changed: 79 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,73 +16,120 @@ use katana_rpc_types::transaction::{
1616
DeclareTxResult, DeployAccountTxResult, InvokeTxResult, Tx,
1717
};
1818
use katana_rpc_types::{ContractClass, FeeEstimate, FeltAsHex, FunctionCall};
19-
use starknet::core::types::TransactionStatus;
19+
use starknet::core::types::{ContractErrorData, TransactionStatus};
2020

21-
#[derive(thiserror::Error, Clone, Copy, Debug)]
21+
#[derive(thiserror::Error, Clone, Debug)]
22+
#[repr(i32)]
2223
pub enum StarknetApiError {
2324
#[error("Failed to write transaction")]
24-
FailedToReceiveTxn = 1,
25+
FailedToReceiveTxn,
2526
#[error("Contract not found")]
26-
ContractNotFound = 20,
27+
ContractNotFound,
2728
#[error("Invalid message selector")]
28-
InvalidMessageSelector = 21,
29+
InvalidMessageSelector,
2930
#[error("Invalid call data")]
30-
InvalidCallData = 22,
31+
InvalidCallData,
3132
#[error("Block not found")]
32-
BlockNotFound = 24,
33+
BlockNotFound,
3334
#[error("Transaction hash not found")]
34-
TxnHashNotFound = 29,
35+
TxnHashNotFound,
3536
#[error("Invalid transaction index in a block")]
36-
InvalidTxnIndex = 27,
37+
InvalidTxnIndex,
3738
#[error("Class hash not found")]
38-
ClassHashNotFound = 28,
39+
ClassHashNotFound,
3940
#[error("Requested page size is too big")]
40-
PageSizeTooBig = 31,
41+
PageSizeTooBig,
4142
#[error("There are no blocks")]
42-
NoBlocks = 32,
43+
NoBlocks,
4344
#[error("The supplied continuation token is invalid or unknown")]
44-
InvalidContinuationToken = 33,
45+
InvalidContinuationToken,
4546
#[error("Contract error")]
46-
ContractError = 40,
47+
ContractError { revert_error: String },
4748
#[error("Invalid contract class")]
48-
InvalidContractClass = 50,
49+
InvalidContractClass,
4950
#[error("Class already declared")]
50-
ClassAlreadyDeclared = 51,
51+
ClassAlreadyDeclared,
5152
#[error("Invalid transaction nonce")]
52-
InvalidTransactionNonce = 52,
53+
InvalidTransactionNonce,
5354
#[error("Max fee is smaller than the minimal transaction cost (validation plus fee transfer)")]
54-
InsufficientMaxFee = 53,
55+
InsufficientMaxFee,
5556
#[error("Account balance is smaller than the transaction's max_fee")]
56-
InsufficientAccountBalance = 54,
57+
InsufficientAccountBalance,
5758
#[error("Account validation failed")]
58-
ValidationFailure = 55,
59+
ValidationFailure,
5960
#[error("Compilation failed")]
60-
CompilationFailed = 56,
61+
CompilationFailed,
6162
#[error("Contract class size is too large")]
62-
ContractClassSizeIsTooLarge = 57,
63+
ContractClassSizeIsTooLarge,
6364
#[error("Sender address in not an account contract")]
64-
NonAccount = 58,
65+
NonAccount,
6566
#[error("A transaction with the same hash already exists in the mempool")]
66-
DuplicateTransaction = 59,
67+
DuplicateTransaction,
6768
#[error("The compiled class hash did not match the one supplied in the transaction")]
68-
CompiledClassHashMismatch = 60,
69+
CompiledClassHashMismatch,
6970
#[error("The transaction version is not supported")]
70-
UnsupportedTransactionVersion = 61,
71+
UnsupportedTransactionVersion,
7172
#[error("The contract class version is not supported")]
72-
UnsupportedContractClassVersion = 62,
73+
UnsupportedContractClassVersion,
7374
#[error("An unexpected error occured")]
74-
UnexpectedError = 63,
75+
UnexpectedError,
7576
#[error("Too many storage keys requested")]
76-
ProofLimitExceeded = 10000,
77+
ProofLimitExceeded,
7778
#[error("Too many keys provided in a filter")]
78-
TooManyKeysInFilter = 34,
79+
TooManyKeysInFilter,
7980
#[error("Failed to fetch pending transactions")]
80-
FailedToFetchPendingTransactions = 38,
81+
FailedToFetchPendingTransactions,
82+
}
83+
84+
impl StarknetApiError {
85+
fn code(&self) -> i32 {
86+
match self {
87+
StarknetApiError::FailedToReceiveTxn => 1,
88+
StarknetApiError::ContractNotFound => 20,
89+
StarknetApiError::InvalidMessageSelector => 21,
90+
StarknetApiError::InvalidCallData => 22,
91+
StarknetApiError::BlockNotFound => 24,
92+
StarknetApiError::InvalidTxnIndex => 27,
93+
StarknetApiError::ClassHashNotFound => 28,
94+
StarknetApiError::TxnHashNotFound => 29,
95+
StarknetApiError::PageSizeTooBig => 31,
96+
StarknetApiError::NoBlocks => 32,
97+
StarknetApiError::InvalidContinuationToken => 33,
98+
StarknetApiError::TooManyKeysInFilter => 34,
99+
StarknetApiError::FailedToFetchPendingTransactions => 38,
100+
StarknetApiError::ContractError { .. } => 40,
101+
StarknetApiError::InvalidContractClass => 50,
102+
StarknetApiError::ClassAlreadyDeclared => 51,
103+
StarknetApiError::InvalidTransactionNonce => 52,
104+
StarknetApiError::InsufficientMaxFee => 53,
105+
StarknetApiError::InsufficientAccountBalance => 54,
106+
StarknetApiError::ValidationFailure => 55,
107+
StarknetApiError::CompilationFailed => 56,
108+
StarknetApiError::ContractClassSizeIsTooLarge => 57,
109+
StarknetApiError::NonAccount => 58,
110+
StarknetApiError::DuplicateTransaction => 59,
111+
StarknetApiError::CompiledClassHashMismatch => 60,
112+
StarknetApiError::UnsupportedTransactionVersion => 61,
113+
StarknetApiError::UnsupportedContractClassVersion => 62,
114+
StarknetApiError::UnexpectedError => 63,
115+
StarknetApiError::ProofLimitExceeded => 10000,
116+
}
117+
}
81118
}
82119

83120
impl From<StarknetApiError> for Error {
84121
fn from(err: StarknetApiError) -> Self {
85-
Error::Call(CallError::Custom(ErrorObject::owned(err as i32, err.to_string(), None::<()>)))
122+
let code = err.code();
123+
let message = err.to_string();
124+
125+
let data = match err {
126+
StarknetApiError::ContractError { revert_error } => {
127+
Some(ContractErrorData { revert_error })
128+
}
129+
_ => None,
130+
};
131+
132+
Error::Call(CallError::Custom(ErrorObject::owned(code, message, data)))
86133
}
87134
}
88135

crates/katana/rpc/src/starknet.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,9 @@ impl StarknetApiServer for StarknetApi {
367367
let res = self.sequencer.call(request, block_id).map_err(|e| match e {
368368
SequencerError::BlockNotFound(_) => StarknetApiError::BlockNotFound,
369369
SequencerError::ContractNotFound(_) => StarknetApiError::ContractNotFound,
370-
SequencerError::EntryPointExecution(_) => StarknetApiError::ContractError,
370+
SequencerError::EntryPointExecution(e) => {
371+
StarknetApiError::ContractError { revert_error: e.to_string() }
372+
}
371373
_ => StarknetApiError::UnexpectedError,
372374
})?;
373375

@@ -449,7 +451,9 @@ impl StarknetApiServer for StarknetApi {
449451

450452
let res = self.sequencer.estimate_fee(transactions, block_id).map_err(|e| match e {
451453
SequencerError::BlockNotFound(_) => StarknetApiError::BlockNotFound,
452-
SequencerError::TransactionExecution(_) => StarknetApiError::ContractError,
454+
SequencerError::TransactionExecution(e) => {
455+
StarknetApiError::ContractError { revert_error: e.to_string() }
456+
}
453457
_ => StarknetApiError::UnexpectedError,
454458
})?;
455459

@@ -473,7 +477,9 @@ impl StarknetApiServer for StarknetApi {
473477
.estimate_fee(vec![tx], block_id)
474478
.map_err(|e| match e {
475479
SequencerError::BlockNotFound(_) => StarknetApiError::BlockNotFound,
476-
SequencerError::TransactionExecution(_) => StarknetApiError::ContractError,
480+
SequencerError::TransactionExecution(e) => {
481+
StarknetApiError::ContractError { revert_error: e.to_string() }
482+
}
477483
_ => StarknetApiError::UnexpectedError,
478484
})?
479485
.pop()

0 commit comments

Comments
 (0)