Add typed unsafe Yul fragments to CompilationModel#1942
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
| \n### CI Failure Hints\n\nFailed jobs: `build`\n\nCopy-paste local triage:\n```bash\nmake check\nlake build\nFOUNDRY_PROFILE=difftest forge test -vv\n``` |
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.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 0e50381. Configure here.
| if (seenCall || fragmentCalls) && fragmentWrites then | ||
| some "raw Yul fragment writes state after an external call" | ||
| else | ||
| none |
There was a problem hiding this comment.
Undeclared call mechanics bypass CEI
High Severity
validateUnsafeYulDeclaredScopeEffects cross-checks binds, assigns, and storage writes against the embedded Yul AST, but LowLevelMechanic tags are not. CEI and external-call detection for Stmt.unsafeYul rely only on fragment.mechanics, so a fragment whose Yul contains call/staticcall/delegatecall but omits those mechanics can skip interaction tracking and later persistent writes without a CEI error.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 0e50381. Configure here.
| let bodyEffects := yulStmtListScopeEffects body | ||
| { bindNames := [name] | ||
| assignNames := [] | ||
| storageWrites := bodyEffects.storageWrites } |
There was a problem hiding this comment.
Yul funcDef pollutes Verity scope
Medium Severity
yulStmtScopeEffects treats a nested Yul function definition name as a bindNames entry like a let. Scope validation then requires that name in declared effects and adds it to the enclosing Verity local scope, even though the name is an internal Yul callable, not a Verity local binding.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 0e50381. Configure here.


Summary
UnsafeYulFragment/RawYulescape hatch toCompilationModel.StmtviaStmt.unsafeYulStmt.rawRevertpath; one-off low-level instructions now live behind reusableUnsafeYulFragmenthelpers such asUnsafeYulFragment.rawRevertUnsafeYulContracts, local obligations,LowLevelMechanicenum tags,ControlFlowSummary, and declared scope effectsunsafeYulToEVMYul, the single bridge from typed raw-Yul fragments to the backend EVMYul ASTunsafeYulToEVMYul_eqandcompileStmt_unsafeYulStmtMetadata,Stmt.fold, andStmt.foldList, reducing constructor-by-constructor duplicationYulImporterpath for imported Solidity/Yul AST blocks to become explicitStmt.unsafeYulfragments with generated metadataWhy
The SPHINCS- verifier models need to mirror Solidity handwritten assembly closely, including exact empty reverts and manually constructed
Error(string)revert data. Adding a first-class Verity statement for every Yul instruction would grow the trusted surface and duplicate backend AST concepts. The cleaner boundary is a typed raw-Yul fragment: the model author supplies the Yul AST, and Verity requires the proof obligations, trust tags, termination/control-flow summary, and scope effects needed by validation and reports.Architecture
Stmtremains separate from backend EVMYulYulStmt. The wrapper is intentional: backend Yul does not carry source-level proof obligations, trust metadata, or validation policy.Stmt.unsafeYul fragmentembeds backend Yul AST statements, not raw Yul strings.mstore,calldatacopy, and other semantically modeled operations remain first-class when they have proof/audit value.UnsafeYulFragments, not newStmtconstructors.compileStmt_unsafeYulshows the compiler emits exactlyfragment.stmts. The larger proof boundary is semantic: each fragment’sUnsafeYulContractand local obligations must be discharged by the model proof.Verification
lake buildlake build Compiler.CompileDriverTestlake build Compiler.CompilationModel.CompileNote
Medium Risk
Touches compiler lowering, validation, CEI, and trust-report surfaces for low-level/assembly code; semantic correctness still depends on discharging fragment obligations rather than full interpreter modeling.
Overview
This PR adds a typed raw-Yul escape hatch via
Stmt.unsafeYulandUnsafeYulFragment, replacing ad-hoc paths like dedicatedStmt.rawRevertwith helpers such asUnsafeYulFragment.rawRevert. Fragments carry EVMYul AST, local obligations,LowLevelMechanictags, scope effects, control-flow/termination summaries, and optionalUnsafeYulContractrefinements; lowering is centralized inunsafeYulToEVMYulwith a provedcompileStmt_unsafeYulpass-through.Validation and scope now require non-empty obligations, check declared scope effects against the embedded Yul AST (binds, assigns, storage writes), and integrate fragments into view/pure, CEI, untrackable writes, and scope validation.
YulImporterturns imported Solidity/Yul blocks intoStmt.unsafeYulwith derived metadata.Trust reporting drops large per-constructor statement walks in favor of
Stmt.fold/StmtMetadata, surfacesunsafeYulContractsin JSON, treatsrawRevertas a denied mechanic, and merges fragment local obligations from function/constructor bodies.ControlFlowSummarydrives “all paths return/revert” checks. Docs and tests cover the new boundary.Reviewed by Cursor Bugbot for commit 0e50381. Bugbot is set up for automated code reviews on this repo. Configure here.