soma.cell

Face Block and Promises

The face block declares a cell's public interface and promises. Promises are runtime-checked guarantees.

Example 095 of the basic Soma programs: a small, commented program that teaches one thing. Every output below was printed by soma 3.2.4 when this page was built.

How it is built

The cell BankAccount declares 3 signals in its face: deposit(account: String, amount: Int) -> Int, withdraw(account: String, amount: Int) -> Int and get_balance(account: String) -> Int; keeps 1 memory slot: balances (Map<String, Int>, persistent and consistent). Handlers: deposit (line 29), withdraw (line 36) and get_balance (line 46).

Generated from soma describe on this file.

The source

095_face_promise.cell

// ============================================================================
// 095 — Face Block and Promises
// ============================================================================
// The face block declares a cell's public interface and promises.
// Promises are runtime-checked guarantees.
//
// Run:   soma check 095_face_promise.cell
// Expect: All checks passed.
//
// Run:   soma run 095_face_promise.cell get_balance Alice
// Expect: 0

cell BankAccount {
    face {
        // signal declarations define the public API
        signal deposit(account: String, amount: Int) -> Int
        signal withdraw(account: String, amount: Int) -> Int
        signal get_balance(account: String) -> Int

        // Promises: guarantees this cell makes
        promise "balance is always non-negative"
        promise all_persistent
    }

    memory {
        balances: Map<String, Int> [persistent, consistent]
    }

    on deposit(account: String, amount: Int) {
        let current = balances.get(account) ?? 0
        let new_balance = current + amount
        balances.set(account, new_balance)
        return new_balance
    }

    on withdraw(account: String, amount: Int) {
        let current = balances.get(account) ?? 0
        if amount > current {
            return response(400, map("error", "insufficient funds"))
        }
        let new_balance = current - amount
        balances.set(account, new_balance)
        return new_balance
    }

    on get_balance(account: String) {
        return balances.get(account) ?? 0
    }
}

What the toolchain says

$ soma check 095_face_promise.cell
note: promise on 'BankAccount' is documentation (not machine-verifiable): "balance is always non-negative"
  --> 095_face_promise.cell:21:17
   |
21 |         promise "balance is always non-negative"
   |                 ^
✓ All checks passed (1 note above).
$ soma run 095_face_promise.cell get_balance Alice
0