1use crate::ObjectID;
5use crate::base_types::SuiAddress;
6use move_binary_format::file_format::{CodeOffset, TypeParameterIndex};
7use move_core_types::language_storage::ModuleId;
8use serde::{Deserialize, Serialize};
9use std::fmt::{self, Display, Formatter};
10use sui_macros::EnumVariantOrder;
11use thiserror::Error;
12
13#[cfg(test)]
14#[path = "unit_tests/execution_status_tests.rs"]
15mod execution_status_tests;
16
17#[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize)]
18pub enum ExecutionStatus {
19 Success,
20 Failure {
22 error: ExecutionFailureStatus,
24 command: Option<CommandIndex>,
26 },
27}
28
29#[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize)]
30pub struct CongestedObjects(pub Vec<ObjectID>);
31
32impl fmt::Display for CongestedObjects {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
34 for obj in &self.0 {
35 write!(f, "{}, ", obj)?;
36 }
37 Ok(())
38 }
39}
40
41#[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Error, EnumVariantOrder)]
42pub enum ExecutionFailureStatus {
43 #[error("Insufficient Gas.")]
47 InsufficientGas,
48 #[error("Invalid Gas Object. Possibly not address-owned or possibly not a SUI coin.")]
49 InvalidGasObject,
50 #[error("INVARIANT VIOLATION.")]
51 InvariantViolation,
52 #[error("Attempted to used feature that is not supported yet")]
53 FeatureNotYetSupported,
54 #[error(
55 "Move object with size {object_size} is larger \
56 than the maximum object size {max_object_size}"
57 )]
58 MoveObjectTooBig {
59 object_size: u64,
60 max_object_size: u64,
61 },
62 #[error(
63 "Move package with size {object_size} is larger than the \
64 maximum object size {max_object_size}"
65 )]
66 MovePackageTooBig {
67 object_size: u64,
68 max_object_size: u64,
69 },
70 #[error("Circular Object Ownership, including object {object}.")]
71 CircularObjectOwnership { object: ObjectID },
72
73 #[error("Insufficient coin balance for operation.")]
77 InsufficientCoinBalance,
78 #[error("The coin balance overflows u64")]
79 CoinBalanceOverflow,
80
81 #[error(
85 "Publish Error, Non-zero Address. \
86 The modules in the package must have their self-addresses set to zero."
87 )]
88 PublishErrorNonZeroAddress,
89
90 #[error(
91 "Sui Move Bytecode Verification Error. \
92 Please run the Sui Move Verifier for more information."
93 )]
94 SuiMoveVerificationError,
95
96 #[error(
101 "Move Primitive Runtime Error. Location: {0}. \
102 Arithmetic error, stack overflow, max value depth, etc."
103 )]
104 MovePrimitiveRuntimeError(MoveLocationOpt),
105 #[error("Move Runtime Abort. Location: {0}, Abort Code: {1}")]
106 MoveAbort(MoveLocation, u64),
107 #[error(
108 "Move Bytecode Verification Error. \
109 Please run the Bytecode Verifier for more information."
110 )]
111 VMVerificationOrDeserializationError,
112 #[error("MOVE VM INVARIANT VIOLATION.")]
113 VMInvariantViolation,
114
115 #[error("Function Not Found.")]
119 FunctionNotFound,
120 #[error(
121 "Arity mismatch for Move function. \
122 The number of arguments does not match the number of parameters"
123 )]
124 ArityMismatch,
125 #[error(
126 "Type arity mismatch for Move function. \
127 Mismatch between the number of actual versus expected type arguments."
128 )]
129 TypeArityMismatch,
130 #[error("Non Entry Function Invoked. Move Call must start with an entry function")]
131 NonEntryFunctionInvoked,
132 #[error("Invalid command argument at {arg_idx}. {kind}")]
133 CommandArgumentError {
134 arg_idx: u16,
135 kind: CommandArgumentError,
136 },
137 #[error("Error for type argument at index {argument_idx}: {kind}")]
138 TypeArgumentError {
139 argument_idx: TypeParameterIndex,
140 kind: TypeArgumentError,
141 },
142 #[error(
143 "Unused result without the drop ability. \
144 Command result {result_idx}, return value {secondary_idx}"
145 )]
146 UnusedValueWithoutDrop { result_idx: u16, secondary_idx: u16 },
147 #[error(
148 "Invalid public Move function signature. \
149 Unsupported return type for return value {idx}"
150 )]
151 InvalidPublicFunctionReturnType { idx: u16 },
152 #[error("Invalid Transfer Object, object does not have public transfer.")]
153 InvalidTransferObject,
154
155 #[error(
160 "Effects of size {current_size} bytes too large. \
161 Limit is {max_size} bytes"
162 )]
163 EffectsTooLarge { current_size: u64, max_size: u64 },
164
165 #[error(
166 "Publish/Upgrade Error, Missing dependency. \
167 A dependency of a published or upgraded package has not been assigned an on-chain \
168 address."
169 )]
170 PublishUpgradeMissingDependency,
171
172 #[error(
173 "Publish/Upgrade Error, Dependency downgrade. \
174 Indirect (transitive) dependency of published or upgraded package has been assigned an \
175 on-chain version that is less than the version required by one of the package's \
176 transitive dependencies."
177 )]
178 PublishUpgradeDependencyDowngrade,
179
180 #[error("Invalid package upgrade. {upgrade_error}")]
181 PackageUpgradeError { upgrade_error: PackageUpgradeError },
182
183 #[error(
185 "Written objects of {current_size} bytes too large. \
186 Limit is {max_size} bytes"
187 )]
188 WrittenObjectsTooLarge { current_size: u64, max_size: u64 },
189
190 #[error("Certificate is on the deny list")]
191 CertificateDenied,
192
193 #[error(
194 "Sui Move Bytecode Verification Timeout. \
195 Please run the Sui Move Verifier for more information."
196 )]
197 SuiMoveVerificationTimedout,
198
199 #[error("The shared object operation is not allowed.")]
200 SharedObjectOperationNotAllowed,
201
202 #[error(
203 "Certificate cannot be executed due to a dependency on a deleted shared object or an object that was transferred out of consensus"
204 )]
205 InputObjectDeleted,
206
207 #[error("Certificate is cancelled due to congestion on shared objects: {congested_objects}")]
208 ExecutionCancelledDueToSharedObjectCongestion { congested_objects: CongestedObjects },
209
210 #[error("Address {address:?} is denied for coin {coin_type}")]
211 AddressDeniedForCoin {
212 address: SuiAddress,
213 coin_type: String,
214 },
215
216 #[error("Coin type is globally paused for use: {coin_type}")]
217 CoinTypeGlobalPause { coin_type: String },
218
219 #[error("Certificate is cancelled because randomness could not be generated this epoch")]
220 ExecutionCancelledDueToRandomnessUnavailable,
221
222 #[error(
223 "Move vector element (passed to MakeMoveVec) with size {value_size} is larger \
224 than the maximum size {max_scaled_size}. Note that this maximum is scaled based on the \
225 type of the vector element."
226 )]
227 MoveVectorElemTooBig {
228 value_size: u64,
229 max_scaled_size: u64,
230 },
231
232 #[error(
233 "Move value (possibly an upgrade ticket or a dev-inspect value) with size {value_size} \
234 is larger than the maximum size {max_scaled_size}. Note that this maximum is scaled based \
235 on the type of the value."
236 )]
237 MoveRawValueTooBig {
238 value_size: u64,
239 max_scaled_size: u64,
240 },
241
242 #[error("A valid linkage was unable to be determined for the transaction")]
243 InvalidLinkage,
244
245 #[error("Insufficient balance for transaction withdrawal")]
246 InsufficientBalanceForWithdraw,
247
248 #[error("Non-exclusive write input object {id} has been modified")]
249 NonExclusiveWriteInputObjectModified { id: ObjectID },
250 }
253
254#[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Hash)]
255pub struct MoveLocation {
256 pub module: ModuleId,
257 pub function: u16,
258 pub instruction: CodeOffset,
259 pub function_name: Option<String>,
260}
261
262#[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Hash)]
263pub struct MoveLocationOpt(pub Option<MoveLocation>);
264
265#[derive(Eq, PartialEq, Copy, Clone, Debug, Serialize, Deserialize, Hash, Error)]
266pub enum CommandArgumentError {
267 #[error("The type of the value does not match the expected type")]
268 TypeMismatch,
269 #[error("The argument cannot be deserialized into a value of the specified type")]
270 InvalidBCSBytes,
271 #[error("The argument cannot be instantiated from raw bytes")]
272 InvalidUsageOfPureArg,
273 #[error(
274 "Invalid argument to private entry function. \
275 These functions cannot take arguments from other Move functions"
276 )]
277 InvalidArgumentToPrivateEntryFunction,
278 #[error("Out of bounds access to input or result vector {idx}")]
279 IndexOutOfBounds { idx: u16 },
280 #[error(
281 "Out of bounds secondary access to result vector \
282 {result_idx} at secondary index {secondary_idx}"
283 )]
284 SecondaryIndexOutOfBounds { result_idx: u16, secondary_idx: u16 },
285 #[error(
286 "Invalid usage of result {result_idx}, \
287 expected a single result but found either no return values or multiple."
288 )]
289 InvalidResultArity { result_idx: u16 },
290 #[error(
291 "Invalid taking of the Gas coin. \
292 It can only be used by-value with TransferObjects"
293 )]
294 InvalidGasCoinUsage,
295 #[error(
296 "Invalid usage of value. \
297 Mutably borrowed values require unique usage. \
298 Immutably borrowed values cannot be taken or borrowed mutably. \
299 Taken values cannot be used again."
300 )]
301 InvalidValueUsage,
302 #[error("Immutable objects cannot be passed by-value.")]
303 InvalidObjectByValue,
304 #[error("Immutable objects cannot be passed by mutable reference, &mut.")]
305 InvalidObjectByMutRef,
306 #[error(
307 "Shared object operations such a wrapping, freezing, or converting to owned are not \
308 allowed."
309 )]
310 SharedObjectOperationNotAllowed,
311 #[error(
312 "Invalid argument arity. Expected a single argument but found a result that expanded to \
313 multiple arguments."
314 )]
315 InvalidArgumentArity,
316 #[error(
317 "Object passed to TransferObject does not have public transfer, i.e. the `store` \
318 ability"
319 )]
320 InvalidTransferObject,
321 #[error(
322 "First argument to MakeMoveVec is not an object. If no type is specified for MakeMoveVec, all arguments must be the same object type."
323 )]
324 InvalidMakeMoveVecNonObjectArgument,
325 #[error("Specified argument location does not have a value and cannot be used")]
326 ArgumentWithoutValue,
327 #[error(
328 "Cannot move a borrowed value. The value's type does resulted in this argument usage \
329 being inferred as a move. This is likely due to the type not having the `copy` ability; \
330 although in rare cases, it could also be this is the last usage of a value without the \
331 `drop` ability."
332 )]
333 CannotMoveBorrowedValue,
334 #[error(
335 "Cannot write to an argument location that is still borrowed, and where that borrow \
336 is an extension of that reference. This is likely due to this argument being used in a \
337 Move call that returns a reference, and that reference is used in a later command."
338 )]
339 CannotWriteToExtendedReference,
340 #[error(
341 "The argument specified cannot be used as a reference argument in the Move call. Either \
342 the argument is a mutable reference and it conflicts with another argument to the call, \
343 or the argument is mutable and another reference extends it and will be used in a later \
344 command."
345 )]
346 InvalidReferenceArgument,
347}
348
349#[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Hash, Error)]
350pub enum PackageUpgradeError {
351 #[error("Unable to fetch package at {package_id}")]
352 UnableToFetchPackage { package_id: ObjectID },
353 #[error("Object {object_id} is not a package")]
354 NotAPackage { object_id: ObjectID },
355 #[error("New package is incompatible with previous version")]
356 IncompatibleUpgrade,
357 #[error("Digest in upgrade ticket and computed digest disagree")]
358 DigestDoesNotMatch { digest: Vec<u8> },
359 #[error("Upgrade policy {policy} is not a valid upgrade policy")]
360 UnknownUpgradePolicy { policy: u8 },
361 #[error("Package ID {package_id} does not match package ID in upgrade ticket {ticket_id}")]
362 PackageIDDoesNotMatch {
363 package_id: ObjectID,
364 ticket_id: ObjectID,
365 },
366}
367
368#[derive(Eq, PartialEq, Clone, Copy, Debug, Serialize, Deserialize, Hash, Error)]
369pub enum TypeArgumentError {
370 #[error("A type was not found in the module specified.")]
371 TypeNotFound,
372 #[error("A type provided did not match the specified constraints.")]
373 ConstraintNotSatisfied,
374}
375
376impl ExecutionFailureStatus {
377 pub fn command_argument_error(kind: CommandArgumentError, arg_idx: u16) -> Self {
378 Self::CommandArgumentError { arg_idx, kind }
379 }
380}
381
382impl Display for MoveLocationOpt {
383 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
384 match &self.0 {
385 None => write!(f, "UNKNOWN"),
386 Some(l) => write!(f, "{l}"),
387 }
388 }
389}
390
391impl Display for MoveLocation {
392 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
393 let Self {
394 module,
395 function,
396 instruction,
397 function_name,
398 } = self;
399 if let Some(fname) = function_name {
400 write!(
401 f,
402 "{module}::{fname} (function index {function}) at offset {instruction}"
403 )
404 } else {
405 write!(
406 f,
407 "{module} in function definition {function} at offset {instruction}"
408 )
409 }
410 }
411}
412
413impl ExecutionStatus {
414 pub fn new_failure(
415 error: ExecutionFailureStatus,
416 command: Option<CommandIndex>,
417 ) -> ExecutionStatus {
418 ExecutionStatus::Failure { error, command }
419 }
420
421 pub fn is_ok(&self) -> bool {
422 matches!(self, ExecutionStatus::Success)
423 }
424
425 pub fn is_err(&self) -> bool {
426 matches!(self, ExecutionStatus::Failure { .. })
427 }
428
429 pub fn unwrap(&self) {
430 match self {
431 ExecutionStatus::Success => {}
432 ExecutionStatus::Failure { .. } => {
433 panic!("Unable to unwrap() on {:?}", self);
434 }
435 }
436 }
437
438 pub fn unwrap_err(self) -> (ExecutionFailureStatus, Option<CommandIndex>) {
439 match self {
440 ExecutionStatus::Success => {
441 panic!("Unable to unwrap() on {:?}", self);
442 }
443 ExecutionStatus::Failure { error, command } => (error, command),
444 }
445 }
446
447 pub fn get_congested_objects(&self) -> Option<&CongestedObjects> {
448 if let ExecutionStatus::Failure {
449 error:
450 ExecutionFailureStatus::ExecutionCancelledDueToSharedObjectCongestion {
451 congested_objects,
452 },
453 ..
454 } = self
455 {
456 Some(congested_objects)
457 } else {
458 None
459 }
460 }
461
462 pub fn is_cancelled(&self) -> bool {
463 matches!(
464 self,
465 ExecutionStatus::Failure {
466 error: ExecutionFailureStatus::ExecutionCancelledDueToSharedObjectCongestion { .. },
467 ..
468 }
469 )
470 }
471}
472
473pub type CommandIndex = usize;