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::CreateAccountOnlyByRegistrar {
164 account_id,
165 predecessor_id,
166 registrar_account_id,
167 } => write!(
168 f,
169 "top-level account {account_id} can only be created by registrar {registrar_account_id}, not by {predecessor_id}"
170 ),
171 Self::CreateAccountNotAllowed {
172 account_id,
173 predecessor_id,
174 } => write!(
175 f,
176 "account {account_id} must be under a namespace of the creator account {predecessor_id}"
177 ),
178 Self::ActorNoPermission {
179 account_id,
180 actor_id,
181 } => write!(
182 f,
183 "actor {actor_id} does not have permission to act on account {account_id}"
184 ),
185 Self::DeleteKeyDoesNotExist {
186 account_id,
187 public_key,
188 } => write!(
189 f,
190 "account {account_id} tries to remove an access key {public_key} that doesn't exist"
191 ),
192 Self::AddKeyAlreadyExists {
193 account_id,
194 public_key,
195 } => write!(
196 f,
197 "public key {public_key} already exists for account {account_id}"
198 ),
199 Self::DeleteAccountStaking { account_id } => {
200 write!(f, "account {account_id} is staking and cannot be deleted")
201 }
202 Self::LackBalanceForState { account_id, amount } => write!(
203 f,
204 "account {account_id} needs {} to cover storage cost",
205 amount.exact_amount_display()
206 ),
207 Self::TriesToUnstake { account_id } => {
208 write!(f, "account {account_id} is not staked but tries to unstake")
209 }
210 Self::TriesToStake {
211 account_id,
212 stake,
213 balance,
214 ..
215 } => write!(
216 f,
217 "account {account_id} doesn't have enough balance ({}) to increase the stake ({})",
218 balance.exact_amount_display(),
219 stake.exact_amount_display()
220 ),
221 Self::InsufficientStake {
222 account_id,
223 stake,
224 minimum_stake,
225 } => write!(
226 f,
227 "account {account_id} has insufficient stake ({}), minimum required is {}",
228 stake.exact_amount_display(),
229 minimum_stake.exact_amount_display()
230 ),
231 Self::FunctionCallError(e) => write!(f, "{e}"),
232 Self::NewReceiptValidationError(e) => {
233 write!(f, "receipt validation error: {e}")
234 }
235 Self::OnlyImplicitAccountCreationAllowed { account_id } => write!(
236 f,
237 "only implicit account creation is allowed for {account_id}"
238 ),
239 Self::DeleteAccountWithLargeState { account_id } => write!(
240 f,
241 "deleting account {account_id} with large state is temporarily banned"
242 ),
243 Self::DelegateActionInvalidSignature => {
244 write!(f, "invalid signature on delegate action")
245 }
246 Self::DelegateActionSenderDoesNotMatchTxReceiver {
247 sender_id,
248 receiver_id,
249 } => write!(
250 f,
251 "delegate action sender {sender_id} does not match transaction receiver {receiver_id}"
252 ),
253 Self::DelegateActionExpired => write!(f, "delegate action has expired"),
254 Self::DelegateActionAccessKeyError(e) => {
255 write!(f, "delegate action access key error: {e}")
256 }
257 Self::DelegateActionInvalidNonce {
258 delegate_nonce,
259 ak_nonce,
260 } => write!(
261 f,
262 "delegate action nonce {delegate_nonce} must be larger than access key nonce {ak_nonce}"
263 ),
264 Self::DelegateActionNonceTooLarge {
265 delegate_nonce,
266 upper_bound,
267 } => write!(
268 f,
269 "delegate action nonce {delegate_nonce} is larger than the upper bound {upper_bound}"
270 ),
271 Self::GlobalContractDoesNotExist { identifier } => {
272 write!(f, "global contract {identifier} does not exist")
273 }
274 Self::GasKeyDoesNotExist {
275 account_id,
276 public_key,
277 } => write!(
278 f,
279 "gas key {public_key} does not exist for account {account_id}"
280 ),
281 Self::InsufficientGasKeyBalance {
282 account_id,
283 public_key,
284 balance,
285 required,
286 } => write!(
287 f,
288 "gas key {public_key} for account {account_id} has insufficient balance ({}, required: {})",
289 balance.exact_amount_display(),
290 required.exact_amount_display()
291 ),
292 Self::GasKeyBalanceTooHigh {
293 account_id,
294 public_key,
295 balance,
296 } => {
297 let key_info = match public_key {
298 Some(pk) => format!("gas key {pk}"),
299 None => "gas keys".to_string(),
300 };
301 write!(
302 f,
303 "balance ({}) of {key_info} for account {account_id} is too high",
304 balance.exact_amount_display()
305 )
306 }
307 }
308 }
309}
310
311#[derive(Debug, Clone, Deserialize)]
317pub enum InvalidTxError {
318 InvalidAccessKeyError(InvalidAccessKeyError),
319 InvalidSignerId {
320 signer_id: String,
321 },
322 SignerDoesNotExist {
323 signer_id: AccountId,
324 },
325 InvalidNonce {
326 ak_nonce: u64,
327 tx_nonce: u64,
328 },
329 NonceTooLarge {
330 tx_nonce: u64,
331 upper_bound: u64,
332 },
333 InvalidReceiverId {
334 receiver_id: String,
335 },
336 InvalidSignature,
337 NotEnoughBalance {
338 balance: NearToken,
339 cost: NearToken,
340 signer_id: AccountId,
341 },
342 LackBalanceForState {
343 amount: NearToken,
344 signer_id: AccountId,
345 },
346 CostOverflow,
347 InvalidChain,
348 Expired,
349 ActionsValidation(ActionsValidationError),
350 TransactionSizeExceeded {
351 limit: u64,
352 size: u64,
353 },
354 InvalidTransactionVersion,
355 StorageError(StorageError),
356 ShardCongested {
357 congestion_level: f64,
358 shard_id: u64,
359 },
360 ShardStuck {
361 missed_chunks: u64,
362 shard_id: u64,
363 },
364 InvalidNonceIndex {
365 num_nonces: u16,
366 #[serde(default)]
367 tx_nonce_index: Option<u16>,
368 },
369 NotEnoughGasKeyBalance {
370 balance: NearToken,
371 cost: NearToken,
372 signer_id: AccountId,
373 },
374 NotEnoughBalanceForDeposit {
375 balance: NearToken,
376 cost: NearToken,
377 reason: DepositCostFailureReason,
378 signer_id: AccountId,
379 },
380}
381
382impl InvalidTxError {
383 pub fn is_retryable(&self) -> bool {
386 matches!(
387 self,
388 InvalidTxError::InvalidNonce { .. }
389 | InvalidTxError::ShardCongested { .. }
390 | InvalidTxError::ShardStuck { .. }
391 )
392 }
393}
394
395impl std::fmt::Display for InvalidTxError {
396 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
397 match self {
398 Self::InvalidAccessKeyError(e) => write!(f, "{e}"),
399 Self::InvalidSignerId { signer_id } => {
400 write!(f, "signer ID {signer_id} is not a valid account ID")
401 }
402 Self::SignerDoesNotExist { signer_id } => {
403 write!(f, "signer account {signer_id} does not exist")
404 }
405 Self::InvalidNonce {
406 ak_nonce, tx_nonce, ..
407 } => write!(
408 f,
409 "transaction nonce {tx_nonce} must be larger than access key nonce {ak_nonce}"
410 ),
411 Self::NonceTooLarge {
412 tx_nonce,
413 upper_bound,
414 } => write!(
415 f,
416 "transaction nonce {tx_nonce} is larger than the upper bound {upper_bound}"
417 ),
418 Self::InvalidReceiverId { receiver_id } => {
419 write!(f, "receiver ID {receiver_id} is not a valid account ID")
420 }
421 Self::InvalidSignature => write!(f, "transaction signature is not valid"),
422 Self::NotEnoughBalance {
423 signer_id,
424 balance,
425 cost,
426 } => write!(
427 f,
428 "account {signer_id} does not have enough balance ({}) to cover transaction cost ({})",
429 balance.exact_amount_display(),
430 cost.exact_amount_display()
431 ),
432 Self::LackBalanceForState { signer_id, amount } => write!(
433 f,
434 "account {signer_id} doesn't have enough balance ({}) after transaction",
435 amount.exact_amount_display()
436 ),
437 Self::CostOverflow => {
438 write!(f, "integer overflow during transaction cost estimation")
439 }
440 Self::InvalidChain => write!(
441 f,
442 "transaction parent block hash doesn't belong to the current chain"
443 ),
444 Self::Expired => write!(f, "transaction has expired"),
445 Self::ActionsValidation(e) => write!(f, "{e}"),
446 Self::TransactionSizeExceeded { size, limit } => write!(
447 f,
448 "serialized transaction size ({size}) exceeded the limit ({limit})"
449 ),
450 Self::InvalidTransactionVersion => write!(f, "invalid transaction version"),
451 Self::StorageError(e) => write!(f, "storage error: {e}"),
452 Self::ShardCongested {
453 shard_id,
454 congestion_level,
455 } => write!(
456 f,
457 "shard {shard_id} is too congested ({congestion_level:.2}/1.00) to accept new transactions"
458 ),
459 Self::ShardStuck {
460 shard_id,
461 missed_chunks,
462 } => write!(
463 f,
464 "shard {shard_id} is {missed_chunks} blocks behind and can't accept transactions"
465 ),
466 Self::InvalidNonceIndex {
467 tx_nonce_index,
468 num_nonces,
469 } => match tx_nonce_index {
470 Some(idx) => write!(
471 f,
472 "invalid nonce index {idx} for key with {num_nonces} nonces"
473 ),
474 None => write!(f, "missing nonce index for key with {num_nonces} nonces"),
475 },
476 Self::NotEnoughGasKeyBalance {
477 signer_id,
478 balance,
479 cost,
480 } => write!(
481 f,
482 "gas key for {signer_id} does not have enough balance ({}) for gas cost ({})",
483 balance.exact_amount_display(),
484 cost.exact_amount_display()
485 ),
486 Self::NotEnoughBalanceForDeposit {
487 signer_id,
488 balance,
489 cost,
490 reason,
491 } => write!(
492 f,
493 "signer {signer_id} does not have enough balance ({}) to cover deposit cost ({}): {reason}",
494 balance.exact_amount_display(),
495 cost.exact_amount_display()
496 ),
497 }
498 }
499}
500
501#[derive(Debug, Clone, Deserialize)]
507pub enum InvalidAccessKeyError {
508 AccessKeyNotFound {
509 account_id: AccountId,
510 public_key: PublicKey,
511 },
512 ReceiverMismatch {
513 ak_receiver: String,
514 tx_receiver: AccountId,
515 },
516 MethodNameMismatch {
517 method_name: String,
518 },
519 RequiresFullAccess,
520 NotEnoughAllowance {
521 account_id: AccountId,
522 allowance: NearToken,
523 cost: NearToken,
524 public_key: PublicKey,
525 },
526 DepositWithFunctionCall,
527}
528
529impl std::fmt::Display for InvalidAccessKeyError {
530 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
531 match self {
532 Self::AccessKeyNotFound {
533 account_id,
534 public_key,
535 } => write!(
536 f,
537 "public key {public_key} doesn't exist for account {account_id}"
538 ),
539 Self::ReceiverMismatch {
540 ak_receiver,
541 tx_receiver,
542 } => write!(
543 f,
544 "transaction receiver {tx_receiver} doesn't match access key receiver {ak_receiver}"
545 ),
546 Self::MethodNameMismatch { method_name } => {
547 write!(f, "method {method_name} isn't allowed by the access key")
548 }
549 Self::RequiresFullAccess => {
550 write!(f, "transaction requires a full access key")
551 }
552 Self::NotEnoughAllowance {
553 account_id,
554 public_key,
555 allowance,
556 cost,
557 } => write!(
558 f,
559 "access key {public_key} for account {account_id} does not have enough allowance ({}) to cover transaction cost ({})",
560 allowance.exact_amount_display(),
561 cost.exact_amount_display()
562 ),
563 Self::DepositWithFunctionCall => {
564 write!(f, "deposits are not allowed with function call access keys")
565 }
566 }
567 }
568}
569
570#[derive(Debug, Clone, Deserialize)]
576pub enum FunctionCallError {
577 WasmUnknownError,
578 #[serde(rename = "_EVMError")]
579 EvmError,
580 CompilationError(CompilationError),
581 LinkError {
582 msg: String,
583 },
584 MethodResolveError(MethodResolveError),
585 WasmTrap(WasmTrap),
586 HostError(HostError),
587 ExecutionError(String),
588}
589
590impl std::fmt::Display for FunctionCallError {
591 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
592 match self {
593 Self::WasmUnknownError => write!(f, "unknown Wasm error"),
594 Self::EvmError => write!(f, "EVM error"),
595 Self::CompilationError(e) => write!(f, "compilation error: {e}"),
596 Self::LinkError { msg } => write!(f, "link error: {msg}"),
597 Self::MethodResolveError(e) => write!(f, "method resolve error: {e}"),
598 Self::WasmTrap(e) => write!(f, "Wasm trap: {e}"),
599 Self::HostError(e) => write!(f, "host error: {e}"),
600 Self::ExecutionError(msg) => write!(f, "execution error: {msg}"),
601 }
602 }
603}
604
605#[derive(Debug, Clone, Deserialize)]
607pub enum CompilationError {
608 CodeDoesNotExist { account_id: AccountId },
609 PrepareError(PrepareError),
610 WasmerCompileError { msg: String },
611}
612
613impl std::fmt::Display for CompilationError {
614 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
615 match self {
616 Self::CodeDoesNotExist { account_id } => {
617 write!(f, "contract code does not exist for account {account_id}")
618 }
619 Self::PrepareError(e) => write!(f, "{e}"),
620 Self::WasmerCompileError { msg } => write!(f, "Wasmer compilation error: {msg}"),
621 }
622 }
623}
624
625#[derive(Debug, Clone, Deserialize)]
627pub enum PrepareError {
628 Serialization,
629 Deserialization,
630 InternalMemoryDeclared,
631 GasInstrumentation,
632 StackHeightInstrumentation,
633 Instantiate,
634 Memory,
635 TooManyFunctions,
636 TooManyLocals,
637 TooManyTables,
638 TooManyTableElements,
639}
640
641impl std::fmt::Display for PrepareError {
642 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
643 match self {
644 Self::Serialization => write!(f, "Wasm serialization error"),
645 Self::Deserialization => write!(f, "Wasm deserialization error"),
646 Self::InternalMemoryDeclared => {
647 write!(f, "Wasm module declares internal memory")
648 }
649 Self::GasInstrumentation => write!(f, "gas instrumentation failed"),
650 Self::StackHeightInstrumentation => {
651 write!(f, "stack height instrumentation failed")
652 }
653 Self::Instantiate => write!(f, "Wasm instantiation error"),
654 Self::Memory => write!(f, "Wasm memory error"),
655 Self::TooManyFunctions => write!(f, "too many functions in Wasm module"),
656 Self::TooManyLocals => write!(f, "too many locals in Wasm module"),
657 Self::TooManyTables => write!(f, "too many tables in Wasm module"),
658 Self::TooManyTableElements => {
659 write!(f, "too many table elements in Wasm module")
660 }
661 }
662 }
663}
664
665#[derive(Debug, Clone, Deserialize)]
667pub enum MethodResolveError {
668 MethodEmptyName,
669 MethodNotFound,
670 MethodInvalidSignature,
671}
672
673impl std::fmt::Display for MethodResolveError {
674 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
675 match self {
676 Self::MethodEmptyName => write!(f, "method name is empty"),
677 Self::MethodNotFound => write!(f, "method not found in contract"),
678 Self::MethodInvalidSignature => write!(f, "method has an invalid signature"),
679 }
680 }
681}
682
683#[derive(Debug, Clone, Deserialize)]
685pub enum WasmTrap {
686 Unreachable,
687 IncorrectCallIndirectSignature,
688 MemoryOutOfBounds,
689 #[serde(rename = "CallIndirectOOB")]
690 CallIndirectOob,
691 IllegalArithmetic,
692 MisalignedAtomicAccess,
693 IndirectCallToNull,
694 StackOverflow,
695 GenericTrap,
696}
697
698impl std::fmt::Display for WasmTrap {
699 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
700 match self {
701 Self::Unreachable => write!(f, "unreachable instruction executed"),
702 Self::IncorrectCallIndirectSignature => {
703 write!(f, "incorrect call indirect signature")
704 }
705 Self::MemoryOutOfBounds => write!(f, "memory out of bounds"),
706 Self::CallIndirectOob => write!(f, "call indirect out of bounds"),
707 Self::IllegalArithmetic => write!(f, "illegal arithmetic operation"),
708 Self::MisalignedAtomicAccess => write!(f, "misaligned atomic access"),
709 Self::IndirectCallToNull => write!(f, "indirect call to null"),
710 Self::StackOverflow => write!(f, "stack overflow"),
711 Self::GenericTrap => write!(f, "generic trap"),
712 }
713 }
714}
715
716#[derive(Debug, Clone, Deserialize)]
718pub enum HostError {
719 #[serde(rename = "BadUTF16")]
720 BadUtf16,
721 #[serde(rename = "BadUTF8")]
722 BadUtf8,
723 GasExceeded,
724 GasLimitExceeded,
725 BalanceExceeded,
726 EmptyMethodName,
727 GuestPanic {
728 panic_msg: String,
729 },
730 IntegerOverflow,
731 InvalidPromiseIndex {
732 promise_idx: u64,
733 },
734 CannotAppendActionToJointPromise,
735 CannotReturnJointPromise,
736 InvalidPromiseResultIndex {
737 result_idx: u64,
738 },
739 InvalidRegisterId {
740 register_id: u64,
741 },
742 IteratorWasInvalidated {
743 iterator_index: u64,
744 },
745 MemoryAccessViolation,
746 InvalidReceiptIndex {
747 receipt_index: u64,
748 },
749 InvalidIteratorIndex {
750 iterator_index: u64,
751 },
752 InvalidAccountId,
753 InvalidMethodName,
754 InvalidPublicKey,
755 ProhibitedInView {
756 method_name: String,
757 },
758 NumberOfLogsExceeded {
759 limit: u64,
760 },
761 KeyLengthExceeded {
762 length: u64,
763 limit: u64,
764 },
765 ValueLengthExceeded {
766 length: u64,
767 limit: u64,
768 },
769 TotalLogLengthExceeded {
770 length: u64,
771 limit: u64,
772 },
773 NumberPromisesExceeded {
774 limit: u64,
775 number_of_promises: u64,
776 },
777 NumberInputDataDependenciesExceeded {
778 limit: u64,
779 number_of_input_data_dependencies: u64,
780 },
781 ReturnedValueLengthExceeded {
782 length: u64,
783 limit: u64,
784 },
785 ContractSizeExceeded {
786 limit: u64,
787 size: u64,
788 },
789 Deprecated {
790 method_name: String,
791 },
792 #[serde(rename = "ECRecoverError")]
793 EcRecoverError {
794 msg: String,
795 },
796 AltBn128InvalidInput {
797 msg: String,
798 },
799 Ed25519VerifyInvalidInput {
800 msg: String,
801 },
802}
803
804impl std::fmt::Display for HostError {
805 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
806 match self {
807 Self::BadUtf16 => write!(f, "bad UTF-16 string"),
808 Self::BadUtf8 => write!(f, "bad UTF-8 string"),
809 Self::GasExceeded => write!(f, "gas exceeded"),
810 Self::GasLimitExceeded => write!(f, "gas limit exceeded"),
811 Self::BalanceExceeded => write!(f, "balance exceeded"),
812 Self::EmptyMethodName => write!(f, "method name is empty"),
813 Self::GuestPanic { panic_msg } => write!(f, "smart contract panicked: {panic_msg}"),
814 Self::IntegerOverflow => write!(f, "integer overflow"),
815 Self::InvalidPromiseIndex { promise_idx } => {
816 write!(f, "invalid promise index {promise_idx}")
817 }
818 Self::CannotAppendActionToJointPromise => {
819 write!(f, "cannot append action to joint promise")
820 }
821 Self::CannotReturnJointPromise => write!(f, "cannot return joint promise"),
822 Self::InvalidPromiseResultIndex { result_idx } => {
823 write!(f, "invalid promise result index {result_idx}")
824 }
825 Self::InvalidRegisterId { register_id } => {
826 write!(f, "invalid register ID {register_id}")
827 }
828 Self::IteratorWasInvalidated { iterator_index } => {
829 write!(f, "iterator {iterator_index} was invalidated")
830 }
831 Self::MemoryAccessViolation => write!(f, "memory access violation"),
832 Self::InvalidReceiptIndex { receipt_index } => {
833 write!(f, "invalid receipt index {receipt_index}")
834 }
835 Self::InvalidIteratorIndex { iterator_index } => {
836 write!(f, "invalid iterator index {iterator_index}")
837 }
838 Self::InvalidAccountId => write!(f, "invalid account ID"),
839 Self::InvalidMethodName => write!(f, "invalid method name"),
840 Self::InvalidPublicKey => write!(f, "invalid public key"),
841 Self::ProhibitedInView { method_name } => {
842 write!(f, "method {method_name} is not allowed in a view call")
843 }
844 Self::NumberOfLogsExceeded { limit } => {
845 write!(f, "number of logs exceeded the limit of {limit}")
846 }
847 Self::KeyLengthExceeded { length, limit } => {
848 write!(f, "key length {length} exceeded the limit of {limit}")
849 }
850 Self::ValueLengthExceeded { length, limit } => {
851 write!(f, "value length {length} exceeded the limit of {limit}")
852 }
853 Self::TotalLogLengthExceeded { length, limit } => {
854 write!(f, "total log length {length} exceeded the limit of {limit}")
855 }
856 Self::NumberPromisesExceeded {
857 number_of_promises,
858 limit,
859 } => write!(
860 f,
861 "number of promises {number_of_promises} exceeded the limit of {limit}"
862 ),
863 Self::NumberInputDataDependenciesExceeded {
864 number_of_input_data_dependencies,
865 limit,
866 } => write!(
867 f,
868 "number of input data dependencies {number_of_input_data_dependencies} exceeded the limit of {limit}"
869 ),
870 Self::ReturnedValueLengthExceeded { length, limit } => {
871 write!(
872 f,
873 "returned value length {length} exceeded the limit of {limit}"
874 )
875 }
876 Self::ContractSizeExceeded { size, limit } => {
877 write!(f, "contract size {size} exceeded the limit of {limit}")
878 }
879 Self::Deprecated { method_name } => {
880 write!(f, "method {method_name} is deprecated")
881 }
882 Self::EcRecoverError { msg } => write!(f, "EC recover error: {msg}"),
883 Self::AltBn128InvalidInput { msg } => {
884 write!(f, "AltBn128 invalid input: {msg}")
885 }
886 Self::Ed25519VerifyInvalidInput { msg } => {
887 write!(f, "Ed25519 verification invalid input: {msg}")
888 }
889 }
890 }
891}
892
893#[derive(Debug, Clone, Deserialize)]
899pub enum ActionsValidationError {
900 DeleteActionMustBeFinal,
901 TotalPrepaidGasExceeded {
902 limit: Gas,
903 total_prepaid_gas: Gas,
904 },
905 TotalNumberOfActionsExceeded {
906 limit: u64,
907 total_number_of_actions: u64,
908 },
909 AddKeyMethodNamesNumberOfBytesExceeded {
910 limit: u64,
911 total_number_of_bytes: u64,
912 },
913 AddKeyMethodNameLengthExceeded {
914 length: u64,
915 limit: u64,
916 },
917 IntegerOverflow,
918 InvalidAccountId {
919 account_id: String,
920 },
921 ContractSizeExceeded {
922 limit: u64,
923 size: u64,
924 },
925 FunctionCallMethodNameLengthExceeded {
926 length: u64,
927 limit: u64,
928 },
929 FunctionCallArgumentsLengthExceeded {
930 length: u64,
931 limit: u64,
932 },
933 UnsuitableStakingKey {
934 public_key: PublicKey,
935 },
936 FunctionCallZeroAttachedGas,
937 DelegateActionMustBeOnlyOne,
938 UnsupportedProtocolFeature {
939 protocol_feature: String,
940 version: u32,
941 },
942 InvalidDeterministicStateInitReceiver {
943 derived_id: AccountId,
944 receiver_id: AccountId,
945 },
946 DeterministicStateInitKeyLengthExceeded {
947 length: u64,
948 limit: u64,
949 },
950 DeterministicStateInitValueLengthExceeded {
951 length: u64,
952 limit: u64,
953 },
954 GasKeyInvalidNumNonces {
955 limit: u16,
956 requested_nonces: u16,
957 },
958 AddGasKeyWithNonZeroBalance {
959 balance: NearToken,
960 },
961 GasKeyFunctionCallAllowanceNotAllowed,
962}
963
964impl std::fmt::Display for ActionsValidationError {
965 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
966 match self {
967 Self::DeleteActionMustBeFinal => {
968 write!(f, "delete action must be the final action in a transaction")
969 }
970 Self::TotalPrepaidGasExceeded {
971 total_prepaid_gas,
972 limit,
973 } => write!(
974 f,
975 "total prepaid gas ({total_prepaid_gas}) exceeded the limit ({limit})"
976 ),
977 Self::TotalNumberOfActionsExceeded {
978 total_number_of_actions,
979 limit,
980 } => write!(
981 f,
982 "number of actions ({total_number_of_actions}) exceeded the limit ({limit})"
983 ),
984 Self::AddKeyMethodNamesNumberOfBytesExceeded {
985 total_number_of_bytes,
986 limit,
987 } => write!(
988 f,
989 "total size of method names ({total_number_of_bytes} bytes) exceeded the limit ({limit}) in add key action"
990 ),
991 Self::AddKeyMethodNameLengthExceeded { length, limit } => write!(
992 f,
993 "method name length ({length}) exceeded the limit ({limit}) in add key action"
994 ),
995 Self::IntegerOverflow => write!(f, "integer overflow"),
996 Self::InvalidAccountId { account_id } => {
997 write!(f, "invalid account ID {account_id}")
998 }
999 Self::ContractSizeExceeded { size, limit } => write!(
1000 f,
1001 "contract size ({size}) exceeded the limit ({limit}) in deploy action"
1002 ),
1003 Self::FunctionCallMethodNameLengthExceeded { length, limit } => write!(
1004 f,
1005 "method name length ({length}) exceeded the limit ({limit}) in function call action"
1006 ),
1007 Self::FunctionCallArgumentsLengthExceeded { length, limit } => write!(
1008 f,
1009 "arguments length ({length}) exceeded the limit ({limit}) in function call action"
1010 ),
1011 Self::UnsuitableStakingKey { public_key } => {
1012 write!(f, "public key {public_key} is not suitable for staking")
1013 }
1014 Self::FunctionCallZeroAttachedGas => {
1015 write!(
1016 f,
1017 "function call must have a positive amount of gas attached"
1018 )
1019 }
1020 Self::DelegateActionMustBeOnlyOne => {
1021 write!(f, "transaction must contain only one delegate action")
1022 }
1023 Self::UnsupportedProtocolFeature {
1024 protocol_feature,
1025 version,
1026 } => write!(
1027 f,
1028 "protocol feature {protocol_feature} is unsupported in version {version}"
1029 ),
1030 Self::InvalidDeterministicStateInitReceiver {
1031 derived_id,
1032 receiver_id,
1033 } => write!(
1034 f,
1035 "invalid receiver {receiver_id} for deterministic account {derived_id}"
1036 ),
1037 Self::DeterministicStateInitKeyLengthExceeded { length, limit } => write!(
1038 f,
1039 "deterministic state init key length ({length}) exceeded the limit ({limit})"
1040 ),
1041 Self::DeterministicStateInitValueLengthExceeded { length, limit } => write!(
1042 f,
1043 "deterministic state init value length ({length}) exceeded the limit ({limit})"
1044 ),
1045 Self::GasKeyInvalidNumNonces {
1046 requested_nonces,
1047 limit,
1048 } => write!(
1049 f,
1050 "gas key requested invalid number of nonces: {requested_nonces} (must be between 1 and {limit})"
1051 ),
1052 Self::AddGasKeyWithNonZeroBalance { balance } => write!(
1053 f,
1054 "adding a gas key with non-zero balance ({}) is not allowed",
1055 balance.exact_amount_display()
1056 ),
1057 Self::GasKeyFunctionCallAllowanceNotAllowed => write!(
1058 f,
1059 "gas keys with function call permission cannot have an allowance"
1060 ),
1061 }
1062 }
1063}
1064
1065#[derive(Debug, Clone, Deserialize)]
1071pub enum ReceiptValidationError {
1072 InvalidPredecessorId {
1073 account_id: String,
1074 },
1075 InvalidReceiverId {
1076 account_id: String,
1077 },
1078 InvalidSignerId {
1079 account_id: String,
1080 },
1081 InvalidDataReceiverId {
1082 account_id: String,
1083 },
1084 ReturnedValueLengthExceeded {
1085 length: u64,
1086 limit: u64,
1087 },
1088 NumberInputDataDependenciesExceeded {
1089 limit: u64,
1090 number_of_input_data_dependencies: u64,
1091 },
1092 ActionsValidation(ActionsValidationError),
1093 ReceiptSizeExceeded {
1094 limit: u64,
1095 size: u64,
1096 },
1097 InvalidRefundTo {
1098 account_id: String,
1099 },
1100}
1101
1102impl std::fmt::Display for ReceiptValidationError {
1103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1104 match self {
1105 Self::InvalidPredecessorId { account_id } => {
1106 write!(f, "invalid predecessor ID {account_id}")
1107 }
1108 Self::InvalidReceiverId { account_id } => {
1109 write!(f, "invalid receiver ID {account_id}")
1110 }
1111 Self::InvalidSignerId { account_id } => {
1112 write!(f, "invalid signer ID {account_id}")
1113 }
1114 Self::InvalidDataReceiverId { account_id } => {
1115 write!(f, "invalid data receiver ID {account_id}")
1116 }
1117 Self::ReturnedValueLengthExceeded { length, limit } => write!(
1118 f,
1119 "returned value length ({length}) exceeded the limit ({limit})"
1120 ),
1121 Self::NumberInputDataDependenciesExceeded {
1122 number_of_input_data_dependencies,
1123 limit,
1124 } => write!(
1125 f,
1126 "number of input data dependencies ({number_of_input_data_dependencies}) exceeded the limit ({limit})"
1127 ),
1128 Self::ActionsValidation(e) => write!(f, "{e}"),
1129 Self::ReceiptSizeExceeded { size, limit } => {
1130 write!(f, "receipt size ({size}) exceeded the limit ({limit})")
1131 }
1132 Self::InvalidRefundTo { account_id } => {
1133 write!(f, "invalid refund-to account ID {account_id}")
1134 }
1135 }
1136 }
1137}
1138
1139#[derive(Debug, Clone, Deserialize)]
1145pub enum StorageError {
1146 StorageInternalError,
1147 MissingTrieValue(MissingTrieValue),
1148 UnexpectedTrieValue,
1149 StorageInconsistentState(String),
1150 FlatStorageBlockNotSupported(String),
1151 MemTrieLoadingError(String),
1152}
1153
1154#[derive(Debug, Clone, Deserialize)]
1156pub struct MissingTrieValue {
1157 pub context: MissingTrieValueContext,
1158 pub hash: CryptoHash,
1159}
1160
1161#[derive(Debug, Clone, Deserialize)]
1163#[allow(clippy::enum_variant_names)] pub enum MissingTrieValueContext {
1165 TrieIterator,
1166 TriePrefetchingStorage,
1167 TrieMemoryPartialStorage,
1168 TrieStorage,
1169}
1170
1171impl std::fmt::Display for MissingTrieValueContext {
1172 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1173 match self {
1174 Self::TrieIterator => write!(f, "trie iterator"),
1175 Self::TriePrefetchingStorage => write!(f, "prefetching storage"),
1176 Self::TrieMemoryPartialStorage => write!(f, "memory partial storage"),
1177 Self::TrieStorage => write!(f, "trie storage"),
1178 }
1179 }
1180}
1181
1182impl std::fmt::Display for StorageError {
1183 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1184 match self {
1185 Self::StorageInternalError => write!(f, "internal storage error"),
1186 Self::MissingTrieValue(v) => {
1187 write!(f, "missing trie value {} in {}", v.hash, v.context)
1188 }
1189 Self::UnexpectedTrieValue => write!(f, "unexpected trie value"),
1190 Self::StorageInconsistentState(msg) => {
1191 write!(f, "storage is in an inconsistent state: {msg}")
1192 }
1193 Self::FlatStorageBlockNotSupported(msg) => {
1194 write!(f, "block is not supported by flat storage: {msg}")
1195 }
1196 Self::MemTrieLoadingError(msg) => {
1197 write!(f, "trie is not loaded in memory: {msg}")
1198 }
1199 }
1200 }
1201}
1202
1203#[derive(Debug, Clone, Deserialize)]
1209pub enum DepositCostFailureReason {
1210 NotEnoughBalance,
1211 LackBalanceForState,
1212}
1213
1214impl std::fmt::Display for DepositCostFailureReason {
1215 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1216 match self {
1217 Self::NotEnoughBalance => write!(f, "not enough balance"),
1218 Self::LackBalanceForState => write!(f, "not enough balance for state"),
1219 }
1220 }
1221}