Skip to main content

iota_sdk_types/
execution_status.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2025 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use thiserror::Error;
6
7use super::{Address, Digest, Identifier, ObjectId};
8
9/// The status of an executed Transaction
10///
11/// # BCS
12///
13/// The BCS serialized form for this type is defined by the following ABNF:
14///
15/// ```text
16/// execution-status = success / failure
17/// success = %d00
18/// failure = %d01 execution-error (option u64)
19/// ```
20#[derive(Clone, Debug, Eq, PartialEq)]
21#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
22#[cfg_attr(feature = "bcs-schema", derive(iota_bcs_schema::BcsSchema))]
23#[non_exhaustive]
24pub enum ExecutionStatus {
25    /// The Transaction successfully executed.
26    Success,
27    /// The Transaction didn't execute successfully.
28    ///
29    /// Failed transactions are still committed to the blockchain but any
30    /// intended effects are rolled back to prior to this transaction
31    /// executing with the caveat that gas objects are still smashed and gas
32    /// usage is still charged.
33    Failure {
34        /// The error encountered during execution.
35        error: ExecutionError,
36        /// The command, if any, during which the error occurred.
37        #[cfg_attr(feature = "proptest", map(|x: Option<u16>| x.map(Into::into)))]
38        command: Option<u64>,
39    },
40}
41
42impl ExecutionStatus {
43    crate::def_is!(Success, Failure);
44
45    pub fn new_failure(error: ExecutionError, command: Option<u64>) -> Self {
46        Self::Failure { error, command }
47    }
48
49    pub fn unwrap(&self) {
50        match self {
51            Self::Success => {}
52            Self::Failure { .. } => {
53                panic!("Unable to unwrap() on {self:?}");
54            }
55        }
56    }
57
58    pub fn unwrap_err(self) -> (ExecutionError, Option<u64>) {
59        match self {
60            Self::Success => {
61                panic!("Unable to unwrap_err() on {self:?}");
62            }
63            Self::Failure { error, command } => (error, command),
64        }
65    }
66
67    /// The error encountered during execution.
68    pub fn error(&self) -> Option<&ExecutionError> {
69        if let Self::Failure { error, .. } = self {
70            Some(error)
71        } else {
72            None
73        }
74    }
75
76    /// The command, if any, during which the error occurred.
77    pub fn error_command(&self) -> Option<u64> {
78        if let Self::Failure { command, .. } = self {
79            *command
80        } else {
81            None
82        }
83    }
84}
85
86impl crate::TreeDisplay for ExecutionStatus {
87    fn fmt_tree(&self, w: &mut crate::TreeWriter<'_, '_>) -> std::fmt::Result {
88        w.enum_name("Execution Status");
89        match self {
90            ExecutionStatus::Success => w.header("Success"),
91            ExecutionStatus::Failure { error, command } => {
92                w.header("Failure")?;
93                w.leaf("Error", error, false)?;
94                w.option_leaf("Command", command, true)
95            }
96        }
97    }
98}
99
100crate::impl_tree_display!(ExecutionStatus);
101
102fn display_move_location_opt(location: &Option<MoveLocation>) -> impl core::fmt::Display + '_ {
103    struct W<'a>(&'a Option<MoveLocation>);
104    impl core::fmt::Display for W<'_> {
105        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
106            match &self.0 {
107                None => write!(f, "UNKNOWN"),
108                Some(l) => write!(f, "{l}"),
109            }
110        }
111    }
112    W(location)
113}
114
115fn display_congested_objects(objects: &[ObjectId]) -> impl core::fmt::Display + '_ {
116    struct W<'a>(&'a [ObjectId]);
117    impl core::fmt::Display for W<'_> {
118        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
119            let mut iter = self.0.iter();
120            if let Some(first) = iter.next() {
121                write!(f, "{first}")?;
122                for obj in iter {
123                    write!(f, ", {obj}")?;
124                }
125            }
126            Ok(())
127        }
128    }
129    W(objects)
130}
131
132/// An error that can occur during the execution of a transaction
133///
134/// # BCS
135///
136/// The BCS serialized form for this type is defined by the following ABNF:
137///
138/// ```text
139/// 
140/// execution-error =  insufficient-gas
141///                 =/ invalid-gas-object
142///                 =/ invariant-violation
143///                 =/ feature-not-yet-supported
144///                 =/ object-too-big
145///                 =/ package-too-big
146///                 =/ circular-object-ownership
147///                 =/ insufficient-coin-balance
148///                 =/ coin-balance-overflow
149///                 =/ publish-error-non-zero-address
150///                 =/ iota-move-verification-error
151///                 =/ move-primitive-runtime-error
152///                 =/ move-abort
153///                 =/ vm-verification-or-deserialization-error
154///                 =/ vm-invariant-violation
155///                 =/ function-not-found
156///                 =/ arity-mismatch
157///                 =/ type-arity-mismatch
158///                 =/ non-entry-function-invoked
159///                 =/ command-argument-error
160///                 =/ type-argument-error
161///                 =/ unused-value-without-drop
162///                 =/ invalid-public-function-return-type
163///                 =/ invalid-transfer-object
164///                 =/ effects-too-large
165///                 =/ publish-upgrade-missing-dependency
166///                 =/ publish-upgrade-dependency-downgrade
167///                 =/ package-upgrade-error
168///                 =/ written-objects-too-large
169///                 =/ certificate-denied
170///                 =/ iota-move-verification-timeout
171///                 =/ shared-object-operation-not-allowed
172///                 =/ input-object-deleted
173///                 =/ execution-canceled-due-to-shared-object-congestion
174///                 =/ address-denied-for-coin
175///                 =/ coin-type-global-pause
176///                 =/ execution-canceled-due-to-randomness-unavailable
177///                 =/ execution-canceled-due-to-shared-object-congestion-v2
178///                 =/ invalid-linkage
179///                 =/ move-authentication-error
180///                 =/ execution-canceled-due-to-execution-worker-congestion
181///
182/// insufficient-gas                                       = %d00
183/// invalid-gas-object                                     = %d01
184/// invariant-violation                                    = %d02
185/// feature-not-yet-supported                              = %d03
186/// object-too-big                                         = %d04 u64 u64
187/// package-too-big                                        = %d05 u64 u64
188/// circular-object-ownership                              = %d06 object-id
189/// insufficient-coin-balance                              = %d07
190/// coin-balance-overflow                                  = %d08
191/// publish-error-non-zero-address                         = %d09
192/// iota-move-verification-error                           = %d10
193/// move-primitive-runtime-error                           = %d11 (option move-location)
194/// move-abort                                             = %d12 move-location u64
195/// vm-verification-or-deserialization-error               = %d13
196/// vm-invariant-violation                                 = %d14
197/// function-not-found                                     = %d15
198/// arity-mismatch                                         = %d16
199/// type-arity-mismatch                                    = %d17
200/// non-entry-function-invoked                             = %d18
201/// command-argument-error                                 = %d19 u16 command-argument-error
202/// type-argument-error                                    = %d20 u16 type-argument-error
203/// unused-value-without-drop                              = %d21 u16 u16
204/// invalid-public-function-return-type                    = %d22 u16
205/// invalid-transfer-object                                = %d23
206/// effects-too-large                                      = %d24 u64 u64
207/// publish-upgrade-missing-dependency                     = %d25
208/// publish-upgrade-dependency-downgrade                   = %d26
209/// package-upgrade-error                                  = %d27 package-upgrade-error
210/// written-objects-too-large                              = %d28 u64 u64
211/// certificate-denied                                     = %d29
212/// iota-move-verification-timeout                         = %d30
213/// shared-object-operation-not-allowed                    = %d31
214/// input-object-deleted                                   = %d32
215/// execution-canceled-due-to-shared-object-congestion    = %d33 (vector object-id)
216/// address-denied-for-coin                                = %d34 address string
217/// coin-type-global-pause                                 = %d35 string
218/// execution-canceled-due-to-randomness-unavailable      = %d36
219/// execution-canceled-due-to-shared-object-congestion-v2 = %d37 (vector object-id) u64
220/// invalid-linkage                                        = %d38
221/// move-authentication-error                              = %d39 execution-error
222/// execution-canceled-due-to-execution-worker-congestion  = %d40 u64
223/// ```
224// WARNING: The variant order of this enum is protocol-significant. Each variant's position
225// determines its BCS discriminant (the integer sent over the wire).
226// Reordering or inserting variants will break protocol compatibility.
227// New variants MUST be added at the end.
228// The `execution_error_bcs_discriminants` snapshot test enforces this.
229#[derive(Clone, Debug, Eq, Error, PartialEq, strum::AsRefStr)]
230#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
231#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
232#[cfg_attr(feature = "bcs-schema", derive(iota_bcs_schema::BcsSchema))]
233#[non_exhaustive]
234pub enum ExecutionError {
235    /// Insufficient Gas
236    #[error("Insufficient Gas")]
237    InsufficientGas,
238    /// Invalid Gas Object.
239    #[error("Invalid Gas Object. Possibly not address-owned or possibly not an IOTA coin")]
240    InvalidGasObject,
241    /// Invariant Violation
242    #[error("INVARIANT VIOLATION")]
243    InvariantViolation,
244    /// Attempted to use feature that is not supported yet
245    #[error("Attempted to use feature that is not supported yet")]
246    FeatureNotYetSupported,
247    /// Move object is larger than the maximum allowed size
248    #[error(
249        "Move object with size {object_size} is larger than the maximum object size {max_object_size}"
250    )]
251    ObjectTooBig {
252        #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
253        object_size: u64,
254        #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
255        max_object_size: u64,
256    },
257    /// Package is larger than the maximum allowed size
258    #[error(
259        "Move package with size {object_size} is larger than the maximum object size {max_object_size}"
260    )]
261    PackageTooBig {
262        #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
263        object_size: u64,
264        #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
265        max_object_size: u64,
266    },
267    /// Circular Object Ownership
268    #[error("Circular Object Ownership, including object {object}")]
269    CircularObjectOwnership { object: ObjectId },
270    /// Insufficient coin balance for requested operation
271    #[error("Insufficient coin balance for operation")]
272    InsufficientCoinBalance,
273    /// Coin balance overflowed an u64
274    #[error("The coin balance overflows u64")]
275    CoinBalanceOverflow,
276    /// Publish Error, Non-zero Address.
277    /// The modules in the package must have their self-addresses set to zero.
278    #[error(
279        "Publish Error, Non-zero Address. The modules in the package must have their self-addresses set to zero."
280    )]
281    PublishErrorNonZeroAddress,
282    /// IOTA Move Bytecode Verification Error.
283    #[error(
284        "IOTA Move Bytecode Verification Error. Please run the IOTA Move Verifier for more information."
285    )]
286    IotaMoveVerificationError,
287    /// Error from a non-abort instruction.
288    /// Possible causes:
289    ///     Arithmetic error, stack overflow, max value depth, etc."
290    #[error(
291        "Move Primitive Runtime Error. Location: {}. Arithmetic error, stack overflow, max value depth, etc.",
292        display_move_location_opt(.location)
293    )]
294    MovePrimitiveRuntimeError { location: Option<MoveLocation> },
295    /// Move runtime abort
296    #[error("Move Runtime Abort. Location: {location}, Abort Code: {code}")]
297    MoveAbort {
298        location: MoveLocation,
299        #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
300        code: u64,
301    },
302    /// Bytecode verification error.
303    #[error(
304        "Move Bytecode Verification Error. Please run the Bytecode Verifier for more information."
305    )]
306    VmVerificationOrDeserializationError,
307    /// MoveVm invariant violation
308    #[error("MOVE VM INVARIANT VIOLATION")]
309    VmInvariantViolation,
310    /// Function not found
311    #[error("Function Not Found")]
312    FunctionNotFound,
313    /// Arity mismatch for Move function.
314    /// The number of arguments does not match the number of parameters
315    #[error(
316        "Arity mismatch for Move function. The number of arguments does not match the number of parameters"
317    )]
318    ArityMismatch,
319    /// Type arity mismatch for Move function.
320    /// Mismatch between the number of actual versus expected type arguments.
321    #[error(
322        "Type arity mismatch for Move function. Mismatch between the number of actual versus expected type arguments."
323    )]
324    TypeArityMismatch,
325    /// Non Entry Function Invoked. Move Call must start with an entry function.
326    #[error("Non Entry Function Invoked. Move Call must start with an entry function")]
327    NonEntryFunctionInvoked,
328    /// Invalid command argument
329    #[error("Invalid command argument at {argument}. {kind}")]
330    CommandArgumentError {
331        argument: u16,
332        kind: CommandArgumentError,
333    },
334    /// Type argument error
335    #[error("Error for type argument at index {type_argument}: {kind}")]
336    TypeArgumentError {
337        /// Index of the problematic type argument
338        type_argument: u16,
339        kind: TypeArgumentError,
340    },
341    /// Unused result without the drop ability.
342    #[error(
343        "Unused result without the drop ability. Command result {result}, return value {subresult}"
344    )]
345    UnusedValueWithoutDrop { result: u16, subresult: u16 },
346    /// Invalid public Move function signature.
347    /// Unsupported return type for return value
348    #[error(
349        "Invalid public Move function signature. Unsupported return type for return value {index}"
350    )]
351    InvalidPublicFunctionReturnType { index: u16 },
352    /// Invalid Transfer Object, object does not have public transfer.
353    #[error("Invalid Transfer Object, object does not have public transfer")]
354    InvalidTransferObject,
355    /// Effects from the transaction are too large
356    #[error("Effects of size {current_size} bytes too large. Limit is {max_size} bytes")]
357    EffectsTooLarge {
358        #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
359        current_size: u64,
360        #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
361        max_size: u64,
362    },
363    /// Publish or Upgrade is missing dependency
364    #[error(
365        "Publish/Upgrade Error, Missing dependency. A dependency of a published or upgraded package has not been assigned an on-chain address."
366    )]
367    PublishUpgradeMissingDependency,
368    /// Publish or Upgrade dependency downgrade.
369    ///
370    /// Indirect (transitive) dependency of published or upgraded package has
371    /// been assigned an on-chain version that is less than the version
372    /// required by one of the package's transitive dependencies.
373    #[error(
374        "Publish/Upgrade Error, Dependency downgrade. Indirect (transitive) dependency of published or upgraded package has been assigned an on-chain version that is less than the version required by one of the package's transitive dependencies."
375    )]
376    PublishUpgradeDependencyDowngrade,
377    /// Invalid package upgrade
378    #[error("Invalid package upgrade. {kind}")]
379    PackageUpgradeError { kind: PackageUpgradeError },
380    /// Indicates the transaction tried to write objects too large to storage
381    #[error("Written objects of {object_size} bytes too large. Limit is {max_object_size} bytes")]
382    WrittenObjectsTooLarge {
383        #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
384        object_size: u64,
385        #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
386        max_object_size: u64,
387    },
388    /// Certificate is on the deny list
389    #[error("Certificate is on the deny list")]
390    CertificateDenied,
391    /// IOTA Move Bytecode verification timed out.
392    #[error(
393        "IOTA Move Bytecode Verification Timeout. Please run the IOTA Move Verifier for more information."
394    )]
395    IotaMoveVerificationTimeout,
396    /// The requested shared object operation is not allowed
397    #[error("The shared object operation is not allowed")]
398    SharedObjectOperationNotAllowed,
399    /// Requested shared object has been deleted
400    #[error("Certificate cannot be executed due to a dependency on a deleted shared object")]
401    InputObjectDeleted,
402    /// Certificate is canceled due to congestion on shared objects
403    #[error("Certificate is canceled due to congestion on shared objects: {}.", display_congested_objects(.congested_objects))]
404    ExecutionCanceledDueToSharedObjectCongestion { congested_objects: Vec<ObjectId> },
405    /// Address is denied for this coin type
406    #[error("Address {address:?} is denied for coin {coin_type}")]
407    AddressDeniedForCoin { address: Address, coin_type: String },
408    /// Coin type is globally paused for use
409    #[error("Coin type is globally paused for use: {coin_type}")]
410    CoinTypeGlobalPause { coin_type: String },
411    /// Certificate is canceled because randomness could not be generated this
412    /// epoch
413    #[error("Certificate is canceled because randomness could not be generated this epoch")]
414    ExecutionCanceledDueToRandomnessUnavailable,
415    /// Certificate is canceled due to congestion on shared objects;
416    /// suggested gas price can be used to give this certificate more priority.
417    #[error(
418        "Certificate is canceled due to congestion on shared objects: {}. To give this certificate more priority to be executed, its gas price can be increased to at least {suggested_gas_price}.",
419        display_congested_objects(.congested_objects)
420    )]
421    ExecutionCanceledDueToSharedObjectCongestionV2 {
422        congested_objects: Vec<ObjectId>,
423        #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
424        suggested_gas_price: u64,
425    },
426    /// A valid linkage was unable to be determined for the transaction or one
427    /// of its commands.
428    #[error("A valid linkage was unable to be determined for the transaction")]
429    InvalidLinkage,
430    /// The transaction's Move-based authentication failed while executing an
431    /// authenticator, before the programmable transaction was run. The
432    /// wrapped error is the failure produced by the authenticator's
433    /// execution.
434    #[error("Move authentication failed: {error}")]
435    #[cfg_attr(feature = "proptest", weight(0))]
436    MoveAuthentication { error: Box<ExecutionError> },
437    /// Certificate is canceled because the execution workers are congested;
438    /// suggested gas price can be used to give this certificate more priority.
439    /// No individual object is responsible, so none is reported.
440    #[error(
441        "Certificate is canceled due to execution-worker congestion. To give this certificate more priority to be executed, its gas price can be increased to at least {suggested_gas_price}."
442    )]
443    ExecutionCanceledDueToExecutionWorkerCongestion {
444        #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
445        suggested_gas_price: u64,
446    },
447}
448
449impl ExecutionError {
450    crate::def_is!(
451        InsufficientGas,
452        InvalidGasObject,
453        InvariantViolation,
454        FeatureNotYetSupported,
455        ObjectTooBig,
456        PackageTooBig,
457        CircularObjectOwnership,
458        InsufficientCoinBalance,
459        CoinBalanceOverflow,
460        PublishErrorNonZeroAddress,
461        IotaMoveVerificationError,
462        MovePrimitiveRuntimeError,
463        MoveAbort,
464        VmVerificationOrDeserializationError,
465        VmInvariantViolation,
466        FunctionNotFound,
467        ArityMismatch,
468        TypeArityMismatch,
469        NonEntryFunctionInvoked,
470        CommandArgumentError,
471        TypeArgumentError,
472        UnusedValueWithoutDrop,
473        InvalidPublicFunctionReturnType,
474        InvalidTransferObject,
475        EffectsTooLarge,
476        PublishUpgradeMissingDependency,
477        PublishUpgradeDependencyDowngrade,
478        PackageUpgradeError,
479        WrittenObjectsTooLarge,
480        CertificateDenied,
481        IotaMoveVerificationTimeout,
482        SharedObjectOperationNotAllowed,
483        InputObjectDeleted,
484        ExecutionCanceledDueToSharedObjectCongestion,
485        AddressDeniedForCoin,
486        CoinTypeGlobalPause,
487        ExecutionCanceledDueToRandomnessUnavailable,
488        ExecutionCanceledDueToSharedObjectCongestionV2,
489        InvalidLinkage,
490        MoveAuthentication,
491        ExecutionCanceledDueToExecutionWorkerCongestion,
492    );
493
494    pub fn command_argument_error(kind: CommandArgumentError, argument: u16) -> Self {
495        Self::CommandArgumentError { argument, kind }
496    }
497}
498
499/// Location in move bytecode where an error occurred
500///
501/// # BCS
502///
503/// The BCS serialized form for this type is defined by the following ABNF:
504///
505/// ```text
506/// move-location = object-id identifier u16 u16 (option identifier)
507/// ```
508#[derive(Clone, Debug, Eq, Hash, PartialEq)]
509#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
510#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
511#[cfg_attr(feature = "bcs-schema", derive(iota_bcs_schema::BcsSchema))]
512pub struct MoveLocation {
513    /// The package id
514    pub package: ObjectId,
515    /// The module name
516    pub module: Identifier,
517    /// The function index
518    pub function: u16,
519    /// Index into the code stream for a jump. The offset is relative to the
520    /// beginning of the instruction stream.
521    pub instruction: u16,
522    /// The name of the function if available
523    pub function_name: Option<Identifier>,
524}
525
526impl core::fmt::Display for MoveLocation {
527    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> std::fmt::Result {
528        let Self {
529            package,
530            module,
531            function,
532            instruction,
533            function_name,
534        } = self;
535        if let Some(fname) = function_name {
536            write!(
537                f,
538                "{package}::{module}::{fname} (function index {function}) at offset {instruction}"
539            )
540        } else {
541            write!(
542                f,
543                "{package}::{module} in function definition {function} at offset {instruction}"
544            )
545        }
546    }
547}
548
549/// An error with an argument to a command
550///
551/// # BCS
552///
553/// The BCS serialized form for this type is defined by the following ABNF:
554///
555/// ```text
556/// command-argument-error =  type-mismatch
557///                        =/ invalid-bcs-bytes
558///                        =/ invalid-usage-of-pure-argument
559///                        =/ invalid-argument-to-private-entry-function
560///                        =/ index-out-of-bounds
561///                        =/ secondary-index-out-of-bound
562///                        =/ invalid-result-arity
563///                        =/ invalid-gas-coin-usage
564///                        =/ invalid-value-usage
565///                        =/ invalid-object-by-value
566///                        =/ invalid-object-by-mut-ref
567///                        =/ shared-object-operation-not-allowed
568///
569/// type-mismatch                               = %d00
570/// invalid-bcs-bytes                           = %d01
571/// invalid-usage-of-pure-argument              = %d02
572/// invalid-argument-to-private-entry-function  = %d03
573/// index-out-of-bounds                         = %d04 u16
574/// secondary-index-out-of-bound                = %d05 u16 u16
575/// invalid-result-arity                        = %d06 u16
576/// invalid-gas-coin-usage                      = %d07
577/// invalid-value-usage                         = %d08
578/// invalid-object-by-value                     = %d09
579/// invalid-object-by-mut-ref                   = %d10
580/// shared-object-operation-not-allowed         = %d11
581/// ```
582#[derive(Clone, Debug, Eq, Error, Hash, PartialEq)]
583#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
584#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
585#[cfg_attr(feature = "bcs-schema", derive(iota_bcs_schema::BcsSchema))]
586#[non_exhaustive]
587pub enum CommandArgumentError {
588    /// The type of the value does not match the expected type
589    #[error("The type of the value does not match the expected type")]
590    TypeMismatch,
591    /// The argument cannot be deserialized into a value of the specified type
592    #[error("The argument cannot be deserialized into a value of the specified type")]
593    InvalidBcsBytes,
594    /// The argument cannot be instantiated from raw bytes
595    #[error("The argument cannot be instantiated from raw bytes")]
596    InvalidUsageOfPureArgument,
597    /// Invalid argument to private entry function.
598    /// Private entry functions cannot take arguments from other Move functions.
599    #[error(
600        "Invalid argument to private entry function. \
601        These functions cannot take arguments from other Move functions"
602    )]
603    InvalidArgumentToPrivateEntryFunction,
604    /// Out of bounds access to input or results
605    #[error("Out of bounds access to input or result vector {index}")]
606    IndexOutOfBounds { index: u16 },
607    /// Out of bounds access to subresult
608    #[error(
609        "Out of bounds secondary access to result vector \
610        {result} at secondary index {subresult}"
611    )]
612    SecondaryIndexOutOfBounds { result: u16, subresult: u16 },
613    /// Invalid usage of result.
614    /// Expected a single result but found either no return value or multiple.
615    #[error(
616        "Invalid usage of result {result}, \
617        expected a single result but found either no return values or multiple."
618    )]
619    InvalidResultArity { result: u16 },
620    /// Invalid usage of Gas coin.
621    /// The Gas coin can only be used by-value with a TransferObjects command.
622    #[error(
623        "Invalid taking of the Gas coin. \
624        It can only be used by-value with TransferObjects"
625    )]
626    InvalidGasCoinUsage,
627    /// Invalid usage of move value.
628    //     Mutably borrowed values require unique usage.
629    //     Immutably borrowed values cannot be taken or borrowed mutably.
630    //     Taken values cannot be used again.
631    #[error(
632        "Invalid usage of value. \
633        Mutably borrowed values require unique usage. \
634        Immutably borrowed values cannot be taken or borrowed mutably. \
635        Taken values cannot be used again."
636    )]
637    InvalidValueUsage,
638    /// Immutable objects cannot be passed by-value.
639    #[error("Immutable objects cannot be passed by-value")]
640    InvalidObjectByValue,
641    /// Immutable objects cannot be passed by mutable reference, &mut.
642    #[error("Immutable objects cannot be passed by mutable reference, &mut")]
643    InvalidObjectByMutRef,
644    /// Shared object operations such a wrapping, freezing, or converting to
645    /// owned are not allowed.
646    #[error(
647        "Shared object operations such a wrapping, freezing, or converting to owned are not \
648        allowed."
649    )]
650    SharedObjectOperationNotAllowed,
651    /// Invalid argument arity. Expected a single argument but found a result
652    /// that expanded to multiple arguments.
653    #[error(
654        "Invalid argument arity. Expected a single argument but found a result that expanded to \
655        multiple arguments."
656    )]
657    InvalidArgumentArity,
658}
659
660impl CommandArgumentError {
661    crate::def_is!(
662        TypeMismatch,
663        InvalidBcsBytes,
664        InvalidUsageOfPureArgument,
665        InvalidArgumentToPrivateEntryFunction,
666        IndexOutOfBounds,
667        SecondaryIndexOutOfBounds,
668        InvalidResultArity,
669        InvalidGasCoinUsage,
670        InvalidValueUsage,
671        InvalidObjectByValue,
672        InvalidObjectByMutRef,
673        SharedObjectOperationNotAllowed,
674    );
675}
676
677/// An error with a upgrading a package
678///
679/// # BCS
680///
681/// The BCS serialized form for this type is defined by the following ABNF:
682///
683/// ```text
684/// package-upgrade-error = unable-to-fetch-package /
685///                         not-a-package           /
686///                         incompatible-upgrade    /
687///                         digest-does-not-match   /
688///                         unknown-upgrade-policy  /
689///                         package-id-does-not-match
690///
691/// unable-to-fetch-package     = %d00 object-id
692/// not-a-package               = %d01 object-id
693/// incompatible-upgrade        = %d02
694/// digest-does-not-match       = %d03 digest
695/// unknown-upgrade-policy      = %d04 u8
696/// package-id-does-not-match   = %d05 object-id object-id
697/// ```
698#[derive(Clone, Debug, Eq, Error, Hash, PartialEq)]
699#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
700#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
701#[cfg_attr(feature = "bcs-schema", derive(iota_bcs_schema::BcsSchema))]
702#[non_exhaustive]
703pub enum PackageUpgradeError {
704    /// Unable to fetch package
705    #[error("Unable to fetch package at {package_id}")]
706    UnableToFetchPackage { package_id: ObjectId },
707    /// Object is not a package
708    #[error("Object {object_id} is not a package")]
709    NotAPackage { object_id: ObjectId },
710    /// Package upgrade is incompatible with previous version
711    #[error("New package is incompatible with previous version")]
712    IncompatibleUpgrade,
713    /// Digest in upgrade ticket and computed digest differ
714    #[error("Digest in upgrade ticket and computed digest disagree")]
715    DigestDoesNotMatch { digest: Digest },
716    /// Upgrade policy is not valid
717    #[error("Upgrade policy {policy} is not a valid upgrade policy")]
718    UnknownUpgradePolicy { policy: u8 },
719    /// PackageId does not match PackageId in upgrade ticket
720    #[error("Package ID {package_id} does not match package ID in upgrade ticket {ticket_id}")]
721    PackageIdDoesNotMatch {
722        package_id: ObjectId,
723        ticket_id: ObjectId,
724    },
725}
726
727impl PackageUpgradeError {
728    crate::def_is!(
729        UnableToFetchPackage,
730        NotAPackage,
731        IncompatibleUpgrade,
732        DigestDoesNotMatch,
733        UnknownUpgradePolicy,
734        PackageIdDoesNotMatch,
735    );
736}
737
738/// An error with a type argument
739///
740/// # BCS
741///
742/// The BCS serialized form for this type is defined by the following ABNF:
743///
744/// ```text
745/// type-argument-error = type-not-found / constraint-not-satisfied
746/// type-not-found = %d00
747/// constraint-not-satisfied = %d01
748/// ```
749#[derive(Clone, Copy, Debug, Eq, Error, Hash, PartialEq)]
750#[cfg_attr(
751    feature = "serde",
752    derive(serde::Deserialize, serde::Serialize),
753    serde(rename_all = "snake_case")
754)]
755#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
756#[cfg_attr(feature = "bcs-schema", derive(iota_bcs_schema::BcsSchema))]
757#[non_exhaustive]
758pub enum TypeArgumentError {
759    /// A type was not found in the module specified
760    #[error("A type was not found in the module specified")]
761    TypeNotFound,
762    /// A type provided did not match the specified constraint
763    #[error("A type provided did not match the specified constraints")]
764    ConstraintNotSatisfied,
765}
766
767impl TypeArgumentError {
768    crate::def_is!(TypeNotFound, ConstraintNotSatisfied);
769}
770
771#[cfg(feature = "serde")]
772#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
773mod serialization {
774    use serde::{Deserialize, Deserializer, Serialize, Serializer};
775
776    use super::*;
777
778    #[derive(serde::Deserialize, serde::Serialize)]
779    #[serde(rename = "ExecutionStatus")]
780    struct ReadableExecutionStatus {
781        success: bool,
782        #[serde(skip_serializing_if = "Option::is_none")]
783        status: Option<FailureStatus>,
784    }
785
786    #[derive(serde::Deserialize, serde::Serialize)]
787    struct FailureStatus {
788        error: ExecutionError,
789        #[serde(skip_serializing_if = "Option::is_none")]
790        command: Option<u16>,
791    }
792
793    #[derive(serde::Deserialize, serde::Serialize)]
794    #[serde(rename = "ExecutionStatus")]
795    enum BinaryExecutionStatus {
796        Success,
797        Failure {
798            error: ExecutionError,
799            command: Option<u64>,
800        },
801    }
802
803    impl Serialize for ExecutionStatus {
804        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
805        where
806            S: Serializer,
807        {
808            if serializer.is_human_readable() {
809                let readable = match self.clone() {
810                    ExecutionStatus::Success => ReadableExecutionStatus {
811                        success: true,
812                        status: None,
813                    },
814                    ExecutionStatus::Failure { error, command } => ReadableExecutionStatus {
815                        success: false,
816                        status: Some(FailureStatus {
817                            error,
818                            command: command.map(|c| c as u16),
819                        }),
820                    },
821                };
822                readable.serialize(serializer)
823            } else {
824                let binary = match self.clone() {
825                    ExecutionStatus::Success => BinaryExecutionStatus::Success,
826                    ExecutionStatus::Failure { error, command } => {
827                        BinaryExecutionStatus::Failure { error, command }
828                    }
829                };
830                binary.serialize(serializer)
831            }
832        }
833    }
834
835    impl<'de> Deserialize<'de> for ExecutionStatus {
836        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
837        where
838            D: Deserializer<'de>,
839        {
840            if deserializer.is_human_readable() {
841                let ReadableExecutionStatus { success, status } =
842                    Deserialize::deserialize(deserializer)?;
843                match (success, status) {
844                    (true, None) => Ok(ExecutionStatus::Success),
845                    (false, Some(FailureStatus { error, command })) => {
846                        Ok(ExecutionStatus::Failure {
847                            error,
848                            command: command.map(Into::into),
849                        })
850                    }
851                    // invalid cases
852                    (true, Some(_)) | (false, None) => {
853                        Err(serde::de::Error::custom("invalid execution status"))
854                    }
855                }
856            } else {
857                BinaryExecutionStatus::deserialize(deserializer).map(|readable| match readable {
858                    BinaryExecutionStatus::Success => Self::Success,
859                    BinaryExecutionStatus::Failure { error, command } => {
860                        Self::Failure { error, command }
861                    }
862                })
863            }
864        }
865    }
866}