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