Solving VeriContest with a Lean-Backed Rust Verifier
Organizations: Asymptotic
Abstract
VeriContest is a benchmark of 1007 competitive-programming problems in Rust, each with a Verus specification, a judge-accepted solution, and a Verus proof. Its authors report that proof generation is the bottleneck for frontier models: given the specification and the code, the best model produces an accepted Verus proof for 13.95% of the problems on the first attempt. We report on solving the same proof-generation task with Rust-Prover, a verifier for Rust backed by Lean 4. The Verus specification and the Rust code are restated and translated into Lean, each specification becomes a theorem, and agents prove the theorems with Lean's kernel as the final check. All 1325 theorems of all 1007 problems were proved. 1259 of them were proved in one run of under 32 hours on Claude Opus 5.5, at a median of 3.2 minutes and $1.17 per proof, and 70% of them on the first iteration. The restated specifications were checked against the benchmark's test suites, and reviewed where no suite applies. None was wrong or weakened. The translated Lean programs were run on 21,413 of the benchmark's test cases and produced the same output as the Rust programs on every one. Across four Claude and four GPT models at five reasoning-effort settings, every current frontier model proves nearly all of a ten-theorem sample at every setting, and more effort raises the cost without raising the number of proofs. The cheapest Claude setting, Sonnet 5.5 at low effort, proves all of the 50 hardest theorems. We also rerun the benchmark's own Verus protocol with Claude Opus 5.5 on the 50 problems with the longest reference proofs. Opus 5.5 alone fails to prove one of them.
Figures & tables
| Task | pass@1 |
|---|---|
| CodeGen (description to code) | 92.18 % |
| SpecGen (description to spec) | 48.31 % |
| ProofGen (spec + code to Verus proof) | 13.95 % |
| End2End | 5.29 % |
| Per proof | Median | Mean | 90th percentile | Max |
|---|---|---|---|---|
| Time, claim to submit | 3.4 min | 4.3 min | 8.4 min | 69.7 min |
| Iterations (budget 40) | 1 | 1.46 | 3 | 7 |
| Cost | $1.20 | $1.35 | $2.40 | $5.67 |
| Difficulty | Proofs | Median time | Mean iterations | Median cost |
|---|---|---|---|---|
| 0 to 50 | 405 | 2.4 min | 1.64 | $0.87 |
| 50 to 100 | 253 | 3.2 min | 1.36 | $1.20 |
| 100 to 200 | 315 | 4.0 min | 1.42 | $1.39 |
| 200 to 400 | 220 | 5.0 min | 1.36 | $1.54 |
| 400 and up | 73 | 8.6 min | 1.19 | $2.63 |
| Theorems proved | low | medium | high | xhigh | max |
|---|---|---|---|---|---|
| Claude | |||||
| Claude Fable 5.1 | 10 of 10 | 10 of 10 | 10 of 10 | 10 of 10 | 10 of 10 |
| Claude Opus 5.5 | 10 of 10 | 10 of 10 | 10 of 10 | 10 of 10 | 10 of 10 |
| Claude Sonnet 5.5 | 9 of 10 | 10 of 10 | 10 of 10 | 10 of 10 | 10 of 10 |
| Claude Haiku 5.5 | 8 of 10 | 10 of 10 | 10 of 10 | 10 of 10 | 10 of 10 |
| Claude Haiku 4.5 | 0 of 9 | 0 of 8 | 0 of 9 | 0 of 8 | 0 of 9 |
| Cost per proved theorem | low | medium | high | xhigh | max |
|---|---|---|---|---|---|
| Claude | |||||
| Claude Fable 5.1 | $3.59 | $4.71 | $5.41 | $7.40 | $7.97 |
| Claude Opus 5.5 | $1.20 | $1.43 | $1.56 | $2.22 | $3.57 |
| Claude Sonnet 5.5 | $0.95 | $0.94 | $0.97 | $1.40 | $2.56 |
| Claude Haiku 5.5 | $0.44 | $0.48 | $0.62 | $0.78 | $1.04 |
| GPT | |||||
| Sonnet 5.5 at low effort, 50 hardest theorems | |
|---|---|
| Proved | 50 of 50 |
| Accepted on the first iteration | 48 of 50 |
| Median time per proof | 16.3 min |
| Median cost per proof | $2.17 |
| Total cost | $118 |
| Opus 5.5, 50 longest reference proofs | Total | Median | Mean | 90th pct. | Max |
|---|---|---|---|---|---|
| Proved | 49 of 50 | ||||
| Accepted on the first attempt | 18 of 50 | ||||
| Time per proof | 6.1 min | 7.4 min | 12.0 min | 26.7 min | |
| Iterations per proof (budget 10) | 2 | 2.31 | 4.2 | 10 | |
| Cost per proof | $0.92 | $1.12 | $2.05 | $4.14 |
Appendix figures & tables1 asset
Supplementary material from the paper’s appendix.
Appendix
| Specialization | Problems | What was done | Why | Evidence of unchanged meaning |
|---|---|---|---|---|
| Implementation rewritten | 2 (lc3046, lc3233) | A nested for with an early return became a while . f64::sqrt became an integer floor square root. Specs unchanged. | The translation could not join that loop’s exits. No floating-point model. | Exhaustive or differential testing against the old code. Review. |
| Spec helper redefined | 1 (lc1700) | A helper that rotates a queue was redefined as a counting model. Code unchanged. | No list construction in the spec crate. | Equivalence proof by induction. 420,000-case differential test against the Verus helper. The test suites. Review. |
| Strings as bytes | 17 (ASCII string problems) | String and Vec<char> became Vec<u8> , character literals became bytes, in code and spec. Suite strings are fed in as bytes. | No char type in the spec crate. | Each problem’s precondition restricts inputs to ASCII, so nothing is lost. Differential test against a Vec<char> transcription. Review. |
| Pairs as parallel vectors | 5 (cf437C, cf479C, cf1788C, lc163, lc885) | A Vec<(A, B)> became two vectors of equal length, in code and spec. | No tuple element types in the spec crate. | Bijection argument per problem. Differential test against a tuple transcription. Review. |
| Hash maps as vectors | 2 (lc421, lc523) | A HashSet and a HashMap became vector lookups with the same contents at every step. Specs unchanged. | Standard hash maps bring opaque hasher axioms into the translation, so no proof over them is kernel-clean. | Same result by construction. Review. |