1use serde::Deserialize;
7
8use super::rpc::GlobalContractIdentifierView;
9use super::{AccountId, CryptoHash, Gas, NearToken, PublicKey};
10
11#[derive(Debug, Clone, Deserialize)]
17pub enum TxExecutionError {
18 ActionError(ActionError),
20 InvalidTxError(InvalidTxError),
22}
23
24impl std::fmt::Display for TxExecutionError {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 match self {
27 Self::ActionError(e) => write!(f, "ActionError: {e}"),
28 Self::InvalidTxError(e) => write!(f, "InvalidTxError: {e}"),
29 }
30 }
31}
32
33impl std::error::Error for TxExecutionError {}
34
35#[derive(Debug, Clone, Deserialize)]
41pub struct ActionError {
42 #[serde(default)]
45 pub index: Option<u64>,
46 pub kind: ActionErrorKind,
48}
49
50impl std::fmt::Display for ActionError {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 match self.index {
53 Some(i) => write!(f, "action #{i}: {}", self.kind),
54 None => write!(f, "{}", self.kind),
55 }
56 }
57}
58
59#[derive(Debug, Clone, Deserialize)]
61pub enum ActionErrorKind {
62 AccountAlreadyExists {
63 account_id: AccountId,
64 },
65 AccountDoesNotExist {
66 account_id: AccountId,
67 },
68 CreateAccountOnlyByRegistrar {
69 account_id: AccountId,
70 predecessor_id: AccountId,
71 registrar_account_id: AccountId,
72 },
73 CreateAccountNotAllowed {
74 account_id: AccountId,
75 predecessor_id: AccountId,
76 },
77 ActorNoPermission {
78 account_id: AccountId,
79 actor_id: AccountId,
80 },
81 DeleteKeyDoesNotExist {
82 account_id: AccountId,
83 public_key: PublicKey,
84 },
85 AddKeyAlreadyExists {
86 account_id: AccountId,
87 public_key: PublicKey,
88 },
89 DeleteAccountStaking {
90 account_id: AccountId,
91 },
92 LackBalanceForState {
93 account_id: AccountId,
94 amount: NearToken,
95 },
96 TriesToUnstake {
97 account_id: AccountId,
98 },
99 TriesToStake {
100 account_id: AccountId,
101 balance: NearToken,
102 locked: NearToken,
103 stake: NearToken,
104 },
105 InsufficientStake {
106 account_id: AccountId,
107 minimum_stake: NearToken,
108 stake: NearToken,
109 },
110 FunctionCallError(FunctionCallError),
111 NewReceiptValidationError(ReceiptValidationError),
112 OnlyImplicitAccountCreationAllowed {
113 account_id: AccountId,
114 },
115 DeleteAccountWithLargeState {
116 account_id: AccountId,
117 },
118 DelegateActionInvalidSignature,
119 DelegateActionSenderDoesNotMatchTxReceiver {
120 receiver_id: AccountId,
121 sender_id: AccountId,
122 },
123 DelegateActionExpired,
124 DelegateActionAccessKeyError(InvalidAccessKeyError),
125 DelegateActionInvalidNonce {
126 ak_nonce: u64,
127 delegate_nonce: u64,
128 },
129 DelegateActionNonceTooLarge {
130 delegate_nonce: u64,
131 upper_bound: u64,
132 },
133 GlobalContractDoesNotExist {
134 identifier: GlobalContractIdentifierView,
135 },
136 GasKeyDoesNotExist {
137 account_id: AccountId,
138 public_key: PublicKey,
139 },
140 InsufficientGasKeyBalance {
141 account_id: AccountId,
142 balance: NearToken,
143 public_key: PublicKey,
144 required: NearToken,
145 },
146 GasKeyBalanceTooHigh {
147 account_id: AccountId,
148 balance: NearToken,
149 #[serde(default)]
150 public_key: Option<PublicKey>,
151 },
152}
153
154impl std::fmt::Display for ActionErrorKind {
155 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
156 match self {
157 Self::AccountAlreadyExists { account_id } => {
158 write!(f, "account {account_id} already exists")
159 }
160 Self::AccountDoesNotExist { account_id } => {
161 write!(f, "account {account_id} does not exist")
162 }
163 Self::LackBalanceForState { account_id, amount } => {
164 write!(f, "account {account_id} lacks {amount} for state")
165 }
166 Self::FunctionCallError(e) => write!(f, "{e}"),
167 _ => write!(f, "{self:?}"),
168 }
169 }
170}
171
172#[derive(Debug, Clone, Deserialize)]
178pub enum InvalidTxError {
179 InvalidAccessKeyError(InvalidAccessKeyError),
180 InvalidSignerId {
181 signer_id: String,
182 },
183 SignerDoesNotExist {
184 signer_id: AccountId,
185 },
186 InvalidNonce {
187 ak_nonce: u64,
188 tx_nonce: u64,
189 },
190 NonceTooLarge {
191 tx_nonce: u64,
192 upper_bound: u64,
193 },
194 InvalidReceiverId {
195 receiver_id: String,
196 },
197 InvalidSignature,
198 NotEnoughBalance {
199 balance: NearToken,
200 cost: NearToken,
201 signer_id: AccountId,
202 },
203 LackBalanceForState {
204 amount: NearToken,
205 signer_id: AccountId,
206 },
207 CostOverflow,
208 InvalidChain,
209 Expired,
210 ActionsValidation(ActionsValidationError),
211 TransactionSizeExceeded {
212 limit: u64,
213 size: u64,
214 },
215 InvalidTransactionVersion,
216 StorageError(StorageError),
217 ShardCongested {
218 congestion_level: f64,
219 shard_id: u64,
220 },
221 ShardStuck {
222 missed_chunks: u64,
223 shard_id: u64,
224 },
225 InvalidNonceIndex {
226 num_nonces: u16,
227 #[serde(default)]
228 tx_nonce_index: Option<u16>,
229 },
230 NotEnoughGasKeyBalance {
231 balance: NearToken,
232 cost: NearToken,
233 signer_id: AccountId,
234 },
235 NotEnoughBalanceForDeposit {
236 balance: NearToken,
237 cost: NearToken,
238 reason: DepositCostFailureReason,
239 signer_id: AccountId,
240 },
241}
242
243impl InvalidTxError {
244 pub fn is_retryable(&self) -> bool {
247 matches!(
248 self,
249 InvalidTxError::InvalidNonce { .. }
250 | InvalidTxError::ShardCongested { .. }
251 | InvalidTxError::ShardStuck { .. }
252 )
253 }
254}
255
256impl std::fmt::Display for InvalidTxError {
257 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
258 match self {
259 Self::InvalidSignature => write!(f, "invalid signature"),
260 Self::NotEnoughBalance {
261 signer_id, cost, ..
262 } => write!(
263 f,
264 "{signer_id} does not have enough balance to cover {cost}"
265 ),
266 Self::InvalidNonce {
267 ak_nonce, tx_nonce, ..
268 } => write!(
269 f,
270 "invalid nonce: tx nonce {tx_nonce}, access key nonce {ak_nonce}"
271 ),
272 Self::Expired => write!(f, "transaction has expired"),
273 Self::ShardCongested { shard_id, .. } => write!(f, "shard {shard_id} is congested"),
274 _ => write!(f, "{self:?}"),
275 }
276 }
277}
278
279#[derive(Debug, Clone, Deserialize)]
285pub enum InvalidAccessKeyError {
286 AccessKeyNotFound {
287 account_id: AccountId,
288 public_key: PublicKey,
289 },
290 ReceiverMismatch {
291 ak_receiver: String,
292 tx_receiver: AccountId,
293 },
294 MethodNameMismatch {
295 method_name: String,
296 },
297 RequiresFullAccess,
298 NotEnoughAllowance {
299 account_id: AccountId,
300 allowance: NearToken,
301 cost: NearToken,
302 public_key: PublicKey,
303 },
304 DepositWithFunctionCall,
305}
306
307#[derive(Debug, Clone, Deserialize)]
313pub enum FunctionCallError {
314 WasmUnknownError,
315 #[serde(rename = "_EVMError")]
316 EvmError,
317 CompilationError(CompilationError),
318 LinkError {
319 msg: String,
320 },
321 MethodResolveError(MethodResolveError),
322 WasmTrap(WasmTrap),
323 HostError(HostError),
324 ExecutionError(String),
325}
326
327impl std::fmt::Display for FunctionCallError {
328 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
329 match self {
330 Self::ExecutionError(msg) => write!(f, "execution error: {msg}"),
331 Self::HostError(e) => write!(f, "host error: {e:?}"),
332 Self::WasmTrap(e) => write!(f, "wasm trap: {e:?}"),
333 Self::CompilationError(e) => write!(f, "compilation error: {e:?}"),
334 Self::MethodResolveError(e) => write!(f, "method resolve error: {e:?}"),
335 Self::LinkError { msg } => write!(f, "link error: {msg}"),
336 _ => write!(f, "{self:?}"),
337 }
338 }
339}
340
341#[derive(Debug, Clone, Deserialize)]
343pub enum CompilationError {
344 CodeDoesNotExist { account_id: AccountId },
345 PrepareError(PrepareError),
346 WasmerCompileError { msg: String },
347}
348
349#[derive(Debug, Clone, Deserialize)]
351pub enum PrepareError {
352 Serialization,
353 Deserialization,
354 InternalMemoryDeclared,
355 GasInstrumentation,
356 StackHeightInstrumentation,
357 Instantiate,
358 Memory,
359 TooManyFunctions,
360 TooManyLocals,
361 TooManyTables,
362 TooManyTableElements,
363}
364
365#[derive(Debug, Clone, Deserialize)]
367pub enum MethodResolveError {
368 MethodEmptyName,
369 MethodNotFound,
370 MethodInvalidSignature,
371}
372
373#[derive(Debug, Clone, Deserialize)]
375pub enum WasmTrap {
376 Unreachable,
377 IncorrectCallIndirectSignature,
378 MemoryOutOfBounds,
379 #[serde(rename = "CallIndirectOOB")]
380 CallIndirectOob,
381 IllegalArithmetic,
382 MisalignedAtomicAccess,
383 IndirectCallToNull,
384 StackOverflow,
385 GenericTrap,
386}
387
388#[derive(Debug, Clone, Deserialize)]
390pub enum HostError {
391 #[serde(rename = "BadUTF16")]
392 BadUtf16,
393 #[serde(rename = "BadUTF8")]
394 BadUtf8,
395 GasExceeded,
396 GasLimitExceeded,
397 BalanceExceeded,
398 EmptyMethodName,
399 GuestPanic {
400 panic_msg: String,
401 },
402 IntegerOverflow,
403 InvalidPromiseIndex {
404 promise_idx: u64,
405 },
406 CannotAppendActionToJointPromise,
407 CannotReturnJointPromise,
408 InvalidPromiseResultIndex {
409 result_idx: u64,
410 },
411 InvalidRegisterId {
412 register_id: u64,
413 },
414 IteratorWasInvalidated {
415 iterator_index: u64,
416 },
417 MemoryAccessViolation,
418 InvalidReceiptIndex {
419 receipt_index: u64,
420 },
421 InvalidIteratorIndex {
422 iterator_index: u64,
423 },
424 InvalidAccountId,
425 InvalidMethodName,
426 InvalidPublicKey,
427 ProhibitedInView {
428 method_name: String,
429 },
430 NumberOfLogsExceeded {
431 limit: u64,
432 },
433 KeyLengthExceeded {
434 length: u64,
435 limit: u64,
436 },
437 ValueLengthExceeded {
438 length: u64,
439 limit: u64,
440 },
441 TotalLogLengthExceeded {
442 length: u64,
443 limit: u64,
444 },
445 NumberPromisesExceeded {
446 limit: u64,
447 number_of_promises: u64,
448 },
449 NumberInputDataDependenciesExceeded {
450 limit: u64,
451 number_of_input_data_dependencies: u64,
452 },
453 ReturnedValueLengthExceeded {
454 length: u64,
455 limit: u64,
456 },
457 ContractSizeExceeded {
458 limit: u64,
459 size: u64,
460 },
461 Deprecated {
462 method_name: String,
463 },
464 #[serde(rename = "ECRecoverError")]
465 EcRecoverError {
466 msg: String,
467 },
468 AltBn128InvalidInput {
469 msg: String,
470 },
471 Ed25519VerifyInvalidInput {
472 msg: String,
473 },
474}
475
476#[derive(Debug, Clone, Deserialize)]
482pub enum ActionsValidationError {
483 DeleteActionMustBeFinal,
484 TotalPrepaidGasExceeded {
485 limit: Gas,
486 total_prepaid_gas: Gas,
487 },
488 TotalNumberOfActionsExceeded {
489 limit: u64,
490 total_number_of_actions: u64,
491 },
492 AddKeyMethodNamesNumberOfBytesExceeded {
493 limit: u64,
494 total_number_of_bytes: u64,
495 },
496 AddKeyMethodNameLengthExceeded {
497 length: u64,
498 limit: u64,
499 },
500 IntegerOverflow,
501 InvalidAccountId {
502 account_id: String,
503 },
504 ContractSizeExceeded {
505 limit: u64,
506 size: u64,
507 },
508 FunctionCallMethodNameLengthExceeded {
509 length: u64,
510 limit: u64,
511 },
512 FunctionCallArgumentsLengthExceeded {
513 length: u64,
514 limit: u64,
515 },
516 UnsuitableStakingKey {
517 public_key: PublicKey,
518 },
519 FunctionCallZeroAttachedGas,
520 DelegateActionMustBeOnlyOne,
521 UnsupportedProtocolFeature {
522 protocol_feature: String,
523 version: u32,
524 },
525 InvalidDeterministicStateInitReceiver {
526 derived_id: AccountId,
527 receiver_id: AccountId,
528 },
529 DeterministicStateInitKeyLengthExceeded {
530 length: u64,
531 limit: u64,
532 },
533 DeterministicStateInitValueLengthExceeded {
534 length: u64,
535 limit: u64,
536 },
537 GasKeyInvalidNumNonces {
538 limit: u16,
539 requested_nonces: u16,
540 },
541 AddGasKeyWithNonZeroBalance {
542 balance: NearToken,
543 },
544 GasKeyFunctionCallAllowanceNotAllowed,
545}
546
547#[derive(Debug, Clone, Deserialize)]
553pub enum ReceiptValidationError {
554 InvalidPredecessorId {
555 account_id: String,
556 },
557 InvalidReceiverId {
558 account_id: String,
559 },
560 InvalidSignerId {
561 account_id: String,
562 },
563 InvalidDataReceiverId {
564 account_id: String,
565 },
566 ReturnedValueLengthExceeded {
567 length: u64,
568 limit: u64,
569 },
570 NumberInputDataDependenciesExceeded {
571 limit: u64,
572 number_of_input_data_dependencies: u64,
573 },
574 ActionsValidation(ActionsValidationError),
575 ReceiptSizeExceeded {
576 limit: u64,
577 size: u64,
578 },
579 InvalidRefundTo {
580 account_id: String,
581 },
582}
583
584#[derive(Debug, Clone, Deserialize)]
590pub enum StorageError {
591 StorageInternalError,
592 MissingTrieValue(MissingTrieValue),
593 UnexpectedTrieValue,
594 StorageInconsistentState(String),
595 FlatStorageBlockNotSupported(String),
596 MemTrieLoadingError(String),
597}
598
599#[derive(Debug, Clone, Deserialize)]
601pub struct MissingTrieValue {
602 pub context: MissingTrieValueContext,
603 pub hash: CryptoHash,
604}
605
606#[derive(Debug, Clone, Deserialize)]
608#[allow(clippy::enum_variant_names)] pub enum MissingTrieValueContext {
610 TrieIterator,
611 TriePrefetchingStorage,
612 TrieMemoryPartialStorage,
613 TrieStorage,
614}
615
616#[derive(Debug, Clone, Deserialize)]
622pub enum DepositCostFailureReason {
623 NotEnoughBalance,
624 LackBalanceForState,
625}