1use crate::crypto::prelude::*;
2use near_primitives_core::{
3 serialize::dec_format,
4 types::{AccountId, Balance, Gas, Nonce},
5};
6use serde::{Deserialize, Serialize};
7use std::fmt::{Debug, Display};
8
9use borsh::{BorshDeserialize, BorshSerialize};
10
11#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
13#[serde(rename_all = "PascalCase")]
14pub struct TxExecutionErrorContainer {
15 pub tx_execution_error: TxExecutionError,
16}
17
18#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
20pub enum TxExecutionError {
21 ActionError(ActionError),
23 InvalidTxError(InvalidTxError),
25}
26
27impl std::error::Error for TxExecutionError {}
28
29impl Display for TxExecutionError {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
31 match self {
32 TxExecutionError::ActionError(e) => write!(f, "{e}"),
33 TxExecutionError::InvalidTxError(e) => write!(f, "{e}"),
34 }
35 }
36}
37
38impl From<ActionError> for TxExecutionError {
39 fn from(error: ActionError) -> Self {
40 TxExecutionError::ActionError(error)
41 }
42}
43
44impl From<InvalidTxError> for TxExecutionError {
45 fn from(error: InvalidTxError) -> Self {
46 TxExecutionError::InvalidTxError(error)
47 }
48}
49
50#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
52pub enum InvalidTxError {
53 InvalidAccessKeyError(InvalidAccessKeyError),
55 InvalidSignerId { signer_id: String },
57 SignerDoesNotExist { signer_id: AccountId },
59 InvalidNonce { tx_nonce: Nonce, ak_nonce: Nonce },
61 NonceTooLarge { tx_nonce: Nonce, upper_bound: Nonce },
63 InvalidReceiverId { receiver_id: String },
65 InvalidSignature,
67 NotEnoughBalance {
69 signer_id: AccountId,
70 #[serde(with = "dec_format")]
71 balance: Balance,
72 #[serde(with = "dec_format")]
73 cost: Balance,
74 },
75 LackBalanceForState {
77 signer_id: AccountId,
79 #[serde(with = "dec_format")]
81 amount: Balance,
82 },
83 CostOverflow,
85 InvalidChain,
87 Expired,
89 ActionsValidation(ActionsValidationError),
91 TransactionSizeExceeded { size: u64, limit: u64 },
93}
94
95impl std::error::Error for InvalidTxError {}
96
97#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
98pub enum InvalidAccessKeyError {
99 AccessKeyNotFound {
101 account_id: AccountId,
102 public_key: Ed25519PublicKey,
103 },
104 ReceiverMismatch {
106 tx_receiver: AccountId,
107 ak_receiver: String,
108 },
109 MethodNameMismatch { method_name: String },
111 RequiresFullAccess,
113 NotEnoughAllowance {
115 account_id: AccountId,
116 public_key: Ed25519PublicKey,
117 #[serde(with = "dec_format")]
118 allowance: Balance,
119 #[serde(with = "dec_format")]
120 cost: Balance,
121 },
122 DepositWithFunctionCall,
124}
125
126#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
128pub enum ActionsValidationError {
129 DeleteActionMustBeFinal,
131 TotalPrepaidGasExceeded { total_prepaid_gas: Gas, limit: Gas },
133 TotalNumberOfActionsExceeded {
135 total_number_of_actions: u64,
136 limit: u64,
137 },
138 AddKeyMethodNamesNumberOfBytesExceeded {
140 total_number_of_bytes: u64,
141 limit: u64,
142 },
143 AddKeyMethodNameLengthExceeded { length: u64, limit: u64 },
145 IntegerOverflow,
147 InvalidAccountId { account_id: String },
149 ContractSizeExceeded { size: u64, limit: u64 },
151 FunctionCallMethodNameLengthExceeded { length: u64, limit: u64 },
153 FunctionCallArgumentsLengthExceeded { length: u64, limit: u64 },
155 UnsuitableStakingKey { public_key: Ed25519PublicKey },
157 FunctionCallZeroAttachedGas,
159}
160
161#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
163pub enum ReceiptValidationError {
164 InvalidPredecessorId { account_id: String },
166 InvalidReceiverId { account_id: String },
168 InvalidSignerId { account_id: String },
170 InvalidDataReceiverId { account_id: String },
172 ReturnedValueLengthExceeded { length: u64, limit: u64 },
174 NumberInputDataDependenciesExceeded {
176 number_of_input_data_dependencies: u64,
177 limit: u64,
178 },
179 ActionsValidation(ActionsValidationError),
181}
182
183impl Display for ReceiptValidationError {
184 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
185 match self {
186 ReceiptValidationError::InvalidPredecessorId { account_id } => {
187 write!(f, "The predecessor_id `{account_id}` of a Receipt is not valid.")
188 }
189 ReceiptValidationError::InvalidReceiverId { account_id } => {
190 write!(f, "The receiver_id `{account_id}` of a Receipt is not valid.")
191 }
192 ReceiptValidationError::InvalidSignerId { account_id } => {
193 write!(f, "The signer_id `{account_id}` of an ActionReceipt is not valid.")
194 }
195 ReceiptValidationError::InvalidDataReceiverId { account_id } => write!(
196 f,
197 "The receiver_id `{account_id}` of a DataReceiver within an ActionReceipt is not valid."
198 ),
199 ReceiptValidationError::ReturnedValueLengthExceeded { length, limit } => write!(
200 f,
201 "The length of the returned data {length} exceeded the limit {limit} in a DataReceipt"
202 ),
203 ReceiptValidationError::NumberInputDataDependenciesExceeded { number_of_input_data_dependencies, limit } => write!(
204 f,
205 "The number of input data dependencies {number_of_input_data_dependencies} exceeded the limit {limit} in an ActionReceipt"
206 ),
207 ReceiptValidationError::ActionsValidation(e) => write!(f, "{e}"),
208 }
209 }
210}
211
212impl std::error::Error for ReceiptValidationError {}
213
214impl Display for ActionsValidationError {
215 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
216 match self {
217 ActionsValidationError::DeleteActionMustBeFinal => {
218 write!(f, "The delete action must be the last action in transaction")
219 }
220 ActionsValidationError::TotalPrepaidGasExceeded { total_prepaid_gas, limit } => {
221 write!(f, "The total prepaid gas {total_prepaid_gas} exceeds the limit {limit}")
222 }
223 ActionsValidationError::TotalNumberOfActionsExceeded {total_number_of_actions, limit } => {
224 write!(
225 f,
226 "The total number of actions {total_number_of_actions} exceeds the limit {limit}"
227 )
228 }
229 ActionsValidationError::AddKeyMethodNamesNumberOfBytesExceeded { total_number_of_bytes, limit } => write!(
230 f,
231 "The total number of bytes in allowed method names {total_number_of_bytes} exceeds the maximum allowed number {limit} in a AddKey action"
232 ),
233 ActionsValidationError::AddKeyMethodNameLengthExceeded { length, limit } => write!(
234 f,
235 "The length of some method name {length} exceeds the maximum allowed length {limit} in a AddKey action"
236 ),
237 ActionsValidationError::IntegerOverflow => write!(
238 f,
239 "Integer overflow during a compute",
240 ),
241 ActionsValidationError::InvalidAccountId { account_id } => write!(
242 f,
243 "Invalid account ID `{account_id}`"
244 ),
245 ActionsValidationError::ContractSizeExceeded { size, limit } => write!(
246 f,
247 "The length of the contract size {size} exceeds the maximum allowed size {limit} in a DeployContract action"
248 ),
249 ActionsValidationError::FunctionCallMethodNameLengthExceeded { length, limit } => write!(
250 f,
251 "The length of the method name {length} exceeds the maximum allowed length {limit} in a FunctionCall action"
252 ),
253 ActionsValidationError::FunctionCallArgumentsLengthExceeded { length, limit } => write!(
254 f,
255 "The length of the arguments {length} exceeds the maximum allowed length {limit} in a FunctionCall action"
256 ),
257 ActionsValidationError::UnsuitableStakingKey { public_key } => write!(
258 f,
259 "The staking key must be ristretto compatible ED25519 key. {public_key} is provided instead."
260 ),
261 ActionsValidationError::FunctionCallZeroAttachedGas => write!(
262 f,
263 "The attached amount of gas in a FunctionCall action has to be a positive number",
264 ),
265 }
266 }
267}
268
269impl std::error::Error for ActionsValidationError {}
270
271#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
273pub struct ActionError {
274 pub index: Option<u64>,
277 pub kind: ActionErrorKind,
279}
280
281#[derive(
282 Debug,
283 Clone,
284 PartialEq,
285 Eq,
286 BorshDeserialize,
287 BorshSerialize,
288 serde::Deserialize,
289 serde::Serialize,
290 strum::IntoStaticStr,
291)]
292pub enum HostError {
293 BadUTF16,
295 BadUTF8,
297 GasExceeded,
299 GasLimitExceeded,
301 BalanceExceeded,
303 EmptyMethodName,
305 GuestPanic { panic_msg: String },
307 IntegerOverflow,
309 InvalidPromiseIndex { promise_idx: u64 },
311 CannotAppendActionToJointPromise,
313 CannotReturnJointPromise,
315 InvalidPromiseResultIndex { result_idx: u64 },
317 InvalidRegisterId { register_id: u64 },
319 IteratorWasInvalidated { iterator_index: u64 },
321 MemoryAccessViolation,
323 InvalidReceiptIndex { receipt_index: u64 },
325 InvalidIteratorIndex { iterator_index: u64 },
327 InvalidAccountId,
329 InvalidMethodName,
331 InvalidPublicKey,
333 ProhibitedInView { method_name: String },
335 NumberOfLogsExceeded { limit: u64 },
337 KeyLengthExceeded { length: u64, limit: u64 },
339 ValueLengthExceeded { length: u64, limit: u64 },
341 TotalLogLengthExceeded { length: u64, limit: u64 },
343 NumberPromisesExceeded { number_of_promises: u64, limit: u64 },
345 NumberInputDataDependenciesExceeded {
347 number_of_input_data_dependencies: u64,
348 limit: u64,
349 },
350 ReturnedValueLengthExceeded { length: u64, limit: u64 },
352 ContractSizeExceeded { size: u64, limit: u64 },
354 Deprecated { method_name: String },
356 ECRecoverError { msg: String },
358 AltBn128InvalidInput { msg: String },
361 Ed25519VerifyInvalidInput { msg: String },
364}
365
366#[derive(
367 Debug,
368 Clone,
369 PartialEq,
370 Eq,
371 BorshDeserialize,
372 BorshSerialize,
373 serde::Deserialize,
374 serde::Serialize,
375 strum::IntoStaticStr,
376)]
377pub enum CompilationError {
378 CodeDoesNotExist {
379 account_id: AccountId,
380 },
381 PrepareError(PrepareError),
382 WasmerCompileError {
386 msg: String,
387 },
388}
389
390#[derive(
391 Debug,
392 Clone,
393 PartialEq,
394 Eq,
395 BorshDeserialize,
396 BorshSerialize,
397 serde::Deserialize,
398 serde::Serialize,
399 strum::IntoStaticStr,
400)]
401pub enum MethodResolveError {
402 MethodEmptyName,
403 MethodNotFound,
404 MethodInvalidSignature,
405}
406
407#[derive(
408 Debug,
409 Clone,
410 PartialEq,
411 Eq,
412 BorshDeserialize,
413 BorshSerialize,
414 serde::Deserialize,
415 serde::Serialize,
416)]
417pub enum PrepareError {
419 Serialization,
421 Deserialization,
423 InternalMemoryDeclared,
425 GasInstrumentation,
429 StackHeightInstrumentation,
433 Instantiate,
438 Memory,
440 TooManyFunctions,
442 TooManyLocals,
444}
445
446#[derive(
447 Debug,
448 Clone,
449 PartialEq,
450 Eq,
451 BorshDeserialize,
452 BorshSerialize,
453 serde::Serialize,
454 serde::Deserialize,
455)]
456pub enum FunctionCallError {
457 CompilationError(CompilationError),
459 LinkError {
463 msg: String,
464 },
465 MethodResolveError(MethodResolveError),
467 WasmUnknownError,
468 HostError(HostError),
470 _EVMError,
473 ExecutionError(String),
474}
475
476impl std::error::Error for ActionError {}
477
478#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
479pub enum ActionErrorKind {
480 AccountAlreadyExists { account_id: AccountId },
482 AccountDoesNotExist { account_id: AccountId },
484 CreateAccountOnlyByRegistrar {
486 account_id: AccountId,
487 registrar_account_id: AccountId,
488 predecessor_id: AccountId,
489 },
490 CreateAccountNotAllowed {
492 account_id: AccountId,
493 predecessor_id: AccountId,
494 },
495 ActorNoPermission {
498 account_id: AccountId,
499 actor_id: AccountId,
500 },
501 DeleteKeyDoesNotExist {
503 account_id: AccountId,
504 public_key: Ed25519PublicKey,
505 },
506 AddKeyAlreadyExists {
508 account_id: AccountId,
509 public_key: Ed25519PublicKey,
510 },
511 DeleteAccountStaking { account_id: AccountId },
513 LackBalanceForState {
515 account_id: AccountId,
517 #[serde(with = "dec_format")]
519 amount: Balance,
520 },
521 TriesToUnstake { account_id: AccountId },
523 TriesToStake {
525 account_id: AccountId,
526 #[serde(with = "dec_format")]
527 stake: Balance,
528 #[serde(with = "dec_format")]
529 locked: Balance,
530 #[serde(with = "dec_format")]
531 balance: Balance,
532 },
533 InsufficientStake {
534 account_id: AccountId,
535 #[serde(with = "dec_format")]
536 stake: Balance,
537 #[serde(with = "dec_format")]
538 minimum_stake: Balance,
539 },
540 FunctionCallError(FunctionCallError),
542 NewReceiptValidationError(ReceiptValidationError),
545 OnlyImplicitAccountCreationAllowed { account_id: AccountId },
549 DeleteAccountWithLargeState { account_id: AccountId },
551}
552
553impl From<ActionErrorKind> for ActionError {
554 fn from(e: ActionErrorKind) -> ActionError {
555 ActionError {
556 index: None,
557 kind: e,
558 }
559 }
560}
561
562impl Display for InvalidTxError {
563 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
564 match self {
565 InvalidTxError::InvalidSignerId { signer_id } => {
566 write!(
567 f,
568 "Invalid signer account ID {signer_id:?} according to requirements"
569 )
570 }
571 InvalidTxError::SignerDoesNotExist { signer_id } => {
572 write!(f, "Signer {signer_id:?} does not exist")
573 }
574 InvalidTxError::InvalidAccessKeyError(access_key_error) => {
575 Display::fmt(&access_key_error, f)
576 }
577 InvalidTxError::InvalidNonce { tx_nonce, ak_nonce } => write!(
578 f,
579 "Transaction nonce {tx_nonce} must be larger than nonce of the used access key {ak_nonce}"
580 ),
581 InvalidTxError::InvalidReceiverId { receiver_id } => {
582 write!(
583 f,
584 "Invalid receiver account ID {receiver_id:?} according to requirements"
585 )
586 }
587 InvalidTxError::InvalidSignature => {
588 write!(f, "Transaction is not signed with the given public key")
589 }
590 InvalidTxError::NotEnoughBalance {
591 signer_id,
592 balance,
593 cost,
594 } => write!(
595 f,
596 "Sender {signer_id:?} does not have enough balance {balance} for operation costing {cost}"
597 ),
598 InvalidTxError::LackBalanceForState { signer_id, amount } => {
599 write!(f, "Failed to execute, because the account {signer_id:?} wouldn't have enough balance to cover storage, required to have {amount} yoctoNEAR more")
600 }
601 InvalidTxError::CostOverflow => {
602 write!(f, "Transaction gas or balance cost is too high")
603 }
604 InvalidTxError::InvalidChain => {
605 write!(
606 f,
607 "Transaction parent block hash doesn't belong to the current chain"
608 )
609 }
610 InvalidTxError::Expired => {
611 write!(f, "Transaction has expired")
612 }
613 InvalidTxError::ActionsValidation(error) => {
614 write!(f, "Transaction actions validation error: {error}")
615 }
616 InvalidTxError::NonceTooLarge {
617 tx_nonce,
618 upper_bound,
619 } => {
620 write!(
621 f,
622 "Transaction nonce {tx_nonce} must be smaller than the access key nonce upper bound {upper_bound}"
623 )
624 }
625 InvalidTxError::TransactionSizeExceeded { size, limit } => {
626 write!(
627 f,
628 "Size of serialized transaction {size} exceeded the limit {limit}"
629 )
630 }
631 }
632 }
633}
634
635impl From<InvalidAccessKeyError> for InvalidTxError {
636 fn from(error: InvalidAccessKeyError) -> Self {
637 InvalidTxError::InvalidAccessKeyError(error)
638 }
639}
640
641impl Display for InvalidAccessKeyError {
642 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
643 match self {
644 InvalidAccessKeyError::AccessKeyNotFound {
645 account_id,
646 public_key,
647 } => write!(
648 f,
649 "Signer {account_id:?} doesn't have access key with the given public_key {public_key}"
650 ),
651 InvalidAccessKeyError::ReceiverMismatch {
652 tx_receiver,
653 ak_receiver,
654 } => write!(
655 f,
656 "Transaction receiver_id {tx_receiver:?} doesn't match the access key receiver_id {ak_receiver:?}",
657 ),
658 InvalidAccessKeyError::MethodNameMismatch { method_name } => write!(
659 f,
660 "Transaction method name {method_name:?} isn't allowed by the access key"
661 ),
662 InvalidAccessKeyError::RequiresFullAccess => {
663 write!(f, "Invalid access key type. Full-access keys are required for transactions that have multiple or non-function-call actions")
664 }
665 InvalidAccessKeyError::NotEnoughAllowance {
666 account_id,
667 public_key,
668 allowance,
669 cost,
670 } => write!(
671 f,
672 "Access Key {account_id:?}:{public_key} does not have enough balance {allowance} for transaction costing {cost}"
673 ),
674 InvalidAccessKeyError::DepositWithFunctionCall => {
675 write!(f, "Having a deposit with a function call action is not allowed with a function call access key.")
676 }
677 }
678 }
679}
680
681impl std::error::Error for InvalidAccessKeyError {}
682
683impl Display for ActionError {
684 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
685 write!(
686 f,
687 "Action #{}: {}",
688 self.index.unwrap_or_default(),
689 self.kind
690 )
691 }
692}
693
694impl Display for ActionErrorKind {
695 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
696 match self {
697 ActionErrorKind::AccountAlreadyExists { account_id } => {
698 write!(f, "Can't create a new account {account_id:?}, because it already exists")
699 }
700 ActionErrorKind::AccountDoesNotExist { account_id } => write!(
701 f,
702 "Can't complete the action because account {account_id:?} doesn't exist"
703 ),
704 ActionErrorKind::ActorNoPermission { actor_id, account_id } => write!(
705 f,
706 "Actor {actor_id:?} doesn't have permission to account {account_id:?} to complete the action"
707 ),
708 ActionErrorKind::LackBalanceForState { account_id, amount } => write!(
709 f,
710 "The account {account_id} wouldn't have enough balance to cover storage, required to have {amount} yoctoNEAR more"
711 ),
712 ActionErrorKind::TriesToUnstake { account_id } => {
713 write!(f, "Account {account_id:?} is not yet staked, but tries to unstake")
714 }
715 ActionErrorKind::TriesToStake { account_id, stake, locked, balance } => write!(
716 f,
717 "Account {account_id:?} tries to stake {stake}, but has staked {locked} and only has {balance}"
718 ),
719 ActionErrorKind::CreateAccountOnlyByRegistrar { account_id, registrar_account_id, predecessor_id } => write!(
720 f,
721 "A top-level account ID {account_id:?} can't be created by {predecessor_id:?}, short top-level account IDs can only be created by {registrar_account_id:?}"
722 ),
723 ActionErrorKind::CreateAccountNotAllowed { account_id, predecessor_id } => write!(
724 f,
725 "A sub-account ID {account_id:?} can't be created by account {predecessor_id:?}"
726 ),
727 ActionErrorKind::DeleteKeyDoesNotExist { account_id, .. } => write!(
728 f,
729 "Account {account_id:?} tries to remove an access key that doesn't exist"
730 ),
731 ActionErrorKind::AddKeyAlreadyExists { public_key, .. } => write!(
732 f,
733 "The public key {public_key:?} is already used for an existing access key"
734 ),
735 ActionErrorKind::DeleteAccountStaking { account_id } => {
736 write!(f, "Account {account_id:?} is staking and can not be deleted")
737 }
738 ActionErrorKind::FunctionCallError(s) => write!(f, "{s:?}"),
739 ActionErrorKind::NewReceiptValidationError(e) => {
740 write!(f, "An new action receipt created during a FunctionCall is not valid: {e}")
741 }
742 ActionErrorKind::InsufficientStake { account_id, stake, minimum_stake } => write!(f, "Account {account_id} tries to stake {stake} but minimum required stake is {minimum_stake}"),
743 ActionErrorKind::OnlyImplicitAccountCreationAllowed { account_id } => write!(f, "CreateAccount action is called on hex-characters account of length 64 {account_id}"),
744 ActionErrorKind::DeleteAccountWithLargeState { account_id } => write!(f, "The state of account {account_id} is too large and therefore cannot be deleted"),
745 }
746 }
747}