near_primitives/
errors.rs

1use crate::hash::CryptoHash;
2use crate::serialize::dec_format;
3use crate::shard_layout::ShardLayoutError;
4use crate::sharding::ChunkHash;
5use crate::types::{AccountId, Balance, EpochId, Gas, Nonce};
6use borsh::{BorshDeserialize, BorshSerialize};
7use near_crypto::PublicKey;
8use near_primitives_core::types::ProtocolVersion;
9use near_schema_checker_lib::ProtocolSchema;
10use std::fmt::{Debug, Display};
11
12/// Error returned in the ExecutionOutcome in case of failure
13#[derive(
14    BorshSerialize,
15    BorshDeserialize,
16    Debug,
17    Clone,
18    PartialEq,
19    Eq,
20    serde::Deserialize,
21    serde::Serialize,
22    ProtocolSchema,
23)]
24pub enum TxExecutionError {
25    /// An error happened during Action execution
26    ActionError(ActionError),
27    /// An error happened during Transaction execution
28    InvalidTxError(InvalidTxError),
29}
30
31impl std::error::Error for TxExecutionError {}
32
33impl Display for TxExecutionError {
34    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
35        match self {
36            TxExecutionError::ActionError(e) => write!(f, "{}", e),
37            TxExecutionError::InvalidTxError(e) => write!(f, "{}", e),
38        }
39    }
40}
41
42impl From<ActionError> for TxExecutionError {
43    fn from(error: ActionError) -> Self {
44        TxExecutionError::ActionError(error)
45    }
46}
47
48impl From<InvalidTxError> for TxExecutionError {
49    fn from(error: InvalidTxError) -> Self {
50        TxExecutionError::InvalidTxError(error)
51    }
52}
53
54/// Error returned from `Runtime::apply`
55#[derive(Debug, Clone, PartialEq, Eq)]
56pub enum RuntimeError {
57    /// An unexpected integer overflow occurred. The likely issue is an invalid state or the transition.
58    UnexpectedIntegerOverflow(String),
59    /// An error happened during TX verification and account charging. It's likely the chunk is invalid.
60    /// and should be challenged.
61    InvalidTxError(InvalidTxError),
62    /// Unexpected error which is typically related to the node storage corruption.
63    /// It's possible the input state is invalid or malicious.
64    StorageError(StorageError),
65    /// An error happens if `check_balance` fails, which is likely an indication of an invalid state.
66    BalanceMismatchError(Box<BalanceMismatchError>),
67    /// The incoming receipt didn't pass the validation, it's likely a malicious behaviour.
68    ReceiptValidationError(ReceiptValidationError),
69    /// Error when accessing validator information. Happens inside epoch manager.
70    ValidatorError(EpochError),
71}
72
73impl std::fmt::Display for RuntimeError {
74    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
75        f.write_str(&format!("{:?}", self))
76    }
77}
78
79impl std::error::Error for RuntimeError {}
80
81/// Contexts in which `StorageError::MissingTrieValue` error might occur.
82#[derive(
83    Debug,
84    Clone,
85    PartialEq,
86    Eq,
87    serde::Deserialize,
88    serde::Serialize,
89    BorshSerialize,
90    BorshDeserialize,
91    ProtocolSchema,
92)]
93pub enum MissingTrieValueContext {
94    /// Missing trie value when reading from TrieIterator.
95    TrieIterator,
96    /// Missing trie value when reading from TriePrefetchingStorage.
97    TriePrefetchingStorage,
98    /// Missing trie value when reading from TrieMemoryPartialStorage.
99    TrieMemoryPartialStorage,
100    /// Missing trie value when reading from TrieStorage.
101    TrieStorage,
102}
103
104impl MissingTrieValueContext {
105    pub fn metrics_label(&self) -> &str {
106        match self {
107            Self::TrieIterator => "trie_iterator",
108            Self::TriePrefetchingStorage => "trie_prefetching_storage",
109            Self::TrieMemoryPartialStorage => "trie_memory_partial_storage",
110            Self::TrieStorage => "trie_storage",
111        }
112    }
113}
114
115/// Errors which may occur during working with trie storages, storing
116/// trie values (trie nodes and state values) by their hashes.
117#[derive(
118    Debug,
119    Clone,
120    PartialEq,
121    Eq,
122    serde::Deserialize,
123    serde::Serialize,
124    BorshSerialize,
125    BorshDeserialize,
126    ProtocolSchema,
127)]
128pub enum StorageError {
129    /// Key-value db internal failure
130    StorageInternalError,
131    /// Requested trie value by its hash which is missing in storage.
132    MissingTrieValue(MissingTrieValueContext, CryptoHash),
133    /// Found trie node which shouldn't be part of state. Raised during
134    /// validation of state sync parts where incorrect node was passed.
135    /// TODO (#8997): consider including hash of trie node.
136    UnexpectedTrieValue,
137    /// Either invalid state or key-value db is corrupted.
138    /// For PartialStorage it cannot be corrupted.
139    /// Error message is unreliable and for debugging purposes only. It's also probably ok to
140    /// panic in every place that produces this error.
141    /// We can check if db is corrupted by verifying everything in the state trie.
142    StorageInconsistentState(String),
143    /// Flat storage error, meaning that it doesn't support some block anymore.
144    /// We guarantee that such block cannot become final, thus block processing
145    /// must resume normally.
146    FlatStorageBlockNotSupported(String),
147    /// In-memory trie could not be loaded for some reason.
148    MemTrieLoadingError(String),
149    /// Indicates that a resharding operation on flat storage is already in progress,
150    /// when it wasn't expected to be so.
151    FlatStorageReshardingAlreadyInProgress,
152}
153
154impl std::fmt::Display for StorageError {
155    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
156        f.write_str(&format!("{:?}", self))
157    }
158}
159
160impl std::error::Error for StorageError {}
161
162/// An error happened during TX execution
163#[derive(
164    BorshSerialize,
165    BorshDeserialize,
166    Debug,
167    Clone,
168    PartialEq,
169    Eq,
170    serde::Deserialize,
171    serde::Serialize,
172    ProtocolSchema,
173)]
174pub enum InvalidTxError {
175    /// Happens if a wrong AccessKey used or AccessKey has not enough permissions
176    InvalidAccessKeyError(InvalidAccessKeyError),
177    /// TX signer_id is not a valid [`AccountId`]
178    InvalidSignerId {
179        signer_id: String,
180    },
181    /// TX signer_id is not found in a storage
182    SignerDoesNotExist {
183        signer_id: AccountId,
184    },
185    /// Transaction nonce must be `account[access_key].nonce + 1`.
186    InvalidNonce {
187        tx_nonce: Nonce,
188        ak_nonce: Nonce,
189    },
190    /// Transaction nonce is larger than the upper bound given by the block height
191    NonceTooLarge {
192        tx_nonce: Nonce,
193        upper_bound: Nonce,
194    },
195    /// TX receiver_id is not a valid AccountId
196    InvalidReceiverId {
197        receiver_id: String,
198    },
199    /// TX signature is not valid
200    InvalidSignature,
201    /// Account does not have enough balance to cover TX cost
202    NotEnoughBalance {
203        signer_id: AccountId,
204        #[serde(with = "dec_format")]
205        balance: Balance,
206        #[serde(with = "dec_format")]
207        cost: Balance,
208    },
209    /// Signer account doesn't have enough balance after transaction.
210    LackBalanceForState {
211        /// An account which doesn't have enough balance to cover storage.
212        signer_id: AccountId,
213        /// Required balance to cover the state.
214        #[serde(with = "dec_format")]
215        amount: Balance,
216    },
217    /// An integer overflow occurred during transaction cost estimation.
218    CostOverflow,
219    /// Transaction parent block hash doesn't belong to the current chain
220    InvalidChain,
221    /// Transaction has expired
222    Expired,
223    /// An error occurred while validating actions of a Transaction.
224    ActionsValidation(ActionsValidationError),
225    /// The size of serialized transaction exceeded the limit.
226    TransactionSizeExceeded {
227        size: u64,
228        limit: u64,
229    },
230    /// Transaction version is invalid.
231    InvalidTransactionVersion,
232    // Error occurred during storage access
233    StorageError(StorageError),
234    /// The receiver shard of the transaction is too congested to accept new
235    /// transactions at the moment.
236    ShardCongested {
237        /// The congested shard.
238        shard_id: u32,
239        /// A value between 0 (no congestion) and 1 (max congestion).
240        congestion_level: ordered_float::NotNan<f64>,
241    },
242    /// The receiver shard of the transaction missed several chunks and rejects
243    /// new transaction until it can make progress again.
244    ShardStuck {
245        /// The shard that fails making progress.
246        shard_id: u32,
247        /// The number of blocks since the last included chunk of the shard.
248        missed_chunks: u64,
249    },
250}
251
252impl From<StorageError> for InvalidTxError {
253    fn from(error: StorageError) -> Self {
254        InvalidTxError::StorageError(error)
255    }
256}
257
258impl std::error::Error for InvalidTxError {}
259
260#[derive(
261    BorshSerialize,
262    BorshDeserialize,
263    Debug,
264    Clone,
265    PartialEq,
266    Eq,
267    serde::Deserialize,
268    serde::Serialize,
269    ProtocolSchema,
270)]
271pub enum InvalidAccessKeyError {
272    /// The access key identified by the `public_key` doesn't exist for the account
273    AccessKeyNotFound { account_id: AccountId, public_key: Box<PublicKey> },
274    /// Transaction `receiver_id` doesn't match the access key receiver_id
275    ReceiverMismatch { tx_receiver: AccountId, ak_receiver: String },
276    /// Transaction method name isn't allowed by the access key
277    MethodNameMismatch { method_name: String },
278    /// Transaction requires a full permission access key.
279    RequiresFullAccess,
280    /// Access Key does not have enough allowance to cover transaction cost
281    NotEnoughAllowance {
282        account_id: AccountId,
283        public_key: Box<PublicKey>,
284        #[serde(with = "dec_format")]
285        allowance: Balance,
286        #[serde(with = "dec_format")]
287        cost: Balance,
288    },
289    /// Having a deposit with a function call action is not allowed with a function call access key.
290    DepositWithFunctionCall,
291}
292
293/// Describes the error for validating a list of actions.
294#[derive(
295    BorshSerialize,
296    BorshDeserialize,
297    Debug,
298    Clone,
299    PartialEq,
300    Eq,
301    serde::Serialize,
302    serde::Deserialize,
303    ProtocolSchema,
304)]
305pub enum ActionsValidationError {
306    /// The delete action must be a final aciton in transaction
307    DeleteActionMustBeFinal,
308    /// The total prepaid gas (for all given actions) exceeded the limit.
309    TotalPrepaidGasExceeded { total_prepaid_gas: Gas, limit: Gas },
310    /// The number of actions exceeded the given limit.
311    TotalNumberOfActionsExceeded { total_number_of_actions: u64, limit: u64 },
312    /// The total number of bytes of the method names exceeded the limit in a Add Key action.
313    AddKeyMethodNamesNumberOfBytesExceeded { total_number_of_bytes: u64, limit: u64 },
314    /// The length of some method name exceeded the limit in a Add Key action.
315    AddKeyMethodNameLengthExceeded { length: u64, limit: u64 },
316    /// Integer overflow during a compute.
317    IntegerOverflow,
318    /// Invalid account ID.
319    InvalidAccountId { account_id: String },
320    /// The size of the contract code exceeded the limit in a DeployContract action.
321    ContractSizeExceeded { size: u64, limit: u64 },
322    /// The length of the method name exceeded the limit in a Function Call action.
323    FunctionCallMethodNameLengthExceeded { length: u64, limit: u64 },
324    /// The length of the arguments exceeded the limit in a Function Call action.
325    FunctionCallArgumentsLengthExceeded { length: u64, limit: u64 },
326    /// An attempt to stake with a public key that is not convertible to ristretto.
327    UnsuitableStakingKey { public_key: Box<PublicKey> },
328    /// The attached amount of gas in a FunctionCall action has to be a positive number.
329    FunctionCallZeroAttachedGas,
330    /// There should be the only one DelegateAction
331    DelegateActionMustBeOnlyOne,
332    /// The transaction includes a feature that the current protocol version
333    /// does not support.
334    ///
335    /// Note: we stringify the protocol feature name instead of using
336    /// `ProtocolFeature` here because we don't want to leak the internals of
337    /// that type into observable borsh serialization.
338    UnsupportedProtocolFeature { protocol_feature: String, version: ProtocolVersion },
339}
340
341/// Describes the error for validating a receipt.
342#[derive(
343    BorshSerialize,
344    BorshDeserialize,
345    Debug,
346    Clone,
347    PartialEq,
348    Eq,
349    serde::Serialize,
350    serde::Deserialize,
351    ProtocolSchema,
352)]
353pub enum ReceiptValidationError {
354    /// The `predecessor_id` of a Receipt is not valid.
355    InvalidPredecessorId { account_id: String },
356    /// The `receiver_id` of a Receipt is not valid.
357    InvalidReceiverId { account_id: String },
358    /// The `signer_id` of an ActionReceipt is not valid.
359    InvalidSignerId { account_id: String },
360    /// The `receiver_id` of a DataReceiver within an ActionReceipt is not valid.
361    InvalidDataReceiverId { account_id: String },
362    /// The length of the returned data exceeded the limit in a DataReceipt.
363    ReturnedValueLengthExceeded { length: u64, limit: u64 },
364    /// The number of input data dependencies exceeds the limit in an ActionReceipt.
365    NumberInputDataDependenciesExceeded { number_of_input_data_dependencies: u64, limit: u64 },
366    /// An error occurred while validating actions of an ActionReceipt.
367    ActionsValidation(ActionsValidationError),
368    /// Receipt is bigger than the limit.
369    ReceiptSizeExceeded { size: u64, limit: u64 },
370}
371
372impl Display for ReceiptValidationError {
373    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
374        match self {
375            ReceiptValidationError::InvalidPredecessorId { account_id } => {
376                write!(f, "The predecessor_id `{}` of a Receipt is not valid.", account_id)
377            }
378            ReceiptValidationError::InvalidReceiverId { account_id } => {
379                write!(f, "The receiver_id `{}` of a Receipt is not valid.", account_id)
380            }
381            ReceiptValidationError::InvalidSignerId { account_id } => {
382                write!(f, "The signer_id `{}` of an ActionReceipt is not valid.", account_id)
383            }
384            ReceiptValidationError::InvalidDataReceiverId { account_id } => write!(
385                f,
386                "The receiver_id `{}` of a DataReceiver within an ActionReceipt is not valid.",
387                account_id
388            ),
389            ReceiptValidationError::ReturnedValueLengthExceeded { length, limit } => write!(
390                f,
391                "The length of the returned data {} exceeded the limit {} in a DataReceipt",
392                length, limit
393            ),
394            ReceiptValidationError::NumberInputDataDependenciesExceeded { number_of_input_data_dependencies, limit } => write!(
395                f,
396                "The number of input data dependencies {} exceeded the limit {} in an ActionReceipt",
397                number_of_input_data_dependencies, limit
398            ),
399            ReceiptValidationError::ActionsValidation(e) => write!(f, "{}", e),
400            ReceiptValidationError::ReceiptSizeExceeded { size, limit } => write!(
401                f,
402                "The size of the receipt exceeded the limit: {} > {}",
403                size, limit
404            ),
405        }
406    }
407}
408
409impl std::error::Error for ReceiptValidationError {}
410
411impl Display for ActionsValidationError {
412    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
413        match self {
414            ActionsValidationError::DeleteActionMustBeFinal => {
415                write!(f, "The delete action must be the last action in transaction")
416            }
417            ActionsValidationError::TotalPrepaidGasExceeded { total_prepaid_gas, limit } => {
418                write!(f, "The total prepaid gas {} exceeds the limit {}", total_prepaid_gas, limit)
419            }
420            ActionsValidationError::TotalNumberOfActionsExceeded {total_number_of_actions, limit } => {
421                write!(
422                    f,
423                    "The total number of actions {} exceeds the limit {}",
424                    total_number_of_actions, limit
425                )
426            }
427            ActionsValidationError::AddKeyMethodNamesNumberOfBytesExceeded { total_number_of_bytes, limit } => write!(
428                f,
429                "The total number of bytes in allowed method names {} exceeds the maximum allowed number {} in a AddKey action",
430                total_number_of_bytes, limit
431            ),
432            ActionsValidationError::AddKeyMethodNameLengthExceeded { length, limit } => write!(
433                f,
434                "The length of some method name {} exceeds the maximum allowed length {} in a AddKey action",
435                length, limit
436            ),
437            ActionsValidationError::IntegerOverflow => write!(
438                f,
439                "Integer overflow during a compute",
440            ),
441            ActionsValidationError::InvalidAccountId { account_id } => write!(
442                f,
443                "Invalid account ID `{}`",
444                account_id
445            ),
446            ActionsValidationError::ContractSizeExceeded { size, limit } => write!(
447                f,
448                "The length of the contract size {} exceeds the maximum allowed size {} in a DeployContract action",
449                size, limit
450            ),
451            ActionsValidationError::FunctionCallMethodNameLengthExceeded { length, limit } => write!(
452                f,
453                "The length of the method name {} exceeds the maximum allowed length {} in a FunctionCall action",
454                length, limit
455            ),
456            ActionsValidationError::FunctionCallArgumentsLengthExceeded { length, limit } => write!(
457                f,
458                "The length of the arguments {} exceeds the maximum allowed length {} in a FunctionCall action",
459                length, limit
460            ),
461            ActionsValidationError::UnsuitableStakingKey { public_key } => write!(
462                f,
463                "The staking key must be ristretto compatible ED25519 key. {} is provided instead.",
464                public_key,
465            ),
466            ActionsValidationError::FunctionCallZeroAttachedGas => write!(
467                f,
468                "The attached amount of gas in a FunctionCall action has to be a positive number",
469            ),
470            ActionsValidationError::DelegateActionMustBeOnlyOne => write!(
471                f,
472                "The actions can contain the ony one DelegateAction"
473            ),
474            ActionsValidationError::UnsupportedProtocolFeature { protocol_feature, version } => write!(
475                    f,
476                    "Transaction requires protocol feature {} / version {} which is not supported by the current protocol version",
477                    protocol_feature,
478                    version,
479            ),
480        }
481    }
482}
483
484impl std::error::Error for ActionsValidationError {}
485
486/// An error happened during Action execution
487#[derive(
488    BorshSerialize,
489    BorshDeserialize,
490    Debug,
491    Clone,
492    PartialEq,
493    Eq,
494    serde::Deserialize,
495    serde::Serialize,
496    ProtocolSchema,
497)]
498pub struct ActionError {
499    /// Index of the failed action in the transaction.
500    /// Action index is not defined if ActionError.kind is `ActionErrorKind::LackBalanceForState`
501    pub index: Option<u64>,
502    /// The kind of ActionError happened
503    pub kind: ActionErrorKind,
504}
505
506impl std::error::Error for ActionError {}
507
508#[derive(
509    BorshSerialize,
510    BorshDeserialize,
511    Debug,
512    Clone,
513    PartialEq,
514    Eq,
515    serde::Deserialize,
516    serde::Serialize,
517    ProtocolSchema,
518)]
519pub enum ActionErrorKind {
520    /// Happens when CreateAccount action tries to create an account with account_id which is already exists in the storage
521    AccountAlreadyExists { account_id: AccountId },
522    /// Happens when TX receiver_id doesn't exist (but action is not Action::CreateAccount)
523    AccountDoesNotExist { account_id: AccountId },
524    /// A top-level account ID can only be created by registrar.
525    CreateAccountOnlyByRegistrar {
526        account_id: AccountId,
527        registrar_account_id: AccountId,
528        predecessor_id: AccountId,
529    },
530
531    /// A newly created account must be under a namespace of the creator account
532    CreateAccountNotAllowed { account_id: AccountId, predecessor_id: AccountId },
533    /// Administrative actions like `DeployContract`, `Stake`, `AddKey`, `DeleteKey`. can be proceed only if sender=receiver
534    /// or the first TX action is a `CreateAccount` action
535    ActorNoPermission { account_id: AccountId, actor_id: AccountId },
536    /// Account tries to remove an access key that doesn't exist
537    DeleteKeyDoesNotExist { account_id: AccountId, public_key: Box<PublicKey> },
538    /// The public key is already used for an existing access key
539    AddKeyAlreadyExists { account_id: AccountId, public_key: Box<PublicKey> },
540    /// Account is staking and can not be deleted
541    DeleteAccountStaking { account_id: AccountId },
542    /// ActionReceipt can't be completed, because the remaining balance will not be enough to cover storage.
543    LackBalanceForState {
544        /// An account which needs balance
545        account_id: AccountId,
546        /// Balance required to complete an action.
547        #[serde(with = "dec_format")]
548        amount: Balance,
549    },
550    /// Account is not yet staked, but tries to unstake
551    TriesToUnstake { account_id: AccountId },
552    /// The account doesn't have enough balance to increase the stake.
553    TriesToStake {
554        account_id: AccountId,
555        #[serde(with = "dec_format")]
556        stake: Balance,
557        #[serde(with = "dec_format")]
558        locked: Balance,
559        #[serde(with = "dec_format")]
560        balance: Balance,
561    },
562    InsufficientStake {
563        account_id: AccountId,
564        #[serde(with = "dec_format")]
565        stake: Balance,
566        #[serde(with = "dec_format")]
567        minimum_stake: Balance,
568    },
569    /// An error occurred during a `FunctionCall` Action, parameter is debug message.
570    FunctionCallError(FunctionCallError),
571    /// Error occurs when a new `ActionReceipt` created by the `FunctionCall` action fails
572    /// receipt validation.
573    NewReceiptValidationError(ReceiptValidationError),
574    /// Error occurs when a `CreateAccount` action is called on a NEAR-implicit or ETH-implicit account.
575    /// See NEAR-implicit account creation NEP: <https://github.com/nearprotocol/NEPs/pull/71>.
576    /// Also, see ETH-implicit account creation NEP: <https://github.com/near/NEPs/issues/518>.
577    ///
578    /// TODO(#8598): This error is named very poorly. A better name would be
579    /// `OnlyNamedAccountCreationAllowed`.
580    OnlyImplicitAccountCreationAllowed { account_id: AccountId },
581    /// Delete account whose state is large is temporarily banned.
582    DeleteAccountWithLargeState { account_id: AccountId },
583    /// Signature does not match the provided actions and given signer public key.
584    DelegateActionInvalidSignature,
585    /// Receiver of the transaction doesn't match Sender of the delegate action
586    DelegateActionSenderDoesNotMatchTxReceiver { sender_id: AccountId, receiver_id: AccountId },
587    /// Delegate action has expired. `max_block_height` is less than actual block height.
588    DelegateActionExpired,
589    /// The given public key doesn't exist for Sender account
590    DelegateActionAccessKeyError(InvalidAccessKeyError),
591    /// DelegateAction nonce must be greater sender[public_key].nonce
592    DelegateActionInvalidNonce { delegate_nonce: Nonce, ak_nonce: Nonce },
593    /// DelegateAction nonce is larger than the upper bound given by the block height
594    DelegateActionNonceTooLarge { delegate_nonce: Nonce, upper_bound: Nonce },
595    /// Non-refundable storage transfer to an existing account is not allowed according to NEP-491.
596    NonRefundableTransferToExistingAccount { account_id: AccountId },
597}
598
599impl From<ActionErrorKind> for ActionError {
600    fn from(e: ActionErrorKind) -> ActionError {
601        ActionError { index: None, kind: e }
602    }
603}
604
605impl Display for InvalidTxError {
606    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
607        match self {
608            InvalidTxError::InvalidSignerId { signer_id } => {
609                write!(f, "Invalid signer account ID {:?} according to requirements", signer_id)
610            }
611            InvalidTxError::SignerDoesNotExist { signer_id } => {
612                write!(f, "Signer {:?} does not exist", signer_id)
613            }
614            InvalidTxError::InvalidAccessKeyError(access_key_error) => {
615                Display::fmt(&access_key_error, f)
616            }
617            InvalidTxError::InvalidNonce { tx_nonce, ak_nonce } => write!(
618                f,
619                "Transaction nonce {} must be larger than nonce of the used access key {}",
620                tx_nonce, ak_nonce
621            ),
622            InvalidTxError::InvalidReceiverId { receiver_id } => {
623                write!(f, "Invalid receiver account ID {:?} according to requirements", receiver_id)
624            }
625            InvalidTxError::InvalidSignature => {
626                write!(f, "Transaction is not signed with the given public key")
627            }
628            InvalidTxError::NotEnoughBalance { signer_id, balance, cost } => write!(
629                f,
630                "Sender {:?} does not have enough balance {} for operation costing {}",
631                signer_id, balance, cost
632            ),
633            InvalidTxError::LackBalanceForState { signer_id, amount } => {
634                write!(f, "Failed to execute, because the account {:?} wouldn't have enough balance to cover storage, required to have {} yoctoNEAR more", signer_id, amount)
635            }
636            InvalidTxError::CostOverflow => {
637                write!(f, "Transaction gas or balance cost is too high")
638            }
639            InvalidTxError::InvalidChain => {
640                write!(f, "Transaction parent block hash doesn't belong to the current chain")
641            }
642            InvalidTxError::Expired => {
643                write!(f, "Transaction has expired")
644            }
645            InvalidTxError::ActionsValidation(error) => {
646                write!(f, "Transaction actions validation error: {}", error)
647            }
648            InvalidTxError::NonceTooLarge { tx_nonce, upper_bound } => {
649                write!(
650                    f,
651                    "Transaction nonce {} must be smaller than the access key nonce upper bound {}",
652                    tx_nonce, upper_bound
653                )
654            }
655            InvalidTxError::TransactionSizeExceeded { size, limit } => {
656                write!(f, "Size of serialized transaction {} exceeded the limit {}", size, limit)
657            }
658            InvalidTxError::InvalidTransactionVersion => {
659                write!(f, "Transaction version is invalid")
660            }
661            InvalidTxError::StorageError(error) => {
662                write!(f, "Storage error: {}", error)
663            }
664            InvalidTxError::ShardCongested { shard_id, congestion_level } => {
665                write!(f, "Shard {shard_id} is currently at congestion level {congestion_level:.3} and rejects new transactions.")
666            }
667            InvalidTxError::ShardStuck { shard_id, missed_chunks } => {
668                write!(
669                    f,
670                    "Shard {shard_id} missed {missed_chunks} chunks and rejects new transactions."
671                )
672            }
673        }
674    }
675}
676
677impl From<InvalidAccessKeyError> for InvalidTxError {
678    fn from(error: InvalidAccessKeyError) -> Self {
679        InvalidTxError::InvalidAccessKeyError(error)
680    }
681}
682
683impl Display for InvalidAccessKeyError {
684    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
685        match self {
686            InvalidAccessKeyError::AccessKeyNotFound { account_id, public_key } => write!(
687                f,
688                "Signer {:?} doesn't have access key with the given public_key {}",
689                account_id, public_key
690            ),
691            InvalidAccessKeyError::ReceiverMismatch { tx_receiver, ak_receiver } => write!(
692                f,
693                "Transaction receiver_id {:?} doesn't match the access key receiver_id {:?}",
694                tx_receiver, ak_receiver
695            ),
696            InvalidAccessKeyError::MethodNameMismatch { method_name } => write!(
697                f,
698                "Transaction method name {:?} isn't allowed by the access key",
699                method_name
700            ),
701            InvalidAccessKeyError::RequiresFullAccess => {
702                write!(f, "Invalid access key type. Full-access keys are required for transactions that have multiple or non-function-call actions")
703            }
704            InvalidAccessKeyError::NotEnoughAllowance {
705                account_id,
706                public_key,
707                allowance,
708                cost,
709            } => write!(
710                f,
711                "Access Key {:?}:{} does not have enough balance {} for transaction costing {}",
712                account_id, public_key, allowance, cost
713            ),
714            InvalidAccessKeyError::DepositWithFunctionCall => {
715                write!(f, "Having a deposit with a function call action is not allowed with a function call access key.")
716            }
717        }
718    }
719}
720
721impl std::error::Error for InvalidAccessKeyError {}
722
723/// Happens when the input balance doesn't match the output balance in Runtime apply.
724#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize, ProtocolSchema)]
725pub struct BalanceMismatchError {
726    // Input balances
727    #[serde(with = "dec_format")]
728    pub incoming_validator_rewards: Balance,
729    #[serde(with = "dec_format")]
730    pub initial_accounts_balance: Balance,
731    #[serde(with = "dec_format")]
732    pub incoming_receipts_balance: Balance,
733    #[serde(with = "dec_format")]
734    pub processed_delayed_receipts_balance: Balance,
735    #[serde(with = "dec_format")]
736    pub initial_postponed_receipts_balance: Balance,
737    #[serde(with = "dec_format")]
738    pub forwarded_buffered_receipts_balance: Balance,
739    // Output balances
740    #[serde(with = "dec_format")]
741    pub final_accounts_balance: Balance,
742    #[serde(with = "dec_format")]
743    pub outgoing_receipts_balance: Balance,
744    #[serde(with = "dec_format")]
745    pub new_delayed_receipts_balance: Balance,
746    #[serde(with = "dec_format")]
747    pub final_postponed_receipts_balance: Balance,
748    #[serde(with = "dec_format")]
749    pub tx_burnt_amount: Balance,
750    #[serde(with = "dec_format")]
751    pub slashed_burnt_amount: Balance,
752    #[serde(with = "dec_format")]
753    pub new_buffered_receipts_balance: Balance,
754    #[serde(with = "dec_format")]
755    pub other_burnt_amount: Balance,
756}
757
758impl Display for BalanceMismatchError {
759    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
760        // Using saturating add to avoid overflow in display
761        let initial_balance = self
762            .incoming_validator_rewards
763            .saturating_add(self.initial_accounts_balance)
764            .saturating_add(self.incoming_receipts_balance)
765            .saturating_add(self.processed_delayed_receipts_balance)
766            .saturating_add(self.initial_postponed_receipts_balance)
767            .saturating_add(self.forwarded_buffered_receipts_balance);
768        let final_balance = self
769            .final_accounts_balance
770            .saturating_add(self.outgoing_receipts_balance)
771            .saturating_add(self.new_delayed_receipts_balance)
772            .saturating_add(self.final_postponed_receipts_balance)
773            .saturating_add(self.tx_burnt_amount)
774            .saturating_add(self.slashed_burnt_amount)
775            .saturating_add(self.other_burnt_amount)
776            .saturating_add(self.new_buffered_receipts_balance);
777
778        write!(
779            f,
780            "Balance Mismatch Error. The input balance {} doesn't match output balance {}\n\
781             Inputs:\n\
782             \tIncoming validator rewards sum: {}\n\
783             \tInitial accounts balance sum: {}\n\
784             \tIncoming receipts balance sum: {}\n\
785             \tProcessed delayed receipts balance sum: {}\n\
786             \tInitial postponed receipts balance sum: {}\n\
787             \tForwarded buffered receipts sum: {}\n\
788             Outputs:\n\
789             \tFinal accounts balance sum: {}\n\
790             \tOutgoing receipts balance sum: {}\n\
791             \tNew delayed receipts balance sum: {}\n\
792             \tFinal postponed receipts balance sum: {}\n\
793             \tTx fees burnt amount: {}\n\
794             \tSlashed amount: {}\n\
795             \tNew buffered receipts balance sum: {}\n\
796             \tOther burnt amount: {}",
797            initial_balance,
798            final_balance,
799            self.incoming_validator_rewards,
800            self.initial_accounts_balance,
801            self.incoming_receipts_balance,
802            self.processed_delayed_receipts_balance,
803            self.initial_postponed_receipts_balance,
804            self.forwarded_buffered_receipts_balance,
805            self.final_accounts_balance,
806            self.outgoing_receipts_balance,
807            self.new_delayed_receipts_balance,
808            self.final_postponed_receipts_balance,
809            self.tx_burnt_amount,
810            self.slashed_burnt_amount,
811            self.new_buffered_receipts_balance,
812            self.other_burnt_amount,
813        )
814    }
815}
816
817impl std::error::Error for BalanceMismatchError {}
818
819#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, ProtocolSchema)]
820pub struct IntegerOverflowError;
821
822impl std::fmt::Display for IntegerOverflowError {
823    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
824        f.write_str(&format!("{:?}", self))
825    }
826}
827
828impl std::error::Error for IntegerOverflowError {}
829
830impl From<IntegerOverflowError> for InvalidTxError {
831    fn from(_: IntegerOverflowError) -> Self {
832        InvalidTxError::CostOverflow
833    }
834}
835
836impl From<IntegerOverflowError> for RuntimeError {
837    fn from(err: IntegerOverflowError) -> Self {
838        RuntimeError::UnexpectedIntegerOverflow(err.to_string())
839    }
840}
841
842impl From<StorageError> for RuntimeError {
843    fn from(e: StorageError) -> Self {
844        RuntimeError::StorageError(e)
845    }
846}
847
848impl From<BalanceMismatchError> for RuntimeError {
849    fn from(e: BalanceMismatchError) -> Self {
850        RuntimeError::BalanceMismatchError(Box::new(e))
851    }
852}
853
854impl From<InvalidTxError> for RuntimeError {
855    fn from(e: InvalidTxError) -> Self {
856        RuntimeError::InvalidTxError(e)
857    }
858}
859
860impl From<EpochError> for RuntimeError {
861    fn from(e: EpochError) -> Self {
862        RuntimeError::ValidatorError(e)
863    }
864}
865
866impl Display for ActionError {
867    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
868        write!(f, "Action #{}: {}", self.index.unwrap_or_default(), self.kind)
869    }
870}
871
872impl Display for ActionErrorKind {
873    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
874        match self {
875            ActionErrorKind::AccountAlreadyExists { account_id } => {
876                write!(f, "Can't create a new account {:?}, because it already exists", account_id)
877            }
878            ActionErrorKind::AccountDoesNotExist { account_id } => write!(
879                f,
880                "Can't complete the action because account {:?} doesn't exist",
881                account_id
882            ),
883            ActionErrorKind::ActorNoPermission { actor_id, account_id } => write!(
884                f,
885                "Actor {:?} doesn't have permission to account {:?} to complete the action",
886                actor_id, account_id
887            ),
888            ActionErrorKind::LackBalanceForState { account_id, amount } => write!(
889                f,
890                "The account {} wouldn't have enough balance to cover storage, required to have {} yoctoNEAR more",
891                account_id, amount
892            ),
893            ActionErrorKind::TriesToUnstake { account_id } => {
894                write!(f, "Account {:?} is not yet staked, but tries to unstake", account_id)
895            }
896            ActionErrorKind::TriesToStake { account_id, stake, locked, balance } => write!(
897                f,
898                "Account {:?} tries to stake {}, but has staked {} and only has {}",
899                account_id, stake, locked, balance
900            ),
901            ActionErrorKind::CreateAccountOnlyByRegistrar { account_id, registrar_account_id, predecessor_id } => write!(
902                f,
903                "A top-level account ID {:?} can't be created by {:?}, short top-level account IDs can only be created by {:?}",
904                account_id, predecessor_id, registrar_account_id,
905            ),
906            ActionErrorKind::CreateAccountNotAllowed { account_id, predecessor_id } => write!(
907                f,
908                "A sub-account ID {:?} can't be created by account {:?}",
909                account_id, predecessor_id,
910            ),
911            ActionErrorKind::DeleteKeyDoesNotExist { account_id, .. } => write!(
912                f,
913                "Account {:?} tries to remove an access key that doesn't exist",
914                account_id
915            ),
916            ActionErrorKind::AddKeyAlreadyExists { public_key, .. } => write!(
917                f,
918                "The public key {:?} is already used for an existing access key",
919                public_key
920            ),
921            ActionErrorKind::DeleteAccountStaking { account_id } => {
922                write!(f, "Account {:?} is staking and can not be deleted", account_id)
923            }
924            ActionErrorKind::FunctionCallError(s) => write!(f, "{:?}", s),
925            ActionErrorKind::NewReceiptValidationError(e) => {
926                write!(f, "An new action receipt created during a FunctionCall is not valid: {}", e)
927            }
928            ActionErrorKind::InsufficientStake { account_id, stake, minimum_stake } => write!(f, "Account {} tries to stake {} but minimum required stake is {}", account_id, stake, minimum_stake),
929            ActionErrorKind::OnlyImplicitAccountCreationAllowed { account_id } => write!(f, "CreateAccount action is called on hex-characters account of length 64 {}", account_id),
930            ActionErrorKind::DeleteAccountWithLargeState { account_id } => write!(f, "The state of account {} is too large and therefore cannot be deleted", account_id),
931            ActionErrorKind::DelegateActionInvalidSignature => write!(f, "DelegateAction is not signed with the given public key"),
932            ActionErrorKind::DelegateActionSenderDoesNotMatchTxReceiver { sender_id, receiver_id } => write!(f, "Transaction receiver {} doesn't match DelegateAction sender {}", receiver_id, sender_id),
933            ActionErrorKind::DelegateActionExpired => write!(f, "DelegateAction has expired"),
934            ActionErrorKind::DelegateActionAccessKeyError(access_key_error) => Display::fmt(&access_key_error, f),
935            ActionErrorKind::DelegateActionInvalidNonce { delegate_nonce, ak_nonce } => write!(f, "DelegateAction nonce {} must be larger than nonce of the used access key {}", delegate_nonce, ak_nonce),
936            ActionErrorKind::DelegateActionNonceTooLarge { delegate_nonce, upper_bound } => write!(f, "DelegateAction nonce {} must be smaller than the access key nonce upper bound {}", delegate_nonce, upper_bound),
937            ActionErrorKind::NonRefundableTransferToExistingAccount { account_id} => {
938                write!(f, "Can't make non-refundable storage transfer to {} because it already exists", account_id)
939            }
940        }
941    }
942}
943
944#[derive(Eq, PartialEq, Clone)]
945pub enum EpochError {
946    /// Error calculating threshold from given stakes for given number of seats.
947    /// Only should happened if calling code doesn't check for integer value of stake > number of seats.
948    ThresholdError {
949        stake_sum: Balance,
950        num_seats: u64,
951    },
952    /// Requesting validators for an epoch that wasn't computed yet.
953    EpochOutOfBounds(EpochId),
954    /// Missing block hash in the storage (means there is some structural issue).
955    MissingBlock(CryptoHash),
956    /// Error due to IO (DB read/write, serialization, etc.).
957    IOErr(String),
958    /// Given account ID is not a validator in the given epoch ID.
959    NotAValidator(AccountId, EpochId),
960    /// Error getting information for a shard
961    ShardingError(String),
962    NotEnoughValidators {
963        num_validators: u64,
964        num_shards: u64,
965    },
966    /// Error selecting validators for a chunk.
967    ChunkValidatorSelectionError(String),
968    /// Error selecting chunk producer for a shard.
969    ChunkProducerSelectionError(String),
970}
971
972impl std::error::Error for EpochError {}
973
974impl Display for EpochError {
975    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
976        match self {
977            EpochError::ThresholdError { stake_sum, num_seats } => write!(
978                f,
979                "Total stake {} must be higher than the number of seats {}",
980                stake_sum, num_seats
981            ),
982            EpochError::EpochOutOfBounds(epoch_id) => {
983                write!(f, "Epoch {:?} is out of bounds", epoch_id)
984            }
985            EpochError::MissingBlock(hash) => write!(f, "Missing block {}", hash),
986            EpochError::IOErr(err) => write!(f, "IO: {}", err),
987            EpochError::NotAValidator(account_id, epoch_id) => {
988                write!(f, "{} is not a validator in epoch {:?}", account_id, epoch_id)
989            }
990            EpochError::ShardingError(err) => write!(f, "Sharding Error: {}", err),
991            EpochError::NotEnoughValidators { num_shards, num_validators } => {
992                write!(f, "There were not enough validator proposals to fill all shards. num_proposals: {}, num_shards: {}", num_validators, num_shards)
993            }
994            EpochError::ChunkValidatorSelectionError(err) => {
995                write!(f, "Error selecting validators for a chunk: {}", err)
996            }
997            EpochError::ChunkProducerSelectionError(err) => {
998                write!(f, "Error selecting chunk producer: {}", err)
999            }
1000        }
1001    }
1002}
1003
1004impl Debug for EpochError {
1005    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1006        match self {
1007            EpochError::ThresholdError { stake_sum, num_seats } => {
1008                write!(f, "ThresholdError({}, {})", stake_sum, num_seats)
1009            }
1010            EpochError::EpochOutOfBounds(epoch_id) => write!(f, "EpochOutOfBounds({:?})", epoch_id),
1011            EpochError::MissingBlock(hash) => write!(f, "MissingBlock({})", hash),
1012            EpochError::IOErr(err) => write!(f, "IOErr({})", err),
1013            EpochError::NotAValidator(account_id, epoch_id) => {
1014                write!(f, "NotAValidator({}, {:?})", account_id, epoch_id)
1015            }
1016            EpochError::ShardingError(err) => write!(f, "ShardingError({})", err),
1017            EpochError::NotEnoughValidators { num_shards, num_validators } => {
1018                write!(f, "NotEnoughValidators({}, {})", num_validators, num_shards)
1019            }
1020            EpochError::ChunkValidatorSelectionError(err) => {
1021                write!(f, "ChunkValidatorSelectionError({})", err)
1022            }
1023            EpochError::ChunkProducerSelectionError(err) => {
1024                write!(f, "ChunkProducerSelectionError({})", err)
1025            }
1026        }
1027    }
1028}
1029
1030impl From<std::io::Error> for EpochError {
1031    fn from(error: std::io::Error) -> Self {
1032        EpochError::IOErr(error.to_string())
1033    }
1034}
1035
1036impl From<ShardLayoutError> for EpochError {
1037    fn from(error: ShardLayoutError) -> Self {
1038        EpochError::ShardingError(error.to_string())
1039    }
1040}
1041
1042#[derive(
1043    Debug,
1044    Clone,
1045    PartialEq,
1046    Eq,
1047    BorshDeserialize,
1048    BorshSerialize,
1049    serde::Deserialize,
1050    serde::Serialize,
1051    ProtocolSchema,
1052)]
1053/// Error that can occur while preparing or executing Wasm smart-contract.
1054pub enum PrepareError {
1055    /// Error happened while serializing the module.
1056    Serialization,
1057    /// Error happened while deserializing the module.
1058    Deserialization,
1059    /// Internal memory declaration has been found in the module.
1060    InternalMemoryDeclared,
1061    /// Gas instrumentation failed.
1062    ///
1063    /// This most likely indicates the module isn't valid.
1064    GasInstrumentation,
1065    /// Stack instrumentation failed.
1066    ///
1067    /// This  most likely indicates the module isn't valid.
1068    StackHeightInstrumentation,
1069    /// Error happened during instantiation.
1070    ///
1071    /// This might indicate that `start` function trapped, or module isn't
1072    /// instantiable and/or unlinkable.
1073    Instantiate,
1074    /// Error creating memory.
1075    Memory,
1076    /// Contract contains too many functions.
1077    TooManyFunctions,
1078    /// Contract contains too many locals.
1079    TooManyLocals,
1080}
1081
1082/// A kind of a trap happened during execution of a binary
1083#[derive(
1084    Debug,
1085    Clone,
1086    PartialEq,
1087    Eq,
1088    BorshDeserialize,
1089    BorshSerialize,
1090    serde::Deserialize,
1091    serde::Serialize,
1092    strum::IntoStaticStr,
1093    ProtocolSchema,
1094)]
1095pub enum WasmTrap {
1096    /// An `unreachable` opcode was executed.
1097    Unreachable,
1098    /// Call indirect incorrect signature trap.
1099    IncorrectCallIndirectSignature,
1100    /// Memory out of bounds trap.
1101    MemoryOutOfBounds,
1102    /// Call indirect out of bounds trap.
1103    CallIndirectOOB,
1104    /// An arithmetic exception, e.g. divided by zero.
1105    IllegalArithmetic,
1106    /// Misaligned atomic access trap.
1107    MisalignedAtomicAccess,
1108    /// Indirect call to null.
1109    IndirectCallToNull,
1110    /// Stack overflow.
1111    StackOverflow,
1112    /// Generic trap.
1113    GenericTrap,
1114}
1115
1116#[derive(
1117    Debug,
1118    Clone,
1119    PartialEq,
1120    Eq,
1121    BorshDeserialize,
1122    BorshSerialize,
1123    serde::Deserialize,
1124    serde::Serialize,
1125    strum::IntoStaticStr,
1126    ProtocolSchema,
1127)]
1128pub enum HostError {
1129    /// String encoding is bad UTF-16 sequence
1130    BadUTF16,
1131    /// String encoding is bad UTF-8 sequence
1132    BadUTF8,
1133    /// Exceeded the prepaid gas
1134    GasExceeded,
1135    /// Exceeded the maximum amount of gas allowed to burn per contract
1136    GasLimitExceeded,
1137    /// Exceeded the account balance
1138    BalanceExceeded,
1139    /// Tried to call an empty method name
1140    EmptyMethodName,
1141    /// Smart contract panicked
1142    GuestPanic { panic_msg: String },
1143    /// IntegerOverflow happened during a contract execution
1144    IntegerOverflow,
1145    /// `promise_idx` does not correspond to existing promises
1146    InvalidPromiseIndex { promise_idx: u64 },
1147    /// Actions can only be appended to non-joint promise.
1148    CannotAppendActionToJointPromise,
1149    /// Returning joint promise is currently prohibited
1150    CannotReturnJointPromise,
1151    /// Accessed invalid promise result index
1152    InvalidPromiseResultIndex { result_idx: u64 },
1153    /// Accessed invalid register id
1154    InvalidRegisterId { register_id: u64 },
1155    /// Iterator `iterator_index` was invalidated after its creation by performing a mutable operation on trie
1156    IteratorWasInvalidated { iterator_index: u64 },
1157    /// Accessed memory outside the bounds
1158    MemoryAccessViolation,
1159    /// VM Logic returned an invalid receipt index
1160    InvalidReceiptIndex { receipt_index: u64 },
1161    /// Iterator index `iterator_index` does not exist
1162    InvalidIteratorIndex { iterator_index: u64 },
1163    /// VM Logic returned an invalid account id
1164    InvalidAccountId,
1165    /// VM Logic returned an invalid method name
1166    InvalidMethodName,
1167    /// VM Logic provided an invalid public key
1168    InvalidPublicKey,
1169    /// `method_name` is not allowed in view calls
1170    ProhibitedInView { method_name: String },
1171    /// The total number of logs will exceed the limit.
1172    NumberOfLogsExceeded { limit: u64 },
1173    /// The storage key length exceeded the limit.
1174    KeyLengthExceeded { length: u64, limit: u64 },
1175    /// The storage value length exceeded the limit.
1176    ValueLengthExceeded { length: u64, limit: u64 },
1177    /// The total log length exceeded the limit.
1178    TotalLogLengthExceeded { length: u64, limit: u64 },
1179    /// The maximum number of promises within a FunctionCall exceeded the limit.
1180    NumberPromisesExceeded { number_of_promises: u64, limit: u64 },
1181    /// The maximum number of input data dependencies exceeded the limit.
1182    NumberInputDataDependenciesExceeded { number_of_input_data_dependencies: u64, limit: u64 },
1183    /// The returned value length exceeded the limit.
1184    ReturnedValueLengthExceeded { length: u64, limit: u64 },
1185    /// The contract size for DeployContract action exceeded the limit.
1186    ContractSizeExceeded { size: u64, limit: u64 },
1187    /// The host function was deprecated.
1188    Deprecated { method_name: String },
1189    /// General errors for ECDSA recover.
1190    ECRecoverError { msg: String },
1191    /// Invalid input to alt_bn128 familiy of functions (e.g., point which isn't
1192    /// on the curve).
1193    AltBn128InvalidInput { msg: String },
1194    /// Invalid input to ed25519 signature verification function (e.g. signature cannot be
1195    /// derived from bytes).
1196    Ed25519VerifyInvalidInput { msg: String },
1197}
1198
1199#[derive(
1200    Debug,
1201    Clone,
1202    PartialEq,
1203    Eq,
1204    BorshDeserialize,
1205    BorshSerialize,
1206    serde::Deserialize,
1207    serde::Serialize,
1208    strum::IntoStaticStr,
1209    ProtocolSchema,
1210)]
1211pub enum MethodResolveError {
1212    MethodEmptyName,
1213    MethodNotFound,
1214    MethodInvalidSignature,
1215}
1216
1217#[derive(
1218    Debug,
1219    Clone,
1220    PartialEq,
1221    Eq,
1222    BorshDeserialize,
1223    BorshSerialize,
1224    serde::Deserialize,
1225    serde::Serialize,
1226    strum::IntoStaticStr,
1227    ProtocolSchema,
1228)]
1229pub enum CompilationError {
1230    CodeDoesNotExist {
1231        account_id: AccountId,
1232    },
1233    PrepareError(PrepareError),
1234    /// This is for defense in depth.
1235    /// We expect our runtime-independent preparation code to fully catch all invalid wasms,
1236    /// but, if it ever misses something we’ll emit this error
1237    WasmerCompileError {
1238        msg: String,
1239    },
1240}
1241
1242/// Serializable version of `near-vm-runner::FunctionCallError`.
1243///
1244/// Must never reorder/remove elements, can only add new variants at the end (but do that very
1245/// carefully). It describes stable serialization format, and only used by serialization logic.
1246#[derive(
1247    Debug,
1248    Clone,
1249    PartialEq,
1250    Eq,
1251    BorshDeserialize,
1252    BorshSerialize,
1253    serde::Serialize,
1254    serde::Deserialize,
1255    ProtocolSchema,
1256)]
1257pub enum FunctionCallError {
1258    /// Wasm compilation error
1259    CompilationError(CompilationError),
1260    /// Wasm binary env link error
1261    ///
1262    /// Note: this is only to deserialize old data, use execution error for new data
1263    LinkError {
1264        msg: String,
1265    },
1266    /// Import/export resolve error
1267    MethodResolveError(MethodResolveError),
1268    /// A trap happened during execution of a binary
1269    ///
1270    /// Note: this is only to deserialize old data, use execution error for new data
1271    WasmTrap(WasmTrap),
1272    WasmUnknownError,
1273    /// Note: this is only to deserialize old data, use execution error for new data
1274    HostError(HostError),
1275    // Unused, can be reused by a future error but must be exactly one error to keep ExecutionError
1276    // error borsh serialized at correct index
1277    _EVMError,
1278    ExecutionError(String),
1279}
1280
1281#[derive(Debug)]
1282pub enum ChunkAccessError {
1283    ChunkMissing(ChunkHash),
1284}
1285
1286impl std::fmt::Display for ChunkAccessError {
1287    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
1288        f.write_str(&format!("{:?}", self))
1289    }
1290}
1291
1292impl std::error::Error for ChunkAccessError {}