C → WebAssembly → Lean

Check a C code change with Lean

A shorter program can still have a bug. In this example, you can change a pricing function and check that both compiled versions return the required price for every input.

Start with the example below. It replaces a loop with multiplication and simplifies the price calculation. Compile both versions, inspect their instructions, then ask AI to write a proof. Lean checks the proof.

The price rule 9¢ per item after discount + 2¢ fee. Add 1¢ for odd orders. See the calculation ↓

Start at 12¢ per item. Apply a 25% discount. Add 2¢ for an even item count, 3¢ for an odd count. Return 0 for orders over 1,000 items. Arithmetic uses unsigned 32-bit values.

price(n) = n ≤ 1000 ? 9 × n + 2 + (n & 1) : 0

3 items → 30¢. 4 items → 38¢. The proof must cover every input, including the bounds.

No access code is needed. The server accepts one job at a time. If it is busy, try again later. You can still explore the explanations.

Step details

1. Change the pricing function

Start here The rule both programs must meet

The code can change. The price rule stays fixed.

For each item count, both programs must finish and return the price below. This is our .

12¢ per item36¢
−
25% discount9¢
+
Even / odd fee3¢
=
Required price30¢

3 is odd. Add the 3¢ fee.

This picture explains the fixed rule. “Run one input” above runs your actual compiled programs.

Different instructions can give the same result

Adding 12 three times and multiplying 12 by 3 both give 36. A faster version can use different instructions.

Here, means both functions finish with the same required result for every 32-bit input. It does not mean identical files or equal speed.

Inputs over 1,000 must return 0. The proof must cover those inputs too.

The original adds 12 for each item in a loop. The edited version uses multiplication. You can change either program.

A Original programC · uint32_t
Repeated addition → discount → fee
B Your editC · uint32_t
Remove the loop, simplify the discount, remove the fee branch.

Start with “Compile & inspect” to explore without calling AI. “Generate and check proof” runs the whole process.

What this example covers

You can try a new rewrite. It does not have to match a preset. Both functions must still meet the fixed price rule.

Supported code

The proof path supports one 32-bit input and result, local variables, integer arithmetic, branches and up to two loops. Calls, memory access, floating point and many other instructions are outside this path. Unsupported code gets an error.

An equivalent edit can still be too hard for the current agent or time limit. “Not established” means no accepted proof was found.

Where the work runs and how to check it yourself

The browser runs the Wasm examples. Compilation, AI requests and Lean checking run through the server.

This uses Jad’s Wasm decoder, loop rules and proof tools. His compiled library is reused; AI writes a new argument for each submitted pair.

You can download the proof source, helper, exact Wasm files, logs and all attempts. Independent checking needs access to the pinned private library and its small lint-only patch.

Exact formal claim and trust boundaries

LiveDemoProof.binaries_same_result checks that Jad’s decoder reads the exact two binaries as the annotated function bodies. It proves actual Core.Steps executions of both function calls to LiveDemo.price n for every i32 input, under any numerical profile and host, in the one-function instances built by the helper. Both return and preserve their stores. return_values_unique uses Jad’s determinism bridge to show that every returning execution agrees.

Separate checked metadata establishes the i32 → i32 type, absence of imports and the compute export. This is a function-call theorem. It does not prove full module instantiation, full ExportEquiv, C compiler correctness or equal resource use. Browser execution is a separate test.

Private Silmaril revision fc6be8f5e6f6de4c7795776842608dc9795c728f, with lint-only fixes; Lean 4.35.0-rc4. Only standard propext, Classical.choice, Quot.sound axioms are accepted. No sorry, native_decide or unproved SMT facts. The library model, toolchain and I/O are trust boundaries.

Native jobs use containers with no network, read-only libraries, and time and resource limits. A failed, busy or unavailable checker establishes no equivalence claim.

Design references and further reading

The page follows the approach used in Red Blob Games’ A* guide: start with one concrete example, inspect the data, and introduce each step beside an interactive view. These guides also informed the explanations:

The illustrations here explain concepts. The live compiler and Lean stages produce the actual artifacts and results.

In plain words