Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Assura Contract Cookbook

Ready-to-copy contract patterns organized by category. Each pattern is self-contained. For syntax basics, see the tutorial.

Arithmetic Safety

Safe Division

Prevents: division by zero, incorrect quotient

contract SafeDivision {
    input(a: Int, b: Int)
    output(result: Int)

    requires { b != 0 }
    ensures  { result * b + (a mod b) == a }
    ensures  { abs(result) <= abs(a) }
    effects  { pure }
}

Integer Overflow Guard

Prevents: silent integer overflow on addition

contract SafeAdd {
    input(a: Int, b: Int, max: Int)
    output(result: Int)

    requires { a >= 0 }
    requires { b >= 0 }
    requires { a + b <= max }
    ensures  { result == a + b }
    ensures  { result >= 0 }
    effects  { pure }
}

Percentage Bounds

Prevents: percentage values outside 0..100

type Percentage = { v: Float | v >= 0.0 && v <= 100.0 };

contract ApplyDiscount {
    input(price: Float, discount: Percentage)
    output(result: Float)

    requires { price >= 0.0 }
    ensures  { result >= 0.0 }
    ensures  { result <= price }
    effects  { pure }
}

Bounds Checking

Safe Array Index

Prevents: out-of-bounds array access

contract SafeIndex {
    input(arr: List<Int>, index: Nat)
    output(result: Int)

    requires { index < arr.length() }
    effects  { pure }
}

Bounded Slice

Prevents: slice overrun past buffer end

contract SafeSlice {
    input(buf: Bytes, offset: Nat, len: Nat)
    output(data: Bytes)

    requires { offset + len <= buf.length() }
    ensures  { data.length() == len }
    effects  { pure }
}

Buffer Capacity

Prevents: writes past allocated buffer capacity

contract BoundedBuffer {
    input(capacity: Nat, count: Nat, item_size: Nat)

    requires { capacity > 0 }
    requires { count * item_size <= capacity }
    invariant { count * item_size <= capacity }
    effects  { pure }
}

String and Bytes

Non-Empty String

Prevents: empty string passed where content is required

contract NonEmptyInput {
    input(name: String)

    requires { name.length() > 0 }
    effects  { pure }
}

Bounded String Length

Prevents: oversized strings causing truncation or overflow

contract BoundedString {
    input(value: String, max_len: Nat)

    requires { value.length() > 0 }
    requires { value.length() <= max_len }
    requires { max_len <= 65535 }
    effects  { pure }
}

Option/Result Safety

Safe Unwrap via Precondition

Prevents: unwrap on None/Err

contract SafeUnwrap {
    input(value: Int?, default_val: Int)
    output(result: Int)

    ensures { result == if value != null then value else default_val }
    effects { pure }
}

Error Propagation

Prevents: unhandled error cases

fn parse_port(s: String) -> Int?
    requires { s.length() > 0 }
    ensures  { result != null implies result >= 1 }
    ensures  { result != null implies result <= 65535 }
    effects  { pure }

Collection Properties

Non-Empty Collection

Prevents: operations on empty collections (head, reduce, min, max)

contract NonEmptyList {
    input(items: List<Int>)
    output(result: Int)

    requires { items.length() > 0 }
    effects  { pure }
}

Sorted Output

Prevents: sort functions that return unsorted data

contract SortContract {
    input(arr: List<Int>)
    output(result: List<Int>)

    requires { arr.length() > 0 }
    ensures  { result.length() == arr.length() }
    ensures  { forall i in 0..result.length() - 1: result[i] <= result[i + 1] }
    effects  { pure }
}

Element Uniqueness

Prevents: duplicate entries in collections that require distinct elements

contract UniqueElements {
    input(items: List<Int>, new_item: Int)
    output(result: List<Int>)

    requires { forall i in items: i != new_item }
    ensures  { result.length() == items.length() + 1 }
    effects  { pure }
}

Monotonicity and Ordering

Monotonic Counter

Prevents: counter decrement, stale sequence numbers

