Aborting Execution
A transaction can either succeed or fail. Successful execution applies all the changes made to
objects and on-chain data, and the transaction is committed to the blockchain. Alternatively, if a
transaction aborts, the changes are not applied. The abort
keyword is used to abort a transaction
and revert the changes made so far.
It is important to note that there is no catch mechanism in Move. If a transaction aborts, the changes made so far are reverted, and the transaction is considered failed.
Abort
The abort
keyword is used to abort the execution of a transaction. It is used in combination with
an abort code, which will be returned to the caller of the transaction. The abort code is an
integer of type u64
.
let user_has_access = true;
// abort with a predefined constant if `user_has_access` is false
if (!user_has_access) {
abort 0
};
// there's an alternative syntax using parenthesis`
if (user_has_access) {
abort(1)
};
The code above will, of course, abort with abort code 1
.
assert!
The assert!
macro is a built-in macro that can be used to assert a condition. If the condition is
false, the transaction will abort with the given abort code. The assert!
macro is a convenient way
to abort a transaction if a condition is not met. The macro shortens the code otherwise written with
an if
expression + abort
. The code
argument is optional, but has to be a u64
value or an
#[error]
(see below for more information).
// aborts if `user_has_access` is `false` with abort code 0
assert!(user_has_access, 0);
// expands into:
if (!user_has_access) {
abort 0
};
Error constants
To make error codes more descriptive, it is a good practice to define
error constants. Error constants are defined as const
declarations and are
usually prefixed with E
followed by a camel case name. Error constants are no different from other
constants and don't have special handling, however, they are used to increase the readability of the
code and make it easier to understand the abort scenarios.
/// Error code for when the user has no access.
const ENoAccess: u64 = 0;
/// Trying to access a field that does not exist.
const ENoField: u64 = 1;
/// Updates a record.
public fun update_record(/* ... , */ user_has_access: bool, field_exists: bool) {
// asserts are way more readable now
assert!(user_has_access, ENoAccess);
assert!(field_exists, ENoField);
/* ... */
}
Error messages
Move 2024 introduces a special type of error constant, marked with the #[error]
attribute. This
attribute allows the error constant to be of type vector<u8>
and can be used to store an error
message.
#[error]
const ENotAuthorized: vector<u8> = b"The user is not authorized to perform this action";
#[error]
const EValueTooLow: vector<u8> = b"The value is too low, it should be at least 10";
/// Performs an action on behalf of the user.
public fun update_value(user: &mut User, value: u64) {
assert!(user.is_authorized, ENotAuthorized);
assert!(value >= 10, EValueTooLow);
user.value = value;
}
Further reading
- Abort and Assert in the Move Reference.
- We suggest reading the Better Error Handling guide to learn about best practices for error handling in Move.