Control Flow, Loops & Labeled Blocks

loop without break has type "never returns" and can be used where any type is expected.

12.1 if / else

if (balance >= amount) {
    withdraw(amount);
} else {
    abort EInsufficientFunds
};
let fee = if (vip) 0 else 100;

12.2 while and loop

loop without break has type "never returns" and can be used where any type is expected. In Move 2024, break can carry a value out of loop: let x = loop { break 42 };.

let mut i = 0;
let mut sum = 0;
while (i < 10) {
    sum = sum + i;
    i = i + 1;
};

let mut n = 0;
loop {
    n = n + 1;
    if (n == 5) continue;
    if (n > 10) break;
};

12.3 for loops (Aptos Move 2)

Sui Move has no for statement; use while, or the integer and vector macros:

// Aptos Move 2
let sum = 0;
for (i in 0..10) {
    sum += i;              // compound assignment (Move 2.1+)
};
// Sui Move 2024
let mut sum = 0;
10u64.do!(|i| sum = sum + i);
vector[1, 2, 3].do!(|x| sum = sum + x);

12.4 Labeled loops and blocks

Both dialects support labels for breaking out of nested loops:

Sui Move 2024 also supports labeled blocks that return early with a value:

'outer: loop {
    let mut j = 0;
    loop {
        j = j + 1;
        if (j == 3) continue 'outer;
        if (j == 100) break 'outer;
    };
};
// Sui Move 2024
fun classify(x: u64): u64 {
    let category = 'calc: {
        if (x == 0) return 'calc 0;
        if (x < 10) return 'calc 1;
        2
    };
    category * 100
}

12.5 return and abort

abort code stops execution and reverts every effect of the transaction.

fun find(v: &vector<u64>, target: u64): Option<u64> {
    let mut i = 0;
    while (i < v.length()) {
        if (v[i] == target) return option::some(i);
        i = i + 1;
    };
    option::none()
}

fun must_be_positive(x: u64) {
    if (x == 0) abort 42;
}

🧪 Part I Exercises

Install either the Sui CLI or the Aptos CLI, start a localnet, fund an address from the faucet, and print your balance.

Create a new package, publish the counter module from Chapter 6 for your chain, call increment three times, and inspect the result in an explorer.

Write a function average(v: &vector<u64>): u64 that returns 0 for an empty vector and never overflows (hint: accumulate in u128).

Write is_prime(n: u64): bool using a while loop, and a labeled loop version that exits early.

Demonstrate each of these aborts in a test: overflow on u8 addition, division by zero, and a failed as u8 cast.

Write reverse_string(s: String): String for ASCII input using std::ascii and vectors.

Explain, in your own words, why a Coin type without copy or drop prevents both double-spending and accidental burning.

Convert a Solidity mapping(address => uint256) balance ledger into a Move design for both Sui (objects) and Aptos (resources). Write the struct definitions only.

Write fizzbuzz(n: u64): vector<String> returning "Fizz", "Buzz", "FizzBuzz", or the number as a string.

Configure Move.toml with a named address and a local dependency on a second package; call a function from the dependency.