near_client/near_primitives_light/
errors.rs

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/// Container for TxExecutionError, when error comes not from TransactionOutcome
12#[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/// Error returned in the ExecutionOutcome in case of failure
19#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
20pub enum TxExecutionError {
21    /// An error happened during Action execution
22    ActionError(ActionError),
23    /// An error happened during Transaction execution
24    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/// An error happened during TX execution
51#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
52pub enum InvalidTxError {
53    /// Happens if a wrong AccessKey used or AccessKey has not enough permissions
54    InvalidAccessKeyError(InvalidAccessKeyError),
55    /// TX signer_id is not a valid [`AccountId`]
56    InvalidSignerId { signer_id: String },
57    /// TX signer_id is not found in a storage
58    SignerDoesNotExist { signer_id: AccountId },
59    /// Transaction nonce must be `account[access_key].nonce + 1`.
60    InvalidNonce { tx_nonce: Nonce, ak_nonce: Nonce },
61    /// Transaction nonce is larger than the upper bound given by the block height
62    NonceTooLarge { tx_nonce: Nonce, upper_bound: Nonce },
63    /// TX receiver_id is not a valid AccountId
64    InvalidReceiverId { receiver_id: String },
65    /// TX signature is not valid
66    InvalidSignature,
67    /// Account does not have enough balance to cover TX cost
68    NotEnoughBalance {
69        signer_id: AccountId,
70        #[serde(with = "dec_format")]
71        balance: Balance,
72        #[serde(with = "dec_format")]
73        cost: Balance,
74    },
75    /// Signer account doesn't have enough balance after transaction.
76    LackBalanceForState {
77        /// An account which doesn't have enough balance to cover storage.
78        signer_id: AccountId,
79        /// Required balance to cover the state.
80        #[serde(with = "dec_format")]
81        amount: Balance,
82    },
83    /// An integer overflow occurred during transaction cost estimation.
84    CostOverflow,
85    /// Transaction parent block hash doesn't belong to the current chain
86    InvalidChain,
87    /// Transaction has expired
88    Expired,
89    /// An error occurred while validating actions of a Transaction.
90    ActionsValidation(ActionsValidationError),
91    /// The size of serialized transaction exceeded the limit.
92    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    /// The access key identified by the `public_key` doesn't exist for the account
100    AccessKeyNotFound {
101        account_id: AccountId,
102        public_key: Ed25519PublicKey,
103    },
104    /// Transaction `receiver_id` doesn't match the access key receiver_id
105    ReceiverMismatch {
106        tx_receiver: AccountId,
107        ak_receiver: String,
108    },
109    /// Transaction method name isn't allowed by the access key
110    MethodNameMismatch { method_name: String },
111    /// Transaction requires a full permission access key.
112    RequiresFullAccess,
113    /// Access Key does not have enough allowance to cover transaction cost
114    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    /// Having a deposit with a function call action is not allowed with a function call access key.
123    DepositWithFunctionCall,
124}
125
126/// Describes the error for validating a list of actions.
127#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
128pub enum ActionsValidationError {
129    /// The delete action must be a final aciton in transaction
130    DeleteActionMustBeFinal,
131    /// The total prepaid gas (for all given actions) exceeded the limit.
132    TotalPrepaidGasExceeded { total_prepaid_gas: Gas, limit: Gas },
133    /// The number of actions exceeded the given limit.
134    TotalNumberOfActionsExceeded {
135        total_number_of_actions: u64,
136        limit: u64,
137    },
138    /// The total number of bytes of the method names exceeded the limit in a Add Key action.
139    AddKeyMethodNamesNumberOfBytesExceeded {
140        total_number_of_bytes: u64,
141        limit: u64,
142    },
143    /// The length of some method name exceeded the limit in a Add Key action.
144    AddKeyMethodNameLengthExceeded { length: u64, limit: u64 },
145    /// Integer overflow during a compute.
146    IntegerOverflow,
147    /// Invalid account ID.
148    InvalidAccountId { account_id: String },
149    /// The size of the contract code exceeded the limit in a DeployContract action.
150    ContractSizeExceeded { size: u64, limit: u64 },
151    /// The length of the method name exceeded the limit in a Function Call action.
152    FunctionCallMethodNameLengthExceeded { length: u64, limit: u64 },
153    /// The length of the arguments exceeded the limit in a Function Call action.
154    FunctionCallArgumentsLengthExceeded { length: u64, limit: u64 },
155    /// An attempt to stake with a public key that is not convertible to ristretto.
156    UnsuitableStakingKey { public_key: Ed25519PublicKey },
157    /// The attached amount of gas in a FunctionCall action has to be a positive number.
158    FunctionCallZeroAttachedGas,
159}
160
161/// Describes the error for validating a receipt.
162#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
163pub enum ReceiptValidationError {
164    /// The `predecessor_id` of a Receipt is not valid.
165    InvalidPredecessorId { account_id: String },
166    /// The `receiver_id` of a Receipt is not valid.
167    InvalidReceiverId { account_id: String },
168    /// The `signer_id` of an ActionReceipt is not valid.
169    InvalidSignerId { account_id: String },
170    /// The `receiver_id` of a DataReceiver within an ActionReceipt is not valid.
171    InvalidDataReceiverId { account_id: String },
172    /// The length of the returned data exceeded the limit in a DataReceipt.
173    ReturnedValueLengthExceeded { length: u64, limit: u64 },
174    /// The number of input data dependencies exceeds the limit in an ActionReceipt.
175    NumberInputDataDependenciesExceeded {
176        number_of_input_data_dependencies: u64,
177        limit: u64,
178    },
179    /// An error occurred while validating actions of an ActionReceipt.
180    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/// An error happened during Action execution
272#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
273pub struct ActionError {
274    /// Index of the failed action in the transaction.
275    /// Action index is not defined if ActionError.kind is `ActionErrorKind::LackBalanceForState`
276    pub index: Option<u64>,
277    /// The kind of ActionError happened
278    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    /// String encoding is bad UTF-16 sequence
294    BadUTF16,
295    /// String encoding is bad UTF-8 sequence
296    BadUTF8,
297    /// Exceeded the prepaid gas
298    GasExceeded,
299    /// Exceeded the maximum amount of gas allowed to burn per contract
300    GasLimitExceeded,
301    /// Exceeded the account balance
302    BalanceExceeded,
303    /// Tried to call an empty method name
304    EmptyMethodName,
305    /// Smart contract panicked
306    GuestPanic { panic_msg: String },
307    /// IntegerOverflow happened during a contract execution
308    IntegerOverflow,
309    /// `promise_idx` does not correspond to existing promises
310    InvalidPromiseIndex { promise_idx: u64 },
311    /// Actions can only be appended to non-joint promise.
312    CannotAppendActionToJointPromise,
313    /// Returning joint promise is currently prohibited
314    CannotReturnJointPromise,
315    /// Accessed invalid promise result index
316    InvalidPromiseResultIndex { result_idx: u64 },
317    /// Accessed invalid register id
318    InvalidRegisterId { register_id: u64 },
319    /// Iterator `iterator_index` was invalidated after its creation by performing a mutable operation on trie
320    IteratorWasInvalidated { iterator_index: u64 },
321    /// Accessed memory outside the bounds
322    MemoryAccessViolation,
323    /// VM Logic returned an invalid receipt index
324    InvalidReceiptIndex { receipt_index: u64 },
325    /// Iterator index `iterator_index` does not exist
326    InvalidIteratorIndex { iterator_index: u64 },
327    /// VM Logic returned an invalid account id
328    InvalidAccountId,
329    /// VM Logic returned an invalid method name
330    InvalidMethodName,
331    /// VM Logic provided an invalid public key
332    InvalidPublicKey,
333    /// `method_name` is not allowed in view calls
334    ProhibitedInView { method_name: String },
335    /// The total number of logs will exceed the limit.
336    NumberOfLogsExceeded { limit: u64 },
337    /// The storage key length exceeded the limit.
338    KeyLengthExceeded { length: u64, limit: u64 },
339    /// The storage value length exceeded the limit.
340    ValueLengthExceeded { length: u64, limit: u64 },
341    /// The total log length exceeded the limit.
342    TotalLogLengthExceeded { length: u64, limit: u64 },
343    /// The maximum number of promises within a FunctionCall exceeded the limit.
344    NumberPromisesExceeded { number_of_promises: u64, limit: u64 },
345    /// The maximum number of input data dependencies exceeded the limit.
346    NumberInputDataDependenciesExceeded {
347        number_of_input_data_dependencies: u64,
348        limit: u64,
349    },
350    /// The returned value length exceeded the limit.
351    ReturnedValueLengthExceeded { length: u64, limit: u64 },
352    /// The contract size for DeployContract action exceeded the limit.
353    ContractSizeExceeded { size: u64, limit: u64 },
354    /// The host function was deprecated.
355    Deprecated { method_name: String },
356    /// General errors for ECDSA recover.
357    ECRecoverError { msg: String },
358    /// Invalid input to alt_bn128 family of functions (e.g., point which isn't
359    /// on the curve).
360    AltBn128InvalidInput { msg: String },
361    /// Invalid input to ed25519 signature verification function (e.g. signature cannot be
362    /// derived from bytes).
363    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    /// This is for defense in depth.
383    /// We expect our runtime-independent preparation code to fully catch all invalid wasms,
384    /// but, if it ever misses something we’ll emit this error
385    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)]
417/// Error that can occur while preparing or executing Wasm smart-contract.
418pub enum PrepareError {
419    /// Error happened while serializing the module.
420    Serialization,
421    /// Error happened while deserializing the module.
422    Deserialization,
423    /// Internal memory declaration has been found in the module.
424    InternalMemoryDeclared,
425    /// Gas instrumentation failed.
426    ///
427    /// This most likely indicates the module isn't valid.
428    GasInstrumentation,
429    /// Stack instrumentation failed.
430    ///
431    /// This  most likely indicates the module isn't valid.
432    StackHeightInstrumentation,
433    /// Error happened during instantiation.
434    ///
435    /// This might indicate that `start` function trapped, or module isn't
436    /// instantiable and/or unlinkable.
437    Instantiate,
438    /// Error creating memory.
439    Memory,
440    /// Contract contains too many functions.
441    TooManyFunctions,
442    /// Contract contains too many locals.
443    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    /// Wasm compilation error
458    CompilationError(CompilationError),
459    /// Wasm binary env link error
460    ///
461    /// Note: this is only to deserialize old data, use execution error for new data
462    LinkError {
463        msg: String,
464    },
465    /// Import/export resolve error
466    MethodResolveError(MethodResolveError),
467    WasmUnknownError,
468    /// Note: this is only to deserialize old data, use execution error for new data
469    HostError(HostError),
470    // Unused, can be reused by a future error but must be exactly one error to keep ExecutionError
471    // error borsh serialized at correct index
472    _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    /// Happens when CreateAccount action tries to create an account with account_id which is already exists in the storage
481    AccountAlreadyExists { account_id: AccountId },
482    /// Happens when TX receiver_id doesn't exist (but action is not Action::CreateAccount)
483    AccountDoesNotExist { account_id: AccountId },
484    /// A top-level account ID can only be created by registrar.
485    CreateAccountOnlyByRegistrar {
486        account_id: AccountId,
487        registrar_account_id: AccountId,
488        predecessor_id: AccountId,
489    },
490    /// A newly created account must be under a namespace of the creator account
491    CreateAccountNotAllowed {
492        account_id: AccountId,
493        predecessor_id: AccountId,
494    },
495    /// Administrative actions like `DeployContract`, `Stake`, `AddKey`, `DeleteKey`. can be proceed only if sender=receiver
496    /// or the first TX action is a `CreateAccount` action
497    ActorNoPermission {
498        account_id: AccountId,
499        actor_id: AccountId,
500    },
501    /// Account tries to remove an access key that doesn't exist
502    DeleteKeyDoesNotExist {
503        account_id: AccountId,
504        public_key: Ed25519PublicKey,
505    },
506    /// The public key is already used for an existing access key
507    AddKeyAlreadyExists {
508        account_id: AccountId,
509        public_key: Ed25519PublicKey,
510    },
511    /// Account is staking and can not be deleted
512    DeleteAccountStaking { account_id: AccountId },
513    /// ActionReceipt can't be completed, because the remaining balance will not be enough to cover storage.
514    LackBalanceForState {
515        /// An account which needs balance
516        account_id: AccountId,
517        /// Balance required to complete an action.
518        #[serde(with = "dec_format")]
519        amount: Balance,
520    },
521    /// Account is not yet staked, but tries to unstake
522    TriesToUnstake { account_id: AccountId },
523    /// The account doesn't have enough balance to increase the stake.
524    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    /// An error occurred during a `FunctionCall` Action, parameter is debug message.
541    FunctionCallError(FunctionCallError),
542    /// Error occurs when a new `ActionReceipt` created by the `FunctionCall` action fails
543    /// receipt validation.
544    NewReceiptValidationError(ReceiptValidationError),
545    /// Error occurs when a `CreateAccount` action is called on hex-characters
546    /// account of length 64.  See implicit account creation NEP:
547    /// <https://github.com/nearprotocol/NEPs/pull/71>.
548    OnlyImplicitAccountCreationAllowed { account_id: AccountId },
549    /// Delete account whose state is large is temporarily banned.
550    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}