Skip to main content

Formal Verification

Formal verification is a primary Ora feature: correctness properties are explicit, mechanically checked, and traceable through the compiler pipeline.

v0.2 verification is build-integrated: a full build runs the verifier, reports counterexamples and proof trust, and refuses verified artifacts when required proof obligations fail, degrade, or return UNKNOWN.

Model

Verification is expressed with specification clauses that live alongside code:

  • requires — preconditions that constrain the verified body and are enforced at public/call boundaries
  • guard — runtime-enforced preconditions the function checks itself (reverts if false, informs the verifier)
  • ensures — postconditions the function must satisfy on all return paths
  • invariant — contract-level or loop-level properties that must hold across all state transitions
  • assume — verification-only constraints (no runtime check)
  • assert — runtime-visible checks also modeled as verification obligations

These clauses are parsed and type-checked in the front end, then lowered into verification-relevant IR for constraint extraction and SMT proof.

Example

pub fn transfer(to: address, amount: u256) -> bool
requires balances[std.msg.sender()] >= amount
guard amount > 0
guard to != std.constants.ZERO_ADDRESS
ensures balances[std.msg.sender()] == old(balances[std.msg.sender()]) - amount
ensures balances[to] == old(balances[to]) + amount
{
// implementation
}

Verification flow

Implemented today

  • Specification clauses are parsed, type-checked, and carried into Ora MLIR.
  • Checked arithmetic, division, assert, ensures, loop invariants, callee preconditions, and active refinement guards become proof obligations.
  • requires clauses become tracked assumptions for the verified body and are enforced at ABI/call boundaries.
  • ensures_ok and ensures_err constrain success and error exits of Result/error-union functions.
  • old(expr) denotes function-entry state for storage/frame reasoning.
  • modifies clauses frame current-contract storage paths for callers.
  • Z3 counterexamples are surfaced when obligations fail.
  • Explain-mode reports expose assumption cores and vacuity risk.
  • Encoding degradation, soundness losses, and UNKNOWN fail closed instead of being counted as verified.

Status

Formal verification is active in the v0.2 build pipeline. It is not a formal EVM-bytecode equivalence proof; the verifier trusts the MLIR-to-SMT encoder and the lowering pipeline, and bytecode conformance tests cover representative runtime behavior.

Ora also has two kernel-checked Lean lanes: a per-contract userland gate and a repository-level compiler/model gate. See Lean Verification: Userland and Kernel Lanes for their commands, proof surfaces, certificates, failure behavior, and exact trust boundaries.

Evidence

  • docs/compiler/formal-verification.md
  • docs/compiler/onboarding/09-z3-smt.md