Skip to content

Commit 30777c2

Browse files
authored
Add typed unsafe Yul fragments to CompilationModel (#1942)
* Add raw revert statement support * Fix rawRevert validation and trust surface coverage * Handle rawRevert in source semantics proof * Cover rawRevert in function body scope proofs * Cover rawRevert in generic induction proofs * Add typed raw Yul fragments * Prove raw Yul lowering preserves fragments * Refine unsafe Yul fragment architecture * Fix unsafe Yul validation regressions * Reject stop-only return paths * Track unsafe Yul effects in modifies and CEI checks Surface declared raw-Yul storage writes in the modifies() write-set, flag computed-slot writes as untrackable, and treat fragment call mechanics as external interactions for CEI ordering and external-call detection.
1 parent 9eaf642 commit 30777c2

25 files changed

Lines changed: 1371 additions & 484 deletions

Compiler/CompilationModel.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import Compiler.CompilationModel.MappingWrites
2222
import Compiler.CompilationModel.ScopeValidation
2323
import Compiler.CompilationModel.StorageWrites
2424
import Compiler.CompilationModel.TrustSurface
25+
import Compiler.CompilationModel.YulImporter
2526
import Compiler.CompilationModel.UsageAnalysis
2627
import Compiler.CompilationModel.ValidationCalls
2728
import Compiler.CompilationModel.ValidationEvents

Compiler/CompilationModel/Compile.lean

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ namespace Compiler.CompilationModel
4242
open Compiler
4343
open Compiler.Yul
4444

45+
/-- Single bridge from typed unsafe/raw Yul fragments into the EVMYul AST.
46+
Proof obligations and trust metadata live on `UnsafeYulFragment`; this
47+
function is intentionally the only compiler lowering point for that escape
48+
hatch. -/
49+
def unsafeYulToEVMYul (fragment : UnsafeYulFragment) : List YulStmt :=
50+
fragment.stmts
51+
52+
theorem unsafeYulToEVMYul_eq (fragment : UnsafeYulFragment) :
53+
unsafeYulToEVMYul fragment = fragment.stmts := rfl
54+
4555
private def compileAdtStorageWrite (fields : List Field)
4656
(dynamicSource : DynamicDataSource) (adtTypes : List AdtTypeDef)
4757
(storageField adtName variantName : String) (args : List Expr) :
@@ -270,6 +280,9 @@ def compileStmt (fields : List Field) (events : List EventDef := [])
270280
-- Unsafe block: transparent wrapper, compile inner body directly (#1728, Axis 6 Step 6a)
271281
compileStmtList fields events errors dynamicSource internalRetNames isInternal inScopeNames adtTypes body
272282

283+
| Stmt.unsafeYul fragment =>
284+
pure (unsafeYulToEVMYul fragment)
285+
273286
| Stmt.emit eventName args => do
274287
compileEmit fields events dynamicSource eventName args
275288

@@ -467,4 +480,17 @@ def compileMatchAdtBranches (fields : List Field) (events : List EventDef)
467480
pure ((variant.tag, fieldBindings ++ bodyStmts) :: restCases)
468481
end
469482

483+
theorem compileStmt_unsafeYul
484+
(fields : List Field) (events : List EventDef := [])
485+
(errors : List ErrorDef := [])
486+
(dynamicSource : DynamicDataSource := .calldata)
487+
(internalRetNames : List String := [])
488+
(isInternal : Bool := false)
489+
(inScopeNames : List String := [])
490+
(adtTypes : List AdtTypeDef := [])
491+
(fragment : UnsafeYulFragment) :
492+
compileStmt fields events errors dynamicSource internalRetNames isInternal inScopeNames adtTypes
493+
(Stmt.unsafeYul fragment) = pure fragment.stmts := by
494+
simp [compileStmt, unsafeYulToEVMYul]
495+
470496
end Compiler.CompilationModel

Compiler/CompilationModel/LogicalPurity.lean

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,8 @@ def stmtContainsUnsafeLogicalCallLike : Stmt → Bool
258258
exprListAnyUnsafeLogicalCallLike args
259259
| Stmt.ecm _ args =>
260260
exprListAnyUnsafeLogicalCallLike args
261+
| Stmt.unsafeYul _ =>
262+
false
261263
termination_by s => sizeOf s
262264
decreasing_by all_goals simp_wf; all_goals omega
263265

Compiler/CompilationModel/ScopeValidation.lean

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,18 @@ def validateScopedStmtIdentifiers
566566
| Stmt.returnBytes _ | Stmt.returnStorageWords _
567567
| Stmt.revertReturndata | Stmt.stop =>
568568
pure localScope
569+
| Stmt.unsafeYul fragment => do
570+
let mut scope := localScope
571+
for name in fragment.scopeEffects.bindNames do
572+
if paramScope.contains name then
573+
throw s!"Compilation error: {context} unsafe Yul fragment '{fragment.label}' result '{name}' shadows a parameter"
574+
if scope.contains name then
575+
throw s!"Compilation error: {context} unsafe Yul fragment '{fragment.label}' redeclares result '{name}' in the same scope"
576+
scope := name :: scope
577+
for name in fragment.scopeEffects.assignNames do
578+
if !scope.contains name then
579+
throw s!"Compilation error: {context} unsafe Yul fragment '{fragment.label}' assigns to undeclared local variable '{name}'"
580+
pure scope
569581
termination_by s => sizeOf s
570582
decreasing_by all_goals simp_wf; all_goals omega
571583

0 commit comments

Comments
 (0)