contract IncrementCounter {
    input(current: Nat, amount: Nat)
    output(result: Nat)

    requires { amount > 0 }
    ensures  { result > current }
    ensures  { result == current + amount }
    effects  { pure }
}

Timestamp Ordering

Prevents: out-of-order event timestamps

contract AppendEvent {
    input(last_ts: Nat, new_ts: Nat)

    requires { new_ts > last_ts }
    ensures  { new_ts > last_ts }
    effects  { pure }
}

Resource Lifecycle

Connection Open/Close

Prevents: use-after-close, double-close, resource leaks

service Connection {
    states: Closed -> Open -> Closed

    operation Open {
        input(host: String)
        requires { host.length() > 0 }
        requires { self.state == Closed }
        ensures  { self.state == Open }
        effects  { net }
    }

    operation Send {
        input(data: Bytes)
        requires { self.state == Open }
        requires { data.length() > 0 }
        ensures  { self.state == Open }
        effects  { net }
    }

    operation Close {
        requires { self.state == Open }
        ensures  { self.state == Closed }
        effects  { net }
    }
}

Acquire/Release Lock

Prevents: double-acquire, use without lock, forgotten release

service Mutex {
    states: Unlocked -> Locked -> Unlocked

    operation Acquire {
        requires { self.state == Unlocked }
        ensures  { self.state == Locked }
        effects  { mem }
    }

    operation Release {
        requires { self.state == Locked }
        ensures  { self.state == Unlocked }
        effects  { mem }
    }
}

Effects and Purity

Pure Computation

Prevents: accidental side effects in business logic

contract PureTransform {
    input(items: List<Int>)
    output(result: List<Int>)

    requires { items.length() > 0 }
    ensures  { result.length() == items.length() }
    effects  { pure }
}

IO Isolation

Prevents: database access from code that should only do network IO

fn fetch_remote(url: String) -> Bytes
    requires { url.length() > 0 }
    effects  { net }

fn save_to_db(data: Bytes) -> Bool
    requires { data.length() > 0 }
    effects  { database.write }

fn api_handler(url: String) -> Bool
    requires { url.length() > 0 }
    effects  { net, database.write }

Taint Tracking

Untrusted Input Validation

Prevents: unsanitized user input reaching sensitive operations

fn read_user_input() -> String @taint:untrusted
    effects { io }

fn validate_input(
    raw: String @taint:untrusted,
    max_len: Nat
) -> String @taint:validated
    requires { max_len > 0 }
    effects  { pure }
{
    validate {
        raw.length() > 0 && raw.length() <= max_len
    } raw
        or ""
}

fn execute_query(query: String @taint:validated) -> Int
    effects { database.read }

Quantifiers

All Elements Positive

Prevents: negative values slipping into a non-negative collection

contract AllPositive {
    input(items: List<Int>)

    requires { items.length() > 0 }
    ensures  { forall i in items: i >= 0 }
    effects  { pure }
}

Element Exists

Prevents: search returning not-found when element is guaranteed present

contract FindElement {
    input(arr: List<Int>, n: Nat, target: Int)
    output(result: Int)

    requires { n > 0 }
    requires { exists i in 0..n: arr[i] == target }
    ensures  { result == target }
    effects  { pure }
}

Bind Declarations

Retrofit Existing Rust Function

Prevents: calling an existing Rust function without contract enforcement

bind "my_crate::math::divide" as safe_divide {
    input(a: Int, b: Int)
    output(result: Int)
    requires { b != 0 }
    ensures  { result * b == a }
}

Bind with Effects

Prevents: calling an FFI function without declaring its side effects

bind "libc::malloc" as safe_malloc {
    input(size: Nat)
    output(result: Bytes)
    requires { size > 0 }
    ensures  { result.length() == size }
    effects  { mem }
}

Key Derivation and Crypto

Secure Key Length

Prevents: weak cryptographic keys

contract SecureKeyDerivation {
    input(password_len: Nat, salt_len: Nat, iterations: Nat)

    requires { password_len >= 8 }
    requires { salt_len >= 16 }
    requires { iterations >= 100000 }
    effects  { pure }
}