Issue: #967
This document defines the target authoring model for proof-carrying Yul subtree rewrites.
Partially implemented:
ExprRule(asExprPatchRule) is active in the deterministic patch engine.StmtRule(asStmtPatchRule) is now supported in the patch engine with the same fail-closed metadata gate.BlockRule(asBlockPatchRule) is now supported in the patch engine with the same fail-closed metadata gate.ObjectRule(asObjectPatchRule) is now supported in the patch engine with the same fail-closed metadata gate.- Codegen now runs a two-stage typed rewrite pipeline:
- runtime-scoped fixpoint pass for
ExprRule/StmtRule/BlockRule; - object pass for
ObjectRule. Foundation packs forStmtRule/BlockRule/ObjectRuleare wired but currently empty.
- runtime-scoped fixpoint pass for
- Rule activation now supports pack-scoped allowlists (
packAllowlist) checked againstRewriteCtx.packId. - Patch execution now supports activation-time proof registry enforcement via
PatchPassConfig.requiredProofRefs. In compiler codegen, this defaults to the selected rewrite bundle proof allowlist, so rules with unregisteredproofIdfail closed even if metadata is non-empty. - Rewrite bundles are now explicit and versioned (currently
foundation), with bundle selection propagated byPatchPassConfig.rewriteBundleId. Object rules are now applied sequentially in deterministic priority order within each object-pass iteration (instead of first-match only), enabling chained compat transforms in one iteration. Contract-specific compatibility bundles (e.g.solc-compat-v0for Morpho) have been extracted to external plugin packages (seemorpho-verity). The core compiler ships only thefoundationbundle. External packages register their bundles by extendingallRewriteBundlesvia plugin imports. Runtime codegen no longer has a separate backend-profile dispatch-helper outlining path; outlining is centralized in proof-gated object rules. - Parity packs now require explicit pack-level proof composition metadata (
compositionProofRef) and proof registry coverage (requiredProofRefs) against the selected rewrite bundle before--parity-packselection is accepted. - Yul pretty-printing now canonicalizes switch zero-tags to
case 0(instead ofcase 0x0) to matchsolctokenization for function-level parity digests.
ExprRule: expression subtree rewrites.StmtRule: statement-level rewrites.BlockRule: block structure rewrites (ordering/grouping/scoping).ObjectRule: deploy/runtime object-level rewrites.
id: stable rule identifier.scope: where the rule may run (runtime,deploy,dispatcher,abi,helper(name)).matcher: typed precondition over target subtree plus context.rewrite: transformed subtree.proofRef: theorem establishing semantic preservation under matcher preconditions.deterministic: explicit guarantee that output is stable.
Rules now receive a typed RewriteCtx with:
- stage scope (
runtime,deploy,object); - pass metadata (phase, iteration, pack ID).
Still planned:
- symbol table and helper registry;
- selector map / ABI layout facts;
- canonicalization settings.
- Rules without
proofRefare not activatable. - Rules whose
proofRefis not in the active proof registry are not activatable. - Out-of-scope rewrite attempts fail closed via scope-checked
RewriteCtx. - Overlapping rules must be conflict-checked.
- Pack composition must have a theorem proving semantics preservation.
- Unit tests per rule (positive/negative match cases).
- Determinism tests (repeatability).
- Blast-radius tests (no unrelated subtree mutation).
- Differential execution backstop between pre/post rewrite artifacts.
Use this rule-authoring order to maximize parity progress per change:
- Target the active hash mismatch function first (currently
fun_accrueInterest#0) before adding isolated helper-family rewrites elsewhere. - Prefer structural normalization rewrites that collapse multiple downstream helper gaps in one pass over micro-rules for single helper names.
- Add helper materialization only as a consequence of normalized callsites, and only when referenced + absent.
- Keep rewrites function-scoped and shape-guarded; avoid broad global rewrites that can introduce non-
solchelper drift. - Preserve
onlyInVerity = 0as a hard invariant for each parity step.
When choosing the next rule, rank candidates by:
- Expected reduction in
hashMismatchfor the active target function. - Number of
onlyInSolidityentries likely to close with one deterministic rewrite. - Blast-radius risk (prefer narrow matcher/scope and auditable proof obligations).
Avoid:
- Broad runtime pruning that removes Solidity-emitted helper families.
- Outlining/introducing helper families not emitted by
solcfor the pinned tuple. - Unsupported-manifest edits without a corresponding proof-gated rewrite + tests.