Skip to content

Commit 0895c5d

Browse files
Claude Sonnet 4.5claude
andcommitted
fix: Address all Bugbot issues and fix CI
**Critical Bugbot Fixes:** 1. **HIGH SEVERITY - SafeCounter overflow protection restored** - Added `Expr.gt` and `Expr.le` operators to ContractSpec DSL - Implemented overflow check in SafeCounter.increment: `require (count + 1 > count)` - On overflow (MAX_UINT + 1 = 0), check fails: 0 is NOT > MAX_UINT - Generated Yul now includes: `if iszero(gt(add(sload(0), 1), sload(0))) { revert(0, 0) }` - Matches original manual Yul and EDSL safeAdd semantics - All 80 Foundry tests passing including overflow protection tests 2. **MEDIUM SEVERITY - Zip function safety** - Added compile-time validation in Compiler/Specs.lean - 7 #guard statements ensure selector count matches function count - Build fails immediately if mismatch occurs - Prevents silent function dropping at compile time 3. **LOW SEVERITY - Dead code removal** - Deleted Compiler/Parser.lean (141 lines, never imported) - Was placeholder for future AST parsing, never used **CI Fixes:** 4. **Fix hardcoded path in differential tests** - Removed `/workspaces/mission-482e3014/dumbcontracts` path (local-only) - Changed to relative path: `export PATH="$HOME/.elan/bin:$PATH" && lake exe ...` - Works in both local dev and GitHub Actions CI - Commented out random-gen call (not needed, using inline PRNG) **Test Results:** ``` All 80 Foundry tests passing: - 76 original tests ✓ - 4 differential tests ✓ (including 100 random transactions) - SafeCounter overflow protection ✓ - All contracts compile ✓ - All 252 Lean proofs verify ✓ ``` **Files Changed:** - Compiler/ContractSpec.lean: Added gt/le operators, updated codegen - Compiler/Specs.lean: Added overflow check to SafeCounter, compile-time validation - Compiler/Parser.lean: Deleted (unused) - compiler/yul/SafeCounter.yul: Regenerated with overflow check - test/DifferentialSimpleStorage.t.sol: Fixed CI path issues **Bugbot Review Thread Responses:** Issue #1 (SafeCounter overflow): Fixed - overflow check restored with new gt operator Issue #2 (Parser dead code): Fixed - file deleted Issue #3 (Zip silent truncation): Fixed - compile-time guards added Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent f514220 commit 0895c5d

7 files changed

Lines changed: 291 additions & 157 deletions

File tree

Compiler/ContractSpec.lean

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,9 @@ inductive Expr
7878
| sub (a b : Expr)
7979
| eq (a b : Expr)
8080
| ge (a b : Expr)
81+
| gt (a b : Expr) -- Greater than (strict)
8182
| lt (a b : Expr)
83+
| le (a b : Expr) -- Less than or equal
8284
deriving Repr
8385

8486
inductive Stmt
@@ -140,7 +142,9 @@ private def compileExpr (fields : List Field) : Expr → YulExpr
140142
| Expr.sub a b => YulExpr.call "sub" [compileExpr fields a, compileExpr fields b]
141143
| Expr.eq a b => YulExpr.call "eq" [compileExpr fields a, compileExpr fields b]
142144
| Expr.ge a b => YulExpr.call "iszero" [YulExpr.call "lt" [compileExpr fields a, compileExpr fields b]]
145+
| Expr.gt a b => YulExpr.call "gt" [compileExpr fields a, compileExpr fields b]
143146
| Expr.lt a b => YulExpr.call "lt" [compileExpr fields a, compileExpr fields b]
147+
| Expr.le a b => YulExpr.call "iszero" [YulExpr.call "gt" [compileExpr fields a, compileExpr fields b]]
144148
termination_by e => sizeOf e
145149

146150
-- Compile statement to Yul
@@ -230,6 +234,7 @@ private def compileConstructor (fields : List Field) (ctor : Option ConstructorS
230234
argLoads ++ body
231235

232236
-- Main compilation function
237+
-- SAFETY: selectors.length must equal spec.functions.length (checked at compile time in Specs.lean)
233238
def compile (spec : ContractSpec) (selectors : List Nat) : IRContract :=
234239
{ name := spec.name
235240
deploy := compileConstructor spec.fields spec.constructor

Compiler/Parser.lean

Lines changed: 0 additions & 141 deletions
This file was deleted.

Compiler/Specs.lean

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,9 @@ def safeCounterSpec : ContractSpec := {
338338
params := []
339339
returnType := none
340340
body := [
341-
-- TODO: Add overflow check (current + 1 >= current)
341+
-- Overflow check: require (count + 1 > count)
342+
-- On overflow, MAX_UINT + 1 = 0, which is NOT > MAX_UINT, so this will revert
343+
Stmt.require (Expr.gt (Expr.add (Expr.storage "count") (Expr.literal 1)) (Expr.storage "count")) "Overflow",
342344
Stmt.setStorage "count" (Expr.add (Expr.storage "count") (Expr.literal 1)),
343345
Stmt.stop
344346
]
@@ -378,4 +380,24 @@ def allSpecs : List (ContractSpec × List Nat) := [
378380
(safeCounterSpec, safeCounterSelectors)
379381
]
380382

383+
/-!
384+
## Compile-Time Validation
385+
386+
Ensure each spec has exactly the right number of selectors.
387+
These checks run at compile time and will fail the build if mismatched.
388+
-/
389+
390+
-- Validate selector counts match function counts
391+
private def validateSpec (name : String) (spec : ContractSpec) (selectors : List Nat) : Bool :=
392+
spec.functions.length == selectors.length
393+
394+
-- Compile-time assertions (evaluated during type-checking)
395+
#guard validateSpec "SimpleStorage" simpleStorageSpec simpleStorageSelectors
396+
#guard validateSpec "Counter" counterSpec counterSelectors
397+
#guard validateSpec "Owned" ownedSpec ownedSelectors
398+
#guard validateSpec "Ledger" ledgerSpec ledgerSelectors
399+
#guard validateSpec "OwnedCounter" ownedCounterSpec ownedCounterSelectors
400+
#guard validateSpec "SimpleToken" simpleTokenSpec simpleTokenSelectors
401+
#guard validateSpec "SafeCounter" safeCounterSpec safeCounterSelectors
402+
381403
end Compiler.Specs

0 commit comments

Comments
 (0)